diff --git a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml index 541009056..36b4996e2 100644 --- a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml +++ b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml @@ -3834,14 +3834,14 @@ 阅片平台 - + - 任务组织级别 + 阅片平台 - + - 影像是否有标注 + 全局阅片 @@ -3856,87 +3856,57 @@ - 仲裁规则/对象 + 仲裁规则 - + - pageId + 阅片模式 - + - 项目ID + 仲裁阅片 - + - 分页名称 + 肿瘤学阅片 - + - 是否启用 + 读片任务显示是否顺序 - + - 是否公共分页 + 任务组织级别 - + - 创建时间 + 图像是否有标注 - + - 创建用户ID + 阅片是否显示受试者信息 - + - 排序 + 阅片是否显示既往结果 - + - 分页名称 + 项目标准集合 - + - 问题名称 - - - - - 类型 - - - - - 父问题触发 - - - - - 父问题名称 - - - - - 是否是必须 - - - - - 类型值 - - - - - 是否启用 + 项目裁判问题集合 @@ -3964,64 +3934,34 @@ 答案组合 - + - 裁判类型 + 项目ID - + - 问题名称 + 阅片方式 - + - 答案分组 + 阅片平台 - + - 答案组合 + 全局阅片 - + - 裁判类型 + 阅片模式 - + - 标准 - - - - - 修约小数点 - - - - - 项目标准Id - - - - - 项目分页 - - - - - 项目问题集合 - - - - - 表单类型 - - - - - 修约小数点 + 仲裁阅片 @@ -4051,7 +3991,7 @@ - IR阅片是否显示既往结果 + 阅片是否显示既往结果 diff --git a/IRaCIS.Core.Application/Service/Allocation/VisitTaskHelpeService.cs b/IRaCIS.Core.Application/Service/Allocation/VisitTaskHelpeService.cs index 6811e2ba1..03191e0ec 100644 --- a/IRaCIS.Core.Application/Service/Allocation/VisitTaskHelpeService.cs +++ b/IRaCIS.Core.Application/Service/Allocation/VisitTaskHelpeService.cs @@ -105,7 +105,7 @@ namespace IRaCIS.Core.Application.Service IsUrgent = subjectVisit.IsUrgent, TaskBlindName = subjectVisit.BlindName, TaskName = subjectVisit.VisitName, - VisitTaskNum=subjectVisit.VisitNum, + VisitTaskNum = subjectVisit.VisitNum, //CheckPassedTime = subjectVisit.CheckPassedTime, ArmEnum = Arm.DoubleReadingArm1,//特殊 Code = currentMaxCodeInt + 1, @@ -132,7 +132,7 @@ namespace IRaCIS.Core.Application.Service currentMaxCodeInt = currentMaxCodeInt + 2; - _provider.Set($"{trialId}_{StaticData.CacheKey.TaskMaxCode}", currentMaxCodeInt , TimeSpan.FromMinutes(30)); + _provider.Set($"{trialId}_{StaticData.CacheKey.TaskMaxCode}", currentMaxCodeInt, TimeSpan.FromMinutes(30)); #region 分配 @@ -142,69 +142,90 @@ namespace IRaCIS.Core.Application.Service if (trialConfig.TaskAllocateObjEnum == TaskAllocateObj.Subject) { + var allocateSubjectArmList = _visitTaskRepository.Where(t => t.SubjectId == subjectVisit.SubjectId && t.TrialId == trialId && t.DoctorUserId != null && t.ArmEnum != Arm.JudgeArm) + .Select(t => new { t.DoctorUserId, t.ArmEnum }).Distinct().ToList(); - if (trialConfig.IsFollowVisitAutoAssign) + + + //不是初次分配 直接分配给Subject 之前的医生 + if (allocateSubjectArmList.Count != 0) { - #region 验证历史任务 - - var allocateSubjectArmList = _visitTaskRepository.Where(t => t.SubjectId == subjectVisit.SubjectId && t.TrialId == trialId && t.DoctorUserId != null && t.ArmEnum != Arm.JudgeArm) - .Select(t => new { t.DoctorUserId, t.ArmEnum }).Distinct().ToList(); - - - //不是初次分配 直接分配给Subject 之前的医生 - if (allocateSubjectArmList.Count != 0) + if (_taskAllocationRuleRepository.Where(t => t.TrialId == trialId && t.IsEnable && t.IsJudgeDoctor == false).Count() < 2) { - if (_taskAllocationRuleRepository.Where(t => t.TrialId == trialId && t.IsEnable && t.IsJudgeDoctor == false).Count() < 2) - { - throw new BusinessValidationFailedException("能参与读片的医生数量必须大于2,自动分配任务中止"); - } + throw new BusinessValidationFailedException("能参与读片的医生数量必须大于2,自动分配任务中止"); + } - if (allocateSubjectArmList.GroupBy(t => t.DoctorUserId).Any(g => g.Count() == 2)) - { - throw new BusinessValidationFailedException("请确认是否改了配置,导致同一受试者 分配给同一个医生 在不同的Arm,无法完成自动分配"); - } - - //手动分配的时候 如果只分配了Arm1 没有分配Arm2 就会有问题 - if (!(allocateSubjectArmList.Any(t => t.ArmEnum == Arm.DoubleReadingArm1) && allocateSubjectArmList.Any(t => t.ArmEnum == Arm.DoubleReadingArm2))) - { - throw new BusinessValidationFailedException("请确认是否改了配置,或者手动分配时,只分配了一个Arm "); - } - - //配置了医生 - if (assignConfigList.Count > 0) - { - var defaultState = trialConfig.FollowVisitAutoAssignDefaultState == TaskAllocateDefaultState.InitAllocated ? TaskAllocationState.InitAllocated : TaskAllocationState.Allocated; - - - task1.TaskAllocationState = defaultState; - task2.TaskAllocationState = defaultState; - - //分配给对应Arm的人 - task1.DoctorUserId = assignConfigList.FirstOrDefault(t => t.ArmEnum == Arm.DoubleReadingArm1).DoctorUserId; - task2.DoctorUserId = assignConfigList.FirstOrDefault(t => t.ArmEnum == Arm.DoubleReadingArm1).DoctorUserId; - } + if (allocateSubjectArmList.GroupBy(t => t.DoctorUserId).Any(g => g.Count() == 2)) + { + throw new BusinessValidationFailedException("请确认是否改了配置,导致同一受试者 分配给同一个医生 在不同的Arm,无法完成自动分配"); + } + //手动分配的时候 如果只分配了Arm1 没有分配Arm2 就会有问题 + if (!(allocateSubjectArmList.Any(t => t.ArmEnum == Arm.DoubleReadingArm1) && allocateSubjectArmList.Any(t => t.ArmEnum == Arm.DoubleReadingArm2))) + { + throw new BusinessValidationFailedException("请确认是否改了配置,或者手动分配时,只分配了一个Arm "); } #endregion + //并且配置了医生 + if (assignConfigList.Count > 0 && trialConfig.IsFollowVisitAutoAssign) + { + var defaultState = trialConfig.FollowVisitAutoAssignDefaultState == TaskAllocateDefaultState.InitAllocated ? TaskAllocationState.InitAllocated : TaskAllocationState.Allocated; + + + task1.TaskAllocationState = defaultState; + task2.TaskAllocationState = defaultState; + + //分配给对应Arm的人 + task1.DoctorUserId = assignConfigList.FirstOrDefault(t => t.ArmEnum == Arm.DoubleReadingArm1).DoctorUserId; + task2.DoctorUserId = assignConfigList.FirstOrDefault(t => t.ArmEnum == Arm.DoubleReadingArm2).DoctorUserId; + + task1.AllocateTime = DateTime.Now; + task2.AllocateTime = DateTime.Now; + } + else + //后续访视不自动分配,或者配置的医生数量不足,就不进行分配 + { + + } + + #region 重阅/退回的时候,需要将之前取消分配的访视类型的 任务重新分配 + + var arm1DoctorUserId = assignConfigList.FirstOrDefault(t => t.ArmEnum == Arm.DoubleReadingArm1).DoctorUserId; + var arm2DoctorUserId = assignConfigList.FirstOrDefault(t => t.ArmEnum == Arm.DoubleReadingArm2).DoctorUserId; + + await _visitTaskRepository.UpdatePartialFromQueryAsync(t => t.TrialId == trialId && t.SubjectId == subjectVisit.SubjectId && t.TaskState == TaskState.Effect && t.DoctorUserId == null + && t.VisitTaskNum > subjectVisit.VisitNum && t.ReadingCategory == ReadingCategory.Visit && t.ArmEnum == Arm.DoubleReadingArm1, u => new VisitTask() + { + TaskAllocationState=TaskAllocationState.Allocated, + DoctorUserId= arm1DoctorUserId, + AllocateTime=DateTime.Now, + }); + + await _visitTaskRepository.UpdatePartialFromQueryAsync(t => t.TrialId == trialId && t.SubjectId == subjectVisit.SubjectId && t.TaskState == TaskState.Effect && t.DoctorUserId == null && t.VisitTaskNum > subjectVisit.VisitNum && t.ReadingCategory == ReadingCategory.Visit && t.ArmEnum == Arm.DoubleReadingArm2, u => new VisitTask() + { + TaskAllocationState = TaskAllocationState.Allocated, + DoctorUserId = arm2DoctorUserId, + AllocateTime = DateTime.Now, + }); + + #endregion + + + } - - //找到配置规则表 进行分配 - - else + // 当前任务没有分配医生,初次分配 { - //后续Subect 不自动分配 不处理 return; } } - task1.AllocateTime = DateTime.Now; - task2.AllocateTime = DateTime.Now; + } @@ -234,7 +255,7 @@ namespace IRaCIS.Core.Application.Service currentMaxCodeInt = currentMaxCodeInt + 1; - _provider.Set($"{trialId}_{StaticData.CacheKey.TaskMaxCode}", currentMaxCodeInt , TimeSpan.FromMinutes(30)); + _provider.Set($"{trialId}_{StaticData.CacheKey.TaskMaxCode}", currentMaxCodeInt, TimeSpan.FromMinutes(30)); #region 分配 @@ -300,57 +321,62 @@ namespace IRaCIS.Core.Application.Service //foreach (var reReadingVisitTask in generateTaskCommand.ReReadingTaskList) //{ - //reReadingVisitTask.OriginalReReadingId = reReadingVisitTask.Id; - //reReadingVisitTask.Id = Guid.Empty; - //reReadingVisitTask.SignTime = null; - //reReadingVisitTask.AllocateTime = null; + //reReadingVisitTask.OriginalReReadingId = reReadingVisitTask.Id; + //reReadingVisitTask.Id = Guid.Empty; + //reReadingVisitTask.SignTime = null; + //reReadingVisitTask.AllocateTime = null; - //reReadingVisitTask.RequestReReadingReason = generateTaskCommand.ReReadingApplyGenerateTaskCommand.RequestReReadingReason; - //reReadingVisitTask.RequestReReadingType = generateTaskCommand.ReReadingApplyGenerateTaskCommand.RequestReReadingType; - //reReadingVisitTask.RequestReReadingUserId = _userInfo.Id; + //reReadingVisitTask.RequestReReadingReason = generateTaskCommand.ReReadingApplyGenerateTaskCommand.RequestReReadingReason; + //reReadingVisitTask.RequestReReadingType = generateTaskCommand.ReReadingApplyGenerateTaskCommand.RequestReReadingType; + //reReadingVisitTask.RequestReReadingUserId = _userInfo.Id; - //reReadingVisitTask.Code = currentMaxCodeInt + 1; - //reReadingVisitTask.TaskCode = AppSettings.GetCodeStr(currentMaxCodeInt + 1, nameof(VisitTask)); + //reReadingVisitTask.Code = currentMaxCodeInt + 1; + //reReadingVisitTask.TaskCode = AppSettings.GetCodeStr(currentMaxCodeInt + 1, nameof(VisitTask)); - // await _visitTaskRepository.AddAsync(reReadingVisitTask); + // await _visitTaskRepository.AddAsync(reReadingVisitTask); - var newTask = await _visitTaskRepository.AddAsync(new VisitTask() - { + var newTask = await _visitTaskRepository.AddAsync(new VisitTask() + { - TrialId = reReadingVisitTask.TrialId, - SubjectId = reReadingVisitTask.SubjectId, - ArmEnum = reReadingVisitTask.ArmEnum, - TaskName = reReadingVisitTask.TaskName, - TaskBlindName = reReadingVisitTask.TaskBlindName, + TrialId = reReadingVisitTask.TrialId, + SubjectId = reReadingVisitTask.SubjectId, + ArmEnum = reReadingVisitTask.ArmEnum, + TaskName = reReadingVisitTask.TaskName, + TaskBlindName = reReadingVisitTask.TaskBlindName, - VisitTaskNum = reReadingVisitTask.VisitTaskNum, - ReadingCategory = reReadingVisitTask.ReadingCategory, - SourceSubjectVisitId = reReadingVisitTask.SourceSubjectVisitId, - SouceReadModuleId = reReadingVisitTask.SouceReadModuleId, + VisitTaskNum = reReadingVisitTask.VisitTaskNum, + ReadingCategory = reReadingVisitTask.ReadingCategory, + SourceSubjectVisitId = reReadingVisitTask.SourceSubjectVisitId, + SouceReadModuleId = reReadingVisitTask.SouceReadModuleId, - IsReReadingCreate = true, - TaskState = TaskState.Effect, - Code = currentMaxCodeInt + 1, - TaskCode = AppSettings.GetCodeStr(currentMaxCodeInt + 1, nameof(VisitTask)), + IsReReadingCreate = true, + TaskState = TaskState.Effect, + Code = currentMaxCodeInt + 1, + TaskCode = AppSettings.GetCodeStr(currentMaxCodeInt + 1, nameof(VisitTask)), - // TaskAllocationState = reReadingVisitTask.TaskAllocationState, - // AllocateTime = DateTime.Now, - //DoctorUserId = reReadingVisitTask.DoctorUserId, + IsAnalysisCreate = reReadingVisitTask.IsAnalysisCreate, + IsSelfAnalysis =reReadingVisitTask.IsSelfAnalysis, + BlindSubjectCode=reReadingVisitTask.BlindSubjectCode, + BlindTrialSiteCode=reReadingVisitTask.BlindTrialSiteCode - }); + // TaskAllocationState = reReadingVisitTask.TaskAllocationState, + // AllocateTime = DateTime.Now, + //DoctorUserId = reReadingVisitTask.DoctorUserId, - generateTaskCommand.Action(newTask); + }); + + generateTaskCommand.Action(newTask); - //await _visitTaskReReadingRepository.BatchUpdateNoTrackingAsync(t=>t.) + //await _visitTaskReReadingRepository.BatchUpdateNoTrackingAsync(t=>t.) - //是否增加任务类别 + //是否增加任务类别 - currentMaxCodeInt = currentMaxCodeInt + 1; + currentMaxCodeInt = currentMaxCodeInt + 1; - _provider.Set($"{trialId}_{StaticData.CacheKey.TaskMaxCode}", currentMaxCodeInt, TimeSpan.FromMinutes(30)); + _provider.Set($"{trialId}_{StaticData.CacheKey.TaskMaxCode}", currentMaxCodeInt, TimeSpan.FromMinutes(30)); //} @@ -382,7 +408,7 @@ namespace IRaCIS.Core.Application.Service BlindTrialSiteCode = task.BlindTrialSiteCode, BlindSubjectCode = task.BlindSubjectCode, - ConsistentAnalysisOriginalTaskId = task.Id , + ConsistentAnalysisOriginalTaskId = task.Id, IsSelfAnalysis = true, @@ -411,19 +437,19 @@ namespace IRaCIS.Core.Application.Service VisitTaskNum = task.VisitTaskNum, ReadingCategory = task.ReadingCategory, - + IsAnalysisCreate = true, TaskState = TaskState.Effect, Code = currentMaxCodeInt + 1, TaskCode = AppSettings.GetCodeStr(currentMaxCodeInt + 1, nameof(VisitTask)), DoctorUserId = task.DoctorUserId, - TaskAllocationState = TaskAllocationState.Allocated, + TaskAllocationState = TaskAllocationState.Allocated, AllocateTime = DateTime.Now, - - IsSelfAnalysis= false, + + IsSelfAnalysis = false, }; @@ -442,24 +468,24 @@ namespace IRaCIS.Core.Application.Service var subjectUser = await _subjectUserRepository.Where(x => x.SubjectId == firstTask.SubjectId && x.ArmEnum == Arm.JudgeArm).FirstOrDefaultAsync(); VisitTask visitTask = new VisitTask() - { - ArmEnum = Arm.JudgeArm, - Id = NewId.NextGuid(), - SubjectId = firstTask.SubjectId, - ReadingTaskState = ReadingTaskState.WaitReading, - TaskName = firstTask.TaskName, - ReadingCategory = ReadingCategory.Judge, - VisitTaskNum= firstTask.VisitTaskNum+ ReadingCommon.TaskNumDic[ReadingCategory.Judge], - TrialId = firstTask.TrialId, - Code = currentMaxCodeInt + 1, - SourceSubjectVisitId = firstTask.SourceSubjectVisitId, - SouceReadModuleId = firstTask.SouceReadModuleId, - TaskCode = AppSettings.GetCodeStr(currentMaxCodeInt + 1, nameof(VisitTask)), - TaskState = TaskState.Effect, - DoctorUserId = subjectUser==null ? null : subjectUser.Id, - TaskAllocationState = subjectUser == null? TaskAllocationState.NotAllocate: TaskAllocationState.Allocated, - AllocateTime = subjectUser == null ?null: DateTime.Now, - }; + { + ArmEnum = Arm.JudgeArm, + Id = NewId.NextGuid(), + SubjectId = firstTask.SubjectId, + ReadingTaskState = ReadingTaskState.WaitReading, + TaskName = firstTask.TaskName, + ReadingCategory = ReadingCategory.Judge, + VisitTaskNum = firstTask.VisitTaskNum + ReadingCommon.TaskNumDic[ReadingCategory.Judge], + TrialId = firstTask.TrialId, + Code = currentMaxCodeInt + 1, + SourceSubjectVisitId = firstTask.SourceSubjectVisitId, + SouceReadModuleId = firstTask.SouceReadModuleId, + TaskCode = AppSettings.GetCodeStr(currentMaxCodeInt + 1, nameof(VisitTask)), + TaskState = TaskState.Effect, + DoctorUserId = subjectUser == null ? null : subjectUser.Id, + TaskAllocationState = subjectUser == null ? TaskAllocationState.NotAllocate : TaskAllocationState.Allocated, + AllocateTime = subjectUser == null ? null : DateTime.Now, + }; await _visitTaskRepository.AddAsync(visitTask); currentMaxCodeInt = currentMaxCodeInt + 1; @@ -482,7 +508,7 @@ namespace IRaCIS.Core.Application.Service //case ReadingCategory.ReadingPeriod: case GenerateTaskCategory.Global: - + if (trialConfig.ReadingType == ReadingMethod.Double) { foreach (var item in generateTaskCommand.ReadingGenerataTaskList) diff --git a/IRaCIS.Core.Application/Service/Allocation/VisitTaskService.cs b/IRaCIS.Core.Application/Service/Allocation/VisitTaskService.cs index a0249f570..e3e5d0d0d 100644 --- a/IRaCIS.Core.Application/Service/Allocation/VisitTaskService.cs +++ b/IRaCIS.Core.Application/Service/Allocation/VisitTaskService.cs @@ -947,10 +947,26 @@ namespace IRaCIS.Core.Application.Service var taskList = await _visitTaskRepository.Where(t => applyReReadingCommand.TaskIdList.Contains(t.Id), true).Include(t => t.JudgeVisitTask).ToListAsync(); - + var trialConfig = (await _trialRepository.Where(t => t.Id == applyReReadingCommand.TrialId).Select(t => new { TrialId = t.Id, t.ReadingType, t.IsReadingTaskViewInOrder }).FirstOrDefaultAsync()).IfNullThrowException(); foreach (var task in taskList) { + if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.ProjectManager && task.IsAnalysisCreate) + { + throw new BusinessValidationFailedException("PM 不允许对一致性分析任务进行申请重阅"); + } + + if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.ProjectManager && task.ReadingCategory != ReadingCategory.Visit) + { + throw new BusinessValidationFailedException("PM 仅仅允许对访视类型的任务申请重阅"); + } + + + if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.IndependentReviewer && !trialConfig.IsReadingTaskViewInOrder && (task.ReadingCategory != ReadingCategory.Visit && task.ReadingCategory != ReadingCategory.Global)) + { + throw new BusinessValidationFailedException("无序阅片,仅仅允许IR 申请 全局和访视类型类别的任务进行重阅"); + } + if (task.ReadingTaskState != ReadingTaskState.HaveSigned) { @@ -967,14 +983,23 @@ namespace IRaCIS.Core.Application.Service throw new BusinessValidationFailedException("访视重阅导致裁判任务重置的,不能申请重阅"); } - if (task.ReadingCategory == ReadingCategory.Oncology) + Expression> filterExpression = t => t.TrialId == task.TrialId && t.SubjectId == task.SubjectId && t.TaskState == TaskState.Effect + && t.ReadingTaskState == ReadingTaskState.HaveSigned && t.DoctorUserId == task.DoctorUserId && t.IsAnalysisCreate == false; + + + if (task.ReadingCategory == ReadingCategory.Judge && await _visitTaskRepository.AnyAsync(filterExpression.And(t => t.ReadingCategory == ReadingCategory.Global))) { - throw new BusinessValidationFailedException("肿瘤学任务只允许申请该阅片人最后一次完成裁判的任务进行重阅"); + throw new BusinessValidationFailedException("只允许申请该受试者阅片人最后一次完成全局任务重阅"); } - if (task.ReadingCategory == ReadingCategory.Judge && await _visitTaskRepository.AnyAsync(t => t.DoctorUserId == task.DoctorUserId && t.SubjectId == task.SubjectId && t.TaskState == TaskState.Effect && t.VisitTaskNum > task.VisitTaskNum)) + if (task.ReadingCategory == ReadingCategory.Oncology && await _visitTaskRepository.AnyAsync(filterExpression.And(t => t.ReadingCategory == ReadingCategory.Oncology))) { - throw new BusinessValidationFailedException("只允许申请该阅片人最后一次完成裁判的任务重阅"); + throw new BusinessValidationFailedException("只允许申请该受试者阅片人最后一次完成肿瘤学任务重阅"); + } + + if (task.ReadingCategory == ReadingCategory.Judge && await _visitTaskRepository.AnyAsync(filterExpression.And(t => t.ReadingCategory == ReadingCategory.Judge))) + { + throw new BusinessValidationFailedException("只允许申请该受试者阅片人最后一次完成裁判的任务重阅"); } task.ReReadingApplyState = ReReadingApplyState.HaveApplyed; @@ -998,10 +1023,6 @@ namespace IRaCIS.Core.Application.Service } - //产生新的任务 - - - await _visitTaskRepository.SaveChangesAsync(); return ResponseOutput.Ok(); @@ -1028,7 +1049,10 @@ namespace IRaCIS.Core.Application.Service { var origenalTask = (await _visitTaskRepository.Where(t => item.OriginalReReadingTaskId == t.Id, true).FirstOrDefaultAsync()).IfNullThrowException(); - //更新原始任务 + + + + //更新原始任务 当前任务处理 origenalTask.ReReadingApplyState = (agreeReReadingCommand.RequestReReadingResultEnum == RequestReReadingResult.Agree ? ReReadingApplyState.Agree : ReReadingApplyState.Reject); origenalTask.TaskState = (agreeReReadingCommand.RequestReReadingResultEnum == RequestReReadingResult.Agree ? TaskState.HaveReturned : origenalTask.TaskState); @@ -1075,139 +1099,198 @@ namespace IRaCIS.Core.Application.Service }); } - - - - } //访视任务 同意重阅 else { - - if (visitTaskReReadingAppply.RequestReReadingType == RequestReReadingType.TrialGroupApply) + //PM申请 SPM / CPM审批 + if (visitTaskReReadingAppply.RequestReReadingType == RequestReReadingType.TrialGroupApply && (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.SPM || _userInfo.UserTypeEnumInt == (int)UserTypeEnum.CPM)) { - //SPM同意 - if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.SPM) + //有序阅片 + if (trialConfig.IsReadingTaskViewInOrder) { - //有序阅片 - if (trialConfig.IsReadingTaskViewInOrder) + + } + //无序阅片 + else + { + //阅片任务产生了裁判 + if (origenalTask.JudgeVisitTaskId != null) { + //裁判任务是否已阅片完成 + var judgeTask = await _visitTaskRepository.FirstOrDefaultAsync(t => t.Id == origenalTask.JudgeVisitTaskId); + + if (judgeTask.ReadingTaskState == ReadingTaskState.HaveSigned) + { + judgeTask.TaskState = TaskState.HaveReturned; + } + //裁判任务未完 + else + { + judgeTask.TaskState = TaskState.Adbandon; + } + } - //无序阅片 - else + + //不管是否触发裁判 阅片任务退回,待影像重传后重新分 配给原阅片人 + + if (trialConfig.ReadingType == ReadingMethod.Double) { - //阅片任务产生了裁判 - if (origenalTask.JudgeVisitTaskId != null) + //考虑该访视 另外一个阅片人的任务也同时退回 + + var otherTask = await _visitTaskRepository.FirstOrDefaultAsync(t => t.SourceSubjectVisitId == origenalTask.SourceSubjectVisitId && t.Id != origenalTask.Id && t.TaskState == TaskState.Effect); + + if (otherTask.ReadingTaskState == ReadingTaskState.HaveSigned) { - - //裁判任务是否已阅片完成 - var judgeTask = await _visitTaskRepository.FirstOrDefaultAsync(t => t.Id == origenalTask.JudgeVisitTaskId); - - if (judgeTask.ReadingTaskState == ReadingTaskState.HaveSigned) - { - judgeTask.TaskState = TaskState.HaveReturned; - } - //裁判任务未完 - else - { - judgeTask.TaskState = TaskState.Adbandon; - } - + otherTask.TaskState = TaskState.HaveReturned; } - - //不管是否触发裁判 阅片任务退回,待影像重传后重新分 配给原阅片人 - - if (trialConfig.ReadingType == ReadingMethod.Double) + else { - //考虑该访视 另外一个阅片人的任务也同时退回 - - var otherTask = await _visitTaskRepository.FirstOrDefaultAsync(t => t.SourceSubjectVisitId == origenalTask.SourceSubjectVisitId && t.Id != origenalTask.Id && t.TaskState == TaskState.Effect); - - if (otherTask.ReadingTaskState == ReadingTaskState.HaveSigned) - { - otherTask.TaskState = TaskState.HaveReturned; - } - else - { - otherTask.TaskState = TaskState.Adbandon; - } - + otherTask.TaskState = TaskState.Adbandon; } - //回退访视 - - if (origenalTask.ReadingCategory == ReadingCategory.Visit) - { - //执行类似一致性核查回退流程 - await VisitBackAsync(origenalTask.SourceSubjectVisitId); - } - // 无序阅片没有 全局 肿瘤学 - - } + + //回退访视 + + if (origenalTask.ReadingCategory == ReadingCategory.Visit) + { + //执行类似一致性核查回退流程 + await VisitBackAsync(origenalTask.SourceSubjectVisitId); + } + // 无序阅片没有 全局 肿瘤学 + + } } - //IR申请 - else + //IR申请 PM 审批 注意这里有一致性分析的申请同意 + else if (visitTaskReReadingAppply.RequestReReadingType == RequestReReadingType.DocotorApply && _userInfo.UserTypeEnumInt == (int)UserTypeEnum.ProjectManager) { - //PM 同意 - if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.ProjectManager) + + //有序阅片 + if (trialConfig.IsReadingTaskViewInOrder) { - //有序阅片 - if (trialConfig.IsReadingTaskViewInOrder) + Expression> filterExpression = t => t.TrialId == trialId && t.SubjectId == origenalTask.SubjectId && t.TaskState == TaskState.Effect; + + //是否是一致性分析任务 + filterExpression = filterExpression.And(t => t.IsAnalysisCreate == origenalTask.IsAnalysisCreate); + + switch (origenalTask.ReadingCategory) { + case ReadingCategory.Visit: + //影响后续访视已经读完的,未读的不做处理 以及其他类型任务 + + filterExpression = filterExpression.And(t => t.VisitTaskNum > origenalTask.VisitTaskNum && t.DoctorUserId == origenalTask.DoctorUserId && + ((t.ReadingTaskState == ReadingTaskState.HaveSigned && t.ReadingCategory == ReadingCategory.Visit) || + t.ReadingCategory == ReadingCategory.Global || + t.ReadingCategory == ReadingCategory.Oncology || + t.ReadingCategory == ReadingCategory.Judge) + ); + break; + + case ReadingCategory.Global: + + //全局不影响后续访视任务 + filterExpression = filterExpression.And(t => t.VisitTaskNum > origenalTask.VisitTaskNum && t.DoctorUserId == origenalTask.DoctorUserId && + ( + t.ReadingCategory == ReadingCategory.Global || + t.ReadingCategory == ReadingCategory.Oncology || + t.ReadingCategory == ReadingCategory.Judge) + ); + break; + + case ReadingCategory.Oncology: + + //仅仅影响自己 后续任务如果是访视任务、全局任务或裁判任务,均不处理 + filterExpression = filterExpression.And(t => /*t.Id == origenalTask.Id*/ t.Id == Guid.Empty); + break; + + case ReadingCategory.Judge: + + + //裁判的影响自己 和后续肿瘤学阅片 + filterExpression = filterExpression.And(t => /*(t.Id == origenalTask.Id) ||*/ (t.VisitTaskNum > origenalTask.VisitTaskNum && t.DoctorUserId == origenalTask.DoctorUserId && t.ReadingCategory == ReadingCategory.Oncology)); + + break; + + + default: + throw new BusinessValidationFailedException("不支持重阅的任务类型"); } - //无序阅片 - else + + + + var influenceTaskList = await _visitTaskRepository.Where(filterExpression, true).ToListAsync(); + + foreach (var influenceTask in influenceTaskList) { - //阅片任务产生了裁判 - if (origenalTask.JudgeVisitTaskId != null) + if (influenceTask.ReadingTaskState == ReadingTaskState.HaveSigned) { + influenceTask.TaskState = TaskState.HaveReturned; + } + else + { + influenceTask.TaskState = TaskState.Adbandon; + } + } - //裁判任务是否已阅片完成 - var judgeTask = await _visitTaskRepository.FirstOrDefaultAsync(t => t.Id == origenalTask.JudgeVisitTaskId); - if (judgeTask.ReadingTaskState == ReadingTaskState.HaveSigned) - { - judgeTask.TaskState = TaskState.HaveReturned; - } - //裁判任务未完 - else - { - judgeTask.TaskState = TaskState.Adbandon; - } + } + //无序阅片 只会申请访视类型和裁判类型的任务 注意这里有一致性分析的申请同意 + else + { + //访视任务产生了裁判 + if (origenalTask.ReadingCategory == ReadingCategory.Visit && origenalTask.JudgeVisitTaskId != null) + { + + //裁判任务是否已阅片完成 + var judgeTask = await _visitTaskRepository.FirstOrDefaultAsync(t => t.Id == origenalTask.JudgeVisitTaskId); + + if (judgeTask.ReadingTaskState == ReadingTaskState.HaveSigned) + { + judgeTask.TaskState = TaskState.HaveReturned; + } + //裁判任务未完 + else + { + judgeTask.TaskState = TaskState.Adbandon; } - //产生的新任务 - await _visitTaskCommonService.AddTaskAsync(new GenerateTaskCommand() - { - TrialId = trialId, - - ReadingCategory = GenerateTaskCategory.ReReading, - - ReReadingTask = origenalTask, - - //同步才可以 - Action = (newTask) => - { - //申请表 设置新任务Id - visitTaskReReadingAppply.NewReReadingTaskId = newTask.Id; - - //生成的任务分配给原始医生 - newTask.DoctorUserId = origenalTask.DoctorUserId; - newTask.TaskAllocationState = TaskAllocationState.Allocated; - newTask.AllocateTime = DateTime.Now; - - } - }); } + + // 不管是访视还是裁判 都会立马产生的新任务并分配出去 + await _visitTaskCommonService.AddTaskAsync(new GenerateTaskCommand() + { + TrialId = trialId, + + ReadingCategory = GenerateTaskCategory.ReReading, + + ReReadingTask = origenalTask, + + //同步才可以 + Action = (newTask) => + { + //申请表 设置新任务Id + visitTaskReReadingAppply.NewReReadingTaskId = newTask.Id; + + //生成的任务分配给原始医生 + newTask.DoctorUserId = origenalTask.DoctorUserId; + newTask.TaskAllocationState = TaskAllocationState.Allocated; + newTask.AllocateTime = DateTime.Now; + + } + }); } } + else + { + throw new BusinessValidationFailedException("不符合 PM申请 SPM / CPM审批 | IR申请 PM 审批 "); + } } } @@ -1235,7 +1318,19 @@ namespace IRaCIS.Core.Application.Service var task = (await _visitTaskRepository.FirstOrDefaultAsync(t => t.Id == taskId)).IfNullThrowException(); //申请的任务 肯定是未完成阅片的 并且是访视类型的 - if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.ProjectManager && task.ReadingCategory == ReadingCategory.Visit && task.ReadingTaskState != ReadingTaskState.HaveSigned) + if (task.ReadingCategory != ReadingCategory.Visit || task.ReadingTaskState != ReadingTaskState.HaveSigned) + { + return ResponseOutput.NotOk("仅仅未完成的访视类型的任务支持PM退回"); + + } + + if (task.IsAnalysisCreate) + { + return ResponseOutput.NotOk("一致性分析的任务,不允许设置退回"); + } + + //PM 才允许操作 + if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.ProjectManager) { #region 有序 无序公用流程 @@ -1364,7 +1459,7 @@ namespace IRaCIS.Core.Application.Service } else { - throw new BusinessValidationFailedException("仅仅未完成的访视类型的任务支持PM退回"); + return ResponseOutput.NotOk("仅PM 可以进行回退操作"); } await _visitTaskRepository.SaveChangesAsync(); @@ -1431,7 +1526,12 @@ namespace IRaCIS.Core.Application.Service var trialConfig = (await _trialRepository.Where(t => t.Id == trialId).Select(t => new { TrialId = t.Id, t.IsReadingTaskViewInOrder, t.ReadingType }).FirstOrDefaultAsync()).IfNullThrowException(); - Expression> filterExpression = t => t.TrialId == trialId && t.SubjectId == filterObj.SubjectId && t.TaskState == TaskState.Effect && t.IsAnalysisCreate == false; + Expression> filterExpression = t => t.TrialId == trialId && t.SubjectId == filterObj.SubjectId && t.TaskState == TaskState.Effect; + + //是否是一致性分析任务 + + filterExpression = filterExpression.And(t => t.IsAnalysisCreate == filterObj.IsAnalysisCreate); + //重阅影响 if (isReReading) @@ -1473,17 +1573,17 @@ namespace IRaCIS.Core.Application.Service ); break; + //1、后续任务如果是访视任务、全局任务或裁判任务,均不处理; case ReadingCategory.Oncology: - //不允许申请,已做限制 - - throw new BusinessValidationFailedException("不支持的申请重阅任务类型"); - + //仅仅影响自己 + filterExpression = filterExpression.And(t => (t.Id == filterObj.Id)); + break; //(只允许申请该阅片人最后一次完成裁判的任务重阅)申请的时候做了限制 case ReadingCategory.Judge: - // 1、后续任务如果是访视任务、全局任务,均不处理; + // 1、后续任务如果是访视任务、全局任务,均不处理; //2、后续若有肿瘤学阅片,若肿瘤学阅片任务状态为阅片完成,则标记为重阅重置;若为阅片中则标记为失效,如为待阅片,则取消分配 //裁判的影响自己 和后续肿瘤学阅片 @@ -1499,13 +1599,13 @@ namespace IRaCIS.Core.Application.Service } //PM 影响所有阅片人 仅仅针对访视 - if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.ProjectManager) + if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.ProjectManager && filterObj.IsAnalysisCreate == false) { switch (filterObj.ReadingCategory) { case ReadingCategory.Visit: - //访视影响当前以及当前之后的 两个月月阅片人的 + //访视影响当前以及当前之后的 两个阅片人的 filterExpression = filterExpression.And(t => t.VisitTaskNum >= filterObj.VisitTaskNum); break; @@ -1514,6 +1614,10 @@ namespace IRaCIS.Core.Application.Service throw new BusinessValidationFailedException("不支持重阅的任务类型"); } } + else + { + throw new BusinessValidationFailedException("一致性分析的任务,只允许IR申请重阅"); + } } //无序 else @@ -1527,15 +1631,22 @@ namespace IRaCIS.Core.Application.Service // 1.当前任务及裁判任务 // 2.影响所有阅片人的任务 - if (filterObj.ReadingCategory == ReadingCategory.Visit && _userInfo.UserTypeEnumInt == (int)UserTypeEnum.ProjectManager) + if (filterObj.ReadingCategory == ReadingCategory.Visit && _userInfo.UserTypeEnumInt == (int)UserTypeEnum.ProjectManager && filterObj.IsAnalysisCreate == false) { var judegTaskNum = filterObj.VisitTaskNum + ReadingCommon.TaskNumDic[ReadingCategory.Judge]; filterExpression = filterExpression.And(t => t.VisitTaskNum == filterObj.VisitTaskNum || t.VisitTaskNum == judegTaskNum); } + else + { + throw new BusinessValidationFailedException("PM 仅允许申请非一致性分析访视类型的任务进行重阅"); + } } } + + + //退回影响 仅仅针对是访视类型的 else { diff --git a/IRaCIS.Core.Domain/Allocation/VisitTaskReReading.cs b/IRaCIS.Core.Domain/Allocation/VisitTaskReReading.cs index 913f57247..57ae1c837 100644 --- a/IRaCIS.Core.Domain/Allocation/VisitTaskReReading.cs +++ b/IRaCIS.Core.Domain/Allocation/VisitTaskReReading.cs @@ -24,7 +24,7 @@ namespace IRaCIS.Core.Domain.Models //产生重阅的根任务Id - public Guid? RootReReadingTaskId { get; set; } + public Guid RootReReadingTaskId { get; set; } //重阅申请 产生的新任务Id public Guid? NewReReadingTaskId { get; set; } diff --git a/IRaCIS.Core.Infra.EFCore/Common/ReadingCommon.cs b/IRaCIS.Core.Infra.EFCore/Common/ReadingCommon.cs index e5db6470f..2a2b26b6b 100644 --- a/IRaCIS.Core.Infra.EFCore/Common/ReadingCommon.cs +++ b/IRaCIS.Core.Infra.EFCore/Common/ReadingCommon.cs @@ -20,7 +20,7 @@ namespace IRaCIS.Core.Infra.EFCore.Common {ReadingCategory.Visit, 0 }, {ReadingCategory.Global,(decimal) 0.03 }, {ReadingCategory.Judge,(decimal) 0.02 }, - {ReadingCategory.Oncology, 0 }, + {ReadingCategory.Oncology, (decimal)0.06 }, }; diff --git a/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs b/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs index 41c2ca6b8..f4a5bf75a 100644 --- a/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs +++ b/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs @@ -95,6 +95,7 @@ namespace IRaCIS.Core.Infra.EFCore modelBuilder.Entity().HasMany(t => t.TaskMedicalReviewList).WithOne(t => t.TaskMedicalReviewRule).HasForeignKey(t => new { t.DoctorUserId, t.TrialId }).HasPrincipalKey(u => new { u.DoctorUserId, u.TrialId }); modelBuilder.Entity().HasMany(t => t.SubjectArmVisitTaskList).WithOne(t => t.SujectArm).HasForeignKey(t => new { t.SubjectId, t.ArmEnum }).HasPrincipalKey(u => new { u.SubjectId, u.ArmEnum }); + modelBuilder.Entity().HasMany(t => t.JudgeVisitList).WithOne(t => t.JudgeVisitTask); //modelBuilder.Entity().HasMany(t => t.VisitTaskList).WithOne(t => t.SourceSubjectVisit).HasForeignKey(t=>t.SourceSubjectVisitId).HasPrincipalKey(t=>t.Id);