diff --git a/IRC.Core.SCP/HostConfig/AutofacModuleSetup.cs b/IRC.Core.SCP/HostConfig/AutofacModuleSetup.cs index 6567c9735..629cf9636 100644 --- a/IRC.Core.SCP/HostConfig/AutofacModuleSetup.cs +++ b/IRC.Core.SCP/HostConfig/AutofacModuleSetup.cs @@ -45,8 +45,8 @@ namespace IRaCIS.Core.SCP .PropertiesAutowired().AsImplementedInterfaces(); - containerBuilder.RegisterType().As().SingleInstance(); - containerBuilder.RegisterType().As().InstancePerLifetimeScope(); + //containerBuilder.RegisterType().As().SingleInstance(); + //containerBuilder.RegisterType().As().InstancePerLifetimeScope(); diff --git a/IRC.Core.SCP/HostConfig/EFSetup.cs b/IRC.Core.SCP/HostConfig/EFSetup.cs index b53095cbd..00ee49222 100644 --- a/IRC.Core.SCP/HostConfig/EFSetup.cs +++ b/IRC.Core.SCP/HostConfig/EFSetup.cs @@ -1,4 +1,6 @@ -using IRaCIS.Core.Infra.EFCore; +using EntityFramework.Exceptions.SqlServer; +using IRaCIS.Core.Domain.Share; +using IRaCIS.Core.Infra.EFCore; using Medallion.Threading; using Medallion.Threading.SqlServer; using Microsoft.EntityFrameworkCore; @@ -11,15 +13,25 @@ namespace IRaCIS.Core.SCP { public static void AddEFSetup( this IServiceCollection services, IConfiguration configuration) { - //services.AddScoped(); + services.AddHttpContextAccessor(); + services.AddScoped(); + //这个注入没有成功--注入是没问题的,构造函数也只是支持参数就好,错在注入的地方不能写DbContext //Web程序中通过重用池中DbContext实例可提高高并发场景下的吞吐量, 这在概念上类似于ADO.NET Provider原生的连接池操作方式,具有节省DbContext实例化成本的优点 - services.AddDbContext(options => + services.AddDbContextPool(options => { - options.UseSqlServer(configuration.GetSection("ConnectionStrings:RemoteNew").Value, + // 在控制台 + //public static readonly ILoggerFactory MyLoggerFactory = LoggerFactory.Create(builder => { builder.AddConsole(); }); + var logFactory = LoggerFactory.Create(builder => { builder.AddDebug(); }); + + options.UseSqlServer(configuration.GetSection("ConnectionStrings:RemoteNew").Value, contextOptionsBuilder => contextOptionsBuilder.EnableRetryOnFailure()); + options.UseLoggerFactory(logFactory); + + options.UseExceptionProcessor(); + options.EnableSensitiveDataLogging(); options.AddInterceptors(new QueryWithNoLockDbCommandInterceptor()); @@ -30,6 +42,12 @@ namespace IRaCIS.Core.SCP }); + //// Register an additional context factory as a Scoped service, which gets a pooled context from the Singleton factory we registered above, + //services.AddScoped(); + + //// Finally, arrange for a context to get injected from our Scoped factory: + //services.AddScoped(sp => sp.GetRequiredService().CreateDbContext()); + //注意区分 easy caching 也有 IDistributedLockProvider services.AddSingleton(sp => { @@ -38,7 +56,6 @@ namespace IRaCIS.Core.SCP return new SqlDistributedSynchronizationProvider(configuration.GetSection("ConnectionStrings:RemoteNew").Value); }); - //services.AddAssemblyTriggers(typeof(SubjectVisitImageDateTrigger).Assembly); } } } diff --git a/IRaCIS.Core.API/_ServiceExtensions/AutofacModuleSetup.cs b/IRaCIS.Core.API/_ServiceExtensions/AutofacModuleSetup.cs index 015405bf1..3806353b2 100644 --- a/IRaCIS.Core.API/_ServiceExtensions/AutofacModuleSetup.cs +++ b/IRaCIS.Core.API/_ServiceExtensions/AutofacModuleSetup.cs @@ -55,8 +55,8 @@ namespace IRaCIS.Core.API - containerBuilder.RegisterType().As().SingleInstance(); - containerBuilder.RegisterType().As().InstancePerLifetimeScope(); + //containerBuilder.RegisterType().As().SingleInstance(); + //containerBuilder.RegisterType().As().InstancePerLifetimeScope(); //注册hangfire任务 依赖注入 diff --git a/IRaCIS.Core.API/_ServiceExtensions/EFSetup.cs b/IRaCIS.Core.API/_ServiceExtensions/EFSetup.cs index 1f4ca4079..820a2a67e 100644 --- a/IRaCIS.Core.API/_ServiceExtensions/EFSetup.cs +++ b/IRaCIS.Core.API/_ServiceExtensions/EFSetup.cs @@ -1,11 +1,15 @@ -using Hangfire.SqlServer; +using Castle.Core.Logging; +using EntityFramework.Exceptions.SqlServer; +using Hangfire.SqlServer; using IRaCIS.Core.Application.Triggers; +using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Infra.EFCore; using Medallion.Threading; using Medallion.Threading.SqlServer; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; using StackExchange.Redis; namespace IRaCIS.Core.API @@ -14,15 +18,28 @@ namespace IRaCIS.Core.API { public static void AddEFSetup( this IServiceCollection services, IConfiguration configuration) { - //services.AddScoped(); + + services.AddHttpContextAccessor(); + services.AddScoped(); + + // First, register a pooling context factory as a Singleton service, as usual: //这个注入没有成功--注入是没问题的,构造函数也只是支持参数就好,错在注入的地方不能写DbContext //Web程序中通过重用池中DbContext实例可提高高并发场景下的吞吐量, 这在概念上类似于ADO.NET Provider原生的连接池操作方式,具有节省DbContext实例化成本的优点 services.AddDbContext(options => { + + // 在控制台 + //public static readonly ILoggerFactory MyLoggerFactory = LoggerFactory.Create(builder => { builder.AddConsole(); }); + var logFactory = LoggerFactory.Create(builder => { builder.AddDebug(); }); + options.UseSqlServer(configuration.GetSection("ConnectionStrings:RemoteNew").Value, contextOptionsBuilder => contextOptionsBuilder.EnableRetryOnFailure()); + options.UseLoggerFactory(logFactory); + + options.UseExceptionProcessor(); + options.EnableSensitiveDataLogging(); options.AddInterceptors(new QueryWithNoLockDbCommandInterceptor()); @@ -62,6 +79,12 @@ namespace IRaCIS.Core.API }); + // Register an additional context factory as a Scoped service, which gets a pooled context from the Singleton factory we registered above, + //services.AddScoped(); + + //// Finally, arrange for a context to get injected from our Scoped factory: + //services.AddScoped(sp => sp.GetRequiredService().CreateDbContext()); + //注意区分 easy caching 也有 IDistributedLockProvider services.AddSingleton(sp => { diff --git a/IRaCIS.Core.API/_ServiceExtensions/ResponseCompressionSetup.cs b/IRaCIS.Core.API/_ServiceExtensions/ResponseCompressionSetup.cs index 6037273da..5bc11b6cb 100644 --- a/IRaCIS.Core.API/_ServiceExtensions/ResponseCompressionSetup.cs +++ b/IRaCIS.Core.API/_ServiceExtensions/ResponseCompressionSetup.cs @@ -1,18 +1,30 @@ using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.ResponseCompression; using Microsoft.Extensions.DependencyInjection; +using System.IO.Compression; namespace IRaCIS.Core.API { - public static class ResponseCompressionSetup + public static class ResponseCompressionSetup { public static void AddResponseCompressionSetup(this IServiceCollection services) { services.AddResponseCompression(options => { + options.EnableForHttps = true; options.Providers.Add(); options.Providers.Add(); }); + + services.Configure(options => + { + options.Level = CompressionLevel.Optimal; + }); + + services.Configure(options => + { + options.Level = CompressionLevel.Optimal; + }); } } } diff --git a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml index a79b6199f..970833ba3 100644 --- a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml +++ b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml @@ -885,6 +885,16 @@ + + + 受试者级别所有的影像 + 访视级别的影响 传递subjectVisitId + 标准Id是可选的 不同标准有些检查可能有过滤 + + + + + 后台任务调用,前端忽略该接口 @@ -5178,6 +5188,16 @@ 是否是正在转化 + + + 是否盲化 + + + + + 是否完整 + + 项目ID @@ -14148,6 +14168,20 @@ + + + 一致性分析临床数据签名 + + + + + + + 一致性分析临床数据签名完设置任务为有效 + + + + 获取单个阅片临床数据的所有文件 diff --git a/IRaCIS.Core.Application/Service/Allocation/DTO/VisitTaskViewModel.cs b/IRaCIS.Core.Application/Service/Allocation/DTO/VisitTaskViewModel.cs index 27bcb5d88..302351e3d 100644 --- a/IRaCIS.Core.Application/Service/Allocation/DTO/VisitTaskViewModel.cs +++ b/IRaCIS.Core.Application/Service/Allocation/DTO/VisitTaskViewModel.cs @@ -201,6 +201,8 @@ namespace IRaCIS.Core.Application.ViewModel public Guid? SourceSubjectVisitId { get; set; } public Guid? SouceReadModuleId { get; set; } + + public bool IsHaveFeedBack { get; set; } //public bool IsAfterConvertedTask { get; set; } } diff --git a/IRaCIS.Core.Application/Service/Allocation/TaskConsistentRuleService.cs b/IRaCIS.Core.Application/Service/Allocation/TaskConsistentRuleService.cs index 0941f9d25..579c1e766 100644 --- a/IRaCIS.Core.Application/Service/Allocation/TaskConsistentRuleService.cs +++ b/IRaCIS.Core.Application/Service/Allocation/TaskConsistentRuleService.cs @@ -88,7 +88,7 @@ namespace IRaCIS.Core.Application.Service /// /// [HttpPost] - public async Task>> GetAnalysisTaskList(VisitTaskQuery queryVisitTask ) + public async Task>> GetAnalysisTaskList(VisitTaskQuery queryVisitTask) { var visitTaskQueryable = _visitTaskRepository.Where(t => t.TrialId == queryVisitTask.TrialId) .Where(t => t.IsAnalysisCreate) @@ -107,7 +107,7 @@ namespace IRaCIS.Core.Application.Service .WhereIf(queryVisitTask.ArmEnum != null, t => t.ArmEnum == queryVisitTask.ArmEnum) .WhereIf(!string.IsNullOrEmpty(queryVisitTask.TrialSiteCode), t => /*(t.BlindTrialSiteCode.Contains(queryVisitTask.TrialSiteCode!) && t.IsAnalysisCreate) ||*/ (t.Subject.TrialSite.TrialSiteCode.Contains(queryVisitTask.TrialSiteCode!) /*&& t.IsAnalysisCreate == false*/)) .WhereIf(!string.IsNullOrEmpty(queryVisitTask.TaskName), t => t.TaskName.Contains(queryVisitTask.TaskName) || t.TaskBlindName.Contains(queryVisitTask.TaskName)) - .WhereIf(!string.IsNullOrEmpty(queryVisitTask.SubjectCode), t => ((t.Subject.Code.Contains(queryVisitTask.SubjectCode)||t.Subject.MedicalNo.Contains(queryVisitTask.SubjectCode)) && t.IsAnalysisCreate == false) || (t.BlindSubjectCode.Contains(queryVisitTask.SubjectCode) && t.IsAnalysisCreate)) + .WhereIf(!string.IsNullOrEmpty(queryVisitTask.SubjectCode), t => ((t.Subject.Code.Contains(queryVisitTask.SubjectCode) || t.Subject.MedicalNo.Contains(queryVisitTask.SubjectCode)) && t.IsAnalysisCreate == false) || (t.BlindSubjectCode.Contains(queryVisitTask.SubjectCode) && t.IsAnalysisCreate)) .WhereIf(queryVisitTask.BeginAllocateDate != null, t => t.AllocateTime >= queryVisitTask.BeginAllocateDate) .WhereIf(queryVisitTask.EndAllocateDate != null, t => t.AllocateTime <= queryVisitTask.EndAllocateDate) .WhereIf(queryVisitTask.BeginSignTime != null, t => t.SignTime >= queryVisitTask.BeginSignTime) @@ -118,7 +118,7 @@ namespace IRaCIS.Core.Application.Service var pageList = await visitTaskQueryable.ToPagedListAsync(queryVisitTask.PageIndex, queryVisitTask.PageSize, queryVisitTask.SortField, queryVisitTask.Asc, string.IsNullOrWhiteSpace(queryVisitTask.SortField), defalutSortArray); - var trialTaskConfig = _repository.Where(t => t.Id == queryVisitTask.TrialId).Select(t => new { IsHaveDoubleReadCriterion=t.TrialReadingCriterionList.Any(t=>t.IsSigned && t.IsConfirm && t.ReadingType==ReadingMethod.Double), t.VitrualSiteCode }).FirstOrDefault(); + var trialTaskConfig = _repository.Where(t => t.Id == queryVisitTask.TrialId).Select(t => new { IsHaveDoubleReadCriterion = t.TrialReadingCriterionList.Any(t => t.IsSigned && t.IsConfirm && t.ReadingType == ReadingMethod.Double), t.VitrualSiteCode }).FirstOrDefault(); return ResponseOutput.Ok(pageList, trialTaskConfig); } @@ -154,7 +154,7 @@ namespace IRaCIS.Core.Application.Service { - var filterObj = await _taskConsistentRuleRepository.Where(t => t.Id == inCommand.TaskConsistentRuleId).Include(t=>t.TrialReadingCriterion).FirstOrDefaultAsync(); + var filterObj = await _taskConsistentRuleRepository.Where(t => t.Id == inCommand.TaskConsistentRuleId).Include(t => t.TrialReadingCriterion).FirstOrDefaultAsync(); var doctorUserId = inCommand.DoctorUserId; var trialReadingCriterionId = filterObj.TrialReadingCriterionId; @@ -169,7 +169,7 @@ namespace IRaCIS.Core.Application.Service throw new BusinessValidationFailedException(_localizer["TaskConsistent_NotAllowedGenerate"]); } - if (subjectList.Count<2 * filterObj.PlanSubjectCount) + if (subjectList.Count < 2 * filterObj.PlanSubjectCount) { throw new BusinessValidationFailedException(_localizer["TaskConsistent_NotAllowedGenerate1"]); } @@ -254,6 +254,17 @@ namespace IRaCIS.Core.Application.Service TaskBlindName = lastTask.TaskBlindName + "_Global", TrialReadingCriterionId = trialReadingCriterionId, }; + + var afterGlobal = _visitTaskRepository.Where(t => t.SubjectId == lastTask.SubjectId && t.TrialReadingCriterionId == trialReadingCriterionId && t.TaskState == TaskState.Effect && t.ReadingCategory == ReadingCategory.Global && t.VisitTaskNum > lastTask.VisitTaskNum).ProjectTo(_mapper.ConfigurationProvider).FirstOrDefault(); + + if (afterGlobal == null) + { + throw new BusinessValidationFailedException("联系后台排查数据,没找到后续全局"); + } + else + { + existGlobal.SouceReadModuleId = afterGlobal.SouceReadModuleId; + } } @@ -294,7 +305,7 @@ namespace IRaCIS.Core.Application.Service /// /// [HttpPost] - public async Task> > GetGroupConsistentRuleSubjectList(GroupConsistentQuery inQuery) + public async Task>> GetGroupConsistentRuleSubjectList(GroupConsistentQuery inQuery) { var trialId = inQuery.TrialId; @@ -304,7 +315,7 @@ namespace IRaCIS.Core.Application.Service if (filterObj == null) { object tt = null; - return ResponseOutput.Ok(new PageOutput(), new { Rule = tt, IsAllowAutoAllocate = false }) ; + return ResponseOutput.Ok(new PageOutput(), new { Rule = tt, IsAllowAutoAllocate = false }); } var query = await GetGroupConsistentQueryAsync(filterObj); @@ -316,9 +327,9 @@ namespace IRaCIS.Core.Application.Service var list = await GetGroupConsistentRuleMatchSubjectIdListAsync(new GroupConsistentSimpleQuery() { TrialId = inQuery.TrialId, TrialReadingCriterionId = inQuery.TrialReadingCriterionId }); - var isAllowAutoAllocate = !list.Any(t => t.IsHaveGeneratedTask) && list.Count() > 2*(rule?.PlanSubjectCount??0); + var isAllowAutoAllocate = !list.Any(t => t.IsHaveGeneratedTask) && list.Count() > 2 * (rule?.PlanSubjectCount ?? 0); - return ResponseOutput.Ok(pagedList, new {Rule=rule, IsAllowAutoAllocate = isAllowAutoAllocate }); + return ResponseOutput.Ok(pagedList, new { Rule = rule, IsAllowAutoAllocate = isAllowAutoAllocate }); } @@ -336,11 +347,11 @@ namespace IRaCIS.Core.Application.Service { var trialId = inCommand.TrialId; - var filterObj = await _taskConsistentRuleRepository.Where(t => t.TrialId == trialId && t.TrialReadingCriterionId == inCommand.TrialReadingCriterionId && t.IsSelfAnalysis == false).Include(t=>t.TrialReadingCriterion).FirstNotNullAsync(); + var filterObj = await _taskConsistentRuleRepository.Where(t => t.TrialId == trialId && t.TrialReadingCriterionId == inCommand.TrialReadingCriterionId && t.IsSelfAnalysis == false).Include(t => t.TrialReadingCriterion).FirstNotNullAsync(); var trialReadingCriterionId = filterObj.TrialReadingCriterionId; - + //随机分配 if (inCommand.IsAutoAllocateGenerateTask) @@ -353,12 +364,12 @@ namespace IRaCIS.Core.Application.Service throw new BusinessValidationFailedException(_localizer["TaskConsistent_NotAllowedGenerate"]); } - if (subjectSelectList.Count< 2 * filterObj.PlanSubjectCount) + if (subjectSelectList.Count < 2 * filterObj.PlanSubjectCount) { throw new BusinessValidationFailedException(_localizer["TaskConsistent_NotAllowedGenerate1"]); } - inCommand.SubejctIdList = subjectSelectList.Select(t => t.SubjectId).ToList().GetRandomCountList(filterObj.PlanSubjectCount) ; + inCommand.SubejctIdList = subjectSelectList.Select(t => t.SubjectId).ToList().GetRandomCountList(filterObj.PlanSubjectCount); } @@ -573,7 +584,7 @@ namespace IRaCIS.Core.Application.Service var subjectQuery = _subjectRepository.Where(t => t.TrialId == trialId && t.SubjectVisitTaskList.AsQueryable().Where(visitTaskFilter).Count() >= filterObj.PlanVisitCount) .WhereIf(filterObj.IsHaveReadingPeriod == true, u => u.SubjectVisitTaskList.AsQueryable().Where(comonTaskFilter) - .Where(t => t.ReadingCategory == ReadingCategory.Visit || t.ReadingCategory == ReadingCategory.Global).Any(t => t.ReadingCategory == ReadingCategory.Global && t.VisitTaskNum>filterObj.PlanVisitCount-1)) + .Where(t => t.ReadingCategory == ReadingCategory.Visit || t.ReadingCategory == ReadingCategory.Global).Any(t => t.ReadingCategory == ReadingCategory.Global && t.VisitTaskNum > filterObj.PlanVisitCount - 1)) ; @@ -684,7 +695,7 @@ namespace IRaCIS.Core.Application.Service t.SubjectVisitTaskList.AsQueryable().Where(visitTaskFilter).GroupBy(t => new { t.SubjectId, t.VisitTaskNum }).Where(g => g.Count() == 2).Count() >= filterObj.PlanVisitCount ) //.WhereIf(filterObj.IsHaveReadingPeriod == true, u => u.SubjectVisitTaskList.AsQueryable().Where(comonTaskFilter).Where(t => t.ReadingCategory == ReadingCategory.Visit || t.ReadingCategory == ReadingCategory.Global).OrderBy(t => t.VisitTaskNum).Take(filterObj.PlanVisitCount * 2 + 2).Any(t => t.ReadingCategory == ReadingCategory.Global)) - .WhereIf(filterObj.IsHaveReadingPeriod == true, u => u.SubjectVisitTaskList.AsQueryable().Where(comonTaskFilter).Where(t => t.ReadingCategory == ReadingCategory.Global && t.VisitTaskNum> filterObj.PlanVisitCount - 1).Select(t => t.DoctorUserId).Distinct().Count() == 2) + .WhereIf(filterObj.IsHaveReadingPeriod == true, u => u.SubjectVisitTaskList.AsQueryable().Where(comonTaskFilter).Where(t => t.ReadingCategory == ReadingCategory.Global && t.VisitTaskNum > filterObj.PlanVisitCount - 1).Select(t => t.DoctorUserId).Distinct().Count() == 2) ; @@ -804,14 +815,14 @@ namespace IRaCIS.Core.Application.Service //全局要>计划访视数量后面 t.SubjectVisitTaskList.AsQueryable().Where(comonTaskFilter) .Where(t => t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId && t.SignTime!.Value.AddDays(taskConsistentRule.IntervalWeeks * 7) < appDateTimeNow && t.DoctorUserId == user.Id) - .Where(t => t.ReadingCategory == ReadingCategory.Visit || t.ReadingCategory == ReadingCategory.Global).Any(t => t.ReadingCategory == ReadingCategory.Global && t.VisitTaskNum>taskConsistentRule.PlanVisitCount-1) + .Where(t => t.ReadingCategory == ReadingCategory.Visit || t.ReadingCategory == ReadingCategory.Global).Any(t => t.ReadingCategory == ReadingCategory.Global && t.VisitTaskNum > taskConsistentRule.PlanVisitCount - 1) && t.SubjectVisitTaskList.AsQueryable().Where(visitTaskFilter) .Where(t => t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId && t.SignTime!.Value.AddDays(taskConsistentRule.IntervalWeeks * 7) < appDateTimeNow && t.DoctorUserId == user.Id) - .Count()>= taskConsistentRule.PlanVisitCount + .Count() >= taskConsistentRule.PlanVisitCount ) - + .Count(), @@ -841,9 +852,9 @@ namespace IRaCIS.Core.Application.Service //var taskConsistentRuleQueryable = _taskConsistentRuleRepository.Where(t => t.TrialId == inQuery.TrialId) // .ProjectTo(_mapper.ConfigurationProvider); - var list= await taskConsistentRuleQueryable.ToListAsync(); + var list = await taskConsistentRuleQueryable.ToListAsync(); - var rule= await _taskConsistentRuleRepository.Where(t => t.TrialId == inQuery.TrialId && t.IsSelfAnalysis == true && t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId).ProjectTo(_mapper.ConfigurationProvider).FirstOrDefaultAsync(); + var rule = await _taskConsistentRuleRepository.Where(t => t.TrialId == inQuery.TrialId && t.IsSelfAnalysis == true && t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId).ProjectTo(_mapper.ConfigurationProvider).FirstOrDefaultAsync(); return ResponseOutput.Ok(list, rule); } @@ -880,7 +891,7 @@ namespace IRaCIS.Core.Application.Service public async Task> GetUpdateVirtualSiteCodeList(Guid trialId) { - var list = await _trialVirtualSiteCodeUpdateRepository.Where(t => t.TrialId == trialId).Select(t => new UpdateTrialSiteCodeCommandView() { TrialId = trialId, VirtualSiteCode = t.VirturalSiteCode, Creatime = t.CreateTime }).OrderByDescending(t=>t.Creatime).ToListAsync(); + var list = await _trialVirtualSiteCodeUpdateRepository.Where(t => t.TrialId == trialId).Select(t => new UpdateTrialSiteCodeCommandView() { TrialId = trialId, VirtualSiteCode = t.VirturalSiteCode, Creatime = t.CreateTime }).OrderByDescending(t => t.Creatime).ToListAsync(); return list; } diff --git a/IRaCIS.Core.Application/Service/Allocation/_MapConfig.cs b/IRaCIS.Core.Application/Service/Allocation/_MapConfig.cs index 510ee9b8b..8ae10c42c 100644 --- a/IRaCIS.Core.Application/Service/Allocation/_MapConfig.cs +++ b/IRaCIS.Core.Application/Service/Allocation/_MapConfig.cs @@ -145,7 +145,7 @@ namespace IRaCIS.Core.Application.Service .ForMember(o => o.HistoryReadingDoctorUserList, t => t.MapFrom(u => u.JudgeVisitList)); CreateMap().IncludeBase() - + .ForMember(o => o.IsHaveFeedBack, t => t.MapFrom(u => u.UserFeedBackList.Any(t=>t.State==0))) ; CreateMap().IncludeBase() diff --git a/IRaCIS.Core.Application/Service/Common/MailService.cs b/IRaCIS.Core.Application/Service/Common/MailService.cs index e34361d6f..fab8dd58f 100644 --- a/IRaCIS.Core.Application/Service/Common/MailService.cs +++ b/IRaCIS.Core.Application/Service/Common/MailService.cs @@ -177,9 +177,7 @@ namespace IRaCIS.Application.Services var topicStr = string.Format(input.topicStr, companyName); var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr), - userName, - _localizer[mfaType == UserMFAType.Login ? "Mail_EmailMFALoginEmail" : "Mail_EmailMFAUnlockEmail"], verificationCode ); @@ -218,7 +216,6 @@ namespace IRaCIS.Application.Services userName, //---您正在进行邮箱重置操作 - _localizer["Mail_ResettingEmail"], verificationCode ); @@ -258,7 +255,6 @@ namespace IRaCIS.Application.Services "Sir/Madam", //---您正在进行邮箱重置密码操作 - _localizer["Mail_ResettingPassword"], verificationCode ); @@ -302,7 +298,7 @@ namespace IRaCIS.Application.Services "Sir/Madam", //---您正在参与展影医疗IRC项目 - _localizer["Mail_IRCProject", companyName], + companyName, verificationCode ); @@ -344,7 +340,7 @@ namespace IRaCIS.Application.Services "Sir/Madam", //---您正在参与展影医疗IRC项目中心调研工作 - _localizer["Mail_CenterResearchReminder", companyName], + companyName, verificationCode ); diff --git a/IRaCIS.Core.Application/Service/ImageAndDoc/DTO/UnionStudyViewDodel.cs b/IRaCIS.Core.Application/Service/ImageAndDoc/DTO/UnionStudyViewDodel.cs index 6be7f1de5..24982f635 100644 --- a/IRaCIS.Core.Application/Service/ImageAndDoc/DTO/UnionStudyViewDodel.cs +++ b/IRaCIS.Core.Application/Service/ImageAndDoc/DTO/UnionStudyViewDodel.cs @@ -214,6 +214,20 @@ namespace IRaCIS.Core.Application.Contracts public int FileCount { get; set; } } + + public class SubejctZipInfoQuery + { + public Guid? SubejctId { get; set; } + + public string? SubjectCode { get; set; } + + + public Guid? SubejectVisitId { get; set; } + + public Guid? TrialReadingCriterionId { get; set; } + + } + public class TaskArchiveStudyCommand { [NotDefault] diff --git a/IRaCIS.Core.Application/Service/ImageAndDoc/DownloadAndUploadService.cs b/IRaCIS.Core.Application/Service/ImageAndDoc/DownloadAndUploadService.cs index 9f71bad89..acf4c3dd5 100644 --- a/IRaCIS.Core.Application/Service/ImageAndDoc/DownloadAndUploadService.cs +++ b/IRaCIS.Core.Application/Service/ImageAndDoc/DownloadAndUploadService.cs @@ -4,6 +4,7 @@ using IRaCIS.Core.Application.Contracts; using IRaCIS.Core.Application.Filter; using IRaCIS.Core.Application.Helper; using IRaCIS.Core.Application.Service.ImageAndDoc.DTO; +using IRaCIS.Core.Domain.Models; using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Infrastructure; using IRaCIS.Core.Infrastructure.Extention; @@ -11,6 +12,7 @@ using MassTransit; using MathNet.Numerics; using Medallion.Threading; using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal; using Newtonsoft.Json; using System; using System.Collections.Generic; @@ -536,36 +538,134 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc - public async Task GetSubejectVisitPathInfo(Guid subjectVisitId) + /// + /// 受试者级别所有的影像 + /// 访视级别的影响 传递subjectVisitId + /// 标准Id是可选的 不同标准有些检查可能有过滤 + /// + /// + /// + /// + public async Task GetSubejectOrVisitZipInfo([FromServices] IRepository _subjectRepository, SubejctZipInfoQuery inQuery) { - var query = from sv in _subjectVisitRepository.Where(t => t.Id == subjectVisitId) + var isImageFilter = false; - select new - { - SubjectCode = sv.Subject.Code, - VisitName = sv.VisitName, - StudyList = sv.StudyList.Select(u => new + var criterionModalitys = string.Empty; + + if (inQuery.TrialReadingCriterionId != null) + { + var criterionInfo = await _repository.Where(t => t.Id == inQuery.TrialReadingCriterionId).Select(t => new { t.IsImageFilter, t.CriterionModalitys }).FirstOrDefaultAsync(); + + if (criterionInfo != null) + { + isImageFilter = criterionInfo.IsImageFilter; + criterionModalitys = criterionInfo.CriterionModalitys; + } + + } + + if (inQuery.SubejectVisitId != null) + { + var query = from sv in _subjectVisitRepository.Where(t => t.Id == inQuery.SubejectVisitId) + + + select new { - u.PatientId, - u.StudyTime, - u.StudyCode, - - SeriesList = u.SeriesList.Select(z => new + SubjectCode = sv.Subject.Code, + VisitName = sv.VisitName, + StudyList = sv.StudyList.AsQueryable().WhereIf(isImageFilter, t => ("|" + criterionModalitys + "|").Contains("|" + t.ModalityForEdit + "|")) + .Select(u => new { - z.Modality, + u.PatientId, + u.StudyTime, + u.StudyCode, - InstancePathList = z.DicomInstanceList.Select(k => new + SeriesList = u.SeriesList.Select(z => new { - k.Path + z.Modality, + + InstancePathList = z.DicomInstanceList.Select(k => new + { + k.Path + }) + }) + + }), + + NoneDicomStudyList = sv.NoneDicomStudyList.AsQueryable().WhereIf(isImageFilter, t => ("|" + criterionModalitys + "|").Contains("|" + t.Modality + "|")) + .Select(nd => new + { + nd.Modality, + nd.StudyCode, + nd.ImageDate, + + FileList = nd.NoneDicomFileList.Select(file => new + { + file.FileName, + file.Path, + file.FileType }) }) + }; - }) - }; + var result = query.ToList(); + + return ResponseOutput.Ok(result); + } + else if (inQuery.SubejctId != null) + { + var query = from sv in _subjectRepository.Where(t => t.Id == inQuery.SubejctId).SelectMany(t=>t.SubjectVisitList) + + + select new + { + SubjectCode = sv.Subject.Code, + VisitName = sv.VisitName, + StudyList = sv.StudyList.AsQueryable().WhereIf(isImageFilter, t => ("|" + criterionModalitys + "|").Contains("|" + t.ModalityForEdit + "|")) + .Select(u => new + { + u.PatientId, + u.StudyTime, + u.StudyCode, + + SeriesList = u.SeriesList.Select(z => new + { + z.Modality, + + InstancePathList = z.DicomInstanceList.Select(k => new + { + k.Path + }) + }) + + }), + + NoneDicomStudyList = sv.NoneDicomStudyList.AsQueryable().WhereIf(isImageFilter, t => ("|" + criterionModalitys + "|").Contains("|" + t.Modality + "|")) + .Select(nd => new + { + nd.Modality, + nd.StudyCode, + nd.ImageDate, + + FileList = nd.NoneDicomFileList.Select(file => new + { + file.FileName, + file.Path, + file.FileType + }) + }) + }; + + var result = query.ToList(); + + return ResponseOutput.Ok(result); + } + else + { + return ResponseOutput.NotOk("不允许 subjectId subjectId 都不传递"); + } - var info = query.FirstOrDefault(); - return ResponseOutput.Ok(info); } /// @@ -765,9 +865,9 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc foreach (var file in noneDicomStudy.FileList) { string destinationPath = Path.Combine(studyNoneDicomFolderPath, Path.GetFileName(file.FileName)); - + //下载到当前目录 - await _oSSService.DownLoadFromOSSAsync(HttpUtility.UrlDecode(file.Path) , destinationPath); + await _oSSService.DownLoadFromOSSAsync(HttpUtility.UrlDecode(file.Path), destinationPath); } } diff --git a/IRaCIS.Core.Application/Service/Management/DTO/UserFeedBackViewModel.cs b/IRaCIS.Core.Application/Service/Management/DTO/UserFeedBackViewModel.cs index 14a6fcd70..51bc992bb 100644 --- a/IRaCIS.Core.Application/Service/Management/DTO/UserFeedBackViewModel.cs +++ b/IRaCIS.Core.Application/Service/Management/DTO/UserFeedBackViewModel.cs @@ -67,6 +67,8 @@ namespace IRaCIS.Core.Application.ViewModel public DateTime? EndCreatime { get; set; } + public Guid? TrialId { get; set; } + } diff --git a/IRaCIS.Core.Application/Service/Management/UserFeedBackService.cs b/IRaCIS.Core.Application/Service/Management/UserFeedBackService.cs index a9217b6a5..5a950602d 100644 --- a/IRaCIS.Core.Application/Service/Management/UserFeedBackService.cs +++ b/IRaCIS.Core.Application/Service/Management/UserFeedBackService.cs @@ -36,6 +36,7 @@ namespace IRaCIS.Core.Application.Service var userFeedBackQueryable = _userFeedBackRepository .WhereIf(isCRCOrIR, t => t.CreateUserId == _userInfo.Id) .WhereIf(inQuery.State != null, t => t.State == inQuery.State) + .WhereIf(inQuery.TrialId != null, t => t.TrialId == inQuery.TrialId) .WhereIf(inQuery.QuestionType != null, t => t.QuestionType == inQuery.QuestionType) .WhereIf(inQuery.BeginCreatime != null, t => t.CreateTime >= inQuery.BeginCreatime) diff --git a/IRaCIS.Core.Application/Service/QC/DTO/QCListViewModel.cs b/IRaCIS.Core.Application/Service/QC/DTO/QCListViewModel.cs index 2db5966a6..3a4ba042c 100644 --- a/IRaCIS.Core.Application/Service/QC/DTO/QCListViewModel.cs +++ b/IRaCIS.Core.Application/Service/QC/DTO/QCListViewModel.cs @@ -62,6 +62,10 @@ namespace IRaCIS.Core.Application.Contracts //public string VisitPlanInfo { get; set; } = String.Empty; public Guid? HandleUserId { get; set; } + + public DateTime? BeginAuditTime { get; set; } + + public DateTime? EndAuditTime { get; set; } } public class GetNextIQCQualityInDto @@ -187,6 +191,13 @@ namespace IRaCIS.Core.Application.Contracts public string SubmitUserName { get; set; } + + public TrialQCProcess QCProcessEnum { get; set; } + + public DateTime? ReviewAuditTime { get; set; } + public DateTime? PreliminaryAuditTime { get; set; } + + public DateTime? AuditTime => QCProcessEnum == TrialQCProcess.SingleAudit ? PreliminaryAuditTime : (QCProcessEnum == TrialQCProcess.DoubleAudit ? ReviewAuditTime : null); } @@ -1110,6 +1121,9 @@ namespace IRaCIS.Core.Application.Contracts public bool IsHaveUploadFailed { get; set; } + + + } public class GetNextCRCChallengeInDto @@ -1415,8 +1429,7 @@ namespace IRaCIS.Core.Application.Contracts public string ReviewAuditUserName { get; set; } = String.Empty; - public DateTime? ReviewAuditTime { get; set; } - public DateTime? PreliminaryAuditTime { get; set; } + public bool IsEnrollmentConfirm { get; set; } = false; public DateTime? SubjectFirstGiveMedicineTime { get; set; } @@ -1491,6 +1504,12 @@ namespace IRaCIS.Core.Application.Contracts public PackState PackState { get; set; } //public Guid? ClinicalDataSignUserId { get; set; } + + public DateTime? ReviewAuditTime { get; set; } + public DateTime? PreliminaryAuditTime { get; set; } + + + public DateTime? AuditTime => QCProcessEnum == TrialQCProcess.SingleAudit ? PreliminaryAuditTime : (QCProcessEnum == TrialQCProcess.DoubleAudit ? ReviewAuditTime : null); } diff --git a/IRaCIS.Core.Application/Service/QC/QCListService.cs b/IRaCIS.Core.Application/Service/QC/QCListService.cs index 4ec4e93bf..dd1e1d662 100644 --- a/IRaCIS.Core.Application/Service/QC/QCListService.cs +++ b/IRaCIS.Core.Application/Service/QC/QCListService.cs @@ -235,7 +235,7 @@ namespace IRaCIS.Core.Application.Image.QA PageSize = 1, }); - return result.Item1.CurrentPageData.Count > 0 ? result.Item1.CurrentPageData[0] : null; + return result.Data.CurrentPageData.Count > 0 ? result.Data.CurrentPageData[0] : null; } /// @@ -244,7 +244,7 @@ namespace IRaCIS.Core.Application.Image.QA /// /// [HttpPost] - public async Task<(PageOutput, TrialSubjectAndSVConfig)> GetQCVisitList(QCVisitSearchDTO visitSearchDTO) + public async Task>> GetQCVisitList(QCVisitSearchDTO visitSearchDTO) { var svExpression = QCCommon.GetSubjectVisitFilter(visitSearchDTO.VisitPlanArray); @@ -266,6 +266,12 @@ namespace IRaCIS.Core.Application.Image.QA || t.QCChallengeDialogList.Any(t => t.CreateUserId == visitSearchDTO.HandleUserId)) .WhereIf(visitSearchDTO.IsUrgent != null, t => t.IsUrgent == visitSearchDTO.IsUrgent) .Where(t => t.SubmitState != SubmitStateEnum.None) + .WhereIf(visitSearchDTO.BeginAuditTime != null, t => t.Trial.QCProcessEnum==TrialQCProcess.SingleAudit? t.PreliminaryAuditTime>= visitSearchDTO.BeginAuditTime: + (t.Trial.QCProcessEnum == TrialQCProcess.DoubleAudit?t.ReviewAuditTime>= visitSearchDTO.BeginAuditTime:true)) + + .WhereIf(visitSearchDTO.EndAuditTime != null, t => t.Trial.QCProcessEnum == TrialQCProcess.SingleAudit ? t.PreliminaryAuditTime <= visitSearchDTO.EndAuditTime : + (t.Trial.QCProcessEnum == TrialQCProcess.DoubleAudit ? t.ReviewAuditTime <= visitSearchDTO.EndAuditTime : true)) + //.WhereIf(visitSearchDTO.SubmitState != null, t => t.SubmitState == visitSearchDTO.SubmitState) //.WhereIf(visitSearchDTO.ChallengeState != null, t => t.ChallengeState == visitSearchDTO.ChallengeState) .ProjectTo(_mapper.ConfigurationProvider); @@ -279,7 +285,7 @@ namespace IRaCIS.Core.Application.Image.QA var config = await _repository.Where(t => t.Id == visitSearchDTO.TrialId).ProjectTo(_mapper.ConfigurationProvider).FirstOrDefaultAsync().IfNullThrowException(); - return (pageList, config); + return ResponseOutput.Ok (pageList, config); } diff --git a/IRaCIS.Core.Application/Service/QC/QCOperationService.cs b/IRaCIS.Core.Application/Service/QC/QCOperationService.cs index d67743443..3bccf5c80 100644 --- a/IRaCIS.Core.Application/Service/QC/QCOperationService.cs +++ b/IRaCIS.Core.Application/Service/QC/QCOperationService.cs @@ -707,7 +707,7 @@ namespace IRaCIS.Core.Application.Image.QA } else { - if (await _subjectVisitRepository.AnyAsync(t => t.Id == updateModalityCommand.SubjectVisitId && t.SubmitState == SubmitStateEnum.Submitted)) + if (await _subjectVisitRepository.AnyAsync(t => t.Id == updateModalityCommand.SubjectVisitId && t.SubmitState == SubmitStateEnum.Submitted && !t.QCChallengeList.Any(c=>c.ReuploadEnum==QCChanllengeReuploadEnum.QCAgreeUpload)) ) { //---提交之后,不允许修改! throw new BusinessValidationFailedException(_localizer["QCOperation_NoModifyAfterSubmit"]); diff --git a/IRaCIS.Core.Application/Service/QC/_MapConfig.cs b/IRaCIS.Core.Application/Service/QC/_MapConfig.cs index 2110ce0bd..b5c088c66 100644 --- a/IRaCIS.Core.Application/Service/QC/_MapConfig.cs +++ b/IRaCIS.Core.Application/Service/QC/_MapConfig.cs @@ -22,6 +22,7 @@ namespace IRaCIS.Core.Application.Service CreateMap(); CreateMap() .ForMember(d => d.TrialSiteCode, u => u.MapFrom(s => s.TrialSite.TrialSiteCode)) + .ForMember(d => d.QCProcessEnum, u => u.MapFrom(s => s.Trial.QCProcessEnum)) .ForMember(d => d.SubjectCode, u => u.MapFrom(s => s.Subject.Code)) .ForMember(d => d.SubmitUserName, u => u.MapFrom(s => s.SubmitUser.FullName)) diff --git a/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/TrialViewModel.cs b/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/TrialViewModel.cs index a25cf7e19..93469cbcf 100644 --- a/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/TrialViewModel.cs +++ b/IRaCIS.Core.Application/Service/TrialSiteUser/DTO/TrialViewModel.cs @@ -159,6 +159,7 @@ namespace IRaCIS.Application.Contracts //public int? StudyCount { get; set; } = 0; //public int? SiteCount { get; set; } = 0; + public int? UserFeedBackUnDealedCount { get; set; } } diff --git a/IRaCIS.Core.Application/Service/TrialSiteUser/_MapConfig.cs b/IRaCIS.Core.Application/Service/TrialSiteUser/_MapConfig.cs index 461523bfa..9a3326db6 100644 --- a/IRaCIS.Core.Application/Service/TrialSiteUser/_MapConfig.cs +++ b/IRaCIS.Core.Application/Service/TrialSiteUser/_MapConfig.cs @@ -77,6 +77,9 @@ namespace IRaCIS.Core.Application.Service .ForMember(d => d.ReviewMode, u => u.MapFrom(s => isEn_Us ? s.ReviewMode.Value : s.ReviewMode.ValueCN)) //.ForMember(d => d.ReviewType, u => u.MapFrom(s => s.ReviewType.Value)) .ForMember(d => d.IsLocked, u => u.MapFrom(s => s.WorkloadList.Any(u => u.DataFrom == (int)WorkLoadFromStatus.FinalConfirm))) + .ForMember(d => d.UserFeedBackUnDealedCount, u => u.MapFrom(s => s.UserFeedBackList.Count(t=>t.State==0))) + + //.ForMember(d => d.SiteCount, u => u.MapFrom(s => userTypeEnumInt == (int)UserTypeEnum.ClinicalResearchCoordinator ? s.TrialSiteUserList.Count(k => k.UserId == userId) : s.TrialSiteList.Count())) //.ForMember(d => d.StudyCount, u => u.MapFrom(s => userTypeEnumInt == (int)UserTypeEnum.ClinicalResearchCoordinator ? s.StudyList.Count(t => t.TrialSite.CRCUserList.Any(t => t.UserId == userId)) : s.StudyList.Count())) //.ForMember(d => d.SubjectCount, u => u.MapFrom(s => userTypeEnumInt == (int)UserTypeEnum.ClinicalResearchCoordinator ? s.SubjectList.Count(t => t.TrialSite.CRCUserList.Any(t => t.UserId == userId)) : s.SubjectList.Count())) diff --git a/IRaCIS.Core.Domain/Allocation/VisitTask.cs b/IRaCIS.Core.Domain/Allocation/VisitTask.cs index 77516f056..5a45dd3c4 100644 --- a/IRaCIS.Core.Domain/Allocation/VisitTask.cs +++ b/IRaCIS.Core.Domain/Allocation/VisitTask.cs @@ -436,5 +436,8 @@ namespace IRaCIS.Core.Domain.Models public int ImageStudyState { get; set; } + [JsonIgnore] + public List UserFeedBackList { get; set; } + } } diff --git a/IRaCIS.Core.Domain/Trial/Trial.cs b/IRaCIS.Core.Domain/Trial/Trial.cs index 2160203ab..f2dc183c9 100644 --- a/IRaCIS.Core.Domain/Trial/Trial.cs +++ b/IRaCIS.Core.Domain/Trial/Trial.cs @@ -59,8 +59,8 @@ namespace IRaCIS.Core.Domain.Models public List TrialSiteUserList { get; set; } = new List(); [JsonIgnore] public List ReadModuleList { get; set; } = new List(); - - + [JsonIgnore] + public List UserFeedBackList { get; set; } = new List(); public Guid IndicationTypeId { get; set; } = Guid.Empty; public Guid? PhaseId { get; set; } = Guid.Empty; diff --git a/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs b/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs index f81edd5f5..44a2ad291 100644 --- a/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs +++ b/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs @@ -24,33 +24,41 @@ using IRaCIS.Core.Infrastructure; namespace IRaCIS.Core.Infra.EFCore { + /// + /// 报错,添加subject 报错,重复添加访视 + /// + //public class IRaCISDBScopedFactory : IDbContextFactory + //{ + + // private readonly IDbContextFactory _pooledFactory; + // private readonly IUserInfo _userInfo; + + // public IRaCISDBScopedFactory(IDbContextFactory pooledFactory,IUserInfo userInfo) + // { + // _pooledFactory = pooledFactory; + // _userInfo = userInfo; + // } + + // public IRaCISDBContext CreateDbContext() + // { + // var context = _pooledFactory.CreateDbContext(); + // context._userInfo = _userInfo; + // return context; + // } + //} + public class IRaCISDBContext : DbContext { - public readonly IUserInfo _userInfo; + private IUserInfo _userInfo; - public readonly ILogger _logger; - // 在控制台 - //public static readonly ILoggerFactory MyLoggerFactory = LoggerFactory.Create(builder => { builder.AddConsole(); }); - // 调试窗口 - public static readonly ILoggerFactory MyLoggerFactory = LoggerFactory.Create(builder => { builder.AddDebug(); }); + private readonly ILogger _logger; public IRaCISDBContext(DbContextOptions options, IUserInfo userInfo, ILogger logger ) : base(options) { - _logger= logger; - _userInfo = userInfo; - - } - - - //比数据库上下文构造函数先执行 不能构造函数注入的方式使用配置文件 - protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) - { - optionsBuilder.UseLoggerFactory(MyLoggerFactory); - - optionsBuilder.UseExceptionProcessor(); - + _userInfo= userInfo; + _logger = logger; }