diff --git a/IRaCIS.Core.API/Controllers/UploadDownLoadController.cs b/IRaCIS.Core.API/Controllers/UploadDownLoadController.cs index d66dc26b7..d8028d2b1 100644 --- a/IRaCIS.Core.API/Controllers/UploadDownLoadController.cs +++ b/IRaCIS.Core.API/Controllers/UploadDownLoadController.cs @@ -991,11 +991,14 @@ namespace IRaCIS.Core.API.Controllers if (!fileName.EndsWith(".xlsx", StringComparison.OrdinalIgnoreCase)) { + // 请用提供格式的模板excel上传需要处理的数据 throw new BusinessValidationFailedException(StaticData.International("UploadDownLoad_TemplateUploadData")); } (serverFilePath, relativePath) = FileStoreHelper.GetOtherFileUploadPath(_hostEnvironment, StaticData.Folder.TempFile, fileName); + //FileStoreHelper.UploadOOS(serverFilePath, "testc/test", true); + return serverFilePath; }); @@ -1006,32 +1009,41 @@ namespace IRaCIS.Core.API.Controllers if (excelList.Any(t => string.IsNullOrWhiteSpace(t.TrialSiteCode) || string.IsNullOrWhiteSpace(t.FirstName) || string.IsNullOrWhiteSpace(t.LastName) || string.IsNullOrWhiteSpace(t.Email) || string.IsNullOrWhiteSpace(t.UserTypeStr))) { + //请确保Excel中 每一行的 中心编号,姓名,邮箱,用户类型数据记录完整再进行上传 throw new BusinessValidationFailedException(StaticData.International("UploadDownLoad_EnsureCompleteData")); } var siteCodeList = excelList.Select(t => t.TrialSiteCode.Trim().ToUpper()).Distinct().ToList(); - - if (_trialSiteRepository.Where(t => t.TrialId==trialId && siteCodeList.Contains(t.TrialSiteCode.ToUpper())).Count() != siteCodeList.Count) + + if (_trialSiteRepository.Where(t => t.TrialId == trialId && siteCodeList.Contains(t.TrialSiteCode.ToUpper())).Count() != siteCodeList.Count) { + //在项目中未找到该Excel中部分或全部中心 throw new BusinessValidationFailedException(StaticData.International("UploadDownLoad_InvalidCenters")); } - if (excelList.GroupBy(t => new { t.UserTypeStr, t.Email }).Any(g => g.Count() > 1)) + if (excelList.GroupBy(t => new {t.TrialSiteCode, t.UserTypeStr, t.Email }).Any(g => g.Count() > 1)) { + // 同一邮箱,同一用户类型,只能生成一个账户,请核查Excel数据 + throw new BusinessValidationFailedException(StaticData.International("UploadDownLoad_CheckDuplicateAccounts")); } if (excelList.Any(t => !t.Email.Contains("@"))) { + //有邮箱不符合邮箱格式,请核查Excel数据 throw new BusinessValidationFailedException(StaticData.International("UploadDownLoad_InvalidEmail")); } var generateUserTypeList = new List() { "CRC", "SR", "CRA" }; if (excelList.Any(t => !generateUserTypeList.Contains(t.UserTypeStr.ToUpper()))) { + //用户类型仅能为 CRC,SR,CRA 请核查Excel数据 throw new BusinessValidationFailedException(StaticData.International("UploadDownLoad_InvalidUserType")); } - + if (excelList.Count == 0) + { + throw new BusinessValidationFailedException(StaticData.International("UploadDownLoad_NoValiddata")); + } //处理好 用户类型 和用户类型枚举 var sysUserTypeList = _usertypeRepository.Where(t => t.UserTypeEnum == UserTypeEnum.CRA || t.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator || t.UserTypeEnum == UserTypeEnum.SR).Select(t => new { UserTypeId = t.Id, t.UserTypeEnum }).ToList(); var siteList = _trialSiteRepository.Where(t => t.TrialId == trialId && siteCodeList.Contains(t.TrialSiteCode)).Select(t => new { t.TrialSiteCode, t.SiteId }).ToList(); @@ -1061,10 +1073,13 @@ namespace IRaCIS.Core.API.Controllers item.SiteId = siteList.FirstOrDefault(t => t.TrialSiteCode.ToUpper() == item.TrialSiteCode.ToUpper()).SiteId; } + + await _trialSiteSurveyService.ImportGenerateAccountAndJoinTrialAsync(trialId, baseUrl, routeUrl, excelList.ToList()); return ResponseOutput.Ok(); + } @@ -1202,15 +1217,15 @@ namespace IRaCIS.Core.API.Controllers public enum UploadFileType { - DataUpload=1, + DataUpload = 1, - DataDownload=2, + DataDownload = 2, - EmailAttachment=3, + EmailAttachment = 3, - EmailBodyHtml=4, + EmailBodyHtml = 4, - Other=5 + Other = 5 } /// @@ -1225,17 +1240,17 @@ namespace IRaCIS.Core.API.Controllers IResponseOutput result = null; switch (fileType) - { + { case UploadFileType.DataUpload: - result= await SingleFileUploadAsync((fileName) => FileStoreHelper.GetSystemFileUploadPath(_hostEnvironment, StaticData.Folder.DataTemplate,fileName)); + result = await SingleFileUploadAsync((fileName) => FileStoreHelper.GetSystemFileUploadPath(_hostEnvironment, StaticData.Folder.DataTemplate, fileName)); break; case UploadFileType.DataDownload: - result= await SingleFileUploadAsync((fileName) => FileStoreHelper.GetSystemFileUploadPath(_hostEnvironment, StaticData.Folder.DataTemplate,fileName)); + result = await SingleFileUploadAsync((fileName) => FileStoreHelper.GetSystemFileUploadPath(_hostEnvironment, StaticData.Folder.DataTemplate, fileName)); break; case UploadFileType.EmailAttachment: - result = await SingleFileUploadAsync((fileName) => FileStoreHelper.GetSystemFileUploadPath(_hostEnvironment, StaticData.Folder.EmailTemplate, fileName)); + result = await SingleFileUploadAsync((fileName) => FileStoreHelper.GetSystemFileUploadPath(_hostEnvironment, StaticData.Folder.EmailTemplate, fileName)); break; @@ -1245,7 +1260,7 @@ namespace IRaCIS.Core.API.Controllers default: result = await SingleFileUploadAsync((fileName) => FileStoreHelper.GetOtherFileUploadPath(_hostEnvironment, StaticData.Folder.TempFile, fileName)); - + break; } diff --git a/IRaCIS.Core.API/Startup.cs b/IRaCIS.Core.API/Startup.cs index 769f9c9b7..b095f6b07 100644 --- a/IRaCIS.Core.API/Startup.cs +++ b/IRaCIS.Core.API/Startup.cs @@ -27,6 +27,8 @@ using Microsoft.AspNetCore.StaticFiles; using IRaCIS.Application.Services.BackGroundJob; using IRaCIS.Core.Application.Helper; using Microsoft.AspNetCore.Http; +using Autofac.Core; +using DocumentFormat.OpenXml.InkML; namespace IRaCIS.Core.API { @@ -92,7 +94,7 @@ namespace IRaCIS.Core.API }) .AddNewtonsoftJsonSetup(); // NewtonsoftJson л - services.AddOptions().Configure( _configuration.GetSection("SystemEmailSendConfig")); + services.AddOptions().Configure(_configuration.GetSection("SystemEmailSendConfig")); services.AddOptions().Configure(_configuration.GetSection("BasicSystemConfig")); @@ -165,7 +167,7 @@ namespace IRaCIS.Core.API } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + public async void Configure(IApplicationBuilder app, IWebHostEnvironment env) { //app.UsePathBase(PathString.FromUriComponent("/api")); @@ -213,7 +215,7 @@ namespace IRaCIS.Core.API app.UseStatusCodePagesWithReExecute("/Error/{0}"); SwaggerSetup.Configure(app, env); - + ////serilog ¼ûϢ @@ -242,7 +244,11 @@ namespace IRaCIS.Core.API }); - HangfireJobHelper.NotImmediatelyOnceOnlyJob(t => t.InitHangfireJobTaskAsync(),TimeSpan.FromSeconds(1)); + var hangfireJobService = app.ApplicationServices.GetRequiredService(); + + await hangfireJobService.InitHangfireJobTaskAsync(); + //еʱÿ + //HangfireJobHelper.NotImmediatelyOnceOnlyJob(t => t.InitHangfireJobTaskAsync(),TimeSpan.FromSeconds(1)); } diff --git a/IRaCIS.Core.Application/Service/Allocation/DTO/VisitTaskViewModel.cs b/IRaCIS.Core.Application/Service/Allocation/DTO/VisitTaskViewModel.cs index d013c1460..74f089551 100644 --- a/IRaCIS.Core.Application/Service/Allocation/DTO/VisitTaskViewModel.cs +++ b/IRaCIS.Core.Application/Service/Allocation/DTO/VisitTaskViewModel.cs @@ -200,8 +200,16 @@ namespace IRaCIS.Core.Application.ViewModel //任务来源访视Id 方便回更访视读片状态 public Guid? SourceSubjectVisitId { get; set; } public Guid? SouceReadModuleId { get; set; } - + + public List PIReadingResultList { get; set; } + } + + public class PIReadingResult + { + public Guid QuestionId { get; set; } + + public string Answer { get; set; } } @@ -478,7 +486,7 @@ namespace IRaCIS.Core.Application.ViewModel public Guid CreateUserId { get; set; } - public string CreateUserName { get; set; } + public string CreateUserName { get; set; } public DateTime CreateTime { get; set; } diff --git a/IRaCIS.Core.Application/Service/Allocation/VisitTaskService.cs b/IRaCIS.Core.Application/Service/Allocation/VisitTaskService.cs index b690812ce..b2c80894a 100644 --- a/IRaCIS.Core.Application/Service/Allocation/VisitTaskService.cs +++ b/IRaCIS.Core.Application/Service/Allocation/VisitTaskService.cs @@ -44,6 +44,7 @@ namespace IRaCIS.Core.Application.Service.Allocation private readonly IRepository _visitTaskReReadingRepository; private readonly IRepository _taskMedicalReviewRepository; private readonly IRepository _readingTaskQuestionAnswerRepository; + private readonly IRepository _readingQuestionTrialRepository; private readonly IRepository _readingClinicalDataReposiotry; @@ -59,7 +60,8 @@ namespace IRaCIS.Core.Application.Service.Allocation IRepository readingTaskQuestionAnswerRepository , IRepository trialReadingCriterionRepository, IRepository readingClinicalDataReposiotry, - IRepository PIAuditRepository + IRepository PIAuditRepository, + IRepository readingQuestionTrialRepository ) { _PIAuditRepository = PIAuditRepository; @@ -73,7 +75,7 @@ namespace IRaCIS.Core.Application.Service.Allocation _taskMedicalReviewRepository = taskMedicalReviewRepository; _readingTaskQuestionAnswerRepository = readingTaskQuestionAnswerRepository; _trialReadingCriterionRepository = trialReadingCriterionRepository; - + _readingQuestionTrialRepository = readingQuestionTrialRepository; } /// @@ -232,6 +234,11 @@ namespace IRaCIS.Core.Application.Service.Allocation var trialTaskConfig = _trialRepository.Where(t => t.Id == queryVisitTask.TrialId).ProjectTo(_mapper.ConfigurationProvider).FirstOrDefault(); + var questionList = _readingQuestionTrialRepository.Where(t => t.TrialId == queryVisitTask.TrialId && t.ReadingQuestionCriterionTrialId == queryVisitTask.TrialReadingCriterionId) + .Where(t => t.IsJudgeQuestion == true) + .Select(t => new { QuestionId = t.Id, QuestionName = _userInfo.IsEn_Us ? t.QuestionEnName : t.QuestionName ,t.DictionaryCode}).ToList(); + + trialTaskConfig!.OtherObj = questionList; return ResponseOutput.Ok(pageList, trialTaskConfig); } @@ -362,7 +369,7 @@ namespace IRaCIS.Core.Application.Service.Allocation public async Task>> GetReadingTaskList(VisitTaskQuery queryVisitTask) { var visitTaskQueryable = GetReadingTaskQueryable(queryVisitTask) - .ProjectTo(_mapper.ConfigurationProvider); + .ProjectTo(_mapper.ConfigurationProvider,new { isEn_Us =_userInfo.IsEn_Us }); var defalutSortArray = new string[] { nameof(VisitTask.IsUrgent) + " desc", nameof(VisitTask.SubjectId), nameof(VisitTask.VisitTaskNum) }; @@ -370,6 +377,11 @@ namespace IRaCIS.Core.Application.Service.Allocation var trialTaskConfig = _trialRepository.Where(t => t.Id == queryVisitTask.TrialId).ProjectTo(_mapper.ConfigurationProvider).FirstOrDefault(); + var questionList = _readingQuestionTrialRepository.Where(t => t.TrialId == queryVisitTask.TrialId && t.Id == queryVisitTask.TrialReadingCriterionId) + .Where(t => t.IsJudgeQuestion == true) + .Select(t => new { QuestionId = t.Id, QuestionName = _userInfo.IsEn_Us ? t.QuestionEnName : t.QuestionName, t.DictionaryCode }).ToList(); + + trialTaskConfig!.OtherObj = questionList; return ResponseOutput.Ok(pageList, trialTaskConfig); } diff --git a/IRaCIS.Core.Application/Service/Allocation/_MapConfig.cs b/IRaCIS.Core.Application/Service/Allocation/_MapConfig.cs index 49a81e3f2..7e60cc7ac 100644 --- a/IRaCIS.Core.Application/Service/Allocation/_MapConfig.cs +++ b/IRaCIS.Core.Application/Service/Allocation/_MapConfig.cs @@ -74,14 +74,16 @@ namespace IRaCIS.Core.Application.Service .ForMember(o => o.PDState, t => t.MapFrom(u => u.SourceSubjectVisit.PDState)) ; - + var isEn_Us = true; CreateMap().IncludeBase() .ForMember(o => o.HistoryReadingDoctorUserList, t => t.MapFrom(u => u.JudgeVisitList)); - CreateMap().IncludeBase(); + CreateMap().IncludeBase() + .ForMember(t=>t.PIReadingResultList,u=>u.MapFrom(c=>c.ReadingTaskQuestionAnswerList + .Where(t=>t.ReadingQuestionTrial.IsJudgeQuestion==true ).Select(d=>new PIReadingResult() { QuestionId= d.ReadingQuestionTrialId,Answer=d.Answer}))); CreateMap().IncludeBase() .ForMember(o => o.FirstAuditUserName, t => t.MapFrom(u => u.FirstAuditUser.UserName)) diff --git a/IRaCIS.Core.Application/Service/Document/EmailSendService.cs b/IRaCIS.Core.Application/Service/Document/EmailSendService.cs index 76263b36f..1f4aa82e5 100644 --- a/IRaCIS.Core.Application/Service/Document/EmailSendService.cs +++ b/IRaCIS.Core.Application/Service/Document/EmailSendService.cs @@ -1,5 +1,7 @@ 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; @@ -28,6 +30,7 @@ namespace IRaCIS.Core.Application.Service Task SendTrialQCQuestionEmailAsync(Guid trialId); Task SendTrialImageQuestionAsync(Guid trialId); + Task SendPIAuditResultAsync(Guid visitTaskId); } public class EmailSendService : BaseService, IEmailSendService @@ -38,13 +41,18 @@ namespace IRaCIS.Core.Application.Service private readonly IRepository _trialRepository; + private readonly IDictionaryService _dictionaryService; private readonly IOptionsMonitor _SystemEmailSendConfig; - public EmailSendService(IRepository trialEmailNoticeConfigRepository, IRepository emailNoticeConfigRepository, IRepository trialRepository, IOptionsMonitor systemEmailSendConfig) + + public readonly static string EmailNamePlaceholder="EmailNamePlaceholder"; + + public EmailSendService(IRepository trialEmailNoticeConfigRepository, IRepository emailNoticeConfigRepository, IRepository trialRepository, IOptionsMonitor systemEmailSendConfig, IDictionaryService dictionaryService) { _trialEmailNoticeConfigRepository = trialEmailNoticeConfigRepository; _emailNoticeConfigRepository = emailNoticeConfigRepository; _trialRepository = trialRepository; _SystemEmailSendConfig = systemEmailSendConfig; + _dictionaryService = dictionaryService; } //入组确认/PD确认 @@ -80,31 +88,33 @@ namespace IRaCIS.Core.Application.Service }).FirstNotNullAsync(); - var resultStr = _userInfo.IsEn_Us ? (result == true ? "Yes" : "No") : (result == true ? "是" : "否"); + var isEn_us = _userInfo.IsEn_Us; + + var resultStr = isEn_us ? (result == true ? "Yes" : "No") : (result == true ? "是" : "否"); if (isEnrollment == true) { - Func topicAndHtmlFunc = trialEmailConfig => + Func topicAndHtmlFunc = trialEmailConfig => { - var topicStr = string.Format(_userInfo.IsEn_Us ? trialEmailConfig.EmailTopic : trialEmailConfig.EmailTopicCN, taskInfo.ResearchProgramNo, taskInfo.SubjectCode); + var topicStr = string.Format(isEn_us ? trialEmailConfig.EmailTopic : trialEmailConfig.EmailTopicCN, taskInfo.ResearchProgramNo, taskInfo.SubjectCode); - var htmlBodyStr = string.Format(_userInfo.IsEn_Us ? trialEmailConfig.EmailHtmlContent : trialEmailConfig.EmailHtmlContentCN, - _userInfo.UserName, taskInfo.ResearchProgramNo, taskInfo.SubjectCode, resultStr); - return (topicStr, htmlBodyStr,null); + 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); } else { - Func topicAndHtmlFunc = trialEmailConfig => + Func topicAndHtmlFunc = trialEmailConfig => { - var topicStr = string.Format(_userInfo.IsEn_Us ? trialEmailConfig.EmailTopic : trialEmailConfig.EmailTopicCN, taskInfo.ResearchProgramNo, taskInfo.SubjectCode, taskInfo.VisitName); + var topicStr = string.Format(isEn_us ? trialEmailConfig.EmailTopic : trialEmailConfig.EmailTopicCN, taskInfo.ResearchProgramNo, taskInfo.SubjectCode, taskInfo.VisitName); - var htmlBodyStr = string.Format(_userInfo.IsEn_Us ? trialEmailConfig.EmailHtmlContent : trialEmailConfig.EmailHtmlContentCN, - _userInfo.UserName, taskInfo.ResearchProgramNo, taskInfo.SubjectCode, taskInfo.VisitName, resultStr); + var htmlBodyStr = string.Format(isEn_us ? trialEmailConfig.EmailHtmlContent : trialEmailConfig.EmailHtmlContentCN, + EmailNamePlaceholder, taskInfo.ResearchProgramNo, taskInfo.SubjectCode, taskInfo.VisitName, resultStr); - return (topicStr, htmlBodyStr,null); + return (topicStr, htmlBodyStr, isEn_us, null); }; await SendTrialEmailAsync(taskInfo.TrialId, businessScenarioEnum, topicAndHtmlFunc); @@ -120,6 +130,7 @@ namespace IRaCIS.Core.Application.Service /// public async Task SendTrialImageQCTaskEmailAsync(Guid trialId) { + var isEn_us = false; var trialInfo = await _repository.Where(t => t.Id == trialId).Select(t => new { t.ResearchProgramNo, t.ExperimentName, t.TrialCode, t.TrialStatusStr }).FirstNotNullAsync(); //找到 该项目的IQC 用户Id @@ -151,12 +162,12 @@ namespace IRaCIS.Core.Application.Service if (sendStat != null && (sendStat.ToBeClaimedCount > 0 || sendStat.ToBeReviewedCount > 0)) { - Func topicAndHtmlFunc = trialEmailConfig => + Func topicAndHtmlFunc = trialEmailConfig => { - var topicStr = string.Format(_userInfo.IsEn_Us ? trialEmailConfig.EmailTopic : trialEmailConfig.EmailTopicCN, trialInfo.ResearchProgramNo); - var htmlBodyStr = string.Format(_userInfo.IsEn_Us ? trialEmailConfig.EmailHtmlContent : trialEmailConfig.EmailHtmlContentCN, + 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, userId); + return (topicStr, htmlBodyStr, false,userId); }; await SendTrialEmailAsync(trialId, EmailBusinessScenario.QCTask, topicAndHtmlFunc); @@ -171,7 +182,8 @@ namespace IRaCIS.Core.Application.Service /// public async Task SendTrialQCQuestionEmailAsync(Guid trialId) { - var trialInfo = _repository.Where(t => t.Id == trialId).Select(t => new { t.ResearchProgramNo, t.ExperimentName, t.TrialCode, t.TrialStatusStr }).FirstOrDefault(); + var isEn_us = false; + var trialInfo = _repository.Where(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(t => t.TrialId == trialId).Where(t => t.User.UserTypeEnum == UserTypeEnum.IQC).Select(t => new { t.UserId, t.User.FullName }).ToListAsync(); @@ -201,13 +213,13 @@ namespace IRaCIS.Core.Application.Service if (sendStat != null && (sendStat.ToBeDealedCount > 0 || sendStat.ReUploadTobeDealedCount > 0)) { - Func topicAndHtmlFunc = trialEmailConfig => + Func topicAndHtmlFunc = trialEmailConfig => { - var topicStr = string.Format(_userInfo.IsEn_Us ? trialEmailConfig.EmailTopic : trialEmailConfig.EmailTopicCN, trialInfo.ResearchProgramNo); - var htmlBodyStr = string.Format(_userInfo.IsEn_Us ? trialEmailConfig.EmailHtmlContent : trialEmailConfig.EmailHtmlContentCN, + 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, userId); + return (topicStr, htmlBodyStr, false, userId); }; await SendTrialEmailAsync(trialId, EmailBusinessScenario.QCQuestion, topicAndHtmlFunc); @@ -222,6 +234,8 @@ namespace IRaCIS.Core.Application.Service /// public async Task SendTrialImageQuestionAsync(Guid trialId) { + var isEn_us = false; + var trialInfo = _repository.Where(t => t.Id == trialId).Select(t => new { t.ResearchProgramNo, t.ExperimentName, t.TrialCode, t.TrialStatusStr }).FirstOrDefault(); //找到 该项目的CRC 用户Id @@ -249,12 +263,12 @@ namespace IRaCIS.Core.Application.Service if (sendStat != null && (sendStat.ToBeDealedCount > 0)) { - Func topicAndHtmlFunc = trialEmailConfig => + Func topicAndHtmlFunc = trialEmailConfig => { - var topicStr = string.Format(_userInfo.IsEn_Us ? trialEmailConfig.EmailTopic : trialEmailConfig.EmailTopicCN, trialInfo.ResearchProgramNo); - var htmlBodyStr = string.Format(_userInfo.IsEn_Us ? trialEmailConfig.EmailHtmlContent : trialEmailConfig.EmailHtmlContentCN, + 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,userId); + return (topicStr, htmlBodyStr, isEn_us, userId); }; await SendTrialEmailAsync(trialId, EmailBusinessScenario.ImageQuestion, topicAndHtmlFunc); @@ -266,24 +280,61 @@ namespace IRaCIS.Core.Application.Service //临床数据质询 public async Task SendClinicalDataQuestionAsync(Guid visitTaskId, string content) { + + var isEn_us = _userInfo.IsEn_Us; + var info = await _repository.Where(t => t.Id == visitTaskId, ignoreQueryFilters: true).Select(t => new { t.TrialId, t.Trial.ResearchProgramNo, t.Trial.TrialCode, t.SourceSubjectVisit.VisitName, t.Subject.Code }).FirstOrDefaultAsync(); - Func topicAndHtmlFunc = trialEmailConfig => + Func topicAndHtmlFunc = trialEmailConfig => { - var topicStr = string.Format(_userInfo.IsEn_Us ? trialEmailConfig.EmailTopic : trialEmailConfig.EmailTopicCN, info.ResearchProgramNo,info.Code,info.VisitName); - var htmlBodyStr = string.Format(_userInfo.IsEn_Us ? trialEmailConfig.EmailHtmlContent : trialEmailConfig.EmailHtmlContentCN, - _userInfo.UserName, info.ResearchProgramNo, info.Code, info.VisitName,_userInfo.UserName,content, _SystemEmailSendConfig.CurrentValue.SiteUrl); - return (topicStr, htmlBodyStr,null); + 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); } + public async Task SendPIAuditResultAsync(Guid visitTaskId) + { + var isEn_us = _userInfo.IsEn_Us; + + var info = await _repository.Where(t => t.Id == visitTaskId, ignoreQueryFilters: true).Select(t => new { t.TrialId, t.Trial.ResearchProgramNo, t.Trial.TrialCode, t.SourceSubjectVisit.VisitName, t.Subject.Code }).FirstOrDefaultAsync(); + var answerList= await _repository.Where(t => t.Id == visitTaskId, ignoreQueryFilters: true).SelectMany(t=>t.ReadingTaskQuestionAnswerList).Select(t=>new { QuestionName= isEn_us? t.ReadingQuestionTrial.QuestionEnName:t.ReadingQuestionTrial.QuestionName, t.ReadingQuestionTrial.DictionaryCode, t.Answer}).ToListAsync(); + + var template = "
{0}: {1}
"; + + var needTranslateDicNameList=answerList.Where(t=>!string.IsNullOrEmpty(t.DictionaryCode)).Select(t=>t.DictionaryCode).ToList(); + + var translateDataList = await _dictionaryService.GetBasicDataSelect(needTranslateDicNameList.ToArray()); - public async Task SendTrialEmailAsync(Guid trialId, EmailBusinessScenario businessScenario, Func topicAndHtmlFunc, Guid? trialReadingCriterionId = null, Guid? subjectId = null) + Func transFunc = (bool isNeedTranslate, string dicCode, string answer) => + { + var result = translateDataList[dicCode].Where(t => t.Code.ToLower() == answer.ToLower()).Select(t => isEn_us ? t.Value : t.ValueCN).FirstOrDefault(); + + return result; + }; + + var piResult= string.Join(' ', answerList.Select(t => string.Format(template, t.QuestionName, transFunc(!string.IsNullOrEmpty(t.DictionaryCode),t.DictionaryCode,t.Answer ) ))) ; + + Func 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); + } + + + + public async Task SendTrialEmailAsync(Guid trialId, EmailBusinessScenario businessScenario, Func topicAndHtmlFunc, Guid? trialReadingCriterionId = null, Guid? subjectId = null) { //找到配置 var trialEmailConfig = await _trialEmailNoticeConfigRepository.Where(t => t.TrialId == trialId && t.TrialReadingCriterionId == trialReadingCriterionId && t.BusinessScenarioEnum == businessScenario, ignoreQueryFilters: true) @@ -294,12 +345,11 @@ namespace IRaCIS.Core.Application.Service { return; } - else { var sendEmailConfig = new SMTPEmailConfig(); - var (topicStr, htmlBodyStr, onlyToUserId) = topicAndHtmlFunc(trialEmailConfig); + var (topicStr, htmlBodyStr, isEn_us,onlyToUserId) = topicAndHtmlFunc(trialEmailConfig); sendEmailConfig.TopicDescription = topicStr; @@ -335,6 +385,10 @@ namespace IRaCIS.Core.Application.Service { toUserList= toUserList.Where(t=>t.UserId == onlyToUserId).ToList(); } + else + { + htmlBodyStr = htmlBodyStr.Replace(EmailNamePlaceholder, string.Join(isEn_us ? ", " : "、", toUserList.Select(t => t.FullName).ToList())); + } if (toUserList.Count() == 0) { @@ -348,7 +402,7 @@ namespace IRaCIS.Core.Application.Service sendEmailConfig.FromEmailAddress = new MimeKit.MailboxAddress(trialEmailConfig.FromName, trialEmailConfig.FromEmail); sendEmailConfig.AuthorizationCode = trialEmailConfig.AuthorizationCode; - sendEmailConfig.UserName = trialEmailConfig.FromEmail; + sendEmailConfig.UserName = trialEmailConfig.FromName; sendEmailConfig.Host = trialEmailConfig.SMTPServerAddress; sendEmailConfig.Port = trialEmailConfig.SMTPServerPort; diff --git a/IRaCIS.Core.Application/Service/Institution/DTO/SiteModel.cs b/IRaCIS.Core.Application/Service/Institution/DTO/SiteModel.cs index 43f027200..0675dad98 100644 --- a/IRaCIS.Core.Application/Service/Institution/DTO/SiteModel.cs +++ b/IRaCIS.Core.Application/Service/Institution/DTO/SiteModel.cs @@ -12,7 +12,7 @@ namespace IRaCIS.Application.Contracts { public Guid? Id { get; set; } public string SiteName { get; set; } = String.Empty; - + public string SiteNameCN { get; set; } = String.Empty; public int Code { get; set; } public string SiteCode { get; set; } = String.Empty; diff --git a/IRaCIS.Core.Application/Service/Institution/SiteService.cs b/IRaCIS.Core.Application/Service/Institution/SiteService.cs index 2f3cc4391..3ccc8139f 100644 --- a/IRaCIS.Core.Application/Service/Institution/SiteService.cs +++ b/IRaCIS.Core.Application/Service/Institution/SiteService.cs @@ -31,6 +31,7 @@ namespace IRaCIS.Application.Services .WhereIf(!string.IsNullOrWhiteSpace(searchModel.AliasName), t => t.AliasName.Contains(searchModel.AliasName)) .WhereIf(!string.IsNullOrWhiteSpace(searchModel.City), t => t.City.Contains(searchModel.City)) .WhereIf(!string.IsNullOrWhiteSpace(searchModel.Country), t => t.Country.Contains(searchModel.Country)) + .WhereIf(!string.IsNullOrWhiteSpace(searchModel.Province), t => t.Country.Contains(searchModel.Province)) .ProjectTo(_mapper.ConfigurationProvider); diff --git a/IRaCIS.Core.Application/Service/Management/UserTypeService.cs b/IRaCIS.Core.Application/Service/Management/UserTypeService.cs index c6b5a168e..fb534f4e9 100644 --- a/IRaCIS.Core.Application/Service/Management/UserTypeService.cs +++ b/IRaCIS.Core.Application/Service/Management/UserTypeService.cs @@ -119,7 +119,7 @@ namespace IRaCIS.Core.Application.Contracts } else { - userTypeEnums = new List() { UserTypeEnum.PI, UserTypeEnum.MIM }; + userTypeEnums = new List() { UserTypeEnum.PI, UserTypeEnum.MIM , UserTypeEnum.IQC}; } } diff --git a/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/TrialConfigDTO.cs b/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/TrialConfigDTO.cs index ba9cedd59..3bdb1e9c5 100644 --- a/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/TrialConfigDTO.cs +++ b/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/TrialConfigDTO.cs @@ -333,7 +333,7 @@ namespace IRaCIS.Core.Application.Contracts public UserTypeEnum? PDProgressDefaultUserType { get; set; } - + public object OtherObj { get; set; } } public class TrialStateChangeDTO diff --git a/IRaCIS.Core.Application/Triggers/VisitTaskIAfterSignTrigger.cs b/IRaCIS.Core.Application/Triggers/VisitTaskIAfterSignTrigger.cs index 95f5e3954..ab1171212 100644 --- a/IRaCIS.Core.Application/Triggers/VisitTaskIAfterSignTrigger.cs +++ b/IRaCIS.Core.Application/Triggers/VisitTaskIAfterSignTrigger.cs @@ -10,33 +10,33 @@ using System.Linq.Expressions; namespace IRaCIS.Core.Application.Triggers { - public class VisitTaskIAfterSignTrigger : IAfterSaveTrigger + public class VisitTaskIAfterSignTrigger : IAfterSaveTrigger,IBeforeSaveTrigger { private readonly IRepository _visitTaskRepository; private readonly IRepository _subjectRepository; + private readonly IUserInfo _userInfo; + private readonly IEmailSendService _emailSendService; + - - public VisitTaskIAfterSignTrigger(IRepository visitTaskRepository, IRepository subjectRepository) + public VisitTaskIAfterSignTrigger(IRepository visitTaskRepository, IRepository subjectRepository, IUserInfo userInfo, IEmailSendService emailSendService) { _visitTaskRepository = visitTaskRepository; _subjectRepository = subjectRepository; + _userInfo = userInfo; + + _emailSendService = emailSendService; } - //添加任务的时候 如果需要签名 并且已经签名了 public async Task AfterSave(ITriggerContext context, CancellationToken cancellationToken) { var visitTask = context.Entity; - if (visitTask.SignTime != null && visitTask.ReadingTaskState == ReadingTaskState.HaveSigned - - //&& _subjectRepository.Where(t=>t.Id==visitTask.SubjectId).SelectMany(c=>c.SubjectVisitList) - //.Any(t=>t.Id==visitTask.SourceSubjectVisitId && t.IsBaseLine) - ) + if (visitTask.SignTime != null && visitTask.ReadingTaskState == ReadingTaskState.HaveSigned ) { //任务阅片完成 自动释放 await _visitTaskRepository.BatchUpdateNoTrackingAsync(t => t.SubjectId == visitTask.SubjectId && t.TrialReadingCriterionId==visitTask.TrialReadingCriterionId , t=>new VisitTask() { SubjectCriterionClaimUserId=null}); @@ -45,6 +45,19 @@ namespace IRaCIS.Core.Application.Triggers } + public async Task BeforeSave(ITriggerContext context, CancellationToken cancellationToken) + { + var visitTask = context.Entity; + if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.PI) + { + visitTask.PIAuditState = PIAuditState.PIAgree; + } + + if (context.ChangeType == ChangeType.Modified && visitTask.PIAuditState!=context.UnmodifiedEntity.PIAuditState && visitTask.PIAuditState==PIAuditState.PIAgree) + { + await _emailSendService.SendPIAuditResultAsync(visitTask.Id); + } + } } } \ No newline at end of file diff --git a/IRaCIS.Core.Domain.Share/Common/EmailScenarioEnum.cs b/IRaCIS.Core.Domain.Share/Common/EmailScenarioEnum.cs index 88c6db1f5..b85e862bc 100644 --- a/IRaCIS.Core.Domain.Share/Common/EmailScenarioEnum.cs +++ b/IRaCIS.Core.Domain.Share/Common/EmailScenarioEnum.cs @@ -57,6 +57,8 @@ namespace IRaCIS.Core.Domain.Share ImageQuestion = 7, ClinicalDataQuestion = 8, + + PIAuditResutl=9 } diff --git a/IRaCIS.Core.Domain/Institution/Site.cs b/IRaCIS.Core.Domain/Institution/Site.cs index 7465935fa..feeeaa044 100644 --- a/IRaCIS.Core.Domain/Institution/Site.cs +++ b/IRaCIS.Core.Domain/Institution/Site.cs @@ -9,15 +9,15 @@ namespace IRaCIS.Core.Domain.Models { [JsonIgnore] public Hospital Hospital { get; set; } - public string SiteName { get; set; } - + public string SiteName { get; set; } = string.Empty; + public string SiteNameCN{ get; set; } = string.Empty; public string AliasName { get; set; } = string.Empty; public string SiteCode { get; set; } public int Code { get; set; } - public string City { get; set; } - public string Country { get; set; } + public string City { get; set; } = string.Empty; + public string Country { get; set; } = string.Empty; public Guid? HospitalId { get; set; } public int State { get; set; }