//--------------------------------------------------------------------
// 此代码由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 IRepository _readModuleRepository;
private readonly IMapper _mapper;
private readonly IUserInfo _userInfo;
private readonly IRepository _visitTaskReReadingRepository;
private readonly IRepository _trialReadingCriterionRepository;
public VisitTaskHelpeService(IRepository visitTaskRepository, IRepository subjectUserRepository, IRepository trialRepository, IEasyCachingProvider provider,
IRepository subjectVisitRepository,
IRepository readModuleRepository,
IRepository readingJudgeInfoRepository,
IRepository taskAllocationRuleRepository, IMapper mapper, IUserInfo userInfo, IRepository visitTaskReReadingRepository, IRepository trialReadingCriterionRepository)
{
_visitTaskRepository = visitTaskRepository;
_trialRepository = trialRepository;
this._readModuleRepository = readModuleRepository;
_provider = provider;
_subjectVisitRepository = subjectVisitRepository;
this._readingJudgeInfoRepository = readingJudgeInfoRepository;
_taskAllocationRuleRepository = taskAllocationRuleRepository;
_subjectUserRepository = subjectUserRepository;
_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 BaseCritrionGenerateVisitTask(Guid trialId, Guid confirmedTrialReadingCriterionId)
{
//找到一致性核查通过且没有产生任务的访视
var needGenerateVisit = await _subjectVisitRepository.Where(t => t.TrialId == trialId && t.CheckState == CheckStateEnum.CVPassed &&
!t.VisitTaskList.Any(u=>u.TrialReadingCriterionId== confirmedTrialReadingCriterionId &&u.SourceSubjectVisitId==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 }).FirstOrDefaultAsync();
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 assignConfigList = await _subjectUserRepository.Where(t => t.TrialId == trialId && t.TrialReadingCriterionId == trialReadingCriterionConfig.TrialReadingCriterionId && t.SubjectId == subjectGroup.SubjectId && t.OrignalSubjectUserId == null && t.IsConfirmed).Select(u => new { u.DoctorUserId, u.ArmEnum }).ToListAsync();
var visitNumList = _subjectVisitRepository.Where(t => t.SubjectId == subjectGroup.SubjectId && t.IsLostVisit == false).Select(t=>t.VisitNum).ToList();
foreach (var subjectVisit in subjectGroup.SubjectVisitList)
{
var blindTaskName = string.Empty;
if (visitNumList.IndexOf(subjectVisit.VisitNum) == 0)
{
blindTaskName = "Baseline";
}
else
{
if (trialReadingCriterionConfig.IsReadingTaskViewInOrder)
{
blindTaskName = AppSettings.BlindTaskPrefix + visitNumList.IndexOf(subjectVisit.VisitNum);
}
else
{
blindTaskName = AppSettings.BlindTaskPrefix;
}
}
if (trialReadingCriterionConfig.ReadingType == ReadingMethod.Double)
{
//每个访视 根据项目配置生成任务 双审生成两个
var task1 = await _visitTaskRepository.AddAsync(new VisitTask()
{
TrialId = trialId,
SubjectId = subjectVisit.SubjectId,
IsUrgent = subjectVisit.IsUrgent,
TaskBlindName = blindTaskName,
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,
TrialReadingCriterionId = trialReadingCriterionConfig.TrialReadingCriterionId
});
var task2 = await _visitTaskRepository.AddAsync(new VisitTask()
{
TrialId = trialId,
SubjectId = subjectVisit.SubjectId,
IsUrgent = subjectVisit.IsUrgent,
TaskBlindName = blindTaskName,
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,
TrialReadingCriterionId = trialReadingCriterionConfig.TrialReadingCriterionId
});
currentMaxCodeInt = currentMaxCodeInt + 2;
_provider.Set($"{trialId}_{StaticData.CacheKey.TaskMaxCode}", currentMaxCodeInt, TimeSpan.FromMinutes(30));
var defaultState = trialReadingCriterionConfig.FollowVisitAutoAssignDefaultState == TaskAllocateDefaultState.InitAllocated ? TaskAllocationState.InitAllocated : TaskAllocationState.Allocated;
if (assignConfigList.Any(t => t.ArmEnum == Arm.DoubleReadingArm1))
{
task1.TaskAllocationState = defaultState;
//分配给对应Arm的人
task1.DoctorUserId = assignConfigList.FirstOrDefault(t => t.ArmEnum == Arm.DoubleReadingArm1).DoctorUserId;
task1.AllocateTime = DateTime.Now;
task1.SuggesteFinishedTime = DateTime.Now.AddDays(7);
}
if (assignConfigList.Any(t => t.ArmEnum == Arm.DoubleReadingArm2))
{
task2.TaskAllocationState = defaultState;
task2.DoctorUserId = assignConfigList.FirstOrDefault(t => t.ArmEnum == Arm.DoubleReadingArm2).DoctorUserId;
task2.AllocateTime = DateTime.Now;
task2.SuggesteFinishedTime = DateTime.Now.AddDays(7);
}
}
else 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,
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
});
currentMaxCodeInt = currentMaxCodeInt + 1;
_provider.Set($"{trialId}_{StaticData.CacheKey.TaskMaxCode}", currentMaxCodeInt, TimeSpan.FromMinutes(30));
var defaultState = trialReadingCriterionConfig.FollowVisitAutoAssignDefaultState == TaskAllocateDefaultState.InitAllocated ? TaskAllocationState.InitAllocated : TaskAllocationState.Allocated;
if (assignConfigList.Any(t => t.ArmEnum == Arm.SingleReadingArm))
{
singleTask.TaskAllocationState = defaultState;
singleTask.DoctorUserId = assignConfigList.FirstOrDefault(t => t.ArmEnum == Arm.SingleReadingArm).DoctorUserId;
singleTask.AllocateTime = DateTime.Now;
singleTask.SuggesteFinishedTime = DateTime.Now.AddDays(7);
}
}
await _visitTaskRepository.SaveChangesAsync();
}
}
}
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.IsFollowGlobalVisitAutoAssign, t.FollowGlobalVisitAutoAssignDefaultState, t.FollowVisitAutoAssignDefaultState,t.TaskAllocateObjEnum } ).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 visitNumList = _subjectVisitRepository.Where(t => t.SubjectId == subjectGroup.SubjectId && t.IsLostVisit==false).Select(t => t.VisitNum).ToList();
foreach (var trialReadingCriterionConfig in trialReadingCriterionConfigList)
{
var assignConfigList = await _subjectUserRepository.Where(t => t.TrialId == trialId && t.TrialReadingCriterionId == trialReadingCriterionConfig.TrialReadingCriterionId && t.SubjectId == subjectVisit.SubjectId && t.OrignalSubjectUserId == null && t.IsConfirmed).Select(u => new { u.DoctorUserId, u.ArmEnum }).ToListAsync();
var blindTaskName = string.Empty;
if (visitNumList.IndexOf(subjectVisit.VisitNum) == 0)
{
blindTaskName = "Baseline";
}
else
{
if (trialReadingCriterionConfig.IsReadingTaskViewInOrder)
{
blindTaskName = AppSettings.BlindTaskPrefix + visitNumList.IndexOf(subjectVisit.VisitNum);
}
else
{
blindTaskName = AppSettings.BlindTaskPrefix;
}
}
if (trialReadingCriterionConfig.ReadingType == ReadingMethod.Double)
{
//每个访视 根据项目配置生成任务 双审生成两个
var task1 = await _visitTaskRepository.AddAsync(new VisitTask()
{
TrialId = trialId,
SubjectId = subjectVisit.SubjectId,
IsUrgent = subjectVisit.IsUrgent,
TaskBlindName = blindTaskName,
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,
TrialReadingCriterionId = trialReadingCriterionConfig.TrialReadingCriterionId
});
var task2 = await _visitTaskRepository.AddAsync(new VisitTask()
{
TrialId = trialId,
SubjectId = subjectVisit.SubjectId,
IsUrgent = subjectVisit.IsUrgent,
TaskBlindName = blindTaskName,
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,
TrialReadingCriterionId = trialReadingCriterionConfig.TrialReadingCriterionId
});
currentMaxCodeInt = currentMaxCodeInt + 2;
_provider.Set($"{trialId}_{StaticData.CacheKey.TaskMaxCode}", currentMaxCodeInt, TimeSpan.FromMinutes(30));
#region 分配
if (isAssignSubjectToDoctor)
{
if (trialReadingCriterionConfig.TaskAllocateObjEnum == TaskAllocateObj.Subject)
{
var allocateSubjectArmList = _visitTaskRepository.Where(t => t.TrialReadingCriterionId == trialReadingCriterionConfig.TrialReadingCriterionId && 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)
{
}
else
{
//并且配置了医生
if (assignConfigList.Count > 0 && trialReadingCriterionConfig.IsFollowVisitAutoAssign)
{
#region 后续访视 未分配的进行再次分配,重置的或者失效的 需要重新生成新的任务 (PM 有序退回 或者PM 有序 申请重阅)
if (trialReadingCriterionConfig.IsReadingTaskViewInOrder)
{
//之前有回退到影像上传的访视 那么当前访视一致性核查通过的时候,当前访视生成但是不分配出去(排除失访的)
var beforeBackVisitTask = await _visitTaskRepository.Where(t => t.TrialId == trialId && t.TrialReadingCriterionId == trialReadingCriterionConfig.TrialReadingCriterionId && t.SubjectId == subjectVisit.SubjectId && t.VisitTaskNum < subjectVisit.VisitNum && t.ReadingCategory == ReadingCategory.Visit && t.SourceSubjectVisit.CheckState != CheckStateEnum.CVPassed && t.SourceSubjectVisit.IsLostVisit == false).OrderBy(t => t.VisitTaskNum).FirstOrDefaultAsync();
//之前有回退的,那么当前访视任务生成但是不分配
if (beforeBackVisitTask != null)
{
//不用进行额外处理
//访视2 PM 回退 基线回退 访视2先一致性核查通过,生成访视2任务,但是不分配
}
else
{
#region 当前访视根据配置规则分配出去
var defaultState = trialReadingCriterionConfig.FollowVisitAutoAssignDefaultState == TaskAllocateDefaultState.InitAllocated ? TaskAllocationState.InitAllocated : TaskAllocationState.Allocated;
if (assignConfigList.Any(t => t.ArmEnum == Arm.DoubleReadingArm1))
{
task1.TaskAllocationState = defaultState;
//分配给对应Arm的人
task1.DoctorUserId = assignConfigList.FirstOrDefault(t => t.ArmEnum == Arm.DoubleReadingArm1).DoctorUserId;
task1.AllocateTime = DateTime.Now;
task1.SuggesteFinishedTime = DateTime.Now.AddDays(7);
}
if (assignConfigList.Any(t => t.ArmEnum == Arm.DoubleReadingArm2))
{
task2.TaskAllocationState = defaultState;
task2.DoctorUserId = assignConfigList.FirstOrDefault(t => t.ArmEnum == Arm.DoubleReadingArm2).DoctorUserId;
task2.AllocateTime = DateTime.Now;
task2.SuggesteFinishedTime = DateTime.Now.AddDays(7);
}
#endregion
}
//后续最近的未一致性核查通过的访视任务
var followBackVisitTask = await _visitTaskRepository.Where(t => t.TrialId == trialId && t.TrialReadingCriterionId == trialReadingCriterionConfig.TrialReadingCriterionId && t.SubjectId == subjectVisit.SubjectId && 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.TrialReadingCriterionId == trialReadingCriterionConfig.TrialReadingCriterionId && t.SubjectId == subjectVisit.SubjectId && 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)
{
var arm1 = visitGroup.FirstOrDefault(t => t.TaskState == TaskState.Effect && t.TaskAllocationState == TaskAllocationState.NotAllocate && t.DoctorUserId == null && t.ArmEnum == Arm.DoubleReadingArm1);
if (arm1 != null)
{
arm1.TaskAllocationState = TaskAllocationState.Allocated;
arm1.AllocateTime = DateTime.Now;
arm1.DoctorUserId = task1.DoctorUserId;
arm1.SuggesteFinishedTime = DateTime.Now.AddDays(7);
}
else
{
var latestTask = visitGroup.Where(t => t.ArmEnum == Arm.DoubleReadingArm1).OrderByDescending(t => t.CreateTime).First();
var taskOne = await _visitTaskRepository.AddAsync(new VisitTask()
{
TrialId = trialId,
SubjectId = subjectVisit.SubjectId,
IsUrgent = subjectVisit.IsUrgent,
ArmEnum = Arm.DoubleReadingArm1,//特殊
Code = currentMaxCodeInt + 1,
TaskCode = AppSettings.GetCodeStr(currentMaxCodeInt + 1, nameof(VisitTask)),
ReadingCategory = ReadingCategory.Visit,
SourceSubjectVisitId = latestTask.SourceSubjectVisitId,
VisitTaskNum = latestTask.VisitTaskNum,
TaskBlindName = AppSettings.BlindTaskPrefix + visitNumList.IndexOf(latestTask.VisitTaskNum) ,
TaskName = latestTask.TaskName,
BlindSubjectCode = latestTask.BlindSubjectCode,
BlindTrialSiteCode = latestTask.BlindTrialSiteCode,
IsAnalysisCreate = latestTask.IsAnalysisCreate,
IsSelfAnalysis = latestTask.IsSelfAnalysis,
TaskAllocationState = TaskAllocationState.Allocated,
AllocateTime = DateTime.Now,
DoctorUserId = task1.DoctorUserId,
SuggesteFinishedTime = DateTime.Now.AddDays(7),
TrialReadingCriterionId = latestTask.TrialReadingCriterionId
});
currentMaxCodeInt = currentMaxCodeInt + 1;
_provider.Set($"{trialId}_{StaticData.CacheKey.TaskMaxCode}", currentMaxCodeInt, TimeSpan.FromMinutes(30));
}
var arm2 = visitGroup.FirstOrDefault(t => t.TaskState == TaskState.Effect && t.TaskAllocationState == TaskAllocationState.NotAllocate && t.DoctorUserId == null && t.ArmEnum == Arm.DoubleReadingArm2);
if (arm2 != null)
{
arm2.TaskAllocationState = TaskAllocationState.Allocated;
arm2.AllocateTime = DateTime.Now;
arm2.DoctorUserId = task2.DoctorUserId;
arm2.SuggesteFinishedTime = DateTime.Now.AddDays(7);
}
else
{
var latestTask = visitGroup.Where(t => t.ArmEnum == Arm.DoubleReadingArm2).OrderByDescending(t => t.CreateTime).First();
var taskTwo = await _visitTaskRepository.AddAsync(new VisitTask()
{
TrialId = trialId,
SubjectId = subjectVisit.SubjectId,
IsUrgent = subjectVisit.IsUrgent,
//CheckPassedTime = subjectVisit.CheckPassedTime,
ArmEnum = Arm.DoubleReadingArm2,//特殊
Code = currentMaxCodeInt + 1,
TaskCode = AppSettings.GetCodeStr(currentMaxCodeInt + 1, nameof(VisitTask)),
ReadingCategory = ReadingCategory.Visit,
SourceSubjectVisitId = latestTask.SourceSubjectVisitId,
VisitTaskNum = latestTask.VisitTaskNum,
TaskBlindName = AppSettings.BlindTaskPrefix + visitNumList.IndexOf(latestTask.VisitTaskNum),
TaskName = latestTask.TaskName,
BlindSubjectCode = latestTask.BlindSubjectCode,
BlindTrialSiteCode = latestTask.BlindTrialSiteCode,
IsAnalysisCreate = latestTask.IsAnalysisCreate,
IsSelfAnalysis = latestTask.IsSelfAnalysis,
TaskAllocationState = TaskAllocationState.Allocated,
AllocateTime = DateTime.Now,
DoctorUserId = task2.DoctorUserId,
SuggesteFinishedTime = DateTime.Now.AddDays(7),
TrialReadingCriterionId = latestTask.TrialReadingCriterionId
});
currentMaxCodeInt = currentMaxCodeInt + 1;
_provider.Set($"{trialId}_{StaticData.CacheKey.TaskMaxCode}", currentMaxCodeInt, TimeSpan.FromMinutes(30));
}
}
}
//无序的时候 生成任务并分配出去
else
{
var defaultState = trialReadingCriterionConfig.FollowVisitAutoAssignDefaultState == TaskAllocateDefaultState.InitAllocated ? TaskAllocationState.InitAllocated : TaskAllocationState.Allocated;
if (assignConfigList.Any(t => t.ArmEnum == Arm.DoubleReadingArm1))
{
task1.TaskAllocationState = defaultState;
//分配给对应Arm的人
task1.DoctorUserId = assignConfigList.FirstOrDefault(t => t.ArmEnum == Arm.DoubleReadingArm1).DoctorUserId;
task1.AllocateTime = DateTime.Now;
task1.SuggesteFinishedTime = DateTime.Now.AddDays(7);
}
if (assignConfigList.Any(t => t.ArmEnum == Arm.DoubleReadingArm2))
{
task2.TaskAllocationState = defaultState;
task2.DoctorUserId = assignConfigList.FirstOrDefault(t => t.ArmEnum == Arm.DoubleReadingArm2).DoctorUserId;
task2.AllocateTime = DateTime.Now;
task2.SuggesteFinishedTime = DateTime.Now.AddDays(7);
}
}
#endregion
}
else
//后续访视不自动分配,或者配置的医生数量不足,就不进行分配
{
}
}
}
}
#endregion
}
else 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,
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
});
currentMaxCodeInt = currentMaxCodeInt + 1;
_provider.Set($"{trialId}_{StaticData.CacheKey.TaskMaxCode}", currentMaxCodeInt, TimeSpan.FromMinutes(30));
#region 分配
if (isAssignSubjectToDoctor)
{
if (trialReadingCriterionConfig.TaskAllocateObjEnum == TaskAllocateObj.Subject)
{
if (trialReadingCriterionConfig.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)
{
#region 重阅/退回的时候,需要将取消分配的访视类型的 任务重新分配
if (trialReadingCriterionConfig.IsReadingTaskViewInOrder)
{
//之前有回退到影像上传的访视 那么当前访视一致性核查通过的时候,当前访视生成但是不分配出去(排除失访的)
var beforeBackVisitTask = await _visitTaskRepository.Where(t => t.TrialId == trialId && t.SubjectId == subjectVisit.SubjectId && t.VisitTaskNum < subjectVisit.VisitNum && t.ReadingCategory == ReadingCategory.Visit && t.SourceSubjectVisit.CheckState != CheckStateEnum.CVPassed && t.SourceSubjectVisit.IsLostVisit==false).OrderBy(t => t.VisitTaskNum).FirstOrDefaultAsync();
if (beforeBackVisitTask == null)
{
#region 访视2 PM 回退 基线回退 访视2先一致性核查通过,生成访视2任务,但是不分配
var defaultState = trialReadingCriterionConfig.FollowVisitAutoAssignDefaultState == TaskAllocateDefaultState.InitAllocated ? TaskAllocationState.InitAllocated : TaskAllocationState.Allocated;
if (assignConfigList.Any(t => t.ArmEnum == Arm.SingleReadingArm))
{
singleTask.TaskAllocationState = defaultState;
singleTask.DoctorUserId = assignConfigList.FirstOrDefault(t => t.ArmEnum == Arm.SingleReadingArm).DoctorUserId;
singleTask.AllocateTime = DateTime.Now;
singleTask.SuggesteFinishedTime = DateTime.Now.AddDays(7);
}
#endregion
var followBackVisitTask = await _visitTaskRepository.Where(t => t.TrialId == trialId && t.SubjectId == subjectVisit.SubjectId && 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.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)
{
var arm = visitGroup.FirstOrDefault(t => t.TaskState == TaskState.Effect && t.TaskAllocationState == TaskAllocationState.NotAllocate && t.DoctorUserId == null && t.ArmEnum == Arm.SingleReadingArm);
if (arm != null)
{
arm.TaskAllocationState = TaskAllocationState.Allocated;
arm.AllocateTime = DateTime.Now;
arm.DoctorUserId = singleTask.DoctorUserId;
arm.SuggesteFinishedTime = DateTime.Now.AddDays(7);
}
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,
SourceSubjectVisitId = latestTask.SourceSubjectVisitId,
VisitTaskNum = latestTask.VisitTaskNum,
TaskBlindName = AppSettings.BlindTaskPrefix + visitNumList.IndexOf(latestTask.VisitTaskNum),
TaskName = latestTask.TaskName,
BlindSubjectCode = latestTask.BlindSubjectCode,
BlindTrialSiteCode = latestTask.BlindTrialSiteCode,
IsAnalysisCreate = latestTask.IsAnalysisCreate,
IsSelfAnalysis = latestTask.IsSelfAnalysis,
TaskAllocationState = TaskAllocationState.Allocated,
AllocateTime = DateTime.Now,
DoctorUserId = singleTask.DoctorUserId
});
currentMaxCodeInt = currentMaxCodeInt + 1;
_provider.Set($"{trialId}_{StaticData.CacheKey.TaskMaxCode}", currentMaxCodeInt, TimeSpan.FromMinutes(30));
}
}
}
//之前有回退的 后续访视不生成或者分配 当前访视生成但是不分配出去
else
{
//不用进行额外处理
}
}
//无序的时候 生成任务并分配出去
else
{
var defaultState = trialReadingCriterionConfig.FollowVisitAutoAssignDefaultState == TaskAllocateDefaultState.InitAllocated ? TaskAllocationState.InitAllocated : TaskAllocationState.Allocated;
if (assignConfigList.Any(t => t.ArmEnum == Arm.SingleReadingArm))
{
singleTask.TaskAllocationState = defaultState;
singleTask.DoctorUserId = assignConfigList.FirstOrDefault(t => t.ArmEnum == Arm.SingleReadingArm).DoctorUserId;
singleTask.AllocateTime = DateTime.Now;
singleTask.SuggesteFinishedTime = DateTime.Now.AddDays(7);
}
}
#endregion
}
}
}
else
{
//后续Subect 不自动分配 不处理
}
}
}
#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;
var newTask = await _visitTaskRepository.AddAsync(new VisitTask()
{
TrialReadingCriterionId = reReadingVisitTask.TrialReadingCriterionId,
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)),
IsAnalysisCreate = reReadingVisitTask.IsAnalysisCreate,
IsSelfAnalysis = reReadingVisitTask.IsSelfAnalysis,
BlindSubjectCode = reReadingVisitTask.BlindSubjectCode,
BlindTrialSiteCode = reReadingVisitTask.BlindTrialSiteCode,
// TaskAllocationState = reReadingVisitTask.TaskAllocationState,
// AllocateTime = DateTime.Now,
//DoctorUserId = reReadingVisitTask.DoctorUserId,
});
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 = DateTime.Now.AddDays(7),
SouceReadModuleId = task.SouceReadModuleId,
SourceSubjectVisitId = task.SourceSubjectVisitId,
BlindTrialSiteCode = task.BlindTrialSiteCode,
BlindSubjectCode = task.BlindSubjectCode,
ConsistentAnalysisOriginalTaskId = task.Id,
IsAnalysisCreate = true,
IsSelfAnalysis = true,
TrialReadingCriterionId = task.TrialReadingCriterionId,
};
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 = DateTime.Now.AddDays(7),
IsAnalysisCreate = true,
IsSelfAnalysis = false,
TrialReadingCriterionId = task.TrialReadingCriterionId,
};
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();
var subjectUser = await _subjectUserRepository.Where(x => x.SubjectId == firstTask.SubjectId && x.ArmEnum == Arm.JudgeArm && x.IsConfirmed &&x.TrialReadingCriterionId==firstTask.TrialReadingCriterionId).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,
TaskBlindName = firstTask.TaskBlindName,
DoctorUserId = subjectUser == null ? null : subjectUser.DoctorUserId,
TaskAllocationState = subjectUser == null ? TaskAllocationState.NotAllocate : TaskAllocationState.Allocated,
AllocateTime = subjectUser == null ? null : DateTime.Now,
SuggesteFinishedTime = subjectUser == null ? null : DateTime.Now.AddDays(7),
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();
// 需要添加全局任务再添加
if (originalTaskInfo.TrialReadingCriterion.IsGlobalTask)
{
foreach (var item in generateTaskCommand.ReadingGenerataTaskList)
{
item.VisitNum = originalTaskInfo.VisitTaskNum;
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 = originalTaskInfo.ArmEnum,//特殊
DoctorUserId = originalTaskInfo.DoctorUserId,
AllocateTime = DateTime.Now,
TaskAllocationState = TaskAllocationState.Allocated,
SuggesteFinishedTime = DateTime.Now.AddDays(7),
Code = currentMaxCodeInt + 1,
TaskBlindName = item.ReadingName,
SouceReadModuleId = item.ReadModuleId,
TaskCode = AppSettings.GetCodeStr(currentMaxCodeInt + 1, nameof(VisitTask)),
ReadingCategory = item.ReadingCategory,
TrialReadingCriterionId = originalTaskInfo.TrialReadingCriterionId,
});
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();
foreach (var item in generateTaskCommand.ReadingGenerataTaskList)
{
//需要 根据标准筛选
var oncologySubjectUser = await _subjectUserRepository.Where(x => x.SubjectId == item.SubjectId && x.ArmEnum == Arm.TumorArm && x.IsConfirmed&&x.TrialReadingCriterionId== originalTaskInfo.TrialReadingCriterionId).FirstOrDefaultAsync();
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 = item.IsUrgent,
TaskName = item.ReadingName,
// 原任务是全局任务 加0.03 就好
VisitTaskNum = originalTaskInfo.VisitTaskNum + 0.03m,
ArmEnum = Arm.TumorArm, //特殊
Code = currentMaxCodeInt + 1,
SouceReadModuleId = item.ReadModuleId,
TaskBlindName = item.ReadingName,
DoctorUserId = oncologySubjectUser == null ? null : oncologySubjectUser.DoctorUserId,
AllocateTime = oncologySubjectUser == null ? null : DateTime.Now,
TaskAllocationState = oncologySubjectUser == null ? TaskAllocationState.NotAllocate : TaskAllocationState.Allocated,
SuggesteFinishedTime = oncologySubjectUser == null ? null : DateTime.Now.AddDays(7),
TaskCode = AppSettings.GetCodeStr(currentMaxCodeInt + 1, nameof(VisitTask)),
ReadingCategory = item.ReadingCategory,
TrialReadingCriterionId = originalTaskInfo.TrialReadingCriterionId,
});
singleTask.AllocateTime = DateTime.Now;
currentMaxCodeInt = currentMaxCodeInt + 1;
_provider.Set($"{trialId}_{StaticData.CacheKey.TaskMaxCode}", currentMaxCodeInt, TimeSpan.FromMinutes(30));
}
break;
}
await _visitTaskRepository.SaveChangesAsync();
}
}
}