diff --git a/IRaCIS.Core.Application/Helper/FileStoreHelper.cs b/IRaCIS.Core.Application/Helper/FileStoreHelper.cs index 0656f480a..e64c16be1 100644 --- a/IRaCIS.Core.Application/Helper/FileStoreHelper.cs +++ b/IRaCIS.Core.Application/Helper/FileStoreHelper.cs @@ -409,6 +409,26 @@ public static class FileStoreHelper return (serverFilePath, relativePath, fileRealName); } + // 获取 入组确认 PD 进展发送邮件Word|PDF 存放路径 + + public static (string PhysicalPath, string RelativePath, string FileRealName) GetSubjectEnrollConfirmOrPDEmailPath(IWebHostEnvironment _hostEnvironment, string fileName, Guid trialId, Guid siteId, Guid subjectId) + { + var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment); + + string uploadFolderPath = Path.Combine(rootPath, StaticData.Folder.TrialDataFolder, trialId.ToString(), siteId.ToString(), subjectId.ToString()); + + if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath); + + var (trustedFileNameForFileStorage, fileRealName) = FileStoreHelper.GetStoreFileName(fileName); + + + var relativePath = $"/{StaticData.Folder.IRaCISDataFolder}/{StaticData.Folder.TrialDataFolder}/{trialId}/{siteId}/{subjectId}/{trustedFileNameForFileStorage}"; + + var serverFilePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage); + + return (serverFilePath, relativePath, fileRealName); + } + public static string GetSubjectVisitDicomFolderPhysicalPath(IWebHostEnvironment _hostEnvironment,Guid trialId, Guid siteId, Guid subjectId, Guid subjectVisitId) { diff --git a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml index 335c47f04..becbece6a 100644 --- a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml +++ b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml @@ -602,14 +602,32 @@ - + 测试邮件 带附件 填充word --前端不需要用 + + + + + + 手动生成入组确认 或者PD 进展的邮件 如果能发送,会返回文件的路径,否则会给出提示 + + + + + + + 手动发送邮件 + + + + + 选择人员下拉 diff --git a/IRaCIS.Core.Application/Service/Document/Interface/ITrialEmailNoticeConfigService.cs b/IRaCIS.Core.Application/Service/Document/Interface/ITrialEmailNoticeConfigService.cs index 4fb10d3ec..b30ba64fb 100644 --- a/IRaCIS.Core.Application/Service/Document/Interface/ITrialEmailNoticeConfigService.cs +++ b/IRaCIS.Core.Application/Service/Document/Interface/ITrialEmailNoticeConfigService.cs @@ -6,23 +6,31 @@ using IRaCIS.Core.Application.ViewModel; using IRaCIS.Core.Domain.Share; +using IRaCIS.Core.Domain.Share.Common; namespace IRaCIS.Core.Application.Interfaces -{ +{ /// /// ITrialEmailNoticeConfigService /// public interface ITrialEmailNoticeConfigService - { + { - - Task> GetTrialEmailNoticeConfigList(TrialEmailNoticeConfigQuery inQuery); - - Task AddOrUpdateTrialEmailNoticeConfig(TrialEmailNoticeConfigAddOrEdit addOrEditTrialEmailNoticeConfig); - Task DeleteTrialEmailNoticeConfig(Guid trialEmailNoticeConfigId); + Task> GetTrialEmailNoticeConfigList(TrialEmailNoticeConfigQuery inQuery); - Task BaseBusinessScenarioSendEmailAsync( Guid visitTaskId, bool? isMedicalReviewAndSuggestApplyReReading = null); + Task AddOrUpdateTrialEmailNoticeConfig(TrialEmailNoticeConfigAddOrEdit addOrEditTrialEmailNoticeConfig); + + Task DeleteTrialEmailNoticeConfig(Guid trialEmailNoticeConfigId); + + Task BaseBusinessScenarioSendEmailAsync(Guid visitTaskId, bool? isMedicalReviewAndSuggestApplyReReading = null, EmailStoreSendMode emailStoreMode = EmailStoreSendMode.StoreLocalSend, string sendFileRelativePath=""); } -} + + public class EmailStoreSendDto + { + public EmailStoreSendMode EmailStoreSendMode { get; set; } = EmailStoreSendMode.StoreLocalSend; + + public string SendFileRelativePath { get; set; } + } +} diff --git a/IRaCIS.Core.Application/Service/Document/TrialEmailNoticeConfigService.cs b/IRaCIS.Core.Application/Service/Document/TrialEmailNoticeConfigService.cs index 0ba787b52..f9f73a8bb 100644 --- a/IRaCIS.Core.Application/Service/Document/TrialEmailNoticeConfigService.cs +++ b/IRaCIS.Core.Application/Service/Document/TrialEmailNoticeConfigService.cs @@ -17,6 +17,8 @@ using IRaCIS.Core.Application.Contracts; using IRaCIS.Core.Application.Filter; using MiniSoftware; using IRaCIS.Core.Application.Service.Reading.Dto; +using IRaCIS.Core.Domain.Share.Common; +using System.IO; namespace IRaCIS.Core.Application.Service { @@ -165,7 +167,7 @@ namespace IRaCIS.Core.Application.Service - private async Task DealMedicalReviewTasKGenerateAndIsSendAsync(Guid trialId, bool? isMedicalReviewAndSuggestApplyReReading,string pdAnswer, List taskIdList, List minUserIdList) + private async Task DealMedicalReviewTasKGenerateAndIsSendAsync(Guid trialId, bool? isMedicalReviewAndSuggestApplyReReading, string pdAnswer, List taskIdList, List minUserIdList) { var isNeedSend = true; @@ -177,7 +179,7 @@ namespace IRaCIS.Core.Application.Service } else { - + //正常阅片为否的 if (isMedicalReviewAndSuggestApplyReReading == null) { isNeedSend = false; @@ -202,7 +204,7 @@ namespace IRaCIS.Core.Application.Service } - + return isNeedSend; @@ -213,9 +215,11 @@ namespace IRaCIS.Core.Application.Service /// /// /// + /// + /// /// /// - public async Task BaseBusinessScenarioSendEmailAsync(Guid visitTaskId, bool? isMedicalReviewAndSuggestApplyReReading) + public async Task BaseBusinessScenarioSendEmailAsync(Guid visitTaskId, bool? isMedicalReviewAndSuggestApplyReReading, EmailStoreSendMode emailStoreMode, string sendFileRelativePath) { CommonDocumentBusinessScenario? businessScenarioEnum = null; @@ -292,7 +296,7 @@ namespace IRaCIS.Core.Application.Service } else { - return; + return string.Empty; } } @@ -317,7 +321,7 @@ namespace IRaCIS.Core.Application.Service { //throw new BusinessValidationFailedException("找不到该项目标准场景下邮件的配置"); - return; + return string.Empty; } @@ -382,7 +386,6 @@ namespace IRaCIS.Core.Application.Service } #endregion - #region 确保 邮件Html存在 //邮件附件 @@ -403,6 +406,46 @@ namespace IRaCIS.Core.Application.Service #endregion + #region 不同场景 Tile 设置 + + if (businessScenarioEnum == CommonDocumentBusinessScenario.EnrollConfirmed) + { + sendEmailConfig.TopicDescription = $"【入组确认报告】关于{taskInfo.ResearchProgramNo}项目{taskInfo.SubjectCode}受试者"; + + using (StreamReader SourceReader = System.IO.File.OpenText(pathToFile)) + { + var templateInfo = SourceReader.ReadToEnd(); + + + sendEmailConfig.HtmlBodyStr = string.Format(templateInfo, + $" 附件为入组确认报告,请查收 " + ); + } + } + else if (businessScenarioEnum == CommonDocumentBusinessScenario.PDConfirmed) + { + sendEmailConfig.TopicDescription = $"【疾病进展确认报告】关于{taskInfo.ResearchProgramNo}项目{taskInfo.SubjectCode}受试者"; + + using (StreamReader SourceReader = System.IO.File.OpenText(pathToFile)) + { + var templateInfo = SourceReader.ReadToEnd(); + + + sendEmailConfig.HtmlBodyStr = string.Format(templateInfo, + $" 附件为疾病进展确认报告,请查收 " + ); + } + } + else + { + // + } + + #endregion + + + #region 不同标准 不同项目配置 发送邮件的时机 处理具体逻辑 + var answer = "否"; var isNeedSend = true; var minUserIdList = _trialUserRepository.Where(t => t.User.UserTypeEnum == Domain.Share.UserTypeEnum.MIM && t.TrialId == taskInfo.TrialId).Select(t => t.UserId).ToList(); @@ -418,35 +461,23 @@ namespace IRaCIS.Core.Application.Service } else { - sendEmailConfig.TopicDescription = $"【入组确认报告】关于{taskInfo.ResearchProgramNo}项目{taskInfo.SubjectCode}受试者"; - using (StreamReader SourceReader = System.IO.File.OpenText(pathToFile)) + if (await _repository.Where().AnyAsync(x => x.VisitTaskId == visitTaskId && x.Answer == TargetState.Exist.GetEnumInt() && + x.ReadingTableQuestionTrial.QuestionMark == QuestionMark.State && x.ReadingQuestionTrial.LesionType == LesionType.TargetLesion)) { - var templateInfo = SourceReader.ReadToEnd(); + answer = "是"; - sendEmailConfig.HtmlBodyStr = string.Format(templateInfo, - $" 附件为入组确认报告,请查收 " - ); - } + //把另外一个人的任务设置为不加急(如果项目加急是否 subject 加急是否) + var urgent = _repository.Where(t => t.Id == taskInfo.SourceSubjectVisitId).Select(t => new { IsSubjectUrgent = t.Subject.IsUrgent, t.Trial.IsUrgent }).FirstOrDefault(); - - if (await _repository.Where().AnyAsync(x => x.VisitTaskId == visitTaskId && x.Answer == TargetState.Exist.GetEnumInt() && - x.ReadingTableQuestionTrial.QuestionMark == QuestionMark.State && x.ReadingQuestionTrial.LesionType == LesionType.TargetLesion)) + if (urgent?.IsUrgent == false || urgent?.IsSubjectUrgent == false) { - - answer = "是"; - - //把另外一个人的任务设置为不加急(如果项目加急是否 subject 加急是否) - var urgent = _repository.Where(t => t.Id == taskInfo.SourceSubjectVisitId).Select(t => new { IsSubjectUrgent = t.Subject.IsUrgent, t.Trial.IsUrgent }).FirstOrDefault(); - - if (urgent?.IsUrgent == false || urgent?.IsSubjectUrgent == false) - { - await _visitTaskRepository.BatchUpdateNoTrackingAsync(t => t.SourceSubjectVisitId == taskInfo.SourceSubjectVisitId && t.TaskState == TaskState.Effect && t.IsAnalysisCreate == false && - t.Id != visitTaskId && t.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId, u => new VisitTask() { IsUrgent = false }); - } - + await _visitTaskRepository.BatchUpdateNoTrackingAsync(t => t.SourceSubjectVisitId == taskInfo.SourceSubjectVisitId && t.TaskState == TaskState.Effect && t.IsAnalysisCreate == false && + t.Id != visitTaskId && t.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId, u => new VisitTask() { IsUrgent = false }); } + + } isNeedSend = await DealMedicalReviewTasKGenerateAndIsSendAsync(taskInfo.TrialId, isMedicalReviewAndSuggestApplyReReading, answer, new List() { visitTaskId }, minUserIdList); } @@ -455,17 +486,7 @@ namespace IRaCIS.Core.Application.Service } else if (businessScenarioEnum == CommonDocumentBusinessScenario.PDConfirmed) { - sendEmailConfig.TopicDescription = $"【疾病进展确认报告】关于{taskInfo.ResearchProgramNo}项目{taskInfo.SubjectCode}受试者"; - using (StreamReader SourceReader = System.IO.File.OpenText(pathToFile)) - { - var templateInfo = SourceReader.ReadToEnd(); - - - sendEmailConfig.HtmlBodyStr = string.Format(templateInfo, - $" 附件为疾病进展确认报告,请查收 " - ); - } //有序 @@ -535,7 +556,7 @@ namespace IRaCIS.Core.Application.Service isNeedSend = await DealMedicalReviewTasKGenerateAndIsSendAsync(taskInfo.TrialId, isMedicalReviewAndSuggestApplyReReading, answer, taskList.Select(t => t.Id).ToList(), minUserIdList); - + } //双人 产生裁判,并且裁判完成 发 else if (taskList.Count == 3 && taskList.Count(t => t.ReadingTaskState == ReadingTaskState.HaveSigned) == 3 && taskList.Where(t => t.ReadingCategory == ReadingCategory.Judge).Count() == 1) @@ -657,7 +678,7 @@ namespace IRaCIS.Core.Application.Service answer = await TranslatePdStateAsync(visitTaskId, taskInfo.ReadingCategory, taskInfo.CriterionType); - isNeedSend = await DealMedicalReviewTasKGenerateAndIsSendAsync(taskInfo.TrialId, isMedicalReviewAndSuggestApplyReReading, answer, taskList.Select(t => t.Id).ToList(), minUserIdList); + isNeedSend = await DealMedicalReviewTasKGenerateAndIsSendAsync(taskInfo.TrialId, isMedicalReviewAndSuggestApplyReReading, answer, taskList.Select(t => t.Id).ToList(), minUserIdList); } else if (taskList.Count == 3 && taskList.Count(t => t.ReadingTaskState == ReadingTaskState.HaveSigned) == 3 && taskList.Where(t => t.ReadingCategory == ReadingCategory.Judge).Count() == 1) { @@ -699,7 +720,7 @@ namespace IRaCIS.Core.Application.Service - + } else @@ -707,21 +728,62 @@ namespace IRaCIS.Core.Application.Service isNeedSend = false; } + #endregion + + #region MiniWord 组织字典 发送 + + + if (emailStoreMode == EmailStoreSendMode.NotStoreLocalOnlySentEmail) + { + + var phyPath = FileStoreHelper.GetPhysicalFilePath(_hostEnvironment, sendFileRelativePath); + + //先预先生成了邮件,发送预先生成的邮件 + sendEmailConfig.EmailAttachMentConfigList.Add(new EmailAttachMentConfig() + { + FileName = emailConfig.FileName, + + FileStream = File.OpenRead(phyPath), + }); + + + await SendEmailHelper.SendEmailAsync(sendEmailConfig); + } + + var value = new Dictionary() + { + ["SponsorName"] = taskInfo.SponsorName, + ["ResearchProgramNo"] = taskInfo.ResearchProgramNo, + ["TrialSiteCode"] = taskInfo.TrialSiteCode, + ["SubjectCode"] = taskInfo.SubjectCode, + ["VisitName"] = taskInfo.SourceSubjectVisitId != null ? taskInfo.VisitName : taskInfo.ModuleVisitName, + ["EarliestScanDate"] = taskInfo.SourceSubjectVisitId != null ? taskInfo.VisitEarliestScanDate : taskInfo.ModuleEarliestScanDate, + ["SignTime"] = taskInfo.SignTime, + ["Result"] = answer + + }; + + var (serverFilePath, relativePath, fileRealName) = FileStoreHelper.GetSubjectEnrollConfirmOrPDEmailPath(_hostEnvironment, Path.GetFileName(path), taskInfo.TrialId, taskInfo.SiteId, taskInfo.SubjectId); + + if (emailStoreMode == EmailStoreSendMode.StoreLocalSend || emailStoreMode == EmailStoreSendMode.OnlyStoreLocalNotSentEmail) + { + MiniSoftware.MiniWord.SaveAsByTemplate(serverFilePath, path, value); + + } + //手动生成发送的邮件内容,但是并不发送 + if (emailStoreMode == EmailStoreSendMode.OnlyStoreLocalNotSentEmail) + { + isNeedSend = false; + + return relativePath; + } + + + //正常的即时生成邮件 并发送邮件 if (isNeedSend) { - var value = new Dictionary() - { - ["SponsorName"] = taskInfo.SponsorName, - ["ResearchProgramNo"] = taskInfo.ResearchProgramNo, - ["TrialSiteCode"] = taskInfo.TrialSiteCode, - ["SubjectCode"] = taskInfo.SubjectCode, - ["VisitName"] = taskInfo.SourceSubjectVisitId != null ? taskInfo.VisitName : taskInfo.ModuleVisitName, - ["EarliestScanDate"] = taskInfo.SourceSubjectVisitId != null ? taskInfo.VisitEarliestScanDate : taskInfo.ModuleEarliestScanDate, - ["SignTime"] = taskInfo.SignTime, - ["Result"] = answer - }; MemoryStream memoryStream = new MemoryStream(); @@ -740,6 +802,15 @@ namespace IRaCIS.Core.Application.Service await SendEmailHelper.SendEmailAsync(sendEmailConfig); } + + + + return string.Empty; + + + + + #endregion @@ -747,6 +818,37 @@ namespace IRaCIS.Core.Application.Service + /// + /// 手动生成入组确认 或者PD 进展的邮件 如果能发送,会返回文件的路径,否则会给出提示 + /// + /// + /// + public async Task ManualGenerateEmailFile(Guid visitTaskId) + { + var filePath = await BaseBusinessScenarioSendEmailAsync(visitTaskId, true, EmailStoreSendMode.OnlyStoreLocalNotSentEmail, string.Empty); + + if (string.IsNullOrEmpty(filePath)) + { + return ResponseOutput.NotOk("该任务不符合发送邮件的条件"); + } + + return ResponseOutput.Ok(filePath); + } + + /// + /// 手动发送邮件 + /// + /// + /// + /// + public async Task ManualSendEmail(Guid visitTaskId, string sendFileRelativePath) + { + var filePath = await BaseBusinessScenarioSendEmailAsync(visitTaskId, true, EmailStoreSendMode.NotStoreLocalOnlySentEmail, sendFileRelativePath); + + return ResponseOutput.Ok(); + + } + private async Task TranslatePdStateAsync(Guid visitTaskId, ReadingCategory readingCategory, CriterionType criterionType) { diff --git a/IRaCIS.Core.Application/Service/Reading/MedicalAudit/ReadingMedicalReviewService.cs b/IRaCIS.Core.Application/Service/Reading/MedicalAudit/ReadingMedicalReviewService.cs index 12c128eb1..39f862560 100644 --- a/IRaCIS.Core.Application/Service/Reading/MedicalAudit/ReadingMedicalReviewService.cs +++ b/IRaCIS.Core.Application/Service/Reading/MedicalAudit/ReadingMedicalReviewService.cs @@ -684,7 +684,7 @@ namespace IRaCIS.Core.Application.Service }); - await _trialEmailNoticeConfigService.BaseBusinessScenarioSendEmailAsync(medicalReviewInfo.VisitTaskId, true&& medicalReviewInfo.IsApplyHeavyReading); + await _trialEmailNoticeConfigService.BaseBusinessScenarioSendEmailAsync(medicalReviewInfo.VisitTaskId, true&& medicalReviewInfo.IsApplyHeavyReading); var result = await _taskMedicalReviewRepository.SaveChangesAsync(); return ResponseOutput.Result(result); diff --git a/IRaCIS.Core.Domain.Share/Common/EmailStoreMode.cs b/IRaCIS.Core.Domain.Share/Common/EmailStoreMode.cs new file mode 100644 index 000000000..7ea286111 --- /dev/null +++ b/IRaCIS.Core.Domain.Share/Common/EmailStoreMode.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace IRaCIS.Core.Domain.Share.Common +{ + + + public enum EmailStoreSendMode + { + //不存储本地 发送 + NotStoreLocalSend = 0, + + //存储本地发送 + StoreLocalSend = 1, + + //存储本地不发送 + OnlyStoreLocalNotSentEmail = 2, + + //不存储本地 发送 + NotStoreLocalOnlySentEmail = 3, + + } + +}