using IRaCIS.Core.Application.Helper; using IRaCIS.Core.Application.MassTransit.Command; using IRaCIS.Core.Application.MassTransit.Consumer.Dto; using IRaCIS.Core.Application.Service.Reading.Dto; using IRaCIS.Core.Domain; using IRaCIS.Core.Domain._DomainEvent; using IRaCIS.Core.Domain.BaseModel; using IRaCIS.Core.Domain.Models; using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Infra.EFCore.Common; using MassTransit; using MassTransit.Mediator; using MassTransit.Scheduling; using Medallion.Threading; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.StaticFiles; using Microsoft.Extensions.Options; using MimeKit; using Newtonsoft.Json; using Panda.DynamicWebApi.Attributes; using RestSharp; using SkiaSharp; using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; namespace IRaCIS.Core.Application.MassTransit.Consumer; /// /// 影像重传和阅片人筛选相关邮件发送 /// public class ImageConsumer( IRepository _userRoleRepository, IRepository _trialUseRoleRepository, IRepository _subjectVisitRepository, IRepository _trialRepository, IRepository _enrollRepository, IRepository _visitTaskRepository, IRepository _readModuleRepository, IRepository _emailNoticeUserTypeRepository, IRepository _trialSiteRepository, IRepository _dictionaryRepository, IRepository _emailNoticeConfigrepository, IOptionsMonitor systemEmailConfig) : IConsumer, IConsumer, IConsumer, IConsumer, IConsumer, IConsumer { private readonly SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue; /// /// 处理直接申请流程的重传事件 /// public async Task Consume(ConsumeContext context) { Console.WriteLine("发送【影像重传-直接申请流程】邮件!!!"); var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US; var subjectVisitId = context.Message.SubjectVisitId; var subjectVisit = await _subjectVisitRepository.Where(x => x.Id == subjectVisitId).Include(x => x.Subject).FirstNotNullAsync(); var trialId = subjectVisit.TrialId; List userTypes = null; // 根据申请角色和状态确定邮件场景 EmailBusinessScenario scenario; if (context.Message.ImageBackState == ImageBackStateEnum.None) { switch (context.Message.ApplyUserRole) { case ImageBackApplyEnum.IQCRequestBack: scenario = EmailBusinessScenario.ImageQC_IQCApplyRe_Uploading; // 64 break; case ImageBackApplyEnum.CRCRequestBack: scenario = EmailBusinessScenario.ImageUploadCRCApplyRe_Uploading; // 65 break; default: scenario = EmailBusinessScenario.ImageQC_IQCApplyRe_Uploading; // 64 break; } } else { scenario = EmailBusinessScenario.ImageReUpload_PMApprovalRe_Uploading; // 66 if (context.Message.ApplyUserRole == ImageBackApplyEnum.IQCRequestBack) { userTypes = new List() { UserTypeEnum.IQC, UserTypeEnum.ClinicalResearchCoordinator }; } else if (context.Message.ApplyUserRole == ImageBackApplyEnum.CRCRequestBack) { userTypes = new List() { UserTypeEnum.ClinicalResearchCoordinator }; } } var emailConfig = _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario && t.IsEnable && t.IsAutoSend).FirstOrDefault(); if (emailConfig != null) { var inDto = new SendImageReuploadEmailInDto { EmailNoticeConfig = emailConfig, Scenario = scenario, SubjectVisit = subjectVisit, TrialId = trialId, UserTypes = userTypes, ImageBackStateEnum = context.Message.ImageBackState }; await SendImageReuploadEmail(inDto); } } /// /// 处理一致性核查申请重传事件 /// public async Task Consume(ConsumeContext context) { Console.WriteLine("发送【一致性核查-影像重传】邮件!!!"); var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US; var subjectVisitId = context.Message.SubjectVisitId; var subjectVisit = await _subjectVisitRepository.Where(x => x.Id == subjectVisitId).Include(x => x.Subject).FirstNotNullAsync(); var trialId = subjectVisit.TrialId; // 根据状态确定邮件场景 EmailBusinessScenario scenario; switch (context.Message.RequestBackState) { case RequestBackStateEnum.CRC_RequestBack: scenario = EmailBusinessScenario.DataReconciliation_CRCApplyRe_Uploading; // 62 break; case RequestBackStateEnum.PM_AgressBack: case RequestBackStateEnum.PM_NotAgree: scenario = EmailBusinessScenario.DataReconciliation_PMApprovalRe_Uploading; // 63 break; default: return; // 其他状态不发送邮件 } var emailConfig = _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario && t.IsEnable && t.IsAutoSend).FirstOrDefault(); if (emailConfig != null) { var inDto = new SendImageReuploadEmailInDto { EmailNoticeConfig = emailConfig, Scenario = scenario, SubjectVisit = subjectVisit, TrialId = trialId, RequestBackStateEnum = context.Message.RequestBackState, }; await SendImageReuploadEmail(inDto); } } /// /// 处理质疑CRC申请重传事件 /// public async Task Consume(ConsumeContext context) { Console.WriteLine("发送【影像质疑-影像重传】邮件!!!"); var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US; var subjectVisitId = context.Message.SubjectVisitId; var subjectVisit = await _subjectVisitRepository.Where(x => x.Id == subjectVisitId).Include(x => x.Subject).FirstNotNullAsync(); var trialId = subjectVisit.TrialId; // 根据状态确定邮件场景 EmailBusinessScenario scenario; switch (context.Message.ReuploadEnum) { case QCChanllengeReuploadEnum.CRCRequestReupload: scenario = EmailBusinessScenario.ImageQueryCRCApplyRe_Uploading; // 60 break; case QCChanllengeReuploadEnum.QCAgreeUpload: scenario = EmailBusinessScenario.ImageQuery_IQCApprovalRe_Uploading; // 61 break; default: return; // 其他状态不发送邮件 } var emailConfig = _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario && t.IsEnable && t.IsAutoSend).FirstOrDefault(); if (emailConfig != null) { var inDto = new SendImageReuploadEmailInDto { EmailNoticeConfig = emailConfig, Scenario = scenario, SubjectVisit = subjectVisit, TrialId = trialId }; await SendImageReuploadEmail(inDto); } } /// /// 处理已阅任务重阅申请事件 /// public async Task Consume(ConsumeContext context) { Console.WriteLine("发送【重阅-影像重传】邮件!!!"); var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US; var visitTaskId = context.Message.VisitTaskId; // 获取VisitTask关联的SubjectVisit var visitTask = await _visitTaskRepository.Where(x => x.Id == visitTaskId).Include(x => x.Subject).Include(x => x.SourceSubjectVisit).FirstNotNullAsync(); var subjectVisit = new SubjectVisit() { }; if (visitTask.SourceSubjectVisitId != null) { subjectVisit = visitTask.SourceSubjectVisit; } else if (visitTask.SouceReadModuleId != null) { var readModule = await _readModuleRepository.Where(x => x.Id == visitTask.SouceReadModuleId).Include(x => x.SubjectVisit).FirstOrDefaultAsync(); subjectVisit = readModule.SubjectVisit; } var trialId = subjectVisit.TrialId; // 根据状态确定邮件场景 EmailBusinessScenario scenario; switch (context.Message.ReReadingApplyState) { case ReReadingApplyState.TrialGroupHaveApplyed: scenario = EmailBusinessScenario.ReadTracking_PMApplyRe_Reading; // 67 break; case ReReadingApplyState.Agree: case ReReadingApplyState.Reject: scenario = EmailBusinessScenario.Re_ReadApproval_SPMCPMApprovalRe_Reading; // 68 break; default: return; // 其他状态不发送邮件 } var emailConfig = _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario && t.IsEnable && t.IsAutoSend).FirstOrDefault(); if (emailConfig != null) { var inDto = new SendImageReuploadEmailInDto { EmailNoticeConfig = emailConfig, Scenario = scenario, SubjectVisit = subjectVisit, TrialId = trialId, ReReadingApplyState= context.Message.ReReadingApplyState, }; await SendImageReuploadEmail(inDto); } } /// /// 发送影像重传相关邮件的通用方法 /// private async Task SendImageReuploadEmail(SendImageReuploadEmailInDto inDto) { var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US; inDto.SubjectVisit = await _subjectVisitRepository.Where(x => x.Id == inDto.SubjectVisit.Id).Include(x => x.Subject).FirstNotNullAsync(); // 获取项目信息 var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == inDto.TrialId); // 根据不同场景获取不同角色的用户 var trialUser = await _trialUseRoleRepository.Where(x => x.TrialId == inDto.TrialId && !x.TrialUser.IsDeleted).Include(x => x.UserRole).Select(x => x.UserRole).ToListAsync(); // 根据场景确定收件人 List toUserList = new List(); List ccUserList = new List(); var emailNoticeUserList = await _emailNoticeUserTypeRepository.Where(x => x.EmailNoticeConfigId == inDto.EmailNoticeConfig.Id).ToListAsync(); var userTypeEnum = emailNoticeUserList.Select(x => x.UserType).ToList(); if (inDto.UserTypes != null) { userTypeEnum = inDto.UserTypes; } var crcUserList = new List() { }; if (userTypeEnum.Contains(UserTypeEnum.ClinicalResearchCoordinator)) { crcUserList = await _trialSiteRepository.Where(x => x.Id == inDto.SubjectVisit.TrialSiteId).SelectMany(x => x.CRCUserList.Select(y => y.UserRole)).ToListAsync(); } if (inDto.UserTypes == null) { var toList = emailNoticeUserList.Where(x => x.EmailUserType == EmailUserType.To && x.UserType != UserTypeEnum.ClinicalResearchCoordinator).Select(x => x.UserType).ToList(); toUserList = trialUser.Where(x => toList.Contains(x.UserTypeEnum)).ToList(); if (emailNoticeUserList.Any(x => x.EmailUserType == EmailUserType.To && x.UserType == UserTypeEnum.ClinicalResearchCoordinator)) { toUserList.AddRange(crcUserList); } } else { var toList = inDto.UserTypes.Where(x => x != UserTypeEnum.ClinicalResearchCoordinator).ToList(); toUserList = trialUser.Where(x => toList.Contains(x.UserTypeEnum)).ToList(); if (inDto.UserTypes.Any(x => x == UserTypeEnum.ClinicalResearchCoordinator)) { toUserList.AddRange(crcUserList); } } var ccList = emailNoticeUserList.Where(x => x.EmailUserType == EmailUserType.Copy && x.UserType != UserTypeEnum.ClinicalResearchCoordinator).Select(x => x.UserType).ToList(); ccUserList = trialUser.Where(x => ccList.Contains(x.UserTypeEnum)).ToList(); if (emailNoticeUserList.Any(x => x.EmailUserType == EmailUserType.Copy && x.UserType == UserTypeEnum.ClinicalResearchCoordinator)) { ccUserList.AddRange(crcUserList); } // 如果没有收件人,则不发送邮件 if (toUserList.Count == 0) { return; } List dictionaryDtos = new List() { new DictionaryDto (){DictionaryCode= "YesOrNo",EnumValue=inDto.SubjectVisit.IsUrgent.ToString().ToLower(), }, //是否加急 }; switch (inDto.Scenario) { case EmailBusinessScenario.Re_ReadApproval_SPMCPMApprovalRe_Reading: dictionaryDtos.Add(new DictionaryDto() { DictionaryCode = "ReReadingApplyState", EnumValue = inDto.ReReadingApplyState.GetEnumInt(), }); break; case EmailBusinessScenario.DataReconciliation_PMApprovalRe_Uploading: dictionaryDtos.Add(new DictionaryDto() { DictionaryCode = "RequestBackState", EnumValue = inDto.RequestBackStateEnum.GetEnumInt(), }); break; default: dictionaryDtos.Add(new DictionaryDto() { DictionaryCode = "ImageBackStateEnum", EnumValue = inDto.ImageBackStateEnum.GetEnumInt(), });//审批结果 break; } var dictionValue = await CommonEmailHelper.TranslationDictionary(new TranslationDictionaryDto() { DictionaryRepository = _dictionaryRepository, IsEn_US = isEn_US, DictionaryList = dictionaryDtos }); foreach (var userinfo in toUserList) { var messageToSend = new MimeMessage(); // 发件地址 messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail)); messageToSend.To.Add(new MailboxAddress(String.Empty, userinfo.EMail)); // 添加抄送 foreach (var ccUser in ccUserList) { messageToSend.Cc.Add(new MailboxAddress(String.Empty, ccUser.EMail)); } // 格式化邮件内容 Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input => { var subjectCode = inDto.SubjectVisit.Subject.Code; var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, inDto.SubjectVisit.VisitName); var htmlBodyStr = string.Format( CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr), userinfo.FullName, // 用户名 {0} trialInfo.ExperimentName, // 项目 {1} subjectCode, // 受试者 {2} inDto.SubjectVisit.VisitName, // 访视 {3} dictionValue[0], // 是否加急 {4} dictionValue[1], // 审批结果 {5} _systemEmailConfig.SiteUrl // 链接 {6} ); return (topicStr, htmlBodyStr); }; await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(inDto.EmailNoticeConfig, messageToSend, emailConfigFunc); await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig); } } /// /// 处理PM申请阅片人筛选事件 /// public async Task Consume(ConsumeContext context) { Console.WriteLine("发送【阅片人筛选-PM申请审批】邮件!!!"); var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US; // 获取项目信息 var enrollIdList = context.Message.EnrollIdList; if (enrollIdList == null || !enrollIdList.Any()) { return; } // 获取第一个Enroll的TrialId var enrollId = enrollIdList.First(); var enroll = await _enrollRepository.Where(x => x.Id == enrollId).FirstNotNullAsync(); var trialId = enroll.TrialId; // 设置邮件场景 var scenario = EmailBusinessScenario.ReviewerSelection_PMApplyApproving; // 69 var emailConfig = _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario && t.IsEnable && t.IsAutoSend).FirstOrDefault(); if (emailConfig != null) { await SendReviewerSelectionEmail(emailConfig, trialId, enrollIdList); } } /// /// 处理SPM审批阅片人筛选事件 /// public async Task Consume(ConsumeContext context) { Console.WriteLine("发送【阅片人筛选-SPM审批】邮件!!!"); var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US; // 获取项目信息 var enrollIdList = context.Message.EnrollIdList; if (enrollIdList == null || !enrollIdList.Any()) { return; } // 获取第一个Enroll的TrialId var enrollId = enrollIdList.First(); var enroll = await _enrollRepository.Where(x => x.Id == enrollId).FirstNotNullAsync(); var trialId = enroll.TrialId; // 设置邮件场景 var scenario = EmailBusinessScenario.ReviewerSelection_SPMCPMApproval; // 70 var emailConfig = _emailNoticeConfigrepository.Where(t => t.BusinessScenarioEnum == scenario && t.IsEnable && t.IsAutoSend).FirstOrDefault(); if (emailConfig != null) { await SendReviewerSelectionEmail(emailConfig, trialId, enrollIdList); } } /// /// 发送阅片人筛选相关邮件的通用方法 /// private async Task SendReviewerSelectionEmail(EmailNoticeConfig emailNoticeConfig, Guid trialId, List enrollIdList) { var isEn_US = CultureInfo.CurrentCulture.Name == StaticData.CultureInfo.en_US; // 获取项目信息 var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialId); // 根据不同场景获取不同角色的用户 var trialUser = await _trialUseRoleRepository.Where(x => x.TrialId == trialId && !x.TrialUser.IsDeleted).Include(x => x.UserRole).Select(x => x.UserRole).ToListAsync(); // 根据场景确定收件人 List toUserList = new List(); List ccUserList = new List(); var emailNoticeUserList = await _emailNoticeUserTypeRepository.Where(x => x.EmailNoticeConfigId == emailNoticeConfig.Id).ToListAsync(); var toList = emailNoticeUserList.Where(x => x.EmailUserType == EmailUserType.To).Select(x => x.UserType).ToList(); toUserList = trialUser.Where(x => toList.Contains(x.UserTypeEnum)).ToList(); var ccList = emailNoticeUserList.Where(x => x.EmailUserType == EmailUserType.Copy && x.UserType != UserTypeEnum.ClinicalResearchCoordinator).Select(x => x.UserType).ToList(); ccUserList = trialUser.Where(x => ccList.Contains(x.UserTypeEnum)).ToList(); // 如果没有收件人,则不发送邮件 if (toUserList.Count == 0) { return; } foreach (var userinfo in toUserList) { var messageToSend = new MimeMessage(); // 发件地址 messageToSend.From.Add(new MailboxAddress(_systemEmailConfig.FromName, _systemEmailConfig.FromEmail)); messageToSend.To.Add(new MailboxAddress(String.Empty, userinfo.EMail)); // 添加抄送 foreach (var ccUser in ccUserList) { messageToSend.Cc.Add(new MailboxAddress(String.Empty, ccUser.EMail)); } // 格式化邮件内容 Func<(string topicStr, string htmlBodyStr), (string topicStr, string htmlBodyStr)> emailConfigFunc = input => { var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo); var htmlBodyStr = string.Format( CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr), userinfo.FullName, // 用户名 {0} trialInfo.ExperimentName, // 项目 {1} "", // 受试者 {2} - 阅片人筛选不涉及受试者 "", // 访视 {3} - 阅片人筛选不涉及访视 "", // 是否加急 {4} "", // 预留 {5} _systemEmailConfig.SiteUrl // 链接 {6} ); return (topicStr, htmlBodyStr); }; await CommonEmailHelper.GetEmailSubejctAndHtmlInfoAndBuildAsync(emailNoticeConfig, messageToSend, emailConfigFunc); await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig); } } }