irc-netcore-api/IRaCIS.Core.Application/Service/Document/EmailSendService.cs

612 lines
31 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using DocumentFormat.OpenXml.EMMA;
using DocumentFormat.OpenXml.Spreadsheet;
using IRaCIS.Application.Contracts;
using IRaCIS.Application.Interfaces;
using IRaCIS.Core.Application.Contracts;
using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Application.Service.Reading.Dto;
using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infrastructure;
using MailKit;
using Microsoft.Extensions.Options;
using Microsoft.VisualBasic;
using MimeKit;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Mail;
using System.Text;
using System.Threading.Tasks;
namespace IRaCIS.Core.Application.Service
{
public interface IEmailSendService
{
Task SendEnrollOrPdEmail(Guid visitTaskId, bool? isEnrollment, bool? isPDConfirm);
Task SendClinicalDataQuestionAsync(Guid visitTaskId, string content);
Task SendTrialImageQCTaskEmailAsync(Guid trialId);
Task SendTrialQCQuestionEmailAsync(Guid trialId);
Task SendTrialImageQuestionAsync(Guid trialId);
Task SendPIAuditResultAsync(Guid visitTaskId);
Task<(TrialEmailNoticeConfig?, SMTPEmailConfig?)> BuildEmailConfig(Guid trialId, EmailBusinessScenario businessScenario, Func<TrialEmailNoticeConfig, (string topicStr, string htmlBodyStr, bool isEn_us, Guid? onlyToUserId)> topicAndHtmlFunc, Guid? siteId = null, Guid? trialReadingCriterionId = null);
}
public class EmailSendService : BaseService, IEmailSendService
{
private readonly IRepository<TrialEmailNoticeConfig> _trialEmailNoticeConfigRepository;
private readonly IRepository<EmailNoticeConfig> _emailNoticeConfigRepository;
private readonly IRepository<Trial> _trialRepository;
private readonly IOptionsMonitor<SystemEmailSendConfig> _SystemEmailSendConfig;
public readonly static string EmailNamePlaceholder = "EmailNamePlaceholder";
private readonly IRepository<Dictionary> _dictionaryRepository;
public EmailSendService(IRepository<TrialEmailNoticeConfig> trialEmailNoticeConfigRepository, IRepository<EmailNoticeConfig> emailNoticeConfigRepository, IRepository<Trial> trialRepository, IOptionsMonitor<SystemEmailSendConfig> systemEmailSendConfig,IRepository<Dictionary> dictionaryRepository)
{
_trialEmailNoticeConfigRepository = trialEmailNoticeConfigRepository;
_emailNoticeConfigRepository = emailNoticeConfigRepository;
_trialRepository = trialRepository;
_SystemEmailSendConfig = systemEmailSendConfig;
_dictionaryRepository=dictionaryRepository;
}
//入组确认/PD确认
public async Task SendEnrollOrPdEmail(Guid visitTaskId, bool? isEnrollment, bool? isPDConfirm)
{
EmailBusinessScenario businessScenarioEnum;
bool? result = null;
if (isEnrollment != null && isPDConfirm == null)
{
businessScenarioEnum = EmailBusinessScenario.EnrollConfirmed;
result = isEnrollment;
}
else
{
businessScenarioEnum = EmailBusinessScenario.PDConfirmed;
result = isPDConfirm;
}
var taskInfo = await _repository.Where<VisitTask>(t => t.Id == visitTaskId).Select(t => new
{
t.Subject.SiteId,
t.Trial.ResearchProgramNo,
t.Subject.TrialSite.TrialSiteCode,
SubjectCode = t.Subject.Code,
t.Trial.Sponsor.SponsorName,
t.SourceSubjectVisit.VisitName,
t.TrialId,
}).FirstNotNullAsync();
var isEn_us = _userInfo.IsEn_Us;
var resultStr = isEn_us ? (result == true ? "Yes" : "No") : (result == true ? "是" : "否");
if (isEnrollment == true)
{
Func<TrialEmailNoticeConfig, (string topicStr, string htmlBodyStr, bool isEn_us, Guid? onlyToUserId)> topicAndHtmlFunc = trialEmailConfig =>
{
var topicStr = string.Format(isEn_us ? trialEmailConfig.EmailTopic : trialEmailConfig.EmailTopicCN, taskInfo.ResearchProgramNo, taskInfo.SubjectCode);
var htmlBodyStr = string.Format(isEn_us ? trialEmailConfig.EmailHtmlContent : trialEmailConfig.EmailHtmlContentCN,
EmailNamePlaceholder, taskInfo.ResearchProgramNo, taskInfo.SubjectCode, resultStr);
return (topicStr, htmlBodyStr, isEn_us, null);
};
await SendTrialEmailAsync(taskInfo.TrialId, businessScenarioEnum, topicAndHtmlFunc, taskInfo.SiteId);
}
else
{
Func<TrialEmailNoticeConfig, (string topicStr, string htmlBodyStr, bool isEn_us, Guid? onlyToUserId)> topicAndHtmlFunc = trialEmailConfig =>
{
var topicStr = string.Format(isEn_us ? trialEmailConfig.EmailTopic : trialEmailConfig.EmailTopicCN, taskInfo.ResearchProgramNo, taskInfo.SubjectCode, taskInfo.VisitName);
var htmlBodyStr = string.Format(isEn_us ? trialEmailConfig.EmailHtmlContent : trialEmailConfig.EmailHtmlContentCN,
EmailNamePlaceholder, taskInfo.ResearchProgramNo, taskInfo.SubjectCode, taskInfo.VisitName, resultStr);
return (topicStr, htmlBodyStr, isEn_us, null);
};
await SendTrialEmailAsync(taskInfo.TrialId, businessScenarioEnum, topicAndHtmlFunc, taskInfo.SiteId);
}
}
/// <summary>
/// 影像质控
/// </summary>
/// <param name="trialId"></param>
/// <returns></returns>
public async Task SendTrialImageQCTaskEmailAsync(Guid trialId)
{
var isEn_us = false;
var trialInfo = await _repository.Where<Trial>(t => t.Id == trialId).Select(t => new { t.ResearchProgramNo, t.ExperimentName, t.TrialCode, t.TrialStatusStr }).FirstNotNullAsync();
//找到 该项目的IQC 用户Id
var userList = await _repository.Where<TrialUser>(t => t.TrialId == trialId).Where(t => t.User.UserTypeEnum == UserTypeEnum.IQC).Select(t => new { t.UserId, t.User.FullName }).ToListAsync();
//判断是否任务可以领取 ,可以的话 发送邮件
var userIdList = userList.Select(t => t.UserId).ToList();
foreach (var user in userList)
{
var userId = user.UserId;
//过滤项目 并且 将 _userInfo.Id 换位 当前发送邮件的Id
var query = _trialRepository.Where(t => t.Id == trialId)
.Where(t => t.QCProcessEnum != TrialQCProcess.NotAudit)
.Select(t => new
{
//待领取量
ToBeClaimedCount = t.SubjectVisitList.Where(u => u.SubmitState == SubmitStateEnum.Submitted && u.CurrentActionUserId == null && (u.PreliminaryAuditUserId == null || (u.PreliminaryAuditUserId != userId && u.ReviewAuditUserId == null))).Count(),
//待审核通过统计从已领取到QC提交之间的 已领取 待审核 审核中 (审核完成 领取人就会清理 所以只用查询当前领取人是自己的就好了)
ToBeReviewedCount = t.SubjectVisitList.Where(u => u.CurrentActionUserId == userId).Count()
});
var sendStat = await query.FirstOrDefaultAsync();
//当前人 有待领取的或者有待审核的才发邮件
if (sendStat != null && (sendStat.ToBeClaimedCount > 0 || sendStat.ToBeReviewedCount > 0))
{
Func<TrialEmailNoticeConfig, (string topicStr, string htmlBodyStr, bool isEn_us, Guid? onlyToUserId)> topicAndHtmlFunc = trialEmailConfig =>
{
var topicStr = string.Format(isEn_us ? trialEmailConfig.EmailTopic : trialEmailConfig.EmailTopicCN, trialInfo.ResearchProgramNo);
var htmlBodyStr = string.Format(isEn_us ? trialEmailConfig.EmailHtmlContent : trialEmailConfig.EmailHtmlContentCN,
user.FullName, DateTime.Now, sendStat.ToBeClaimedCount, sendStat.ToBeReviewedCount, _SystemEmailSendConfig.CurrentValue.SiteUrl);
return (topicStr, htmlBodyStr, false, userId);
};
await SendTrialEmailAsync(trialId, EmailBusinessScenario.QCTask, topicAndHtmlFunc);
}
}
}
/// <summary>
/// QC质疑
/// </summary>
/// <param name="trialId"></param>
/// <returns></returns>
public async Task SendTrialQCQuestionEmailAsync(Guid trialId)
{
var isEn_us = false;
var trialInfo = _repository.Where<Trial>(t => t.Id == trialId).Select(t => new { t.ResearchProgramNo, t.ExperimentName, t.TrialCode, t.TrialStatusStr, t.DeclarationTypeEnumList }).FirstOrDefault();
//找到 该项目的IQC 用户Id
var userList = await _repository.Where<TrialUser>(t => t.TrialId == trialId).Where(t => t.User.UserTypeEnum == UserTypeEnum.IQC).Select(t => new { t.UserId, t.User.FullName }).ToListAsync();
//判断是否任务可以领取 ,可以的话 发送邮件
foreach (var user in userList)
{
var userId = user.UserId;
//过滤项目 并且 将 _userInfo.Id 换位 当前发送邮件的Id
var query = _trialRepository
.Where(t => t.Id == trialId)
.Select(t => new
{
ReUploadTobeDealedCount = t.SubjectVisitList.SelectMany(c => c.QCChallengeList)
.Where(u => u.CreateUserId == userId && u.IsClosed == false && u.LatestReplyUser.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator && u.ReuploadEnum == QCChanllengeReuploadEnum.CRCRequestReupload).Count(),
//质疑待处理 发送邮件的时候 需要减去ReUploadTobeDealedCount
ToBeDealedCount = t.SubjectVisitList.SelectMany(c => c.QCChallengeList)
.Where(u => u.CreateUserId == userId && u.IsClosed == false && u.LatestReplyUser.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator).Count(),
});
var sendStat = await query.FirstOrDefaultAsync();
//当前人
if (sendStat != null && (sendStat.ToBeDealedCount > 0 || sendStat.ReUploadTobeDealedCount > 0))
{
Func<TrialEmailNoticeConfig, (string topicStr, string htmlBodyStr, bool isEn_us, Guid? onlyToUserId)> topicAndHtmlFunc = trialEmailConfig =>
{
var topicStr = string.Format(isEn_us ? trialEmailConfig.EmailTopic : trialEmailConfig.EmailTopicCN, trialInfo.ResearchProgramNo);
var htmlBodyStr = string.Format(isEn_us ? trialEmailConfig.EmailHtmlContent : trialEmailConfig.EmailHtmlContentCN,
user.FullName, DateTime.Now, sendStat.ToBeDealedCount - sendStat.ReUploadTobeDealedCount, sendStat.ReUploadTobeDealedCount, _SystemEmailSendConfig.CurrentValue.SiteUrl);
return (topicStr, htmlBodyStr, false, userId);
};
await SendTrialEmailAsync(trialId, EmailBusinessScenario.QCQuestion, topicAndHtmlFunc);
}
}
}
/// <summary>
/// 影像质疑
/// </summary>
/// <param name="trialId"></param>
/// <returns></returns>
public async Task SendTrialImageQuestionAsync(Guid trialId)
{
var isEn_us = false;
var trialInfo = _repository.Where<Trial>(t => t.Id == trialId).Select(t => new { t.ResearchProgramNo, t.ExperimentName, t.TrialCode, t.TrialStatusStr }).FirstOrDefault();
//找到 该项目的CRC 用户Id
var userList = await _repository.Where<TrialUser>(t => t.TrialId == trialId).Where(t => t.User.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator).Select(t => new { t.UserId, t.User.FullName }).ToListAsync();
//判断是否任务可以领取 ,可以的话 发送邮件
foreach (var user in userList)
{
var userId = user.UserId;
//过滤项目 并且 将 _userInfo.Id 换位 当前发送邮件的Id
var query = _trialRepository.Where(t => t.Id == trialId)
.Select(t => new
{
//质疑待处理
ToBeDealedCount = t.SubjectVisitList.Where(t => t.TrialSite.CRCUserList.Any(t => t.UserId == userId)).SelectMany(c => c.QCChallengeList)
.Where(u => u.IsClosed == false && (u.LatestReplyUser.UserTypeEnum == UserTypeEnum.IQC || u.LatestReplyUserId == null)).Count(),
});
var sendStat = await query.FirstOrDefaultAsync();
//当前人
if (sendStat != null && (sendStat.ToBeDealedCount > 0))
{
Func<TrialEmailNoticeConfig, (string topicStr, string htmlBodyStr, bool isEn_us, Guid? onlyToUserId)> topicAndHtmlFunc = trialEmailConfig =>
{
var topicStr = string.Format(isEn_us ? trialEmailConfig.EmailTopic : trialEmailConfig.EmailTopicCN, trialInfo.ResearchProgramNo);
var htmlBodyStr = string.Format(isEn_us ? trialEmailConfig.EmailHtmlContent : trialEmailConfig.EmailHtmlContentCN,
user.FullName, DateTime.Now, sendStat.ToBeDealedCount, _SystemEmailSendConfig.CurrentValue.SiteUrl);
return (topicStr, htmlBodyStr, isEn_us, userId);
};
await SendTrialEmailAsync(trialId, EmailBusinessScenario.ImageQuestion, topicAndHtmlFunc);
}
}
}
//临床数据质询
public async Task SendClinicalDataQuestionAsync(Guid visitTaskId, string content)
{
var isEn_us = _userInfo.IsEn_Us;
var info = await _repository.Where<VisitTask>(t => t.Id == visitTaskId, ignoreQueryFilters: true).Select(t => new { t.TrialId, t.Trial.ResearchProgramNo, t.Trial.TrialCode, t.SourceSubjectVisit.VisitName, t.Subject.SiteId, t.Subject.Code }).FirstOrDefaultAsync();
Func<TrialEmailNoticeConfig, (string topicStr, string htmlBodyStr, bool isEn_us, Guid? onlyToUserId)> topicAndHtmlFunc = trialEmailConfig =>
{
var topicStr = string.Format(isEn_us ? trialEmailConfig.EmailTopic : trialEmailConfig.EmailTopicCN, info.ResearchProgramNo, info.Code, info.VisitName);
var htmlBodyStr = string.Format(isEn_us ? trialEmailConfig.EmailHtmlContent : trialEmailConfig.EmailHtmlContentCN,
EmailNamePlaceholder, info.ResearchProgramNo, info.Code, info.VisitName, _userInfo.UserName, content, _SystemEmailSendConfig.CurrentValue.SiteUrl);
return (topicStr, htmlBodyStr, isEn_us, null);
};
await SendTrialEmailAsync(info.TrialId, EmailBusinessScenario.ClinicalDataQuestion, topicAndHtmlFunc, info.SiteId);
}
public async Task SendPIAuditResultAsync(Guid visitTaskId)
{
var isEn_us = _userInfo.IsEn_Us;
var info = await _repository.Where<VisitTask>(t => t.Id == visitTaskId, ignoreQueryFilters: true).Select(t => new { t.TrialId, t.Trial.ResearchProgramNo, t.Trial.TrialCode, t.SourceSubjectVisit.VisitName, t.Subject.SiteId, t.Subject.Code }).FirstOrDefaultAsync();
var answerList = await _repository.Where<VisitTask>(t => t.Id == visitTaskId, ignoreQueryFilters: true).SelectMany(t => t.ReadingTaskQuestionAnswerList).Where(t => t.ReadingQuestionTrial.IsJudgeQuestion == true).Select(t => new { QuestionName = isEn_us ? t.ReadingQuestionTrial.QuestionEnName : t.ReadingQuestionTrial.QuestionName, t.ReadingQuestionTrial.DictionaryCode, t.Answer }).ToListAsync();
var template = " <div style=\"margin-left: 2ch;\"> {0}: {1} </div>";
var needTranslateDicNameList = answerList.Where(t => !string.IsNullOrEmpty(t.DictionaryCode)).Select(t => t.DictionaryCode).ToList();
var searchList = await _dictionaryRepository.Where(t => needTranslateDicNameList.ToArray().Contains(t.Parent.Code) && t.ParentId != null && t.IsEnable).ProjectTo<BasicDicSelectCopy>(_mapper.ConfigurationProvider, new { isEn_Us = _userInfo.IsEn_Us }).ToListAsync();
var translateDataList = searchList.GroupBy(t => t.ParentCode).ToDictionary(g => g.Key, g => g.OrderBy(t => t.ShowOrder).ToList());
Func<bool, string, string, string> transFunc = (bool isNeedTranslate, string dicCode, string answer) =>
{
if (isNeedTranslate && translateDataList.ContainsKey(dicCode))
{
var result = translateDataList[dicCode].Where(t => t.Code.ToLower() == answer.ToLower()).Select(t => isEn_us ? t.Value : t.ValueCN).FirstOrDefault() ?? answer;
return result;
}
else
{
return answer;
}
};
var piResult = string.Join(' ', answerList.Select(t => string.Format(template, t.QuestionName, transFunc(!string.IsNullOrEmpty(t.DictionaryCode), t.DictionaryCode, t.Answer))));
Func<TrialEmailNoticeConfig, (string topicStr, string htmlBodyStr, bool isEn_us, Guid? onlyToUserId)> topicAndHtmlFunc = trialEmailConfig =>
{
var topicStr = string.Format(isEn_us ? trialEmailConfig.EmailTopic : trialEmailConfig.EmailTopicCN, info.ResearchProgramNo, info.Code, info.VisitName);
var htmlBodyStr = string.Format(isEn_us ? trialEmailConfig.EmailHtmlContent : trialEmailConfig.EmailHtmlContentCN,
EmailNamePlaceholder, info.ResearchProgramNo, info.Code, info.VisitName, _userInfo.UserName, piResult, _SystemEmailSendConfig.CurrentValue.SiteUrl);
return (topicStr, htmlBodyStr, isEn_us, null);
};
await SendTrialEmailAsync(info.TrialId, EmailBusinessScenario.PIAuditResutl, topicAndHtmlFunc, info.SiteId);
}
public async Task SendTrialEmailAsync(Guid trialId, EmailBusinessScenario businessScenario, Func<TrialEmailNoticeConfig, (string topicStr, string htmlBodyStr, bool isEn_us, Guid? onlyToUserId)> topicAndHtmlFunc, Guid? siteId = null, Guid? trialReadingCriterionId = null)
{
//找到配置
var trialEmailConfig = await _trialEmailNoticeConfigRepository.Where(t => t.TrialId == trialId && t.TrialReadingCriterionId == trialReadingCriterionId && t.BusinessScenarioEnum == businessScenario, ignoreQueryFilters: true)
.Include(t => t.TrialEmailNoticeUserList).Include(t => t.TrialEmailBlackUserList).FirstOrDefaultAsync();
if (trialEmailConfig == null || trialEmailConfig.IsAutoSend == false || trialEmailConfig.IsEnable==false)
{
return;
}
else
{
var sendEmailConfig = new SMTPEmailConfig();
var (topicStr, htmlBodyStr, isEn_us, onlyToUserId) = topicAndHtmlFunc(trialEmailConfig);
sendEmailConfig.TopicDescription = topicStr;
sendEmailConfig.HtmlBodyStr = htmlBodyStr;
var blackUserIdList = trialEmailConfig.TrialEmailBlackUserList.Select(t => t.UserId).ToList();
var toUserTypeEnumList = trialEmailConfig.TrialEmailNoticeUserList.Where(t => t.EmailUserType == EmailUserType.To).Select(c => c.UserType).ToList();
var copyUserTypeEnumList = trialEmailConfig.TrialEmailNoticeUserList.Where(t => t.EmailUserType == EmailUserType.Copy).Select(c => c.UserType).ToList();
var allUserTypeEnumList = toUserTypeEnumList.Union(copyUserTypeEnumList).Distinct().ToList();
var allUserList = await _repository.Where<TrialUser>(t => t.TrialId == trialId && allUserTypeEnumList.Contains(t.User.UserTypeEnum)).Select(t => new { t.UserId, t.User.EMail, t.User.FullName, t.User.UserTypeEnum }).ToListAsync();
var toUserList = allUserList.Where(t => toUserTypeEnumList.Contains(t.UserTypeEnum))
.ToList();
//收件人 有CRC CRA CRC CRA的账户要按照中心发送
if (siteId == null && toUserTypeEnumList.Any(t => t == UserTypeEnum.ClinicalResearchCoordinator || t == UserTypeEnum.CRA) && onlyToUserId == null)
{
throw new BusinessValidationFailedException("当前场景收件人包含CRC CRA,但是没有siteId,请联系后端开发");
}
if (siteId != null && toUserTypeEnumList.Any(t => t == UserTypeEnum.ClinicalResearchCoordinator || t == UserTypeEnum.CRA))
{
var curentSiteUserIdList = _repository.Where<TrialSiteUser>(t => t.TrialId == trialId && t.SiteId == siteId).Select(t => t.UserId).ToList();
toUserList = toUserList.Where(t => (t.UserTypeEnum != UserTypeEnum.CRA && t.UserTypeEnum != UserTypeEnum.ClinicalResearchCoordinator) || curentSiteUserIdList.Contains(t.UserId)).ToList();
}
//去除黑名单
toUserList = toUserList.Where(t => !blackUserIdList.Contains(t.UserId)).ToList();
var copyUserList = allUserList.Where(t => copyUserTypeEnumList.Contains(t.UserTypeEnum))
.Where(t => !blackUserIdList.Contains(t.UserId)).ToList();
if (siteId != null && copyUserTypeEnumList.Any(t => t == UserTypeEnum.ClinicalResearchCoordinator || t == UserTypeEnum.CRA))
{
var curentSiteUserIdList = _repository.Where<TrialSiteUser>(t => t.TrialId == trialId && t.SiteId == siteId).Select(t => t.UserId).ToList();
copyUserList = copyUserList.Where(t => (t.UserTypeEnum != UserTypeEnum.CRA && t.UserTypeEnum != UserTypeEnum.ClinicalResearchCoordinator) || curentSiteUserIdList.Contains(t.UserId)).ToList();
}
if (onlyToUserId != null)
{
toUserList = toUserList.Where(t => t.UserId == onlyToUserId).ToList();
}
else
{
sendEmailConfig.HtmlBodyStr = htmlBodyStr.Replace(EmailNamePlaceholder, string.Join(isEn_us ? ", " : "、", toUserList.Select(t => t.FullName).ToList()));
}
if (toUserList.Count == 0)
{
//---没有收件人,无法发送邮件
throw new BusinessValidationFailedException(_localizer["TrialEmailN_NoRecipient"]);
}
if (trialEmailConfig.FromEmail.Contains("@") && !string.IsNullOrEmpty(trialEmailConfig.FromEmail))
{
sendEmailConfig.FromEmailAddress = new MimeKit.MailboxAddress(trialEmailConfig.FromName, trialEmailConfig.FromEmail);
sendEmailConfig.AuthorizationCode = trialEmailConfig.AuthorizationCode;
sendEmailConfig.UserName = trialEmailConfig.FromEmail;
sendEmailConfig.Host = trialEmailConfig.SMTPServerAddress;
sendEmailConfig.Port = trialEmailConfig.SMTPServerPort;
}
else
{
//---项目发件邮箱配置有误,请核实
throw new BusinessValidationFailedException(_localizer["TrialEmailN_InvalidEmailConfig"]);
}
foreach (var item in toUserList)
{
if (item.EMail.Contains("@") && !string.IsNullOrEmpty(item.EMail))
{
sendEmailConfig.ToMailAddressList.Add(new MimeKit.MailboxAddress(item.FullName, item.EMail));
}
}
foreach (var item in copyUserList)
{
if (item.EMail.Contains("@") && !string.IsNullOrEmpty(item.EMail))
{
sendEmailConfig.CopyToMailAddressList.Add(new MimeKit.MailboxAddress(item.FullName, item.EMail));
}
}
await SendEmailHelper.SendEmailAsync(sendEmailConfig);
}
}
public async Task<(TrialEmailNoticeConfig?, SMTPEmailConfig?)> BuildEmailConfig(Guid trialId, EmailBusinessScenario businessScenario, Func<TrialEmailNoticeConfig, (string topicStr, string htmlBodyStr, bool isEn_us, Guid? onlyToUserId)> topicAndHtmlFunc, Guid? siteId = null, Guid? trialReadingCriterionId = null)
{
//找到配置
var trialEmailConfig = await _trialEmailNoticeConfigRepository.Where(t => t.TrialId == trialId && t.TrialReadingCriterionId == trialReadingCriterionId && t.BusinessScenarioEnum == businessScenario, ignoreQueryFilters: true)
.Include(t => t.TrialEmailNoticeUserList).Include(t => t.TrialEmailBlackUserList).FirstOrDefaultAsync();
if (trialEmailConfig == null || trialEmailConfig.IsAutoSend == false || trialEmailConfig.IsEnable==false)
{
return (null, null);
}
else
{
var sendEmailConfig = new SMTPEmailConfig();
var (topicStr, htmlBodyStr, isEn_us, onlyToUserId) = topicAndHtmlFunc(trialEmailConfig);
sendEmailConfig.TopicDescription = topicStr;
sendEmailConfig.HtmlBodyStr = htmlBodyStr;
var blackUserIdList = trialEmailConfig.TrialEmailBlackUserList.Select(t => t.UserId).ToList();
var toUserTypeEnumList = trialEmailConfig.TrialEmailNoticeUserList.Where(t => t.EmailUserType == EmailUserType.To).Select(c => c.UserType).ToList();
var copyUserTypeEnumList = trialEmailConfig.TrialEmailNoticeUserList.Where(t => t.EmailUserType == EmailUserType.Copy).Select(c => c.UserType).ToList();
var allUserTypeEnumList = toUserTypeEnumList.Union(copyUserTypeEnumList).Distinct().ToList();
var allUserList = await _repository.Where<TrialUser>(t => t.TrialId == trialId && allUserTypeEnumList.Contains(t.User.UserTypeEnum)).Select(t => new { t.UserId, t.User.EMail, t.User.FullName, t.User.UserTypeEnum }).ToListAsync();
var toUserList = allUserList.Where(t => toUserTypeEnumList.Contains(t.UserTypeEnum))
.ToList();
//收件人 有CRC CRA CRC CRA的账户要按照中心发送
if (siteId == null && toUserTypeEnumList.Any(t => t == UserTypeEnum.ClinicalResearchCoordinator || t == UserTypeEnum.CRA) && onlyToUserId == null)
{
throw new BusinessValidationFailedException("当前场景收件人包含CRC CRA,但是没有siteId,请联系后端开发");
}
if (siteId != null && toUserTypeEnumList.Any(t => t == UserTypeEnum.ClinicalResearchCoordinator || t == UserTypeEnum.CRA))
{
var curentSiteUserIdList = _repository.Where<TrialSiteUser>(t => t.TrialId == trialId && t.SiteId == siteId).Select(t => t.UserId).ToList();
toUserList = toUserList.Where(t => (t.UserTypeEnum != UserTypeEnum.CRA && t.UserTypeEnum != UserTypeEnum.ClinicalResearchCoordinator) || curentSiteUserIdList.Contains(t.UserId)).ToList();
}
//去除黑名单
toUserList = toUserList.Where(t => !blackUserIdList.Contains(t.UserId)).ToList();
var copyUserList = allUserList.Where(t => copyUserTypeEnumList.Contains(t.UserTypeEnum))
.Where(t => !blackUserIdList.Contains(t.UserId)).ToList();
if (siteId != null && copyUserTypeEnumList.Any(t => t == UserTypeEnum.ClinicalResearchCoordinator || t == UserTypeEnum.CRA))
{
var curentSiteUserIdList = _repository.Where<TrialSiteUser>(t => t.TrialId == trialId && t.SiteId == siteId).Select(t => t.UserId).ToList();
copyUserList = copyUserList.Where(t => (t.UserTypeEnum != UserTypeEnum.CRA && t.UserTypeEnum != UserTypeEnum.ClinicalResearchCoordinator) || curentSiteUserIdList.Contains(t.UserId)).ToList();
}
if (onlyToUserId != null)
{
toUserList = toUserList.Where(t => t.UserId == onlyToUserId).ToList();
}
else
{
sendEmailConfig.HtmlBodyStr = htmlBodyStr.Replace(EmailNamePlaceholder, string.Join(isEn_us ? ", " : "、", toUserList.Select(t => t.FullName).ToList()));
}
if (toUserList.Count == 0)
{
//---没有收件人,无法发送邮件
throw new BusinessValidationFailedException(_localizer["TrialEmailN_NoRecipient"]);
}
if (trialEmailConfig.FromEmail.Contains("@") && !string.IsNullOrEmpty(trialEmailConfig.FromEmail))
{
sendEmailConfig.FromEmailAddress = new MimeKit.MailboxAddress(trialEmailConfig.FromName, trialEmailConfig.FromEmail);
sendEmailConfig.AuthorizationCode = trialEmailConfig.AuthorizationCode;
sendEmailConfig.UserName = trialEmailConfig.FromEmail;
sendEmailConfig.Host = trialEmailConfig.SMTPServerAddress;
sendEmailConfig.Port = trialEmailConfig.SMTPServerPort;
}
else
{
//---项目发件邮箱配置有误,请核实
throw new BusinessValidationFailedException(_localizer["TrialEmailN_InvalidEmailConfig"]);
}
foreach (var item in toUserList)
{
if (item.EMail.Contains("@") && !string.IsNullOrEmpty(item.EMail))
{
sendEmailConfig.ToMailAddressList.Add(new MimeKit.MailboxAddress(item.FullName, item.EMail));
}
}
foreach (var item in copyUserList)
{
if (item.EMail.Contains("@") && !string.IsNullOrEmpty(item.EMail))
{
sendEmailConfig.CopyToMailAddressList.Add(new MimeKit.MailboxAddress(item.FullName, item.EMail));
}
}
//邮件附件 这里是原格式发送不是PDF
//if (trialEmailConfig.AttachCNPath != string.Empty && trialEmailConfig.AttachPath != string.Empty)
//{
// var phyPath = FileStoreHelper.GetPhysicalFilePath(_hostEnvironment, isEn_us? trialEmailConfig.AttachName: trialEmailConfig.AttachNameCN);
// //先预先生成了邮件,发送预先生成的邮件
// sendEmailConfig.EmailAttachMentConfigList.Add(new EmailAttachMentConfig()
// {
// FileName = $"{attachPrefix}_{Path.GetFileName(_userInfo.IsEn_Us ? trialEmailConfig.AttachName : trialEmailConfig.AttachNameCN)}",
// FileStream = File.OpenRead(phyPath),
// });
//}
return (trialEmailConfig, sendEmailConfig);
}
}
}
}