//-------------------------------------------------------------------- // 此代码由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; using System.Linq.Expressions; using IRaCIS.Core.Domain.Share.Reading; using IRaCIS.Core.Application.Service.Reading.Dto; using IRaCIS.Core.Application.Contracts; 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 _readModuleRepository; private readonly IRepository _readingTaskQuestionAnswerRepository; private readonly IRepository _readingTableAnswerRowInfoRepository; private readonly IRepository _readingTableQuestionAnswerRepository; private readonly IRepository _readingTableQuestionTrialRepository; private readonly IRepository _readingQuestionTrialRepository; private readonly IMapper _mapper; private readonly IUserInfo _userInfo; private readonly IRepository _visitTaskReReadingRepository; private readonly IRepository _trialReadingCriterionRepository; private readonly IRepository _trialClinicalDataSetRepository; private readonly IRepository _readingClinicalDataRepository; public VisitTaskHelpeService(IRepository visitTaskRepository, IRepository trialRepository, IEasyCachingProvider provider, IRepository subjectVisitRepository, IRepository readModuleRepository, IRepository readingTaskQuestionAnswerRepository, IRepository readingTableAnswerRowInfoRepository, IRepository readingTableQuestionAnswerRepository, IRepository readingTableQuestionTrialRepository, IRepository readingQuestionTrialRepository, IRepository readingJudgeInfoRepository, IMapper mapper, IUserInfo userInfo, IRepository visitTaskReReadingRepository, IRepository trialReadingCriterionRepository, IRepository trialClinicalDataSetRepository, IRepository readingClinicalDataRepository ) { _readingClinicalDataRepository = readingClinicalDataRepository; _trialClinicalDataSetRepository = trialClinicalDataSetRepository; _visitTaskRepository = visitTaskRepository; _trialRepository = trialRepository; this._readModuleRepository = readModuleRepository; this._readingTaskQuestionAnswerRepository = readingTaskQuestionAnswerRepository; this._readingTableAnswerRowInfoRepository = readingTableAnswerRowInfoRepository; this._readingTableQuestionAnswerRepository = readingTableQuestionAnswerRepository; this._readingTableQuestionTrialRepository = readingTableQuestionTrialRepository; this._readingQuestionTrialRepository = readingQuestionTrialRepository; _provider = provider; _subjectVisitRepository = subjectVisitRepository; this._readingJudgeInfoRepository = readingJudgeInfoRepository; _mapper = mapper; _userInfo = userInfo; _visitTaskReReadingRepository = visitTaskReReadingRepository; _trialReadingCriterionRepository = trialReadingCriterionRepository; } //查询列表的时候,一致性核查通过未产生任务的 自动产生任务 如果是一致性核查,那么还会自动分配 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 = GenerateTaskCategory.Visit }); } /// /// 添加转变任务 /// /// /// public async Task AddConvertedTask(Guid taskId) { var taskInfo = await _visitTaskRepository.Where(x => x.Id == taskId).IgnoreAutoIncludes().AsNoTracking().FirstNotNullAsync(); taskInfo.ReadingTaskState = ReadingTaskState.WaitReading; taskInfo.FirstReadingTime = null; taskInfo.SignTime = null; taskInfo.TaskState = TaskState.Effect; //taskInfo.IsConvertedTask = true; taskInfo.BeforeConvertedTaskId = taskId; taskInfo.Id = NewId.NextGuid(); //await _visitTaskRepository.BatchUpdateNoTrackingAsync(x => // x.IsAnalysisCreate == taskInfo.IsAnalysisCreate // && x.IsSelfAnalysis == taskInfo.IsSelfAnalysis // && x.VisitTaskNum > taskInfo.VisitTaskNum // && x.DoctorUserId == taskInfo.DoctorUserId // && x.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId // && x.SubjectId == taskInfo.SubjectId // && x.ArmEnum == taskInfo.ArmEnum && // x.TaskState == TaskState.Effect, x => new VisitTask() // { // IsConvertedTask = true // }); await _visitTaskRepository.AddAsync(taskInfo); await _visitTaskRepository.BatchUpdateNoTrackingAsync(x => x.Id == taskId, x => new VisitTask() { TaskState = TaskState.Freeze }); await _visitTaskRepository.SaveChangesAsync(); } //基于标准签名 产生任务 (或者手动选择某些访视生成该标准的任务) public async Task BaseCritrionGenerateVisitTask(Guid trialId, Guid confirmedTrialReadingCriterionId, bool? isManualSelectVisit = null, List? subjectVisitIdList = null) { var needGenerateVisit = new List(); if (isManualSelectVisit == null) { //找到一致性核查通过且没有产生任务的访视 needGenerateVisit = await _subjectVisitRepository.Where(t => t.TrialId == trialId && t.CheckState == CheckStateEnum.CVPassed && !t.VisitTaskList.Any(u => u.TrialReadingCriterionId == confirmedTrialReadingCriterionId && u.SourceSubjectVisitId == t.Id && u.TaskState == TaskState.Effect && u.IsAnalysisCreate == false)).ToListAsync(); } else { needGenerateVisit = await _subjectVisitRepository.Where(t => subjectVisitIdList.Contains(t.Id)).ToListAsync(); } var trialReadingCriterionConfig = await _trialReadingCriterionRepository.Where(t => t.Id == confirmedTrialReadingCriterionId).Select(t => new { TrialReadingCriterionId = t.Id, t.ReadingTool, t.ReadingType, t.IsReadingTaskViewInOrder, t.IsFollowVisitAutoAssign, t.IsFollowGlobalVisitAutoAssign, t.FollowGlobalVisitAutoAssignDefaultState, t.FollowVisitAutoAssignDefaultState, t.TaskAllocateObjEnum, t.CriterionType }).FirstOrDefaultAsync(); //获取确认的临床数据配置 var clinicalDataConfirmList = _trialClinicalDataSetRepository.Where(t => t.TrialId == trialId && t.IsConfirm).Include(t => t.TrialClinicalDataSetCriteriaList).ToList(); var visitBlindConfig = _trialRepository.Where(t => t.Id == trialId).Select(t => new { t.BlindBaseLineName, t.BlindFollowUpPrefix }).FirstOrDefault(); 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; foreach (var subjectGroup in needGenerateVisit.GroupBy(t => t.SubjectId).Select(g => new { SubjectId = g.Key, SubjectVisitList = g.ToList() })) { var visitNumList = _subjectVisitRepository.Where(t => t.SubjectId == subjectGroup.SubjectId && t.IsLostVisit == false).OrderBy(t => t.VisitNum).Select(t => t.VisitNum).ToList(); foreach (var subjectVisit in subjectGroup.SubjectVisitList) { var blindTaskName = string.Empty; var isNeedClinicalDataSign = IsNeedClinicalDataSign(ReadingCategory.Visit, subjectVisit.IsBaseLine, trialReadingCriterionConfig.TrialReadingCriterionId, clinicalDataConfirmList); var isClinicalDataSign = IsClinicalDataSign(ReadingCategory.Visit, subjectVisit.IsBaseLine, trialReadingCriterionConfig.TrialReadingCriterionId, clinicalDataConfirmList, subjectVisit.Id, trialId); if (visitNumList.IndexOf(subjectVisit.VisitNum) == 0) { blindTaskName = visitBlindConfig.BlindBaseLineName; } else { if (trialReadingCriterionConfig.IsReadingTaskViewInOrder) { blindTaskName = visitBlindConfig.BlindFollowUpPrefix + " " + visitNumList.IndexOf(subjectVisit.VisitNum); } else { blindTaskName = visitBlindConfig.BlindFollowUpPrefix; } } //每个访视 根据项目配置生成任务 双审生成两个 TaskUrgentType? taskUrgentType = null; if (subjectVisit.PDState == PDStateEnum.PDProgress) { taskUrgentType = TaskUrgentType.PDProgress; } else if (subjectVisit.IsEnrollmentConfirm) { taskUrgentType = TaskUrgentType.EnrollmentConfirm; } else if (subjectVisit.IsUrgent) { taskUrgentType = TaskUrgentType.VisitUrgent; } bool isCanEditUrgentState = taskUrgentType == TaskUrgentType.EnrollmentConfirm || taskUrgentType == TaskUrgentType.PDProgress ? false : true; //为防止脏数据 这里也多判断一次 var existCurrentVisitTaskList = _visitTaskRepository.Where(t => t.TrialId == trialId && t.SubjectId == subjectVisit.SubjectId && t.TrialReadingCriterionId == trialReadingCriterionConfig.TrialReadingCriterionId && t.TaskState == TaskState.Effect && t.SourceSubjectVisitId == subjectVisit.Id).ToList(); //只有单重阅片 if (trialReadingCriterionConfig.ReadingType == ReadingMethod.Single) { VisitTask? singleTask = existCurrentVisitTaskList.FirstOrDefault(t => t.ArmEnum == Arm.SingleReadingArm); if (!existCurrentVisitTaskList.Any(t => t.ArmEnum == Arm.SingleReadingArm)) { currentMaxCodeInt = currentMaxCodeInt + 1; singleTask = await _visitTaskRepository.AddAsync(new VisitTask() { TrialId = trialId, SubjectId = subjectVisit.SubjectId, IsUrgent = subjectVisit.IsUrgent, TaskBlindName = blindTaskName, TaskName = subjectVisit.VisitName, VisitTaskNum = subjectVisit.VisitNum, TaskUrgentType = taskUrgentType, IsCanEditUrgentState = isCanEditUrgentState, //CheckPassedTime = subjectVisit.CheckPassedTime, ArmEnum = Arm.SingleReadingArm, //特殊 Code = currentMaxCodeInt + 1, SourceSubjectVisitId = subjectVisit.Id, TaskCode = AppSettings.GetCodeStr(currentMaxCodeInt + 1, nameof(VisitTask)), ReadingCategory = ReadingCategory.Visit, TrialReadingCriterionId = trialReadingCriterionConfig.TrialReadingCriterionId, IsNeedClinicalDataSign = isNeedClinicalDataSign, IsClinicalDataSign = isClinicalDataSign, SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget) }); } _provider.Set($"{trialId}_{StaticData.CacheKey.TaskMaxCode}", currentMaxCodeInt, TimeSpan.FromMinutes(30)); var defaultState = trialReadingCriterionConfig.FollowVisitAutoAssignDefaultState == TaskAllocateDefaultState.InitAllocated ? TaskAllocationState.InitAllocated : TaskAllocationState.Allocated; } } } await _visitTaskRepository.SaveChangesAsync(); } private bool IsNeedClinicalDataSign(ReadingCategory readingCategory, bool isbaseLine, Guid trialReadingCriterionId, List trialClinicalDataSetList) { //访视 if (readingCategory == ReadingCategory.Visit) { if (isbaseLine) { //return trialClinicalDataSetList.Where(t=>t.CriterionEnumList.Any(c=>c==(int)criterionType) && (t.ClinicalDataLevel == ClinicalLevel.Subject || t.ClinicalDataLevel == ClinicalLevel.SubjectVisit)).Count()> 0; return trialClinicalDataSetList.Any(t => t.TrialClinicalDataSetCriteriaList.Any(c => c.TrialReadingCriterionId == trialReadingCriterionId) && (t.ClinicalDataLevel == ClinicalLevel.Subject || t.ClinicalDataLevel == ClinicalLevel.SubjectVisit)); } else { return trialClinicalDataSetList.Any(t => t.TrialClinicalDataSetCriteriaList.Any(c => c.TrialReadingCriterionId == trialReadingCriterionId) && t.ClinicalDataLevel == ClinicalLevel.SubjectVisit); } } else if (readingCategory == ReadingCategory.Judge) { return false; } //阅片期 else if (readingCategory == ReadingCategory.Global) { return trialClinicalDataSetList.Any(t => t.TrialClinicalDataSetCriteriaList.Any(c => c.TrialReadingCriterionId == trialReadingCriterionId) && t.ClinicalDataLevel == ClinicalLevel.ImageRead); } // 肿瘤学 else if (readingCategory == ReadingCategory.Oncology) { return trialClinicalDataSetList.Any(t => t.TrialClinicalDataSetCriteriaList.Any(c => c.TrialReadingCriterionId == trialReadingCriterionId) && t.ClinicalDataLevel == ClinicalLevel.OncologyRead); } else { return false; } } // 有可能在任务生成之前 就签名完了临床数据 private bool IsClinicalDataSign(ReadingCategory readingCategory, bool isbaseLine, Guid trialReadingCriterionId, List trialClinicalDataSetList, Guid readingId, Guid trialId) { //不需要签名的 直接返回 if (IsNeedClinicalDataSign(readingCategory, isbaseLine, trialReadingCriterionId, trialClinicalDataSetList) == false) { return false; } var isClinicalDataSign = false; var needSignCount = 0; //CRC 的自动签名 不用管 只用处理PM的就好 var haveSignedCount = _readingClinicalDataRepository .Where(t => t.TrialId == trialId && t.IsSign && t.ReadingClinicalDataState == ReadingClinicalDataStatus.HaveSigned && t.ReadingId == readingId && t.ClinicalDataTrialSet.UploadRole == UploadRole.PM).Count(); var readModule = _readModuleRepository.Where(t => t.Id == readingId).FirstOrDefault(); //CRC 阅片期自定义结构化录入是否签名 bool crcReadModuleSign = true; //访视 if (readingCategory == ReadingCategory.Visit) { if (isbaseLine) { //CRC 的自动签名 不用管 只用处理PM 的就好 needSignCount = trialClinicalDataSetList.Where(t => t.TrialClinicalDataSetCriteriaList.Any(c => c.TrialReadingCriterionId == trialReadingCriterionId) && (t.ClinicalDataLevel == ClinicalLevel.Subject || t.ClinicalDataLevel == ClinicalLevel.SubjectVisit) && t.UploadRole == UploadRole.PM).Count(); } else { needSignCount = trialClinicalDataSetList.Where(t => t.TrialClinicalDataSetCriteriaList.Any(c => c.TrialReadingCriterionId == trialReadingCriterionId) && t.ClinicalDataLevel == ClinicalLevel.SubjectVisit && t.UploadRole == UploadRole.PM).Count(); } } else if (readingCategory == ReadingCategory.Judge) { } //阅片期 else if (readingCategory == ReadingCategory.Global) { needSignCount = trialClinicalDataSetList.Where(t => t.TrialClinicalDataSetCriteriaList.Any(c => c.TrialReadingCriterionId == trialReadingCriterionId) && t.ClinicalDataLevel == ClinicalLevel.ImageRead && t.UploadRole == UploadRole.PM).Count(); if (readModule != null) { // 不存在需要CRC上传的临床数据 或者 PM已确认 crcReadModuleSign = !trialClinicalDataSetList.Any(x => x.UploadRole == UploadRole.CRC && x.ClinicalDataLevel == ClinicalLevel.ImageRead && x.ClinicalUploadType == ClinicalUploadType.Structuring && x.TrialClinicalDataSetCriteriaList.Any(c => c.TrialReadingCriterionId == trialReadingCriterionId)) || readModule.IsPMConfirm; } } // 肿瘤学 else if (readingCategory == ReadingCategory.Oncology) { needSignCount = trialClinicalDataSetList.Where(t => t.TrialClinicalDataSetCriteriaList.Any(c => c.TrialReadingCriterionId == trialReadingCriterionId) && t.ClinicalDataLevel == ClinicalLevel.OncologyRead && t.UploadRole == UploadRole.PM).Count(); if (readModule != null) { // 不存在需要CRC上传的临床数据 或者 PM已确认 crcReadModuleSign = !trialClinicalDataSetList.Any(x => x.UploadRole == UploadRole.CRC && x.ClinicalDataLevel == ClinicalLevel.OncologyRead && x.ClinicalUploadType == ClinicalUploadType.Structuring && x.TrialClinicalDataSetCriteriaList.Any(c => c.TrialReadingCriterionId == trialReadingCriterionId)) || readModule.IsPMConfirm; } } else { needSignCount = trialClinicalDataSetList.Where(t => t.TrialClinicalDataSetCriteriaList.Any(c => c.TrialReadingCriterionId == trialReadingCriterionId) && t.ClinicalDataLevel == ClinicalLevel.OncologyRead && t.UploadRole == UploadRole.PM).Count(); } //可能仅仅CRC 基线 没有PM if (needSignCount == haveSignedCount && crcReadModuleSign) { isClinicalDataSign = true; } return isClinicalDataSign; } public DateTime GetSuggessFinishTime(bool isInOrder, UrgentType urgentType) { var datetime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 22, 0, 0).AddDays(7); //switch (urgentType) //{ // case UrgentType.NotUrget: // datetime= new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day + 7, 22, 0, 0); // break; // case UrgentType.EnrollConfirm: // datetime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day , 22, 0, 0); // break; // case UrgentType.EnrollConfirmOtherNotUrgent: // datetime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day+5, 22, 0, 0); // break; // case UrgentType.PDVProgressVisitOrGlobal: // datetime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 22, 0, 0); // break; // case UrgentType.PDVProgressJudge: // datetime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day+1, 22, 0, 0); // break; // //不加急 7天 // case UrgentType.NormalUrgent: // datetime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day + 7, 22, 0, 0); // break; // default: // break; //} return datetime; } public async Task AddTaskAsync(GenerateTaskCommand generateTaskCommand) { var trialId = generateTaskCommand.TrialId; var isAssignSubjectToDoctor = generateTaskCommand.IsAssignSubjectToDoctor; var trialReadingCriterionConfigList = _trialReadingCriterionRepository.Where(t => t.TrialId == trialId && t.ReadingInfoSignTime != null).Select(t => new { TrialReadingCriterionId = t.Id, t.ReadingTool, t.ReadingType, t.IsReadingTaskViewInOrder, t.IsFollowVisitAutoAssign, t.IsAutoCreate, t.IsFollowGlobalVisitAutoAssign, t.FollowGlobalVisitAutoAssignDefaultState, t.FollowVisitAutoAssignDefaultState, t.TaskAllocateObjEnum, t.CriterionType }).ToList(); var visitBlindConfig = _trialRepository.Where(t => t.Id == trialId).Select(t => new { t.BlindBaseLineName, t.BlindFollowUpPrefix }).FirstOrDefault(); //获取确认的临床数据配置 var clinicalDataConfirmList = _trialClinicalDataSetRepository.Where(t => t.TrialId == trialId && t.IsConfirm).Include(t => t.TrialClinicalDataSetCriteriaList).ToList(); 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 GenerateTaskCategory.Visit: //每个Subject 的每个访视 都要根据每个标准进行任务的生成 和分配(考虑回退后 的分配) foreach (var subjectGroup in generateTaskCommand.VisitGenerataTaskList.GroupBy(t => t.SubjectId).Select(g => new { SubjectId = g.Key, SubjectVisitList = g.ToList() })) { foreach (var subjectVisit in subjectGroup.SubjectVisitList) { var subjectVisitInfo = await _subjectVisitRepository.Where(x => x.Id == subjectVisit.Id).Select(x => new { x.PDState, x.IsEnrollmentConfirm, x.IsUrgent, }).FirstNotNullAsync(); TaskUrgentType? taskUrgentType = null; if (subjectVisitInfo.PDState == PDStateEnum.PDProgress) { taskUrgentType = TaskUrgentType.PDProgress; } else if (subjectVisitInfo.IsEnrollmentConfirm) { taskUrgentType = TaskUrgentType.EnrollmentConfirm; } else if (subjectVisitInfo.IsUrgent) { taskUrgentType = TaskUrgentType.VisitUrgent; } bool isCanEditUrgentState = taskUrgentType == TaskUrgentType.EnrollmentConfirm || taskUrgentType == TaskUrgentType.PDProgress ? false : true; var visitNumList = _subjectVisitRepository.Where(t => t.SubjectId == subjectGroup.SubjectId && t.IsLostVisit == false).OrderBy(t => t.VisitNum).Select(t => t.VisitNum).ToList(); foreach (var trialReadingCriterionConfig in trialReadingCriterionConfigList) { var trialReadingCriterionId = trialReadingCriterionConfig.TrialReadingCriterionId; if (trialReadingCriterionConfig.IsAutoCreate == true) { var blindTaskName = string.Empty; var isNeedClinicalDataSign = IsNeedClinicalDataSign(ReadingCategory.Visit, subjectVisit.IsBaseLine, trialReadingCriterionId, clinicalDataConfirmList); var isClinicalDataSign = IsClinicalDataSign(ReadingCategory.Visit, subjectVisit.IsBaseLine, trialReadingCriterionId, clinicalDataConfirmList, subjectVisit.Id, trialId); var isFrontTaskNeedSignButNotSign = await _visitTaskRepository.AnyAsync(t => t.TrialReadingCriterionId == trialReadingCriterionId && t.SubjectId == subjectVisit.SubjectId && t.TaskState == TaskState.Effect && t.VisitTaskNum < subjectVisit.VisitNum && t.IsNeedClinicalDataSign == true && t.IsClinicalDataSign == false); if (visitNumList.IndexOf(subjectVisit.VisitNum) == 0) { blindTaskName = visitBlindConfig.BlindBaseLineName; } else { if (trialReadingCriterionConfig.IsReadingTaskViewInOrder) { blindTaskName = visitBlindConfig.BlindFollowUpPrefix + " " + visitNumList.IndexOf(subjectVisit.VisitNum); } else { blindTaskName = visitBlindConfig.BlindFollowUpPrefix; } } if (trialReadingCriterionConfig.ReadingType == ReadingMethod.Single) { var singleTask = await _visitTaskRepository.AddAsync(new VisitTask() { TrialId = trialId, SubjectId = subjectVisit.SubjectId, IsUrgent = subjectVisit.IsUrgent, TaskBlindName = blindTaskName, TaskName = subjectVisit.VisitName, TaskUrgentType = taskUrgentType, IsCanEditUrgentState = isCanEditUrgentState, 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, TrialReadingCriterionId = trialReadingCriterionConfig.TrialReadingCriterionId, IsNeedClinicalDataSign = isNeedClinicalDataSign, IsClinicalDataSign = isClinicalDataSign, IsFrontTaskNeedSignButNotSign= isFrontTaskNeedSignButNotSign }); currentMaxCodeInt = currentMaxCodeInt + 1; _provider.Set($"{trialId}_{StaticData.CacheKey.TaskMaxCode}", currentMaxCodeInt, TimeSpan.FromMinutes(30)); #region 重阅/退回的时候,需要后续任务生成 if (trialReadingCriterionConfig.IsReadingTaskViewInOrder) { //之前有回退到影像上传的访视 那么当前访视一致性核查通过的时候,当前访视生成但是不分配出去(排除失访的) var beforeBackVisitTask = await _visitTaskRepository.Where(t => t.TrialId == trialId && t.SubjectId == subjectVisit.SubjectId && t.TrialReadingCriterionId== trialReadingCriterionId && t.VisitTaskNum < subjectVisit.VisitNum && t.ReadingCategory == ReadingCategory.Visit && t.SourceSubjectVisit.CheckState != CheckStateEnum.CVPassed && t.SourceSubjectVisit.IsLostVisit == false).OrderBy(t => t.VisitTaskNum).FirstOrDefaultAsync(); singleTask.SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget); if (beforeBackVisitTask == null) { var followBackVisitTask = await _visitTaskRepository.Where(t => t.TrialId == trialId && t.SubjectId == subjectVisit.SubjectId && t.TrialReadingCriterionId == trialReadingCriterionId && t.VisitTaskNum > subjectVisit.VisitNum && t.ReadingCategory == ReadingCategory.Visit && t.SourceSubjectVisit.CheckState != CheckStateEnum.CVPassed && t.SourceSubjectVisit.IsLostVisit == false).OrderBy(t => t.VisitTaskNum).FirstOrDefaultAsync(); //存在退回访视1 又退回基线 这种情况 生成任务 考虑基线先一致性核查通过,但是访视1还未通过时 生成任务 var followVisitTaskList = await _visitTaskRepository .Where(t => t.TrialId == trialId && t.SubjectId == subjectVisit.SubjectId && t.TrialReadingCriterionId == trialReadingCriterionId && t.VisitTaskNum > subjectVisit.VisitNum && t.SourceSubjectVisit.CheckState == CheckStateEnum.CVPassed && t.ReadingCategory == ReadingCategory.Visit && t.IsAnalysisCreate == false, true) .WhereIf(followBackVisitTask != null, t => t.VisitTaskNum < followBackVisitTask.VisitTaskNum) .ToListAsync(); var followVisitGroup = followVisitTaskList.GroupBy(t => t.VisitTaskNum); //每个访视去判断 是分配还是生成 foreach (var visitGroup in followVisitGroup) { //如果后续访视已分配有效 就不用处理 if (visitGroup.Any(t => t.TaskState == TaskState.Effect && t.ArmEnum == Arm.SingleReadingArm)) { //不做处理 } else { var arm = visitGroup.FirstOrDefault(t => t.TaskState == TaskState.Effect && t.DoctorUserId == null && t.ArmEnum == Arm.SingleReadingArm); if (arm != null) { arm.SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget); } else { var latestTask = visitGroup.Where(t => t.ArmEnum == Arm.SingleReadingArm).OrderByDescending(t => t.CreateTime).First(); var taskOne = await _visitTaskRepository.AddAsync(new VisitTask() { TrialId = trialId, SubjectId = subjectVisit.SubjectId, IsUrgent = subjectVisit.IsUrgent, ArmEnum = Arm.SingleReadingArm,//特殊 Code = currentMaxCodeInt + 1, TaskCode = AppSettings.GetCodeStr(currentMaxCodeInt + 1, nameof(VisitTask)), ReadingCategory = ReadingCategory.Visit, TaskUrgentType = latestTask.TaskUrgentType, SourceSubjectVisitId = latestTask.SourceSubjectVisitId, VisitTaskNum = latestTask.VisitTaskNum, TaskBlindName = visitBlindConfig.BlindFollowUpPrefix + " " + visitNumList.IndexOf(latestTask.VisitTaskNum), TaskName = latestTask.TaskName, BlindSubjectCode = latestTask.BlindSubjectCode, BlindTrialSiteCode = latestTask.BlindTrialSiteCode, IsAnalysisCreate = latestTask.IsAnalysisCreate, IsSelfAnalysis = latestTask.IsSelfAnalysis, SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget), TrialReadingCriterionId = latestTask.TrialReadingCriterionId, IsNeedClinicalDataSign = latestTask.IsNeedClinicalDataSign, IsClinicalDataSign = latestTask.IsClinicalDataSign }); currentMaxCodeInt = currentMaxCodeInt + 1; _provider.Set($"{trialId}_{StaticData.CacheKey.TaskMaxCode}", currentMaxCodeInt, TimeSpan.FromMinutes(30)); } } } } } else { singleTask.SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget); } #endregion } } } await _subjectVisitRepository.BatchUpdateNoTrackingAsync(t => t.TrialId == trialId && t.Id == subjectVisit.Id, u => new SubjectVisit() { IsVisitTaskGenerated = true }); } } break; case GenerateTaskCategory.ReReading: var reReadingVisitTask = generateTaskCommand.ReReadingTask; Guid? subjectVisitId = Guid.Empty; if (reReadingVisitTask.SourceSubjectVisitId == null) { subjectVisitId = _readModuleRepository.Where(t => t.Id == reReadingVisitTask.SouceReadModuleId).Select(t => t.SubjectVisitId).FirstOrDefault(); } else { subjectVisitId = reReadingVisitTask.SourceSubjectVisitId; } var subjectVisitUrgentInfo = await _subjectVisitRepository.Where(x => x.Id == subjectVisitId).Select(x => new { x.PDState, x.IsEnrollmentConfirm, x.IsUrgent, }).FirstNotNullAsync(); TaskUrgentType? taskUrgent = null; if (subjectVisitUrgentInfo.PDState == PDStateEnum.PDProgress) { taskUrgent = TaskUrgentType.PDProgress; } else if (subjectVisitUrgentInfo.IsEnrollmentConfirm) { taskUrgent = TaskUrgentType.EnrollmentConfirm; } else if (subjectVisitUrgentInfo.IsUrgent) { taskUrgent = TaskUrgentType.VisitUrgent; } bool isCanEditUrgent = taskUrgent == TaskUrgentType.EnrollmentConfirm || taskUrgent == TaskUrgentType.PDProgress ? false : true; //加一个去重的判断 IR 申请重阅的时候,有脏数据 (例如多个follow 2 ),但是生成时候不生成 //var existTask = _visitTaskRepository.Where(t => t.TrialId == trialId && t.SubjectId == reReadingVisitTask.SubjectId //&& t.TrialReadingCriterionId == reReadingVisitTask.TrialReadingCriterionId && t.TaskState == TaskState.Effect // && t.SourceSubjectVisitId == reReadingVisitTask.SourceSubjectVisitId && t.ArmEnum == reReadingVisitTask.ArmEnum && t.DoctorUserId == reReadingVisitTask.DoctorUserId).FirstOrDefault(); var newTask = await _visitTaskRepository.AddAsync(new VisitTask() { TrialId = reReadingVisitTask.TrialId, SubjectId = reReadingVisitTask.SubjectId, ArmEnum = reReadingVisitTask.ArmEnum, TaskName = reReadingVisitTask.TaskName, TaskBlindName = reReadingVisitTask.TaskBlindName, IsUrgent = reReadingVisitTask.IsAnalysisCreate ? false : subjectVisitUrgentInfo.IsUrgent, TaskUrgentType = reReadingVisitTask.IsAnalysisCreate ? null : taskUrgent, IsCanEditUrgentState = isCanEditUrgent, 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)), IsAnalysisCreate = reReadingVisitTask.IsAnalysisCreate, IsSelfAnalysis = reReadingVisitTask.IsSelfAnalysis, BlindSubjectCode = reReadingVisitTask.BlindSubjectCode, BlindTrialSiteCode = reReadingVisitTask.BlindTrialSiteCode, TrialReadingCriterionId = reReadingVisitTask.TrialReadingCriterionId, IsNeedClinicalDataSign = reReadingVisitTask.IsNeedClinicalDataSign, IsClinicalDataSign = reReadingVisitTask.IsClinicalDataSign, BeforeConvertedTaskId = reReadingVisitTask.BeforeConvertedTaskId, ReReadingApplyState = ReReadingApplyState.Default, // TaskAllocationState = reReadingVisitTask.TaskAllocationState, // AllocateTime = DateTime.Now, //DoctorUserId = reReadingVisitTask.DoctorUserId, SuggesteFinishedTime= reReadingVisitTask.SuggesteFinishedTime, }); generateTaskCommand.Action(newTask); if (reReadingVisitTask.ReadingCategory == ReadingCategory.Judge) { var judgeRecord = await _readingJudgeInfoRepository.Where(t => t.JudgeTaskId == reReadingVisitTask.Id).FirstOrDefaultAsync(); var origenalTaskIdList = new Guid[] { judgeRecord.TaskIdOne, judgeRecord.TaskIdTwo }; await _visitTaskRepository.BatchUpdateNoTrackingAsync(x => origenalTaskIdList.Contains(x.Id), x => new VisitTask() { JudgeVisitTaskId = newTask.Id }); await _readingJudgeInfoRepository.AddAsync(new ReadingJudgeInfo() { JudgeTaskId = newTask.Id, SubjectId = judgeRecord.SubjectId, TrialId = judgeRecord.TrialId, TaskIdOne = judgeRecord.TaskIdOne, TaskIdTwo = judgeRecord.TaskIdTwo }); } //是否增加任务类别 currentMaxCodeInt = currentMaxCodeInt + 1; _provider.Set($"{trialId}_{StaticData.CacheKey.TaskMaxCode}", currentMaxCodeInt, TimeSpan.FromMinutes(30)); //} break; case GenerateTaskCategory.SelfConsistent: 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, TaskState = TaskState.Effect, Code = currentMaxCodeInt + 1, TaskCode = AppSettings.GetCodeStr(currentMaxCodeInt + 1, nameof(VisitTask)), DoctorUserId = task.DoctorUserId, TaskAllocationState = TaskAllocationState.Allocated, AllocateTime = DateTime.Now, SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget), SouceReadModuleId = task.SouceReadModuleId, SourceSubjectVisitId = task.SourceSubjectVisitId, ConsistentAnalysisOriginalTaskId = task.Id, IsAnalysisCreate = true, IsSelfAnalysis = true, TrialReadingCriterionId = task.TrialReadingCriterionId, BlindTrialSiteCode = task.BlindTrialSiteCode, BlindSubjectCode = task.BlindSubjectCode, IsNeedClinicalDataSign = task.IsNeedClinicalDataSign, IsClinicalDataSign = task.IsClinicalDataSign }; await _visitTaskRepository.AddAsync(consistentTask); currentMaxCodeInt = currentMaxCodeInt + 1; _provider.Set($"{trialId}_{StaticData.CacheKey.TaskMaxCode}", currentMaxCodeInt, TimeSpan.FromMinutes(30)); } break; case GenerateTaskCategory.GroupConsistent: foreach (var task in generateTaskCommand.GenerataGroupConsistentTaskList) { 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, TaskState = TaskState.Effect, Code = currentMaxCodeInt + 1, TaskCode = AppSettings.GetCodeStr(currentMaxCodeInt + 1, nameof(VisitTask)), SouceReadModuleId = task.SouceReadModuleId, SourceSubjectVisitId = task.SourceSubjectVisitId, DoctorUserId = task.DoctorUserId, TaskAllocationState = TaskAllocationState.Allocated, AllocateTime = DateTime.Now, SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget), IsAnalysisCreate = true, IsSelfAnalysis = false, TrialReadingCriterionId = task.TrialReadingCriterionId, BlindTrialSiteCode = task.BlindTrialSiteCode, BlindSubjectCode = task.BlindSubjectCode, IsNeedClinicalDataSign = task.IsNeedClinicalDataSign, IsClinicalDataSign = task.IsClinicalDataSign }; await _visitTaskRepository.AddAsync(consistentTask); currentMaxCodeInt = currentMaxCodeInt + 1; _provider.Set($"{trialId}_{StaticData.CacheKey.TaskMaxCode}", currentMaxCodeInt, TimeSpan.FromMinutes(30)); } break; case GenerateTaskCategory.Judge: var firstTask = await _visitTaskRepository.Where(x => generateTaskCommand.JudgeVisitTaskIdList.Contains(x.Id)).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, IsCanEditUrgentState = firstTask.IsCanEditUrgentState, SourceSubjectVisitId = firstTask.SourceSubjectVisitId, SouceReadModuleId = firstTask.SouceReadModuleId, TaskCode = AppSettings.GetCodeStr(currentMaxCodeInt + 1, nameof(VisitTask)), TaskState = TaskState.Effect, TaskBlindName = firstTask.TaskBlindName, TrialReadingCriterionId = firstTask.TrialReadingCriterionId, }; 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 GenerateTaskCategory.Global: var originalTaskInfo = await _visitTaskRepository.Where(x => x.Id == generateTaskCommand.OriginalVisitId).Include(x => x.TrialReadingCriterion).FirstNotNullAsync(); //var criterionType = await _trialReadingCriterionRepository.Where(t => t.Id == originalTaskInfo.TrialReadingCriterionId).Select(t => t.CriterionType).FirstOrDefaultAsync(); // 需要添加全局任务再添加 if (originalTaskInfo.TrialReadingCriterion.IsGlobalReading) { var visitNumList = _subjectVisitRepository.Where(t => t.SubjectId == originalTaskInfo.SubjectId && t.IsLostVisit == false).OrderBy(t => t.VisitNum).Select(t => t.VisitNum).ToList(); foreach (var item in generateTaskCommand.ReadingGenerataTaskList) { item.VisitNum = originalTaskInfo.VisitTaskNum; var task1 = await _visitTaskRepository.AddAsync(new VisitTask() { TrialId = trialId, //IsConvertedTask = originalTaskInfo.IsConvertedTask, SubjectId = item.SubjectId, IsUrgent = originalTaskInfo.IsUrgent, VisitTaskNum = item.VisitNum + ReadingCommon.TaskNumDic[ReadingCategory.Global], TaskName = item.ReadingName, ArmEnum = originalTaskInfo.ArmEnum,//特殊 TaskUrgentType = originalTaskInfo.TaskUrgentType, IsCanEditUrgentState = originalTaskInfo.IsCanEditUrgentState, TaskUrgentRemake = originalTaskInfo.TaskUrgentRemake, DoctorUserId = originalTaskInfo.DoctorUserId, AllocateTime = DateTime.Now, TaskAllocationState = TaskAllocationState.Allocated, SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget), Code = currentMaxCodeInt + 1, TaskBlindName = "G-" + visitNumList.IndexOf(originalTaskInfo.VisitTaskNum), SouceReadModuleId = item.ReadModuleId, TaskCode = AppSettings.GetCodeStr(currentMaxCodeInt + 1, nameof(VisitTask)), ReadingCategory = item.ReadingCategory, TrialReadingCriterionId = originalTaskInfo.TrialReadingCriterionId, IsNeedClinicalDataSign = IsNeedClinicalDataSign(ReadingCategory.Global, false, originalTaskInfo.TrialReadingCriterionId, clinicalDataConfirmList), IsClinicalDataSign = IsClinicalDataSign(ReadingCategory.Global, false, originalTaskInfo.TrialReadingCriterionId, clinicalDataConfirmList, item.ReadModuleId, trialId) }); currentMaxCodeInt = currentMaxCodeInt + 1; _provider.Set($"{trialId}_{StaticData.CacheKey.TaskMaxCode}", currentMaxCodeInt, TimeSpan.FromMinutes(30)); } } break; case GenerateTaskCategory.Oncology: originalTaskInfo = await _visitTaskRepository.Where(x => x.Id == generateTaskCommand.OriginalVisitId).FirstNotNullAsync(); //criterionType = await _trialReadingCriterionRepository.Where(t => t.Id == originalTaskInfo.TrialReadingCriterionId).Select(t => t.CriterionType).FirstOrDefaultAsync(); foreach (var item in generateTaskCommand.ReadingGenerataTaskList) { item.VisitNum = await _readModuleRepository.Where(x => x.Id == item.ReadModuleId).Select(x => x.SubjectVisit.VisitNum).FirstOrDefaultAsync(); var singleTask = await _visitTaskRepository.AddAsync(new VisitTask() { TrialId = trialId, SubjectId = item.SubjectId, IsUrgent = originalTaskInfo.IsUrgent, TaskName = item.ReadingName, //IsConvertedTask = originalTaskInfo.IsConvertedTask, // 原任务是全局任务 加0.03 就好 VisitTaskNum = originalTaskInfo.VisitTaskNum + 0.03m, ArmEnum = Arm.TumorArm, //特殊 Code = currentMaxCodeInt + 1, SouceReadModuleId = item.ReadModuleId, TaskBlindName = item.ReadingName, TaskCode = AppSettings.GetCodeStr(currentMaxCodeInt + 1, nameof(VisitTask)), ReadingCategory = item.ReadingCategory, TrialReadingCriterionId = originalTaskInfo.TrialReadingCriterionId, IsNeedClinicalDataSign = IsNeedClinicalDataSign(ReadingCategory.Oncology, false, originalTaskInfo.TrialReadingCriterionId, clinicalDataConfirmList), IsClinicalDataSign = IsClinicalDataSign(ReadingCategory.Oncology, false, originalTaskInfo.TrialReadingCriterionId, clinicalDataConfirmList, item.ReadModuleId, trialId) }); singleTask.AllocateTime = DateTime.Now; currentMaxCodeInt = currentMaxCodeInt + 1; _provider.Set($"{trialId}_{StaticData.CacheKey.TaskMaxCode}", currentMaxCodeInt, TimeSpan.FromMinutes(30)); } break; } await _visitTaskRepository.SaveChangesAsync(); } } }