//-------------------------------------------------------------------- // 此代码由T4模板自动生成 byzhouhang 20210918 // 生成时间 2022-06-07 14:10:49 // 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。 //-------------------------------------------------------------------- using IRaCIS.Core.Domain.Models; using Microsoft.AspNetCore.Mvc; using IRaCIS.Core.Application.Interfaces; using IRaCIS.Core.Application.ViewModel; using EasyCaching.Core; using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Infrastructure; using AutoMapper; using MassTransit; using IRaCIS.Core.Infra.EFCore.Common; namespace IRaCIS.Core.Application.Service { /// /// 访视读片任务 /// [ApiExplorerSettings(GroupName = "Trial")] public class VisitTaskHelpeService : IVisitTaskHelpeService { private readonly IRepository _visitTaskRepository; private readonly IRepository _trialRepository; private readonly IEasyCachingProvider _provider; private readonly IRepository _subjectVisitRepository; private readonly IRepository _readingJudgeInfoRepository; private readonly IRepository _taskAllocationRuleRepository; private readonly IRepository _subjectUserRepository; private readonly IMapper _mapper; private readonly IUserInfo _userInfo; private readonly IRepository _visitTaskReReadingRepository; public VisitTaskHelpeService(IRepository visitTaskRepository, IRepository subjectUserRepository, IRepository trialRepository, IEasyCachingProvider provider, IRepository subjectVisitRepository, IRepository readingJudgeInfoRepository, IRepository taskAllocationRuleRepository, IMapper mapper, IUserInfo userInfo, IRepository visitTaskReReadingRepository) { _visitTaskRepository = visitTaskRepository; _trialRepository = trialRepository; _provider = provider; _subjectVisitRepository = subjectVisitRepository; this._readingJudgeInfoRepository = readingJudgeInfoRepository; _taskAllocationRuleRepository = taskAllocationRuleRepository; _subjectUserRepository = subjectUserRepository; _mapper = mapper; _userInfo = userInfo; _visitTaskReReadingRepository = visitTaskReReadingRepository; } //查询列表的时候,一致性核查通过未产生任务的 自动产生任务 如果是一致性核查,那么还会自动分配 public async Task GenerateVisitTaskAsync(Guid trialId, List subjectVisitIdList, bool isAssignSubjectToDoctor = false) { if (subjectVisitIdList.Count == 0) { return; } var subjectVisitList = _subjectVisitRepository.Where(t => subjectVisitIdList.Contains(t.Id)).ProjectTo(_mapper.ConfigurationProvider).Distinct().ToList(); await AddTaskAsync(new GenerateTaskCommand() { TrialId = trialId, IsAssignSubjectToDoctor = isAssignSubjectToDoctor, VisitGenerataTaskList = subjectVisitList, ReadingCategory = ReadingCategory.Visit }); } public async Task AddTaskAsync(GenerateTaskCommand generateTaskCommand) { var trialId = generateTaskCommand.TrialId; var isAssignSubjectToDoctor = generateTaskCommand.IsAssignSubjectToDoctor; var trialConfig = (await _trialRepository.Where(t => t.Id == trialId).Select(t => new { TrialId = t.Id, t.ReadingType, t.IsFollowVisitAutoAssign, t.IsFollowGlobalVisitAutoAssign, t.FollowGlobalVisitAutoAssignDefaultState, t.FollowVisitAutoAssignDefaultState, t.TaskAllocateObjEnum }).FirstOrDefaultAsync()).IfNullThrowException(); var dbMaxCode = _visitTaskRepository.Where(t => t.TrialId == trialId).Select(t => t.Code).DefaultIfEmpty().Max(); var cacheMaxCodeInt = _provider.Get($"{trialId}_{StaticData.CacheKey.TaskMaxCode}").Value; int currentMaxCodeInt = cacheMaxCodeInt > dbMaxCode ? cacheMaxCodeInt : dbMaxCode; switch (generateTaskCommand.ReadingCategory) { case ReadingCategory.Visit: foreach (var subjectVisit in generateTaskCommand.VisitGenerataTaskList) { var assignConfigList = await _subjectUserRepository.Where(t => t.TrialId == trialId && t.SubjectId == subjectVisit.SubjectId && t.OrignalSubjectUserId == null && t.IsConfirmed).Select(u => new { u.DoctorUserId, u.ArmEnum }).ToListAsync(); if (trialConfig.ReadingType == ReadingMethod.Double) { //每个访视 根据项目配置生成任务 双审生成两个 var task1 = await _visitTaskRepository.AddAsync(new VisitTask() { TrialId = trialId, SubjectId = subjectVisit.SubjectId, IsUrgent = subjectVisit.IsUrgent, TaskBlindName = subjectVisit.BlindName, TaskName = subjectVisit.VisitName, VisitTaskNum=subjectVisit.VisitNum, //CheckPassedTime = subjectVisit.CheckPassedTime, ArmEnum = Arm.DoubleReadingArm1,//特殊 Code = currentMaxCodeInt + 1, SourceSubjectVisitId = subjectVisit.Id, TaskCode = AppSettings.GetCodeStr(currentMaxCodeInt + 1, nameof(VisitTask)), ReadingCategory = ReadingCategory.Visit }); var task2 = await _visitTaskRepository.AddAsync(new VisitTask() { TrialId = trialId, SubjectId = subjectVisit.SubjectId, IsUrgent = subjectVisit.IsUrgent, TaskBlindName = subjectVisit.BlindName, TaskName = subjectVisit.VisitName, VisitTaskNum = subjectVisit.VisitNum, //CheckPassedTime = subjectVisit.CheckPassedTime, ArmEnum = Arm.DoubleReadingArm2,//特殊 Code = currentMaxCodeInt + 2, SourceSubjectVisitId = subjectVisit.Id, TaskCode = AppSettings.GetCodeStr(currentMaxCodeInt + 2, nameof(VisitTask)), ReadingCategory = ReadingCategory.Visit }); currentMaxCodeInt = currentMaxCodeInt + 2; _provider.Set($"{trialId}_{StaticData.CacheKey.TaskMaxCode}", currentMaxCodeInt , TimeSpan.FromMinutes(30)); #region 分配 if (isAssignSubjectToDoctor) { if (trialConfig.TaskAllocateObjEnum == TaskAllocateObj.Subject) { if (trialConfig.IsFollowVisitAutoAssign) { #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) { 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; } } #endregion } //找到配置规则表 进行分配 else { //后续Subect 不自动分配 不处理 return; } } task1.AllocateTime = DateTime.Now; task2.AllocateTime = DateTime.Now; } #endregion } else if (trialConfig.ReadingType == ReadingMethod.Single) { var singleTask = await _visitTaskRepository.AddAsync(new VisitTask() { TrialId = trialId, SubjectId = subjectVisit.SubjectId, IsUrgent = subjectVisit.IsUrgent, TaskBlindName = subjectVisit.BlindName, TaskName = subjectVisit.VisitName, VisitTaskNum = subjectVisit.VisitNum, //CheckPassedTime = subjectVisit.CheckPassedTime, ArmEnum = Arm.SingleReadingArm, //特殊 Code = currentMaxCodeInt + 1, SourceSubjectVisitId = subjectVisit.Id, TaskCode = AppSettings.GetCodeStr(currentMaxCodeInt + 1, nameof(VisitTask)), ReadingCategory = ReadingCategory.Visit }); currentMaxCodeInt = currentMaxCodeInt + 1; _provider.Set($"{trialId}_{StaticData.CacheKey.TaskMaxCode}", currentMaxCodeInt , TimeSpan.FromMinutes(30)); #region 分配 if (isAssignSubjectToDoctor) { if (trialConfig.TaskAllocateObjEnum == TaskAllocateObj.Subject) { if (trialConfig.IsFollowVisitAutoAssign) { //该Subject 之前是否有已分配的 如果改变配置 可能会出现 一个Subject 分配的同一个医生 有的在Arm1 有的在Arm2 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 (allocateSubjectArmList.Count != 0) { if (_taskAllocationRuleRepository.Where(t => t.TrialId == trialId && t.IsEnable).Count() < 2) { throw new BusinessValidationFailedException("能参与读片的医生数量必须大于2,自动分配任务中止"); } //配置了医生 if (assignConfigList.Count > 0) { var defaultState = trialConfig.FollowVisitAutoAssignDefaultState == TaskAllocateDefaultState.InitAllocated ? TaskAllocationState.InitAllocated : TaskAllocationState.Allocated; singleTask.TaskAllocationState = defaultState; singleTask.DoctorUserId = assignConfigList.FirstOrDefault(t => t.ArmEnum == 0).DoctorUserId; } } } else { //后续Subect 不自动分配 不处理 return; } } singleTask.AllocateTime = DateTime.Now; } #endregion } await _subjectVisitRepository.BatchUpdateNoTrackingAsync(t => t.TrialId == trialId && t.Id == subjectVisit.Id, u => new SubjectVisit() { IsVisitTaskGenerated = true }); } break; case ReadingCategory.ReReading: var reReadingVisitTask = generateTaskCommand.ReReadingTask; //foreach (var reReadingVisitTask in generateTaskCommand.ReReadingTaskList) //{ //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.Code = currentMaxCodeInt + 1; //reReadingVisitTask.TaskCode = AppSettings.GetCodeStr(currentMaxCodeInt + 1, nameof(VisitTask)); // await _visitTaskRepository.AddAsync(reReadingVisitTask); var newTask = await _visitTaskRepository.AddAsync(new VisitTask() { 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, IsReReadingCreate = true, TaskState = TaskState.Effect, Code = currentMaxCodeInt + 1, TaskCode = AppSettings.GetCodeStr(currentMaxCodeInt + 1, nameof(VisitTask)), // TaskAllocationState = reReadingVisitTask.TaskAllocationState, // AllocateTime = DateTime.Now, //DoctorUserId = reReadingVisitTask.DoctorUserId, }); generateTaskCommand.Action(newTask); //await _visitTaskReReadingRepository.BatchUpdateNoTrackingAsync(t=>t.) //是否增加任务类别 currentMaxCodeInt = currentMaxCodeInt + 1; _provider.Set($"{trialId}_{StaticData.CacheKey.TaskMaxCode}", currentMaxCodeInt, TimeSpan.FromMinutes(30)); //} break; case ReadingCategory.Consistent: foreach (var task in generateTaskCommand.GenerataConsistentTaskList) { var consistentTask = new VisitTask() { TrialId = task.TrialId, SubjectId = task.SubjectId, ArmEnum = task.ArmEnum, TaskName = task.TaskName, TaskBlindName = task.TaskBlindName, VisitTaskNum = task.VisitTaskNum, ReadingCategory = task.ReadingCategory, IsReReadingCreate = true, TaskState = TaskState.Effect, Code = currentMaxCodeInt + 1, TaskCode = AppSettings.GetCodeStr(currentMaxCodeInt + 1, nameof(VisitTask)), }; await _visitTaskRepository.AddAsync(consistentTask); currentMaxCodeInt = currentMaxCodeInt + 1; _provider.Set($"{trialId}_{StaticData.CacheKey.TaskMaxCode}", currentMaxCodeInt, TimeSpan.FromMinutes(30)); } break; case ReadingCategory.Judge: var firstTask = await _visitTaskRepository.Where(x => generateTaskCommand.JudgeVisitTaskIdList.Contains(x.Id)).FirstOrDefaultAsync(); 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 = DateTime.Now, }; await _visitTaskRepository.AddAsync(visitTask); currentMaxCodeInt = currentMaxCodeInt + 1; _provider.Set($"{trialId}_{StaticData.CacheKey.TaskMaxCode}", currentMaxCodeInt, TimeSpan.FromMinutes(30)); await _visitTaskRepository.BatchUpdateNoTrackingAsync(x => generateTaskCommand.JudgeVisitTaskIdList.Contains(x.Id), x => new VisitTask() { JudgeVisitTaskId = visitTask.Id }); await _readingJudgeInfoRepository.AddAsync(new ReadingJudgeInfo() { JudgeTaskId = visitTask.Id, SubjectId = firstTask.SubjectId, TrialId = firstTask.TrialId, TaskIdOne = generateTaskCommand.JudgeVisitTaskIdList[0], TaskIdTwo = generateTaskCommand.JudgeVisitTaskIdList[1] }); break; //case ReadingCategory.ReadingPeriod: case ReadingCategory.Global: if (trialConfig.ReadingType == ReadingMethod.Double) { foreach (var item in generateTaskCommand.ReadingGenerataTaskList) { //每个访视 根据项目配置生成任务 双审生成两个 var task1 = await _visitTaskRepository.AddAsync(new VisitTask() { TrialId = trialId, SubjectId = item.SubjectId, IsUrgent = item.IsUrgent, VisitTaskNum = item.VisitNum + ReadingCommon.TaskNumDic[ReadingCategory.Global], TaskName = item.ReadingName, ArmEnum = Arm.DoubleReadingArm1,//特殊 Code = currentMaxCodeInt + 1, TaskBlindName = item.ReadingName, SouceReadModuleId = item.ReadModuleId, TaskCode = AppSettings.GetCodeStr(currentMaxCodeInt + 1, nameof(VisitTask)), ReadingCategory = item.ReadingCategory }); var task2 = await _visitTaskRepository.AddAsync(new VisitTask() { TrialId = trialId, SubjectId = item.SubjectId, IsUrgent = item.IsUrgent, VisitTaskNum = item.VisitNum + ReadingCommon.TaskNumDic[ReadingCategory.Global], TaskName = item.ReadingName, ArmEnum = Arm.DoubleReadingArm2,//特殊 Code = currentMaxCodeInt + 2, TaskBlindName = item.ReadingName, SouceReadModuleId = item.ReadModuleId, TaskCode = AppSettings.GetCodeStr(currentMaxCodeInt + 2, nameof(VisitTask)), ReadingCategory = item.ReadingCategory }); currentMaxCodeInt = currentMaxCodeInt + 2; _provider.Set($"{trialId}_{StaticData.CacheKey.TaskMaxCode}", currentMaxCodeInt, TimeSpan.FromMinutes(30)); } } else { foreach (var item in generateTaskCommand.ReadingGenerataTaskList) { var singleTask = await _visitTaskRepository.AddAsync(new VisitTask() { TrialId = trialId, SubjectId = item.SubjectId, IsUrgent = item.IsUrgent, TaskName = item.ReadingName, VisitTaskNum = item.VisitNum + ReadingCommon.TaskNumDic[ReadingCategory.Global], ArmEnum = Arm.SingleReadingArm, //特殊 Code = currentMaxCodeInt + 1, SouceReadModuleId = item.ReadModuleId, TaskBlindName = item.ReadingName, TaskCode = AppSettings.GetCodeStr(currentMaxCodeInt + 1, nameof(VisitTask)), ReadingCategory = item.ReadingCategory }); singleTask.AllocateTime = DateTime.Now; currentMaxCodeInt = currentMaxCodeInt + 1; _provider.Set($"{trialId}_{StaticData.CacheKey.TaskMaxCode}", currentMaxCodeInt, TimeSpan.FromMinutes(30)); } } break; case ReadingCategory.Oncology: foreach (var item in generateTaskCommand.ReadingGenerataTaskList) { var singleTask = await _visitTaskRepository.AddAsync(new VisitTask() { TrialId = trialId, SubjectId = item.SubjectId, IsUrgent = item.IsUrgent, TaskName = item.ReadingName, VisitTaskNum = item.VisitNum + ReadingCommon.TaskNumDic[ReadingCategory.Oncology], ArmEnum = Arm.TumorArm, //特殊 Code = currentMaxCodeInt + 1, SouceReadModuleId = item.ReadModuleId, TaskBlindName = item.ReadingName, TaskCode = AppSettings.GetCodeStr(currentMaxCodeInt + 1, nameof(VisitTask)), ReadingCategory = item.ReadingCategory }); singleTask.AllocateTime = DateTime.Now; currentMaxCodeInt = currentMaxCodeInt + 1; _provider.Set($"{trialId}_{StaticData.CacheKey.TaskMaxCode}", currentMaxCodeInt, TimeSpan.FromMinutes(30)); } break; } await _visitTaskRepository.SaveChangesAsync(); } } }