using IRaCIS.Core.Application.Helper; using IRaCIS.Core.Application.MassTransit.Command; 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 _dictionaryRepository, IRepository _trialEmailNoticeConfigrepository, 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; // 根据申请角色和状态确定邮件场景 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 } var trialEmailConfig = _trialEmailNoticeConfigrepository.Where(t => t.TrialId == trialId && t.BusinessScenarioEnum == scenario && t.IsAutoSend && t.IsEnable).FirstOrDefault(); if (trialEmailConfig != null) { await SendImageReuploadEmail(trialEmailConfig, scenario, subjectVisit, trialId); } } /// /// 处理一致性核查申请重传事件 /// 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: scenario = EmailBusinessScenario.DataReconciliation_PMApprovalRe_Uploading; // 63 break; default: return; // 其他状态不发送邮件 } var trialEmailConfig = _trialEmailNoticeConfigrepository.Where(t => t.TrialId == trialId && t.BusinessScenarioEnum == scenario && t.IsAutoSend && t.IsEnable).FirstOrDefault(); if (trialEmailConfig != null) { await SendImageReuploadEmail(trialEmailConfig, scenario, subjectVisit, trialId); } } /// /// 处理质疑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 trialEmailConfig = _trialEmailNoticeConfigrepository.Where(t => t.TrialId == trialId && t.BusinessScenarioEnum == scenario && t.IsAutoSend && t.IsEnable).FirstOrDefault(); if (trialEmailConfig != null) { await SendImageReuploadEmail(trialEmailConfig, scenario, subjectVisit, trialId); } } /// /// 处理已阅任务重阅申请事件 /// 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 trialEmailConfig = _trialEmailNoticeConfigrepository.Where(t => t.TrialId == trialId && t.BusinessScenarioEnum == scenario && t.IsAutoSend && t.IsEnable).FirstOrDefault(); if (trialEmailConfig != null) { await SendImageReuploadEmail(trialEmailConfig, scenario, subjectVisit, trialId); } } /// /// 发送影像重传相关邮件的通用方法 /// private async Task SendImageReuploadEmail(TrialEmailNoticeConfig trialEmailConfig, EmailBusinessScenario scenario, SubjectVisit subjectVisit, Guid trialId) { 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(); switch (scenario) { case EmailBusinessScenario.ImageQC_IQCApplyRe_Uploading: // 64 - IQC申请重传 - Code: 42 // PM收件 toUserList = trialUser.Where(x => x.UserTypeEnum == UserTypeEnum.ProjectManager).ToList(); break; case EmailBusinessScenario.ImageUploadCRCApplyRe_Uploading: // 65 - CRC申请重传 - Code: 43 // PM、APM收件 toUserList = trialUser.Where(x => x.UserTypeEnum == UserTypeEnum.APM || x.UserTypeEnum == UserTypeEnum.ProjectManager).ToList(); break; case EmailBusinessScenario.ImageReUpload_PMApprovalRe_Uploading: // 66 - PM审批重传 - Code: 44 // CRC、IQC收件 toUserList = trialUser.Where(x => x.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator || x.UserTypeEnum == UserTypeEnum.IQC).ToList(); break; case EmailBusinessScenario.DataReconciliation_PMApprovalRe_Uploading: // 63 - 一致性核查PM审批重传 - Code: 41 // CRC收件 toUserList = trialUser.Where(x => x.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator).ToList(); break; case EmailBusinessScenario.ImageQuery_IQCApprovalRe_Uploading: // 61 - 影像质疑IQC审批重传 - Code: 39 // CRC收件 toUserList = trialUser.Where(x => x.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator).ToList(); break; case EmailBusinessScenario.DataReconciliation_CRCApplyRe_Uploading: // 62 - 一致性核查CRC申请重传 - Code: 40 // PM、APM收件 toUserList = trialUser.Where(x => x.UserTypeEnum == UserTypeEnum.APM || x.UserTypeEnum == UserTypeEnum.ProjectManager).ToList(); break; case EmailBusinessScenario.ImageQueryCRCApplyRe_Uploading: // 60 - 影像质疑CRC申请重传 - Code: 38 // IQC收件 toUserList = trialUser.Where(x => x.UserTypeEnum == UserTypeEnum.IQC).ToList(); break; case EmailBusinessScenario.ReadTracking_PMApplyRe_Reading: // 67 - PM申请重阅 - Code: 45 // CPM、SPM收件 toUserList = trialUser.Where(x => x.UserTypeEnum == UserTypeEnum.SPM || x.UserTypeEnum == UserTypeEnum.CPM).ToList(); break; case EmailBusinessScenario.Re_ReadApproval_SPMCPMApprovalRe_Reading: // 68 - SPM/CPM审批重阅 - Code: 46 // CRC收件 toUserList = trialUser.Where(x => x.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator).ToList(); break; } // 如果没有收件人,则不发送邮件 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 subjectCode = subjectVisit.Subject.Code; var topicStr = string.Format(input.topicStr, trialInfo.ResearchProgramNo, subjectCode, subjectVisit.VisitName); var htmlBodyStr = string.Format( CommonEmailHelper.ReplaceCompanyName(_systemEmailConfig, input.htmlBodyStr), userinfo.FullName, // 用户名 {0} trialInfo.ExperimentName, // 项目 {1} subjectCode, // 受试者 {2} subjectVisit.VisitName, // 访视 {3} "是", // 是否加急 {4} - 固定为"是" "", // 预留 {5} _systemEmailConfig.SiteUrl // 链接 {6} ); return (topicStr, htmlBodyStr); }; await CommonEmailHelper.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, scenario, 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 trialEmailConfig = _trialEmailNoticeConfigrepository.Where(t => t.TrialId == trialId && t.BusinessScenarioEnum == scenario && t.IsAutoSend && t.IsEnable).FirstOrDefault(); if (trialEmailConfig != null) { await SendReviewerSelectionEmail(trialEmailConfig, scenario, 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 trialEmailConfig = _trialEmailNoticeConfigrepository.Where(t => t.TrialId == trialId && t.BusinessScenarioEnum == scenario && t.IsAutoSend && t.IsEnable).FirstOrDefault(); if (trialEmailConfig != null) { await SendReviewerSelectionEmail(trialEmailConfig, scenario, trialId, enrollIdList); } } /// /// 发送阅片人筛选相关邮件的通用方法 /// private async Task SendReviewerSelectionEmail(TrialEmailNoticeConfig trialEmailConfig, EmailBusinessScenario scenario, 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(); switch (scenario) { case EmailBusinessScenario.ReviewerSelection_PMApplyApproving: // 69 - PM申请审批 - Code: 47 // CPM、SPM收件 toUserList = trialUser.Where(x => x.UserTypeEnum == UserTypeEnum.SPM || x.UserTypeEnum == UserTypeEnum.CPM).ToList(); break; case EmailBusinessScenario.ReviewerSelection_SPMCPMApproval: // 70 - SPM审批 - Code: 48 // APM、PM收件 toUserList = trialUser.Where(x => x.UserTypeEnum == UserTypeEnum.ProjectManager || x.UserTypeEnum == UserTypeEnum.APM).ToList(); break; } // 如果没有收件人,则不发送邮件 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.GetTrialEmailSubejctAndHtmlInfoAndBuildAsync(trialEmailConfig, scenario, messageToSend, emailConfigFunc); await SendEmailHelper.SendEmailAsync(messageToSend, _systemEmailConfig); } } }