Compare commits

...

52 Commits

Author SHA1 Message Date
he 6374781d26 修改阅片期计划的排序
continuous-integration/drone/push Build is failing Details
2025-06-20 17:33:23 +08:00
he b28013a02f 阅片期计划可以选择基线 2025-06-20 17:32:07 +08:00
he fe429d2bdc 修改受试者内随机
continuous-integration/drone/push Build is passing Details
2025-06-20 09:37:48 +08:00
he d63af2ed20 修改稽查的单位翻译
continuous-integration/drone/push Build is passing Details
2025-06-19 17:16:42 +08:00
hang cebf9875b1 禁用人员系统查看文档
continuous-integration/drone/push Build is passing Details
2025-06-19 10:31:24 +08:00
hang 131681a0b3 完全随机触发系统盲态名称 2025-06-19 10:22:06 +08:00
hang f833adc710 修改有序阅片生成任务bug 2025-06-19 10:21:59 +08:00
hang df80d1e551 修改影像下载bug
continuous-integration/drone/push Build is passing Details
2025-06-18 10:36:26 +08:00
he 82dc092247 修改阅片期计划生成裁判的逻辑
continuous-integration/drone/push Build is passing Details
2025-06-17 16:42:47 +08:00
he 44894fcaa9 生成阅片期计划的时候 产生裁判
continuous-integration/drone/push Build is passing Details
2025-06-17 16:24:00 +08:00
hang 083bebdc03 真实随机阅片导表-1
continuous-integration/drone/push Build is passing Details
2025-06-17 10:06:41 +08:00
hang e808764dd6 随机阅片排序-5 2025-06-17 10:06:33 +08:00
hang 77d198cb09 随机阅片-NextTask-5 2025-06-17 10:05:55 +08:00
hang 180b02b28c 随机阅片NextTask-4 2025-06-17 10:04:26 +08:00
hang c49a74d742 Merge branch 'Uat_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Uat_IRC_Net8
continuous-integration/drone/push Build is passing Details
2025-06-17 10:02:34 +08:00
he c76fc8f052 修改阅片期选择访视下拉框的数据
continuous-integration/drone/push Build is running Details
2025-06-17 10:02:04 +08:00
he 14875dfacc 生成了裁判任务 阅片期不让删除和修改 2025-06-17 10:02:02 +08:00
hang 0a68788c0f 随机阅片序号3 2025-06-17 10:00:39 +08:00
hang b17e5d9ff3 随机阅片序号2 2025-06-17 10:00:34 +08:00
hang 05ce4b7155 随机阅片随机序号 2025-06-17 10:00:28 +08:00
he c8bbb3da48 Merge branch 'Uat_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Uat_IRC_Net8
continuous-integration/drone/push Build is passing Details
2025-06-16 15:16:20 +08:00
he 65de108ecd 添加阅片期 产生裁判 2025-06-16 15:16:19 +08:00
hang d20c306219 末次访视的展示+ 展示基线选择阅片期
continuous-integration/drone/push Build is passing Details
2025-06-16 14:50:23 +08:00
hang e69991ae37 修改重置阅片稽查3
continuous-integration/drone/push Build is passing Details
2025-06-13 09:57:33 +08:00
hang e1e2544ee3 修改阅片重置稽查 2025-06-13 09:57:30 +08:00
hang 318333bae4 修改重置阅片稽查 2025-06-13 09:57:26 +08:00
hang d569de4dfe 确认浏览临床数据
continuous-integration/drone/push Build is passing Details
2025-06-12 10:52:46 +08:00
hang 05627ff126 肿瘤学稽查修改
continuous-integration/drone/push Build is passing Details
2025-06-11 10:03:01 +08:00
hang 627618c854 增加进入阅片中稽查 2025-06-11 10:02:57 +08:00
hang 2711c5eb04 稽查 申请PM 重阅,有SPM 判断 2025-06-11 10:00:57 +08:00
hang a6982f79c3 稽查修改,区分标识 2025-06-11 10:00:53 +08:00
hang 2a542949cd 增加稽查标识 2025-06-11 10:00:49 +08:00
he a8ccbce76f 稽查添加
continuous-integration/drone/push Build is passing Details
2025-06-05 16:46:06 +08:00
he df7cf30aed 测量值可以为空
continuous-integration/drone/push Build is passing Details
2025-06-04 14:25:57 +08:00
he 0664fbdfb7 验证修改
continuous-integration/drone/push Build is passing Details
2025-06-04 09:57:08 +08:00
he 0a6ee05417 Merge branch 'Test_IRC_Net8' into Uat_IRC_Net8
continuous-integration/drone/push Build is passing Details
2025-05-22 18:01:11 +08:00
hang f9bd8c3f5c Merge branch 'Test_IRC_Net8' into Uat_IRC_Net8
continuous-integration/drone/push Build is passing Details
2025-05-21 15:16:26 +08:00
he cb83c2a737 Merge branch 'Test_IRC_Net8' into Uat_IRC_Net8
continuous-integration/drone/push Build is passing Details
2025-05-21 14:05:30 +08:00
he fdd9afd4f0 Merge branch 'Test_IRC_Net8' into Uat_IRC_Net8
continuous-integration/drone/push Build is passing Details
2025-05-20 15:46:24 +08:00
he 53d26c0445 Merge branch 'Test_IRC_Net8' into Uat_IRC_Net8
continuous-integration/drone/push Build is passing Details
2025-05-20 10:55:36 +08:00
he 40d035e7a7 解决合并的冲突
continuous-integration/drone/push Build is passing Details
2025-05-15 09:33:17 +08:00
he a13807ae5f 合并冲突修改
continuous-integration/drone/push Build is failing Details
2025-05-15 09:29:41 +08:00
he 9d5aaf1e26 Merge branch 'Test_IRC_Net8' into Uat_IRC_Net8
continuous-integration/drone/push Build is failing Details
2025-05-15 09:20:22 +08:00
he c347d08e2b 合并
continuous-integration/drone/push Build is failing Details
2025-05-15 09:14:10 +08:00
hang 87f2d0e429 非dicom 删除上传
continuous-integration/drone/push Build is passing Details
2025-04-15 13:27:33 +08:00
he 89d009fcbf Revert "修改"
continuous-integration/drone/push Build is passing Details
This reverts commit 7d65cf5051.
2025-04-09 11:00:45 +08:00
he 7d65cf5051 修改
continuous-integration/drone/push Build is passing Details
2025-04-09 09:45:49 +08:00
he e74427c45c 解决冲突
continuous-integration/drone/push Build is passing Details
2025-04-08 11:05:31 +08:00
he e8825c7efa 修改查询 2025-04-08 11:04:52 +08:00
hang 628e0ad034 修改异地登录bug 设置最后一次登录的iP
continuous-integration/drone/push Build is passing Details
2025-04-03 13:55:04 +08:00
hang 2f3f639918 修改异地登录ip逻辑 2025-04-03 13:55:00 +08:00
hang 87caf24dd1 验证环境生成缩略图测试ok提交
continuous-integration/drone/push Build is passing Details
2025-04-03 13:49:34 +08:00
24 changed files with 20625 additions and 379 deletions

View File

@ -13307,7 +13307,7 @@
阅片期配置
</summary>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadingPeriodSetService.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectVisit},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingPeriodSet},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadModule},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.VisitStage},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.VisitTask},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionCriterionTrial},IRaCIS.Core.Application.Service.IVisitTaskHelpeService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingPeriodPlan},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Site},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Subject},AutoMapper.IMapper,IRaCIS.Core.Domain.Share.IUserInfo,Microsoft.Extensions.Localization.IStringLocalizer)">
<member name="M:IRaCIS.Core.Application.Service.ReadingPeriodSetService.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectVisit},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingPeriodSet},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadModule},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.VisitStage},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},IRaCIS.Core.Application.Contracts.IReadingImageTaskService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.VisitTask},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionCriterionTrial},IRaCIS.Core.Application.Service.IVisitTaskHelpeService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingPeriodPlan},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Site},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Subject},AutoMapper.IMapper,IRaCIS.Core.Domain.Share.IUserInfo,Microsoft.Extensions.Localization.IStringLocalizer)">
<summary>
阅片期配置
</summary>
@ -13379,7 +13379,7 @@
生成的阅片模块(在大列表上展示的) 阅片期
</summary>
</member>
<member name="M:IRaCIS.Core.Application.Service.ReadModuleService.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectVisit},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Subject},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.UserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},IRaCIS.Core.Application.Service.IVisitTaskHelpeService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.VisitTask},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ClinicalDataTrialSet},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadModuleView},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionCriterionTrial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DicomInstance},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.NoneDicomStudyFile},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingClinicalData},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingPeriodSet},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadModule},AutoMapper.IMapper,IRaCIS.Core.Domain.Share.IUserInfo,Microsoft.Extensions.Localization.IStringLocalizer)">
<member name="M:IRaCIS.Core.Application.Service.ReadModuleService.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectVisit},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Subject},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.UserRole},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},IRaCIS.Core.Application.Service.IVisitTaskHelpeService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.VisitTask},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ClinicalDataTrialSet},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadModuleView},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionCriterionTrial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DicomInstance},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.NoneDicomStudyFile},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingClinicalData},IRaCIS.Core.Application.Contracts.IReadingImageTaskService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingPeriodSet},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadModule},AutoMapper.IMapper,IRaCIS.Core.Domain.Share.IUserInfo,Microsoft.Extensions.Localization.IStringLocalizer)">
<summary>
生成的阅片模块(在大列表上展示的) 阅片期
</summary>

View File

@ -216,6 +216,8 @@ namespace IRaCIS.Core.Application.ViewModel
//public bool IsAfterConvertedTask { get; set; }
public string PMBackReason { get; set; }
public int? RandomOrder { get; set; }
}
@ -482,6 +484,9 @@ namespace IRaCIS.Core.Application.ViewModel
public string? RequestReReadingReason { get; set; }
public ExportResult? ReadingExportType { get; set; }
public int? RandomOrder { get; set; }
public bool? IsRandomOrderList { get; set; }
}
@ -908,6 +913,30 @@ namespace IRaCIS.Core.Application.ViewModel
CancelAssign = 4,
}
public class SetRandomTaskOrderCommand
{
[NotDefault]
public Guid TrialId { get; set; }
[NotDefault]
public Guid TrialReadingCriterionId { get; set; }
[NotDefault]
public Guid DoctorUserId { get; set; }
public bool IsAutoSet { get; set; }
public List<VisitTaskOrderCommand> SetList { get; set; }
}
public class VisitTaskOrderCommand
{
public Guid Id { get; set; }
public int? RandomOrder { get; set; }
}
}

View File

@ -35,7 +35,7 @@ namespace IRaCIS.Core.Application.Service
IRepository<ReadingQuestionCriterionTrial> _trialReadingCriterionRepository,
IRepository<ClinicalDataTrialSet> _trialClinicalDataSetRepository,
IRepository<ReadingClinicalData> _readingClinicalDataRepository,
IRepository<ReadingConsistentClinicalData> _readingConsistentClinicalDataRepository,
IRepository<ReadingConsistentClinicalData> _readingConsistentClinicalDataRepository,
IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer, IWebHostEnvironment _hostEnvironment, IFusionCache _fusionCache) : BaseService, IVisitTaskHelpeService
{
@ -47,16 +47,16 @@ namespace IRaCIS.Core.Application.Service
/// <param name="inDto"></param>
/// <returns></returns>
public async Task<FileResult> ExportTemplateAsync(ExportTemplateAsyncDto inDto)
public async Task<FileResult> ExportTemplateAsync(ExportTemplateAsyncDto inDto)
{
return await ExcelExportHelper.ExportTemplateAsync(new ExportTemplateServiceDto()
{
Data=inDto.Data,
commonDocumentRepository= _commonDocumentRepository,
TemplateCode=inDto.TemplateCode,
ExportFileName=inDto.ExportFileName,
hostEnvironment=_hostEnvironment,
IsEnglish=_userInfo.IsEn_Us,
Data = inDto.Data,
commonDocumentRepository = _commonDocumentRepository,
TemplateCode = inDto.TemplateCode,
ExportFileName = inDto.ExportFileName,
hostEnvironment = _hostEnvironment,
IsEnglish = _userInfo.IsEn_Us,
});
}
@ -757,248 +757,30 @@ namespace IRaCIS.Core.Application.Service
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 (trialReadingCriterionConfig.IsReadingTaskViewInOrder == ReadingOrder.InOrder)
{
//并且配置了医生
if (assignConfigList.Count > 0 && trialReadingCriterionConfig.IsFollowVisitAutoAssign)
#region 当前访视处理
//配置了医生
if (assignConfigList.Count > 0)
{
//之前有回退到影像上传的访视 那么当前访视一致性核查通过的时候,当前访视生成但是不分配出去(排除失访的)
#region 后续访视 未分配的进行再次分配,重置的或者失效的 需要重新生成新的任务 (PM 有序退回 或者PM 有序 申请重阅)
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 (trialReadingCriterionConfig.IsReadingTaskViewInOrder == ReadingOrder.InOrder)
//之前有回退的,那么当前访视任务生成但是不分配
if (beforeBackVisitTask != null)
{
//之前有回退到影像上传的访视 那么当前访视一致性核查通过的时候,当前访视生成但是不分配出去(排除失访的)
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 != null)
{
task1.TaskAllocationState = defaultState;
//分配给对应Arm的人
task1.DoctorUserId = assignConfigList.FirstOrDefault(t => t.ArmEnum == Arm.DoubleReadingArm1)!.DoctorUserId;
task1.AllocateTime = DateTime.Now;
task1.SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget);
}
if (assignConfigList.Any(t => t.ArmEnum == Arm.DoubleReadingArm2) && task2 != null)
{
task2.TaskAllocationState = defaultState;
task2.DoctorUserId = assignConfigList.FirstOrDefault(t => t.ArmEnum == Arm.DoubleReadingArm2)!.DoctorUserId;
task2.AllocateTime = DateTime.Now;
task2.SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget);
}
#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 visit = await _subjectVisitRepository.Where(x => x.Id == visitGroup.First().SourceSubjectVisitId).Select(x => new
{
x.PDState,
x.IsEnrollmentConfirm,
x.IsUrgent,
}).FirstNotNullAsync();
TaskUrgentType? urgentType = null;
if (subjectVisitInfo.PDState == PDStateEnum.PDProgress)
{
urgentType = TaskUrgentType.PDProgress;
}
else if (subjectVisitInfo.IsEnrollmentConfirm)
{
urgentType = TaskUrgentType.EnrollmentConfirm;
}
else if (subjectVisitInfo.IsUrgent)
{
urgentType = TaskUrgentType.VisitUrgent;
}
bool isCanEdit = urgentType == TaskUrgentType.EnrollmentConfirm || urgentType == TaskUrgentType.PDProgress ? false : true;
//如果后续访视已分配有效 就不用处理
if (visitGroup.Any(t => t.TaskState == TaskState.Effect && t.TaskAllocationState == TaskAllocationState.Allocated && t.ArmEnum == Arm.DoubleReadingArm1))
{
//不做处理
}
else
{
var arm1 = visitGroup.FirstOrDefault(t => t.TaskState == TaskState.Effect && t.TaskAllocationState == TaskAllocationState.NotAllocate && t.DoctorUserId == null && t.ArmEnum == Arm.DoubleReadingArm1);
if (arm1 != null)
{
//有可能仅仅只分配了一个Subject 未分配 那么
if (assignConfigList.Any(t => t.ArmEnum == Arm.DoubleReadingArm1) && task1 != null)
{
arm1.IsUrgent = visit.IsUrgent;
arm1.TaskUrgentType = urgentType;
arm1.IsCanEditUrgentState = isCanEdit;
arm1.TaskAllocationState = TaskAllocationState.Allocated;
arm1.AllocateTime = DateTime.Now;
arm1.DoctorUserId = task1.DoctorUserId;
arm1.SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget);
}
}
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 = visit.IsUrgent,
TaskUrgentType = urgentType,
IsCanEditUrgentState = isCanEdit,
ArmEnum = Arm.DoubleReadingArm1,//特殊
Code = currentMaxCodeInt + 1,
TaskCode = AppSettings.GetCodeStr(currentMaxCodeInt + 1, nameof(VisitTask)),
ReadingCategory = ReadingCategory.Visit,
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,
TaskAllocationState = TaskAllocationState.Allocated,
AllocateTime = DateTime.Now,
DoctorUserId = task1!.DoctorUserId,
SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget),
TrialReadingCriterionId = latestTask.TrialReadingCriterionId,
IsNeedClinicalDataSign = latestTask.IsNeedClinicalDataSign,
IsClinicalDataSign = latestTask.IsClinicalDataSign
});
currentMaxCodeInt = currentMaxCodeInt + 1;
_fusionCache.Set<int>(CacheKeys.TrialStudyMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30));
}
}
//如果后续访视已分配有效 就不用处理
if (visitGroup.Any(t => t.TaskState == TaskState.Effect && t.TaskAllocationState == TaskAllocationState.Allocated && t.ArmEnum == Arm.DoubleReadingArm2))
{
//不做处理
}
else
{
var arm2 = visitGroup.FirstOrDefault(t => t.TaskState == TaskState.Effect && t.TaskAllocationState == TaskAllocationState.NotAllocate && t.DoctorUserId == null && t.ArmEnum == Arm.DoubleReadingArm2);
if (arm2 != null)
{
//有可能仅仅只分配了一个Subject
if (assignConfigList.Any(t => t.ArmEnum == Arm.DoubleReadingArm2) && task2 != null)
{
arm2.IsUrgent = visit.IsUrgent;
arm2.TaskUrgentType = urgentType;
arm2.IsCanEditUrgentState = isCanEdit;
arm2.TaskAllocationState = TaskAllocationState.Allocated;
arm2.AllocateTime = DateTime.Now;
arm2.DoctorUserId = task2.DoctorUserId;
arm2.SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget);
}
}
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 = visit.IsUrgent,
TaskUrgentType = urgentType,
IsCanEditUrgentState = isCanEdit,
//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 = visitBlindConfig.BlindFollowUpPrefix + " " + 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 = GetSuggessFinishTime(true, UrgentType.NotUrget),
TrialReadingCriterionId = latestTask.TrialReadingCriterionId,
IsNeedClinicalDataSign = latestTask.IsNeedClinicalDataSign,
IsClinicalDataSign = latestTask.IsClinicalDataSign
});
currentMaxCodeInt = currentMaxCodeInt + 1;
_fusionCache.Set<int>(CacheKeys.TrialStudyMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30));
}
}
}
//不用进行额外处理
//访视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 != null)
@ -1019,21 +801,237 @@ namespace IRaCIS.Core.Application.Service
task2.SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget);
}
#endregion
}
#endregion
}
else
//后续访视不自动分配,或者配置的医生数量不足,就不进行分配
#endregion
#region 后续访视处理
//后续最近的未一致性核查通过的访视任务
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 visit = await _subjectVisitRepository.Where(x => x.Id == visitGroup.First().SourceSubjectVisitId).Select(x => new
{
x.PDState,
x.IsEnrollmentConfirm,
x.IsUrgent,
}).FirstNotNullAsync();
TaskUrgentType? urgentType = null;
if (subjectVisitInfo.PDState == PDStateEnum.PDProgress)
{
urgentType = TaskUrgentType.PDProgress;
}
else if (subjectVisitInfo.IsEnrollmentConfirm)
{
urgentType = TaskUrgentType.EnrollmentConfirm;
}
else if (subjectVisitInfo.IsUrgent)
{
urgentType = TaskUrgentType.VisitUrgent;
}
bool isCanEdit = urgentType == TaskUrgentType.EnrollmentConfirm || urgentType == TaskUrgentType.PDProgress ? false : true;
//如果后续访视已分配有效 就不用处理
if (visitGroup.Any(t => t.TaskState == TaskState.Effect && t.TaskAllocationState == TaskAllocationState.Allocated && t.ArmEnum == Arm.DoubleReadingArm1))
{
//不做处理
}
else
{
var arm1 = visitGroup.FirstOrDefault(t => t.TaskState == TaskState.Effect && t.TaskAllocationState == TaskAllocationState.NotAllocate && t.DoctorUserId == null && t.ArmEnum == Arm.DoubleReadingArm1);
if (arm1 != null)
{
arm1.IsUrgent = visit.IsUrgent;
arm1.TaskUrgentType = urgentType;
arm1.IsCanEditUrgentState = isCanEdit;
//有可能仅仅只分配了一个Subject 未分配 那么
if (assignConfigList.Any(t => t.ArmEnum == Arm.DoubleReadingArm1) && task1 != null)
{
arm1.TaskAllocationState = TaskAllocationState.Allocated;
arm1.AllocateTime = DateTime.Now;
arm1.DoctorUserId = task1.DoctorUserId;
arm1.SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget);
}
}
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 = visit.IsUrgent,
TaskUrgentType = urgentType,
IsCanEditUrgentState = isCanEdit,
ArmEnum = Arm.DoubleReadingArm1,//特殊
Code = currentMaxCodeInt + 1,
TaskCode = AppSettings.GetCodeStr(currentMaxCodeInt + 1, nameof(VisitTask)),
ReadingCategory = ReadingCategory.Visit,
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,
TrialReadingCriterionId = latestTask.TrialReadingCriterionId,
IsNeedClinicalDataSign = latestTask.IsNeedClinicalDataSign,
IsClinicalDataSign = latestTask.IsClinicalDataSign
});
if (assignConfigList.Any(t => t.ArmEnum == Arm.DoubleReadingArm1) && task1 != null)
{
taskOne.TaskAllocationState = TaskAllocationState.Allocated;
taskOne.AllocateTime = DateTime.Now;
taskOne. DoctorUserId = task1!.DoctorUserId;
taskOne. SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget);
}
currentMaxCodeInt = currentMaxCodeInt + 1;
_fusionCache.Set<int>(CacheKeys.TrialStudyMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30));
}
}
//如果后续访视已分配有效 就不用处理
if (visitGroup.Any(t => t.TaskState == TaskState.Effect && t.TaskAllocationState == TaskAllocationState.Allocated && t.ArmEnum == Arm.DoubleReadingArm2))
{
//不做处理
}
else
{
var arm2 = visitGroup.FirstOrDefault(t => t.TaskState == TaskState.Effect && t.TaskAllocationState == TaskAllocationState.NotAllocate && t.DoctorUserId == null && t.ArmEnum == Arm.DoubleReadingArm2);
if (arm2 != null)
{
arm2.IsUrgent = visit.IsUrgent;
arm2.TaskUrgentType = urgentType;
arm2.IsCanEditUrgentState = isCanEdit;
//有可能仅仅只分配了一个Subject
if (assignConfigList.Any(t => t.ArmEnum == Arm.DoubleReadingArm2) && task2 != null)
{
arm2.TaskAllocationState = TaskAllocationState.Allocated;
arm2.AllocateTime = DateTime.Now;
arm2.DoctorUserId = task2.DoctorUserId;
arm2.SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget);
}
}
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 = visit.IsUrgent,
TaskUrgentType = urgentType,
IsCanEditUrgentState = isCanEdit,
//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 = visitBlindConfig.BlindFollowUpPrefix + " " + visitNumList.IndexOf(latestTask.VisitTaskNum),
TaskName = latestTask.TaskName,
BlindSubjectCode = latestTask.BlindSubjectCode,
BlindTrialSiteCode = latestTask.BlindTrialSiteCode,
IsAnalysisCreate = latestTask.IsAnalysisCreate,
IsSelfAnalysis = latestTask.IsSelfAnalysis,
TrialReadingCriterionId = latestTask.TrialReadingCriterionId,
IsNeedClinicalDataSign = latestTask.IsNeedClinicalDataSign,
IsClinicalDataSign = latestTask.IsClinicalDataSign
});
if (assignConfigList.Any(t => t.ArmEnum == Arm.DoubleReadingArm2) && task2 != null)
{
taskTwo.TaskAllocationState = TaskAllocationState.Allocated;
taskTwo.AllocateTime = DateTime.Now;
taskTwo.DoctorUserId = task2!.DoctorUserId;
taskTwo.SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget);
}
currentMaxCodeInt = currentMaxCodeInt + 1;
_fusionCache.Set<int>(CacheKeys.TrialStudyMaxCode(trialId), currentMaxCodeInt, TimeSpan.FromMinutes(30));
}
}
}
}
#endregion
}
else
{
//无序的时候 生成任务并分配出去
if (assignConfigList.Count > 0 && trialReadingCriterionConfig.IsFollowVisitAutoAssign)
{
var defaultState = trialReadingCriterionConfig.FollowVisitAutoAssignDefaultState == TaskAllocateDefaultState.InitAllocated ? TaskAllocationState.InitAllocated : TaskAllocationState.Allocated;
if (assignConfigList.Any(t => t.ArmEnum == Arm.DoubleReadingArm1) && task1 != null)
{
task1.TaskAllocationState = defaultState;
//分配给对应Arm的人
task1.DoctorUserId = assignConfigList.FirstOrDefault(t => t.ArmEnum == Arm.DoubleReadingArm1)!.DoctorUserId;
task1.AllocateTime = DateTime.Now;
task1.SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget);
}
if (assignConfigList.Any(t => t.ArmEnum == Arm.DoubleReadingArm2) && task2 != null)
{
task2.TaskAllocationState = defaultState;
task2.DoctorUserId = assignConfigList.FirstOrDefault(t => t.ArmEnum == Arm.DoubleReadingArm2)!.DoctorUserId;
task2.AllocateTime = DateTime.Now;
task2.SuggesteFinishedTime = GetSuggessFinishTime(true, UrgentType.NotUrget);
}
}
}
}

View File

@ -74,7 +74,7 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
return await _visitTaskRepository.SaveChangesAsync();
}
public async Task<List<TrialReadingCriterionDto>> GetTrialCriterionList(Guid trialId, bool isHaveSigned = true, bool? isAutoCreate = null)
public async Task<List<TrialReadingCriterionDto>> GetTrialCriterionList(Guid trialId, bool isHaveSigned = true, bool? isAutoCreate = null, bool? isRandom = null)
{
var list = await _readingQuestionCriterionTrialRepository.Where(t => t.TrialId == trialId && t.IsConfirm)
@ -107,7 +107,8 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
return list.AsQueryable().WhereIf(isHaveSigned == true, t => t.ReadingInfoSignTime != null)
.WhereIf(isAutoCreate == false, t => t.IsAutoCreate == isAutoCreate).ToList();
.WhereIf(isAutoCreate == false, t => t.IsAutoCreate == isAutoCreate)
.WhereIf(isRandom == true, t => t.IsReadingTaskViewInOrder == ReadingOrder.Random).ToList();
}
@ -761,6 +762,8 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
.WhereIf(inQuery.EndAllocateDate != null, t => t.AllocateTime < inQuery.EndAllocateDate)
.WhereIf(inQuery.BeginSignTime != null, t => t.SignTime > inQuery.BeginSignTime)
.WhereIf(inQuery.EndSignTime != null, t => t.SignTime < inQuery.EndSignTime)
.WhereIf(inQuery.RandomOrder != null, t => t.RandomOrder == inQuery.RandomOrder)
.WhereIf(inQuery.IsRandomOrderList == true, t => (t.ReadingTaskState == ReadingTaskState.WaitReading || t.ReadingTaskState==ReadingTaskState.Reading) && t.TaskAllocationState==TaskAllocationState.Allocated)
.ProjectTo<ReadingTaskView>(_mapper.ConfigurationProvider);
var defalutSortArray = new string[] { nameof(ReadingTaskView.IsUrgent) + " desc", nameof(ReadingTaskView.SubjectCode), nameof(ReadingTaskView.VisitTaskNum) };
@ -1055,7 +1058,7 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
ReadingCategory = u.ReadingCategory,
IsAnalysisCreate = u.IsAnalysisCreate,
ArmEnum = u.ArmEnum,
IsExistUnprocessedFeedback=u.UserFeedBackList.Any(t => t.State ==0),
IsExistUnprocessedFeedback = u.UserFeedBackList.Any(t => t.State == 0),
TrialReadingCriterionId = u.TrialReadingCriterionId,
IsNeedClinicalDataSign = u.IsNeedClinicalDataSign,
IsClinicalDataSign = u.IsClinicalDataSign,
@ -2209,7 +2212,7 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
_ = _readingCustomTagRepository.AddRangeAsync(readingCustomTagList).Result;
var readingTaskQuestionAnswerList = _readingTaskQuestionAnswerRepository.Where(t => t.VisitTaskId == origenalTask.Id).ToList();
@ -2233,7 +2236,7 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
item.MeasureData = item.MeasureData.Replace(origenalTask.Id.ToString(), newTask.Id.ToString());
}
//ReadingTableAnswerRowInfo ReadingTableQuestionAnswer 一起加
var readingTableAnswerRowInfoList = _readingTableAnswerRowInfoRepository.Where(t => t.VisitTaskId == origenalTask.Id).Include(t => t.LesionAnswerList).ToList();
@ -2244,7 +2247,7 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
var originalVisitTaskId = item.VisitTaskId;
var originalFristAddTaskId = item.FristAddTaskId;
var newRowId= NewId.NextSequentialGuid();
var newRowId = NewId.NextSequentialGuid();
foreach (var mark in readingTaskQuestionMarkList)
{
@ -2285,7 +2288,7 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
[UnitOfWork]
[TrialGlobalLimit("AfterStopCannNotOpt")]
public async Task<IResponseOutput> PMSetTaskBack(Guid trialId, Guid taskId,string pmBackReason)
public async Task<IResponseOutput> PMSetTaskBack(Guid trialId, Guid taskId, string pmBackReason)
{
//var trialConfig = (await _trialRepository.Where(t => t.Id == trialId).Select(t => new { TrialId = t.Id, t.IsReadingTaskViewInOrder, t.ReadingType }).FirstOrDefaultAsync()).IfNullThrowException();
@ -2616,7 +2619,7 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
private bool IsSpmOrCPM()
{
return _userInfo.UserTypeEnumInt == (int)UserTypeEnum.SPM || _userInfo.UserTypeEnumInt == (int)UserTypeEnum.CPM ;
return _userInfo.UserTypeEnumInt == (int)UserTypeEnum.SPM || _userInfo.UserTypeEnumInt == (int)UserTypeEnum.CPM;
}
/// <summary>
@ -2679,9 +2682,9 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
}
else
{
//默认影响的都是该标准的任务
filterExpression = filterExpression.And(t => t.TrialReadingCriterionId == filterObj.TrialReadingCriterionId);
//默认影响的都是该标准的任务
filterExpression = filterExpression.And(t => t.TrialReadingCriterionId == filterObj.TrialReadingCriterionId);
}
@ -2942,6 +2945,88 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
}
#region 完全随机设置序号
[HttpPost]
[UnitOfWork]
[TrialGlobalLimit("AfterStopCannNotOpt")]
public async Task<IResponseOutput> SetRandomTaskOrder(SetRandomTaskOrderCommand inCommand)
{
if (inCommand.IsAutoSet)
{
//找到所有的已分配的,未阅片的,生效的 非一致性分析
var needRandomOrderList = _visitTaskRepository.Where(t => t.TrialId == inCommand.TrialId && t.TrialReadingCriterionId == inCommand.TrialReadingCriterionId && t.DoctorUserId == inCommand.DoctorUserId)
.Where(t => t.TaskAllocationState == TaskAllocationState.Allocated && t.ReadingTaskState == ReadingTaskState.WaitReading && (t.TaskState == TaskState.Effect || t.TaskState == TaskState.Freeze))
.Select(t => t.Id).ToList();
//var haveSignOrderList = _visitTaskRepository.Where(t => t.TrialId == inCommand.TrialId && t.TrialReadingCriterionId == inCommand.TrialReadingCriterionId && t.DoctorUserId == inCommand.DoctorUserId)
// .Where(t => t.ReadingTaskState == ReadingTaskState.HaveSigned && t.SignTime != null && (t.TaskState == TaskState.Effect || t.TaskState == TaskState.Freeze))
// .Select(t => t.RandomOrder).ToList();
//已阅,阅片中任务的序号
await _visitTaskRepository.BatchUpdateNoTrackingAsync(t => t.TrialId == inCommand.TrialId && t.TrialReadingCriterionId == inCommand.TrialReadingCriterionId
&& t.DoctorUserId == inCommand.DoctorUserId && t.ReadingTaskState != ReadingTaskState.WaitReading, u => new VisitTask() { RandomOrder = null });
//随机赋值编号 比如要处理5个任务实例化一个包含1-5的数组每次随机取出一个
List<int> availableNumbers = Enumerable.Range(1, needRandomOrderList.Count).ToList();
Random rng = new Random();
foreach (var id in needRandomOrderList)
{
int randomIndex = rng.Next(availableNumbers.Count);
var num = availableNumbers[randomIndex];
var order = 11 + 5 * (num - 1);
await _visitTaskRepository.BatchUpdateNoTrackingAsync(t => t.Id == id, t => new VisitTask() { RandomOrder = order });
availableNumbers.RemoveAt(randomIndex);
}
}
else
{
foreach (var item in inCommand.SetList)
{
var task = await _visitTaskRepository.Where(t => t.Id == item.Id).Select(t => new { t.RandomOrder, t.ReadingTaskState, t.TaskAllocationState, t.DoctorUserId }).FirstNotNullAsync();
if (task.ReadingTaskState != ReadingTaskState.WaitReading || task.DoctorUserId != inCommand.DoctorUserId
|| task.TaskAllocationState != TaskAllocationState.Allocated)
{
//"任务不符合设置阅片序号条件"
return ResponseOutput.NotOk(_localizer["VisitTask_NotRandomOrderTask"]);
}
//设置交换序号的任务,可能不符合条件
//没有序号,直接设置
if (task.RandomOrder == null)
{
await _visitTaskRepository.BatchUpdateNoTrackingAsync(t => t.Id == item.Id, t => new VisitTask() { RandomOrder = item.RandomOrder });
}
else
{
if(!_visitTaskRepository.Any(t => t.TrialId == inCommand.TrialId && t.TrialReadingCriterionId == inCommand.TrialReadingCriterionId && t.DoctorUserId == inCommand.DoctorUserId
&& t.TaskAllocationState == TaskAllocationState.Allocated && t.ReadingTaskState == ReadingTaskState.WaitReading && (t.TaskState == TaskState.Effect || t.TaskState == TaskState.Freeze)
&& t.RandomOrder == item.RandomOrder))
{
await _visitTaskRepository.BatchUpdateNoTrackingAsync(t => t.Id == item.Id, t => new VisitTask() { RandomOrder = item.RandomOrder });
}
else
{
//"序号已被占用!"
return ResponseOutput.NotOk(_localizer["VisitTask_RandomOrderUserd"]);
}
}
}
}
return ResponseOutput.Ok();
}
#endregion
#region 暂时废弃

View File

@ -361,7 +361,7 @@ namespace IRaCIS.Core.Application.Service.Common
var systemDocQuery =
from sysDoc in _systemDocumentRepository.AsQueryable(false)
.Where(t => inQuery.UserTypeId != null ? t.NeedConfirmedUserTypeList.Any(t => t.NeedConfirmUserTypeId == inQuery.UserTypeId) : true)
from identityUser in _identityUserRepository.AsQueryable(false).Where(t => t.UserRoleList.Where(t => t.IsUserRoleDisabled == false).Any(t => sysDoc.NeedConfirmedUserTypeList.AsQueryable().Any(c => c.NeedConfirmUserTypeId == t.UserTypeId)))
from identityUser in _identityUserRepository.AsQueryable(false).Where(t => t.Status == UserStateEnum.Enable && t.UserRoleList.Where(t => t.IsUserRoleDisabled == false).Any(t => sysDoc.NeedConfirmedUserTypeList.AsQueryable().Any(c => c.NeedConfirmUserTypeId == t.UserTypeId)))
.Where(t => inQuery.UserId != null ? t.Id == inQuery.UserId : true)
.Where(t => inQuery.UserTypeId != null ? t.UserRoleList.Any(t => t.UserTypeId == inQuery.UserTypeId && t.IsUserRoleDisabled == false) : true)
join confirm in _systemDocConfirmedUserRepository.Where() on new { ConfirmUserId = identityUser.Id, SystemDocumentId = sysDoc.Id } equals new { confirm.ConfirmUserId, confirm.SystemDocumentId } into cc
@ -1302,39 +1302,65 @@ namespace IRaCIS.Core.Application.Service.Common
[FromServices] IRepository<Trial> _trialRepository)
{
var list = await _visitTaskRepository.Where(t => t.TrialId == inQuery.TrialId && t.IsAnalysisCreate == false)
//.Where(t => t.IsAnalysisCreate == false && t.DoctorUserId != null)
//.Where(t => t.IsAnalysisCreate == false && t.DoctorUserId != null)
.WhereIf(inQuery.TaskState != null, t => t.TaskState == inQuery.TaskState)
.WhereIf(inQuery.ArmEnum != null, t => t.ArmEnum == inQuery.ArmEnum)
.WhereIf(inQuery.TrialSiteId != null, t => t.Subject.TrialSiteId == inQuery.TrialSiteId)
.WhereIf(inQuery.SubjectId != null, t => t.SubjectId == inQuery.SubjectId)
.WhereIf(inQuery.IsUrgent != null, t => t.IsUrgent == inQuery.IsUrgent)
.WhereIf(inQuery.DoctorUserId != null, t => t.DoctorUserId == inQuery.DoctorUserId)
.WhereIf(inQuery.ReadingCategory != null, t => t.ReadingCategory == inQuery.ReadingCategory)
.WhereIf(inQuery.ReadingTaskState != null, t => t.ReadingTaskState == inQuery.ReadingTaskState)
.WhereIf(inQuery.TaskAllocationState != null, t => t.TaskAllocationState == inQuery.TaskAllocationState)
.WhereIf(inQuery.TrialReadingCriterionId != null, t => t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId)
.WhereIf(inQuery.IsEffect == true, t => t.TaskState == TaskState.Effect || t.TaskState == TaskState.Freeze)
.WhereIf(inQuery.IsEffect == false, t => t.TaskState == TaskState.Adbandon || t.TaskState == TaskState.HaveReturned)
.WhereIf(inQuery.TaskState != null, t => t.TaskState == inQuery.TaskState)
.WhereIf(inQuery.TrialSiteId != null, t => t.Subject.TrialSiteId == inQuery.TrialSiteId)
.WhereIf(inQuery.SubjectId != null, t => t.SubjectId == inQuery.SubjectId)
.WhereIf(inQuery.IsUrgent != null, t => t.IsUrgent == inQuery.IsUrgent)
.WhereIf(inQuery.DoctorUserId != null, t => t.DoctorUserId == inQuery.DoctorUserId)
.WhereIf(inQuery.ReadingCategory != null, t => t.ReadingCategory == inQuery.ReadingCategory)
.WhereIf(inQuery.ReadingTaskState != null, t => t.ReadingTaskState == inQuery.ReadingTaskState)
.WhereIf(inQuery.TaskAllocationState != null, t => t.TaskAllocationState == inQuery.TaskAllocationState)
.WhereIf(inQuery.TrialReadingCriterionId != null, t => t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId)
.WhereIf(inQuery.ReReadingApplyState != null, t => t.ReReadingApplyState == inQuery.ReReadingApplyState)
.WhereIf(inQuery.CompleteClinicalDataEnum == CompleteClinicalDataEnum.Complete, t => t.IsClinicalDataSign && t.IsNeedClinicalDataSign == true)
.WhereIf(inQuery.CompleteClinicalDataEnum == CompleteClinicalDataEnum.NotComplete, t => t.IsClinicalDataSign == false && t.IsNeedClinicalDataSign == true)
.WhereIf(inQuery.CompleteClinicalDataEnum == CompleteClinicalDataEnum.NA, t => t.IsNeedClinicalDataSign == false)
.WhereIf(!string.IsNullOrEmpty(inQuery.TrialSiteCode), t => (t.BlindTrialSiteCode.Contains(inQuery.TrialSiteCode!) && t.IsAnalysisCreate) || (t.Subject.TrialSite.TrialSiteCode.Contains(inQuery.TrialSiteCode!) && t.IsAnalysisCreate == false))
.WhereIf(!string.IsNullOrEmpty(inQuery.TaskName), t => t.TaskName.Contains(inQuery.TaskName) || t.TaskBlindName.Contains(inQuery.TaskName))
.WhereIf(!string.IsNullOrEmpty(inQuery.SubjectCode), t => (t.Subject.Code.Contains(inQuery.SubjectCode) && t.IsAnalysisCreate == false) || (t.BlindSubjectCode.Contains(inQuery.SubjectCode) && t.IsAnalysisCreate))
.WhereIf(inQuery.BeginAllocateDate != null, t => t.AllocateTime > inQuery.BeginAllocateDate)
.WhereIf(inQuery.EndAllocateDate != null, t => t.AllocateTime < inQuery.EndAllocateDate)
.WhereIf(inQuery.BeginSignTime != null, t => t.SignTime > inQuery.BeginSignTime)
.WhereIf(inQuery.EndSignTime != null, t => t.SignTime < inQuery.EndSignTime)
.WhereIf(inQuery.RandomOrder != null, t => t.RandomOrder == inQuery.RandomOrder)
.WhereIf(inQuery.IsRandomOrderList == true, t => (t.ReadingTaskState == ReadingTaskState.WaitReading || t.ReadingTaskState == ReadingTaskState.Reading) && t.TaskAllocationState == TaskAllocationState.Allocated)
.WhereIf(!string.IsNullOrEmpty(inQuery.TrialSiteCode), t => (t.BlindTrialSiteCode.Contains(inQuery.TrialSiteCode!) && t.IsAnalysisCreate) || (t.Subject.TrialSite.TrialSiteCode.Contains(inQuery.TrialSiteCode!) && t.IsAnalysisCreate == false))
.WhereIf(!string.IsNullOrEmpty(inQuery.TaskName), t => t.TaskName.Contains(inQuery.TaskName) || t.TaskBlindName.Contains(inQuery.TaskName))
.WhereIf(!string.IsNullOrEmpty(inQuery.SubjectCode), t => t.Subject.Code.Contains(inQuery.SubjectCode) || t.BlindSubjectCode.Contains(inQuery.SubjectCode))
.WhereIf(inQuery.BeginAllocateDate != null, t => t.AllocateTime > inQuery.BeginAllocateDate)
.WhereIf(inQuery.EndAllocateDate != null, t => t.AllocateTime < inQuery.EndAllocateDate!.Value.AddDays(1))
.ProjectTo<ReadingTaskExportDto>(_mapper.ConfigurationProvider).ToListAsync();
//var defalutSortArray = new string[] { nameof(VisitTask.IsUrgent) + " desc", nameof(VisitTask.SubjectId), nameof(VisitTask.VisitTaskNum) };
list = list.OrderBy(t => t.TrialSiteCode).ThenBy(t => t.SubjectCode).ThenBy(t => t.VisitTaskNum).ToList();
var exportInfo = (await _trialRepository.Where(t => t.Id == inQuery.TrialId).IgnoreQueryFilters().ProjectTo<ExcelExportInfo>(_mapper.ConfigurationProvider).FirstOrDefaultAsync()).IfNullThrowException();
exportInfo.List = ExportExcelConverterDate.ConvertToClientTimeInObject(list, _userInfo.TimeZoneId);
exportInfo.CurrentTime = ExportExcelConverterDate.DateTimeInternationalToString(DateTime.Now, _userInfo.TimeZoneId);
return await ExcelExportHelper.DataExportAsync(StaticData.Export.TrialReadingTaskList_Export, exportInfo, $"{exportInfo.ResearchProgramNo}", _commonDocumentRepository, _hostEnvironment, _dictionaryService, typeof(ReadingTaskExportDto));
if (inQuery.IsRandomOrderList == true)
{
list = list.OrderBy(t => t.RandomOrder).ToList();
exportInfo.List = ExportExcelConverterDate.ConvertToClientTimeInObject(list, _userInfo.TimeZoneId);
return await ExcelExportHelper.DataExportAsync(StaticData.Export.TrialTaskRandomOrderList_Export, exportInfo, $"{exportInfo.ResearchProgramNo}", _commonDocumentRepository, _hostEnvironment, _dictionaryService, typeof(ReadingTaskExportDto));
}
else
{
list = list.OrderBy(t => t.TrialSiteCode).ThenBy(t => t.SubjectCode).ThenBy(t => t.VisitTaskNum).ToList();
exportInfo.List = ExportExcelConverterDate.ConvertToClientTimeInObject(list, _userInfo.TimeZoneId);
return await ExcelExportHelper.DataExportAsync(StaticData.Export.TrialReadingTaskList_Export, exportInfo, $"{exportInfo.ResearchProgramNo}", _commonDocumentRepository, _hostEnvironment, _dictionaryService, typeof(ReadingTaskExportDto));
}
}

View File

@ -799,7 +799,7 @@ namespace IRaCIS.Core.Application.Services
var systemDocQuery =
from sysDoc in _systemDocumentRepository.AsQueryable(false)
.Where(t => inQuery.UserTypeId != null ? t.NeedConfirmedUserTypeList.Any(t => t.NeedConfirmUserTypeId == inQuery.UserTypeId) : true)
from identityUser in _identityUserRepository.AsQueryable(false).Where(t => t.UserRoleList.Where(t => t.IsUserRoleDisabled == false).Any(t => sysDoc.NeedConfirmedUserTypeList.AsQueryable().Any(c => c.NeedConfirmUserTypeId == t.UserTypeId)))
from identityUser in _identityUserRepository.AsQueryable(false).Where(t =>t.Status== UserStateEnum.Enable && t.UserRoleList.Where(t => t.IsUserRoleDisabled == false).Any(t => sysDoc.NeedConfirmedUserTypeList.AsQueryable().Any(c => c.NeedConfirmUserTypeId == t.UserTypeId)))
.Where(t => inQuery.UserId != null ? t.Id == inQuery.UserId : true)
.Where(t => inQuery.UserTypeId != null ? t.UserRoleList.Any(t => t.UserTypeId == inQuery.UserTypeId && t.IsUserRoleDisabled == false) : true)
join confirm in _systemDocConfirmedUserRepository.Where() on new { ConfirmUserId = identityUser.Id, SystemDocumentId = sysDoc.Id } equals new { confirm.ConfirmUserId, confirm.SystemDocumentId } into cc

View File

@ -13,6 +13,7 @@ using MassTransit.Initializers;
using Medallion.Threading;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using NPOI.SS.Formula.Functions;
using System.Data;
using System.IO.Compression;
using System.Text;
@ -901,8 +902,9 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
}
var query = _visitTaskRepository.Where(t => t.SubjectId == subjectId && t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId
&& t.SourceSubjectVisitId != null && t.DoctorUserId == doctorUserId && t.TaskState == TaskState.Effect)
//满足 有序或者随机只看到当前任务的dicom 非dicom检查
&& t.SourceSubjectVisitId != null && t.DoctorUserId == doctorUserId)
//满足 有序或者随机只看到当前任务的dicom 非dicom检查
.WhereIf(inQuery.VisitTaskId == null, t => t.TaskState == TaskState.Effect)//从待阅列表进入,要筛选出有效的,任务可能重阅了,也要看到该任务的的
.WhereIf(criterionInfo.IsReadingTaskViewInOrder != ReadingOrder.SubjectRandom && inQuery.VisitTaskId != null, t => t.Id == inQuery.VisitTaskId)
.ProjectTo<SubjectCRCImageUploadedDto>(_mapper.ConfigurationProvider);

View File

@ -897,6 +897,8 @@ namespace IRaCIS.Core.Application.Contracts
/*string.Format("{0}分钟", (ReadingDurationTimeSpan)?.TotalMinutes)*/;
}
}
public int? RandomOrder { get; set; }
}

View File

@ -12,6 +12,7 @@ namespace IRaCIS.Core.Application.Contracts
{
public interface IReadingImageTaskService
{
Task TriggerJudgeQuestion(Guid visitTaskId);
Task<IResponseOutput> SubmitVisitTaskQuestions(SubmitVisitTaskQuestionsInDto inDto);
Task<IResponseOutput> SubmitJudgeVisitTaskResult(SaveJudgeVisitTaskResult inDto);

View File

@ -54,7 +54,7 @@ namespace IRaCIS.Core.Application.Service
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
[TrialGlobalLimit( "AfterStopCannNotOpt" )]
[TrialGlobalLimit("AfterStopCannNotOpt")]
public async Task<IResponseOutput> BatchSubmitGlobalReadingInfo(BatchSubmitGlobalReadingInfo inDto)
{
await VerifyTaskIsSign(inDto.GlobalTaskId);
@ -94,7 +94,7 @@ namespace IRaCIS.Core.Application.Service
})).ToList();
await _readingGlobalTaskInfoRepository.AddRangeAsync(answers);
await _visitTaskRepository.UpdatePartialFromQueryAsync(t => t.Id == inDto.GlobalTaskId, u => new VisitTask() { ReadingTaskState = ReadingTaskState.Reading });
await _visitTaskRepository.UpdatePartialFromEFAutoAsync(inDto.GlobalTaskId, u => new VisitTask() { ReadingTaskState = ReadingTaskState.Reading });
var result = await _readingGlobalTaskInfoRepository.SaveChangesAsync();
return ResponseOutput.Ok(result);
}
@ -107,7 +107,7 @@ namespace IRaCIS.Core.Application.Service
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
[TrialGlobalLimit( "AfterStopCannNotOpt" )]
[TrialGlobalLimit("AfterStopCannNotOpt")]
public async Task<IResponseOutput> SaveGlobalReadingInfo(SaveGlobalReadingInfoInDto inDto)
{
await VerifyTaskIsSign(inDto.GlobalTaskId);
@ -301,7 +301,7 @@ namespace IRaCIS.Core.Application.Service
LimitEdit = y.LimitEdit,
MaxAnswerLength = y.MaxAnswerLength,
FileType = y.FileType,
Unit=y.Unit,
Unit = y.Unit,
QuestionGenre = y.QuestionGenre,
ShowOrder = y.ShowOrder,
DictionaryCode = y.DictionaryCode,

View File

@ -647,7 +647,7 @@ namespace IRaCIS.Core.Application.Service
IsCurrentTask = x.Id == inDto.VisitTaskId,
IsConvertedTask = x.IsConvertedTask,
IsFirstChangeTask = x.BeforeConvertedTaskId != null,
IsExistUnprocessedFeedback=x.UserFeedBackList.Any(y => y.State == 0),
IsExistUnprocessedFeedback = x.UserFeedBackList.Any(y => y.State == 0),
}).ToListAsync();
@ -1649,7 +1649,7 @@ namespace IRaCIS.Core.Application.Service
QuestionMark.IsLymph,
};
switch (taskInfo.TrialReadingCriterion.CriterionType)
{
@ -2449,14 +2449,14 @@ namespace IRaCIS.Core.Application.Service
// }
// }
// }
//}
break;
}
var criterionId = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).Select(x => x.TrialReadingCriterionId).FirstOrDefaultAsync();
var criterionInfo = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == criterionId).FirstNotNullAsync();
var tableQuestionIds = inDto.AnswerList.Select(x => x.TableQuestionId).ToList();
@ -3034,7 +3034,9 @@ namespace IRaCIS.Core.Application.Service
var subjectTaskList = (await _visitTaskService.GetSubjectReadingIQueryable(new GetReadingIQueryableInDto()
{
TrialId = inDto.TrialId,
SubjectId = inDto.SubjectId,
TrialReadingCriterionId = trialReadingCriterionId!.Value,
SubjectCode = inDto.SubjectCode,
PageIndex = 1,
PageSize = 99999,
@ -3117,24 +3119,45 @@ namespace IRaCIS.Core.Application.Service
&& x.TrialReadingCriterionId == trialReadingCriterionId
&& x.TaskState == TaskState.Effect)
.Where(x => !cacheSkipIds.Contains(x.Id));
var count = await query.CountAsync();
if (count == 0)
{
throw new BusinessValidationFailedException(_localizer["ReadingImage_TaskFinish"], ApiResponseCodeEnum.CloseCurrentWindows);
}
//如果是随机阅片
Random random = new Random();
var skipcount = 0;
var minRandomOrder = query.Where(t => t.RandomOrder != null).Select(t => t.RandomOrder).MinOrDefault();
//以随机序号优先阅片中优先先给IR
if (minRandomOrder != null)
{
query = query.Where(x => x.RandomOrder == minRandomOrder);
skipcount = 0;
}
else
{
//没有随机序号的,那么就按照阅片中最新的时间给
var maxReadingTime = query.MaxOrDefault(x => x.FirstReadingTime);
if (maxReadingTime != null)
{
query = query.Where(x => x.FirstReadingTime == maxReadingTime);
skipcount = 0;
}
}
var count = await query.CountAsync();
if (count >= 2)
{
skipcount = random.Next(0, count - 1);
}
var maxReadingTime = query.MaxOrDefault(x => x.FirstReadingTime);
if (maxReadingTime != null)
if (count == 0)
{
query = query.Where(x => x.FirstReadingTime == maxReadingTime);
skipcount = 0;
throw new BusinessValidationFailedException(_localizer["ReadingImage_TaskFinish"], ApiResponseCodeEnum.CloseCurrentWindows);
}
task = await query
.Select(x => new GetReadingTaskDto()
{
@ -3155,6 +3178,14 @@ namespace IRaCIS.Core.Application.Service
{
throw new BusinessValidationFailedException(_localizer["ReadingImage_TaskFinish"], ApiResponseCodeEnum.CloseCurrentWindows);
}
else
{
//触发任务随机编号
await _downloadAndUploadService.SubejctRandomReadingTaskNameDeal(task.SubjectId, task.TrialReadingCriterionId);
task.TaskBlindName = await _visitTaskRepository.Where(t => t.Id == task.VisitTaskId).Select(t => t.TaskBlindName).FirstOrDefaultAsync() ?? "";
}
if (task.SubjectCode.IsNullOrEmpty())
{
@ -3235,7 +3266,7 @@ namespace IRaCIS.Core.Application.Service
task.SubjectCode = blindSubjectCode.IsNullOrEmpty() ? task.SubjectCode : blindSubjectCode;
task.ExistsManual = (await GetManualList(new GetManualListInDto() { TrialId = visitTaskInfo.TrialId })).Count > 0;
task.ReadingTaskState = visitTaskInfo.ReadingTaskState;
task.IsShowStudyName= trialInfo.IsShowStudyName;
task.IsShowStudyName = trialInfo.IsShowStudyName;
task.IsBaseLine = isBaseLine;
task.ReadingVersionEnum = criterionInfo.ReadingVersionEnum;
task.ReadingToolList = criterionInfo.ReadingToolList;
@ -3271,7 +3302,7 @@ namespace IRaCIS.Core.Application.Service
await _readingTableQuestionAnswerRepository.BatchDeleteNoTrackingAsync(x => x.VisitTaskId == inDto.VisitTaskId);
await _readingTaskQuestionMarkRepository.BatchDeleteNoTrackingAsync(x => x.VisitTaskId == inDto.VisitTaskId);
await _readingCustomTagRepository.BatchDeleteNoTrackingAsync(x => x.VisitTaskId == inDto.VisitTaskId);
await _visitTaskRepository.UpdatePartialFromQueryAsync(x => x.Id == inDto.VisitTaskId, x => new VisitTask()
await _visitTaskRepository.BatchUpdateNoTrackingAsync(x => x.Id == inDto.VisitTaskId, x => new VisitTask()
{
ReadingTaskState = ReadingTaskState.WaitReading
});
@ -3351,7 +3382,7 @@ namespace IRaCIS.Core.Application.Service
[HttpPost]
public async Task<bool> ResetReadingRestTime(Guid? userRoleId)
{
var roleId = (userRoleId != null && userRoleId != Guid.Empty) ? (Guid) userRoleId : _userInfo.UserRoleId;
var roleId = (userRoleId != null && userRoleId != Guid.Empty) ? (Guid)userRoleId : _userInfo.UserRoleId;
//int readingMinute = 120; // 为60整数
int restMinute = 10; //

View File

@ -346,7 +346,7 @@ namespace IRaCIS.Core.Application.Service
var relatedVisitTaskIds = JsonConvert.SerializeObject(relatedVisitTaskIdList);
// 这里先保存 签名的时候 会统一创建关系
await _visitTaskRepository.UpdatePartialFromQueryAsync(t => t.Id == inDto.OncologyTaskId, u => new VisitTask()
await _visitTaskRepository.BatchUpdateNoTrackingAsync(t => t.Id == inDto.OncologyTaskId, u => new VisitTask()
{
RelatedVisitTaskIds = relatedVisitTaskIds
});

View File

@ -1,6 +1,8 @@
using IRaCIS.Core.Application.Filter;
using IRaCIS.Core.Application.Contracts;
using IRaCIS.Core.Application.Filter;
using IRaCIS.Core.Application.Service.Reading.Dto;
using IRaCIS.Core.Application.ViewModel;
using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infrastructure;
using MassTransit;
@ -25,6 +27,7 @@ namespace IRaCIS.Core.Application.Service
IRepository<DicomInstance> _dicomInstanceRepository,
IRepository<NoneDicomStudyFile> _noneDicomStudyFileRepository,
IRepository<ReadingClinicalData> _readingClinicalDataRepository,
IReadingImageTaskService _readingImageTaskService,
IRepository<ReadingPeriodSet> _readingPeriodSetRepository,
IRepository<ReadModule> _readModuleRepository, IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer) : BaseService
{
@ -64,7 +67,7 @@ namespace IRaCIS.Core.Application.Service
var resultlist = await visitQuery.WhereIf(finalVisitNum != null && finalVisitNum != 0, x => x.VisitNum <= finalVisitNum)
.Where(x => x.VisitNum > mixReadVisitNum|| x.VisitNum==thisVisitNum)
.Where(x => !x.IsBaseLine) // 排除基线
//.Where(x => !x.IsBaseLine) // 排除基线
.WhereIf(inDto.ReadingSetType == ReadingSetType.TumorReading, x => readModulequery.Where(y => y.SubjectVisitId == x.Id && y.TrialReadingCriterionId == inDto.TrialReadingCriterionId && y.ReadingSetType == ReadingSetType.ImageReading).Count() > 0)
.WhereIf(inDto.ReadingSetType == ReadingSetType.ImageReading, x => readModulequery.Where(y => y.Id != inDto.Id && y.SubjectVisitId == x.Id && y.TrialReadingCriterionId == inDto.TrialReadingCriterionId && y.ReadingSetType == ReadingSetType.ImageReading).Count() == 0)
.Select(x => new GetSubjectReadVisitsOutDto()
@ -94,6 +97,29 @@ namespace IRaCIS.Core.Application.Service
throw new BusinessValidationFailedException(_localizer["ReadModule_CRCConfirmCanNtoEdit"]);
}
var readModule = await _readModuleRepository.Where(x => x.Id == inDto.Id).FirstNotNullAsync();
var criterionInfo = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == readModule.TrialReadingCriterionId).Select(x => new
{
x.ReadingType,
x.IsArbitrationReading,
x.IsReadingPeriod,
x.ArbitrationRule,
x.IsGlobalReading,
x.IsOncologyReading,
}).FirstNotNullAsync();
// 如果生成了 访视级别的阅片期裁判 不让修改
if (criterionInfo.IsArbitrationReading && criterionInfo.IsReadingPeriod && !criterionInfo.IsGlobalReading && criterionInfo.ArbitrationRule == ArbitrationRule.Reading)
{
if (await _visitTaskRepository.AnyAsync(x => x.SourceSubjectVisitId == readModule.SubjectVisitId && x.ReadingCategory == ReadingCategory.Judge))
{
//---当前阅片已生成裁判任务,操作失败。
throw new BusinessValidationFailedException(_localizer["ReadModule_JudgeTaskGenerated"]);
}
}
await _readModuleRepository.UpdatePartialFromQueryAsync(x => x.Id == inDto.Id, x => new ReadModule()
{
SubjectVisitId = inDto.SubjectVisitIdId,
@ -499,8 +525,8 @@ namespace IRaCIS.Core.Application.Service
#region 方式二
var subjectVisitQuery = _subjectVisitRepository.Where(t => t.TrialId == inQuery.TrialId).Where(t => t.IsLostVisit == false)
.Where(sv => sv.Subject.FinalSubjectVisitId == null ? true : sv.VisitNum < sv.Subject.LatestSubjectVisit.VisitNum).Select(sv => new ReadModuleView()
var subjectVisitQuery = _subjectVisitRepository.Where(t => t.TrialId == inQuery.TrialId)/*.Where(t => t.IsLostVisit == false)*/
.Where(sv => sv.Subject.FinalSubjectVisitId == null ? true : sv.VisitNum <= sv.Subject.LatestSubjectVisit.VisitNum).Select(sv => new ReadModuleView()
{
Id = sv.Id,
CreateTime = sv.CreateTime,
@ -885,7 +911,7 @@ namespace IRaCIS.Core.Application.Service
var resultlist = await visitQuery.WhereIf(finalVisitNum != 0, x => x.VisitNum <= finalVisitNum)
.WhereIf(inDto.ReadingSetType == ReadingSetType.TumorReading, x => readModulequery.Where(y => y.SubjectVisitId == x.Id && y.TrialReadingCriterionId == inDto.TrialReadingCriterionId && y.ReadingSetType == ReadingSetType.ImageReading).Count() > 0)
.Where(x => x.VisitNum > maxReadVisitNum)
.Where(x => !x.IsBaseLine) // 排除基线
//.Where(x => !x.IsBaseLine) // 排除基线
.Where(x => readModulequery.Where(y => y.SubjectVisitId == x.Id && y.TrialReadingCriterionId == inDto.TrialReadingCriterionId && y.ReadingSetType == inDto.ReadingSetType).Count() == 0).OrderBy(x => finalVisitNum)
.Select(x => new GetSubjectReadVisitsOutDto()
{
@ -954,6 +980,8 @@ namespace IRaCIS.Core.Application.Service
&& !x.IsAnalysisCreate && x.TrialReadingCriterionId == dto.TrialReadingCriterionId
).ToListAsync();
// 生成全局阅片任务 具体是否需要生成在_visitTaskHelpeService里面有逻辑判断
foreach (var taskInfo in taskListInfo)
{
await _visitTaskHelpeService.AddTaskAsync(new GenerateTaskCommand()
@ -974,6 +1002,13 @@ namespace IRaCIS.Core.Application.Service
}
});
}
// 生成裁判任务 是否需要生成函数里面有逻辑判断
if (taskListInfo.Count() > 0)
{
await _readingImageTaskService.TriggerJudgeQuestion(taskListInfo[0].Id);
}
break;
case ModuleTypeEnum.Oncology:
@ -1066,6 +1101,15 @@ namespace IRaCIS.Core.Application.Service
var readModule = await _readModuleRepository.Where(x => x.Id == readModuleId).FirstNotNullAsync();
var criterionInfo = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == readModule.TrialReadingCriterionId).Select(x => new
{
x.ReadingType,
x.IsArbitrationReading,
x.IsReadingPeriod,
x.ArbitrationRule,
x.IsGlobalReading,
x.IsOncologyReading,
}).FirstNotNullAsync();
if (await _readingClinicalDataRepository.Where(t => t.ReadingId == readModuleId).AnyAsync(t => t.ReadingClinicalDataState == ReadingClinicalDataStatus.HaveSigned))
{
@ -1094,6 +1138,17 @@ namespace IRaCIS.Core.Application.Service
throw new BusinessValidationFailedException(_localizer["ReadModule_TaskGenerated"]);
}
// 如果生成了 访视级别的阅片期裁判 不让删除
if (criterionInfo.IsArbitrationReading && criterionInfo.IsReadingPeriod && !criterionInfo.IsGlobalReading && criterionInfo.ArbitrationRule == ArbitrationRule.Reading)
{
if (await _visitTaskRepository.AnyAsync(x => x.SourceSubjectVisitId == readModule.SubjectVisitId && x.ReadingCategory == ReadingCategory.Judge))
{
//---当前阅片已生成裁判任务,操作失败。
throw new BusinessValidationFailedException(_localizer["ReadModule_JudgeTaskGenerated"]);
}
}
await _visitTaskRepository.BatchUpdateNoTrackingAsync(x => readModuleId == x.SouceReadModuleId, x => new VisitTask()
{

View File

@ -1,4 +1,5 @@
using IRaCIS.Core.Application.Filter;
using IRaCIS.Core.Application.Contracts;
using IRaCIS.Core.Application.Filter;
using IRaCIS.Core.Application.Service.Reading.Dto;
using IRaCIS.Core.Application.ViewModel;
using IRaCIS.Core.Domain.Share;
@ -17,6 +18,7 @@ namespace IRaCIS.Core.Application.Service
IRepository<ReadModule> _readModuleRepository,
IRepository<VisitStage> _visitStageRepository,
IRepository<Trial> _trialRepository,
IReadingImageTaskService _readingImageTaskService,
IRepository<VisitTask> _visitTaskRepository,
IRepository<ReadingQuestionCriterionTrial> _readingQuestionCriterionTrialRepository,
IVisitTaskHelpeService _visitTaskHelpeService,
@ -165,6 +167,9 @@ namespace IRaCIS.Core.Application.Service
});
};
await _readModuleRepository.AddRangeAsync(readModules);
await _readModuleRepository.SaveChangesAsync();
// 判断是否要添加肿瘤学或者全局阅片任务
var subjectVisitIds = readModules.Select(x => x.SubjectVisitId).ToList();
@ -201,6 +206,14 @@ namespace IRaCIS.Core.Application.Service
});
}
}
// 根据SourceSubjectVisitId 分组
var visitTaskid = taskInfoList.GroupBy(x => x.SourceSubjectVisitId).Select(x => x.Max(y => y.Id)).ToList();
// 生成裁判任务 是否需要生成函数里面有逻辑判断
foreach (var item in visitTaskid)
{
await _readingImageTaskService.TriggerJudgeQuestion(item);
}
break;
case ReadingSetType.TumorReading:
@ -269,7 +282,7 @@ namespace IRaCIS.Core.Application.Service
break;
}
await _readModuleRepository.AddRangeAsync(readModules);
@ -443,13 +456,13 @@ namespace IRaCIS.Core.Application.Service
List<GetReadingVisitListOutDto> result = await _visitStageRepository.Where(x => x.TrialId == inDto.TrialId)
.WhereIf(inDto.ReadingSetType == ReadingSetType.TumorReading, x => globalVisitNum.Contains(x.VisitNum))
.Where(x => x.VisitNum > 0)// 不能是基线
//.Where(x => x.VisitNum > 0)// 不能是基线
.Where(x => x.VisitNum == thisVisitNum || x.VisitNum >= maxVisitNum).Select(x => new GetReadingVisitListOutDto()
{
VisitName = x.VisitName,
VisitNum = x.VisitNum,
VisitStageId = x.Id,
}).ToListAsync();
}).OrderBy(x=>x.VisitNum).ToListAsync();
return result;
}

View File

@ -729,6 +729,21 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate
throw new BusinessValidationFailedException(_localizer["MRIPDFF_AllNeedToBeMark"]);
}
try
{
List<QuestionMark?> questionMarkList = new List<QuestionMark?>() { QuestionMark.FirstMeasurement, QuestionMark.SecondMeasurement, QuestionMark.ThirdMeasurement };
var measuredValueList = rowInfo.SelectMany(x => x.TableQuestionList).Where(x =>x.Answer.IsNotNullOrEmpty()&& questionMarkList.Contains(x.QuestionMark)).Select(x => decimal.Parse(x.Answer)).ToList();
if (measuredValueList.Any(x => x > 100))
{
throw new BusinessValidationFailedException(_localizer["MRIPDFF_MeasurementGT100"]);
}
}
catch (Exception)
{
throw new BusinessValidationFailedException(_localizer["MRIPDFF_MeasurementGT100"]);
}
var notableQuestionList = rowInfo.Where(x => x.TableQuestionList.Any(x => x.QuestionMark == QuestionMark.IsMeasurable && x.Answer.EqEnum(YesOrNoOrNa.No))).ToList();

View File

@ -288,4 +288,13 @@ public class VisitTask : BaseFullAuditEntity
[Comment("退回原因")]
public string PMBackReason { get; set; }
#region 完全随机增加字段
[Comment("完全随机阅片号")]
public int? RandomOrder { get; set; }
#endregion
}

View File

@ -83,7 +83,29 @@ namespace IRaCIS.Core.Infra.EFCore.Common
}
}
/// <summary>
/// 翻译单位
/// </summary>
/// <param name="answerType">答案类型</param>
/// <param name="unit">单位</param>
/// <param name="customUnit">自定义单位</param>
/// <param name="unitDataList">单位字典</param>
/// <param name="answer">答案</param>
/// <returns></returns>
public string Translationunit(string answerType, ValueUnit? unit, string customUnit, List<UnitData> unitDataList,string? answer)
{
if (answerType == "upload")
{
return "❄❅❆❇❈❉❊";
}
if (unit == ValueUnit.Custom)
{
return answer + customUnit;
}
return answer + unitDataList.Where(y => y.Unit == unit).Select(x => x.UnitName).FirstIsNullReturnEmpty();
}
public string GetEntityAuditOpt(EntityEntry entityEntry)
{
if (entityEntry.State == EntityState.Added)
@ -188,7 +210,7 @@ namespace IRaCIS.Core.Infra.EFCore.Common
//TrialDicList = string.Join(",", trialDics)
ImageFormatListStr = string.Join("|", entity.ImageFormatList),
StudyNamesStr = string.Join("|", entity.StudyNameList.Where(x => x.IsChoose).Select(x=>_userInfo.IsEn_Us?x.EnName:x.Name )),
StudyNamesStr = string.Join("|", entity.StudyNameList.Where(x => x.IsChoose).Select(x => _userInfo.IsEn_Us ? x.EnName : x.Name)),
CriterionNames = string.Join(",", criterionNameList.Union(memoryCriterionNameList).Distinct()),
@ -1738,11 +1760,11 @@ namespace IRaCIS.Core.Infra.EFCore.Common
var entity = item.Entity as IdentityUser;
await InsertInspection<IdentityUser>(entity, type, x => new InspectionConvertDTO
{
IsDistinctionInterface = type == AuditOpt.Update ? true : false,
});
await InsertInspection<IdentityUser>(entity, type, x => new InspectionConvertDTO
{
IsDistinctionInterface = type == AuditOpt.Update ? true : false,
});
}
// 项目参与人员
@ -1777,7 +1799,7 @@ namespace IRaCIS.Core.Infra.EFCore.Common
identityUser.Phone,
identityUser.OrganizationName,
});
}
}
}
// 项目人员
@ -1795,7 +1817,7 @@ namespace IRaCIS.Core.Infra.EFCore.Common
//var user = await _dbContext.Users.Include(x => x.UserTypeRole).FirstOrDefaultAsync(x => x.Id == entity.UserId);
await InsertInspection<TrialUserRole>(entity, type, x => new InspectionConvertDTO
{
IsDistinctionInterface = false,
IsDistinctionInterface = false,
TrialId = x.TrialId,
ObjectRelationParentId = x.TrialId,
ExtraIndentification = extraIndentification,
@ -2018,10 +2040,23 @@ namespace IRaCIS.Core.Infra.EFCore.Common
foreach (var item in entitys.Where(x => x.Entity.GetType() == typeof(DicomStudy)))
{
var type = GetEntityAuditOpt(item);
var extraIdentification = string.Empty;
switch (_userInfo.RequestUrl)
{
case "QCOperation/updateModality":
if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.ClinicalResearchCoordinator)
{
extraIdentification = "/2";
}
break;
}
await InsertInspection<DicomStudy>(item.Entity as DicomStudy, type, x => new InspectionConvertDTO()
{
ObjectRelationParentId = x.SubjectVisitId
ObjectRelationParentId = x.SubjectVisitId,
ExtraIndentification = extraIdentification
});
}
@ -3013,6 +3048,7 @@ namespace IRaCIS.Core.Infra.EFCore.Common
QuestionId = t.Id,
t.DictionaryCode,
t.Unit,
t.CustomUnit,
t.ShowOrder,
AnswerType = t.Type,
}).OrderBy(t => t.ShowOrder).ToListAsync();
@ -3060,7 +3096,7 @@ namespace IRaCIS.Core.Infra.EFCore.Common
new
{
//如果问题类型是附件 特殊处理 方便前端解析
Answer = u.AnswerType == "upload" ? "❄❅❆❇❈❉❊" + t.Answer : t.Answer,
Answer = Translationunit(u.AnswerType, u.Unit, u.CustomUnit, unitDataList, t.Answer),
u.QuestionName,
u.QuestionEnName,
u.DictionaryCode,
@ -3091,8 +3127,7 @@ namespace IRaCIS.Core.Infra.EFCore.Common
(t, u) =>
new
{
Answer = u.AnswerType == "upload" ? "❄❅❆❇❈❉❊" + t.Answer : t.Answer + unitDataList.Where(y => y.Unit == u.Unit).Select(x => x.UnitName).FirstIsNullReturnEmpty()
,
Answer = Translationunit(u.AnswerType, u.Unit,u.CustomUnit, unitDataList, t.Answer),
u.DictionaryCode,
u.QuestionName,
u.QuestionEnName,
@ -3220,7 +3255,7 @@ namespace IRaCIS.Core.Infra.EFCore.Common
new
{
//如果问题类型是附件 特殊处理 方便前端解析
Answer = u.AnswerType == "upload" ? "❄❅❆❇❈❉❊" + t.Answer : t.Answer + unitDataList.Where(y => y.Unit == u.Unit).Select(x => x.UnitName).FirstIsNullReturnEmpty(),
Answer = Translationunit(u.AnswerType, u.Unit, u.CustomUnit, unitDataList, t.Answer),
//t.Answer /*u.Unit==ValueUnit.Custom? t.Answer+u.CustomUnit:(u.Unit != ValueUnit.None|| u.Unit != null)*/,
u.QuestionName,
u.QuestionEnName,
@ -3228,7 +3263,7 @@ namespace IRaCIS.Core.Infra.EFCore.Common
u.ShowOrder
}
).OrderBy(t => t.ShowOrder).ToList()
},_userInfo.AuditIdentification);
}, _userInfo.AuditIdentification);
////添加/修改病灶接口 只会对单个病灶进行操作
@ -3489,18 +3524,24 @@ namespace IRaCIS.Core.Infra.EFCore.Common
{
isDistinctionInterface = false;
switch (_userInfo.RequestUrl)
{
//申请重阅
case "VisitTask/applyReReading":
extraIdentification = "/" + (int)entity.ReReadingApplyState;
//PM 申请重阅区分不了是否有SPM参与
if (entity.ReReadingApplyState== ReReadingApplyState.TrialGroupHaveApplyed)
if (entity.ReReadingApplyState == ReReadingApplyState.TrialGroupHaveApplyed)
{
var hasSPM = _dbContext.VisitTaskReReading.Any(t => t.OriginalReReadingTaskId == entity.Id);
//var hasSPM = _dbContext.VisitTaskReReading.Any(t => t.OriginalReReadingTaskId == entity.Id);
var hasSPM = entitys.Where(x => x.Entity.GetType() == typeof(VisitTaskReReading))
.Select(t => t.Entity as VisitTaskReReading).Any(t => t.OriginalReReadingTaskId == entity.Id);
if (!hasSPM)
{
@ -3515,6 +3556,7 @@ namespace IRaCIS.Core.Infra.EFCore.Common
//同意重阅
case "VisitTask/ConfirmReReading":
if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.ProjectManager || _userInfo.UserTypeEnumInt == (int)UserTypeEnum.APM)
{
extraIdentification = "/" + 1;
@ -3536,51 +3578,95 @@ namespace IRaCIS.Core.Infra.EFCore.Common
break;
case "ReadingImageTask/SubmitVisitTaskQuestions":
//访视任务-- 非Dicom 阅片
if (entity.ReadingTaskState != ReadingTaskState.HaveSigned)
{
//提交访视任务的时候 会多次更新同一个记录 只记录最后一次
return;
}
break;
//Dicom 阅片 签名
case "ReadingImageTask/SubmitDicomVisitTask":
//跳转阅片结果需要该参数
var subjectCode = _dbContext.Subject.Where(t => t.Id == entity.SubjectId).Select(t => t.Code).First();
obj.SubjectCode = subjectCode;
break;
case "ReadingImageTask/resetReadingTask":
//跳转阅片结果需要该参数
obj.IsReadingReset = true;
break;
}
#region 裁判、肿瘤学、全局 都是通用的
//裁判任务 结果的保存 和签名提交
if (entity.JudgeResultTaskId != null && (_userInfo.RequestUrl == "ReadingImageTask/SaveJudgeVisitTaskResult" || _userInfo.RequestUrl == "ReadingImageTask/SubmitJudgeVisitTaskResult"))
{
var visitTaskNum = entity.VisitTaskNum - ReadingCommon.TaskNumDic[ReadingCategory.Judge];
var list = await _dbContext.VisitTask.Where(t => t.TaskState == TaskState.Effect && t.SubjectId == entity.SubjectId && t.VisitTaskNum == visitTaskNum && t.JudgeVisitTaskId == entity.Id && t.TrialReadingCriterionId == entity.TrialReadingCriterionId).Select(t => new { t.Id, t.DoctorUser.FullName, t.ArmEnum }).OrderBy(t => t.ArmEnum).ToListAsync();
var r1 = list.Where(t => t.ArmEnum == Arm.DoubleReadingArm1).FirstOrDefault();
var r2 = list.Where(t => t.ArmEnum == Arm.DoubleReadingArm2).FirstOrDefault();
obj.R1 = r1.FullName;
obj.R2 = r2.FullName;
obj.SelectResult = r1.Id == entity.JudgeResultTaskId ? "R1" : "R2";
}
#endregion
//增加进入阅片中的稽查
//重置阅片也会从待阅片 变为阅片中,因为复制病灶依赖这个改变
if (obj.IsReadingReset != true)
{
if (entity.ReadingTaskState == ReadingTaskState.Reading)
{
if (_dbContext.VisitTask.Where(t => t.Id == entity.Id).Any(t => t.ReadingTaskState == ReadingTaskState.WaitReading))
{
isDistinctionInterface = false;
extraIdentification = "/ChangeToReading";
}
}
}
if (entity.IsReadClinicalData == true)
{
if (_dbContext.VisitTask.Where(t => t.Id == entity.Id).Any(t => t.IsReadClinicalData == false))
{
isDistinctionInterface = false;
extraIdentification = "/ReadClinicalData";
}
}
if(entity.TaskBlindName.Contains("Timepoint Ran"))
{
if(_dbContext.VisitTask.Where(t => t.Id == entity.Id).Any(t => !t.TaskBlindName.Contains("Timepoint Ran")))
{
isDistinctionInterface = false;
extraIdentification = "/TriggerSystemBlindingName";
}
}
}
//访视任务-- 非Dicom 阅片
if (_userInfo.RequestUrl == "ReadingImageTask/SubmitVisitTaskQuestions" && entity.ReadingTaskState != ReadingTaskState.HaveSigned && type == AuditOpt.Update)
{
//提交访视任务的时候 会多次更新同一个记录 只记录最后一次
return;
}
//Dicom 阅片 签名
if (_userInfo.RequestUrl == "ReadingImageTask/SubmitDicomVisitTask")
{
//跳转阅片结果需要该参数
var subjectCode = _dbContext.Subject.Where(t => t.Id == entity.SubjectId).Select(t => t.Code).First();
obj.SubjectCode = subjectCode;
}
#region 裁判、肿瘤学、全局 都是通用的
//裁判任务 结果的保存 和签名提交
if (entity.JudgeResultTaskId != null && (_userInfo.RequestUrl == "ReadingImageTask/SaveJudgeVisitTaskResult" || _userInfo.RequestUrl == "ReadingImageTask/SubmitJudgeVisitTaskResult"))
{
var visitTaskNum = entity.VisitTaskNum - ReadingCommon.TaskNumDic[ReadingCategory.Judge];
var list = await _dbContext.VisitTask.Where(t => t.TaskState == TaskState.Effect && t.SubjectId == entity.SubjectId && t.VisitTaskNum == visitTaskNum && t.JudgeVisitTaskId == entity.Id && t.TrialReadingCriterionId == entity.TrialReadingCriterionId).Select(t => new { t.Id, t.DoctorUser.FullName, t.ArmEnum }).OrderBy(t => t.ArmEnum).ToListAsync();
var r1 = list.Where(t => t.ArmEnum == Arm.DoubleReadingArm1).FirstOrDefault();
var r2 = list.Where(t => t.ArmEnum == Arm.DoubleReadingArm2).FirstOrDefault();
obj.R1 = r1.FullName;
obj.R2 = r2.FullName;
obj.SelectResult = r1.Id == entity.JudgeResultTaskId ? "R1" : "R2";
}
#endregion
#region 通过链接跳转 2022 12-19
@ -3697,7 +3783,7 @@ namespace IRaCIS.Core.Infra.EFCore.Common
/// <param name="expression">表达式</param>
/// <param name="otherItem">其他对象</param>
/// <returns></returns>
public async Task InsertInspection<T>(T entityObj, string type, Expression<Func<T, InspectionConvertDTO>> expression = null, object otherItem = null,string auditIdentification = "") where T : Entity
public async Task InsertInspection<T>(T entityObj, string type, Expression<Func<T, InspectionConvertDTO>> expression = null, object otherItem = null, string auditIdentification = "") where T : Entity
{
InspectionConvertDTO inspection = new InspectionConvertDTO();
@ -3924,7 +4010,7 @@ namespace IRaCIS.Core.Infra.EFCore.Common
/// 获取稽查记录的标识符 部分业务会进行特殊处理
/// </summary>
/// <returns></returns>
public string GetInspectionRecordIdentification<T>(T entityObj, string type, bool IsDistinctionInterface = true, bool isSelfDefine = false,string auditIdentification="")
public string GetInspectionRecordIdentification<T>(T entityObj, string type, bool IsDistinctionInterface = true, bool isSelfDefine = false, string auditIdentification = "")
{
//var entityType = _dbContext.Model.FindEntityType(entityObj.GetType());
//var tableName = entityType.GetTableName();
@ -3943,11 +4029,11 @@ namespace IRaCIS.Core.Infra.EFCore.Common
//自定义 标识后面 补充由代码上层的 extraIdentification 附加
if (isSelfDefine)
{
result= $"{_userInfo.RequestUrl}/{entityTypeName}";
result = $"{_userInfo.RequestUrl}/{entityTypeName}";
}
else
{
result= $"{_userInfo.RequestUrl}/{entityTypeName}/{type}";
result = $"{_userInfo.RequestUrl}/{entityTypeName}/{type}";
}

View File

@ -62,6 +62,8 @@ namespace IRaCIS.Core.Infra.EFCore.Common
public string CutOffVisitName { get; set; }
public string SelectResult { get; set; }
public bool? IsReadingReset { get;set; }
}
public class InspectionConvertDTO : DataInspection
{

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,70 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace IRaCIS.Core.Infra.EFCore.Migrations
{
/// <inheritdoc />
public partial class addRandomOrder : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<int>(
name: "RandomOrder",
table: "VisitTask",
type: "int",
nullable: true,
comment: "完全随机阅片号");
//migrationBuilder.CreateIndex(
// name: "IX_NoneDicomStudy_TrialId",
// table: "NoneDicomStudy",
// column: "TrialId");
//migrationBuilder.CreateIndex(
// name: "IX_ClinicalForm_ReadingId",
// table: "ClinicalForm",
// column: "ReadingId");
//migrationBuilder.AddForeignKey(
// name: "FK_ClinicalForm_SubjectVisit_ReadingId",
// table: "ClinicalForm",
// column: "ReadingId",
// principalTable: "SubjectVisit",
// principalColumn: "Id");
//migrationBuilder.AddForeignKey(
// name: "FK_NoneDicomStudy_Trial_TrialId",
// table: "NoneDicomStudy",
// column: "TrialId",
// principalTable: "Trial",
// principalColumn: "Id",
// onDelete: ReferentialAction.Cascade);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_ClinicalForm_SubjectVisit_ReadingId",
table: "ClinicalForm");
migrationBuilder.DropForeignKey(
name: "FK_NoneDicomStudy_Trial_TrialId",
table: "NoneDicomStudy");
migrationBuilder.DropIndex(
name: "IX_NoneDicomStudy_TrialId",
table: "NoneDicomStudy");
migrationBuilder.DropIndex(
name: "IX_ClinicalForm_ReadingId",
table: "ClinicalForm");
migrationBuilder.DropColumn(
name: "RandomOrder",
table: "VisitTask");
}
}
}

View File

@ -487,6 +487,8 @@ namespace IRaCIS.Core.Infra.EFCore.Migrations
b.HasIndex("CreateUserId");
b.HasIndex("ReadingId");
b.HasIndex("SubjectId");
b.ToTable("ClinicalForm", t =>
@ -3287,6 +3289,8 @@ namespace IRaCIS.Core.Infra.EFCore.Migrations
b.HasIndex("SubjectVisitId");
b.HasIndex("TrialId");
b.ToTable("NoneDicomStudy", t =>
{
t.HasComment("影像 - 非dicom检查");
@ -14390,6 +14394,10 @@ namespace IRaCIS.Core.Infra.EFCore.Migrations
.HasColumnType("nvarchar(2000)")
.HasComment("既往任务Id 不包括自己");
b.Property<int?>("RandomOrder")
.HasColumnType("int")
.HasComment("完全随机阅片号");
b.Property<int>("ReReadingApplyState")
.HasColumnType("int")
.HasComment("重阅状态");
@ -14867,6 +14875,10 @@ namespace IRaCIS.Core.Infra.EFCore.Migrations
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("IRaCIS.Core.Domain.Models.SubjectVisit", "SubjectVisit")
.WithMany("ClinicalFormList")
.HasForeignKey("ReadingId");
b.HasOne("IRaCIS.Core.Domain.Models.Subject", "Subject")
.WithMany("ClinicalFormList")
.HasForeignKey("SubjectId")
@ -14878,6 +14890,8 @@ namespace IRaCIS.Core.Infra.EFCore.Migrations
b.Navigation("CreateUserRole");
b.Navigation("Subject");
b.Navigation("SubjectVisit");
});
modelBuilder.Entity("IRaCIS.Core.Domain.Models.ClinicalQuestionAnswer", b =>
@ -15467,6 +15481,12 @@ namespace IRaCIS.Core.Infra.EFCore.Migrations
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("IRaCIS.Core.Domain.Models.Trial", null)
.WithMany("NoneDicomStudyList")
.HasForeignKey("TrialId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("CreateUserRole");
b.Navigation("Subject");
@ -16573,7 +16593,7 @@ namespace IRaCIS.Core.Infra.EFCore.Migrations
.IsRequired();
b.HasOne("IRaCIS.Core.Domain.Models.VisitTask", "VisitTask")
.WithMany()
.WithMany("ReadingTaskQuestionMarkList")
.HasForeignKey("VisitTaskId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
@ -19241,6 +19261,8 @@ namespace IRaCIS.Core.Infra.EFCore.Migrations
{
b.Navigation("CheckChallengeDialogList");
b.Navigation("ClinicalFormList");
b.Navigation("NoneDicomStudyList");
b.Navigation("PreviousHistoryList");
@ -19309,6 +19331,8 @@ namespace IRaCIS.Core.Infra.EFCore.Migrations
b.Navigation("EnrollList");
b.Navigation("NoneDicomStudyList");
b.Navigation("ReadModuleList");
b.Navigation("ReadingClinicalDataList");
@ -19436,6 +19460,8 @@ namespace IRaCIS.Core.Infra.EFCore.Migrations
b.Navigation("ReadingTaskQuestionAnswerList");
b.Navigation("ReadingTaskQuestionMarkList");
b.Navigation("TaskInfluenceList");
b.Navigation("TaskMedicalReviewList");

View File

@ -35,15 +35,19 @@ namespace IRaCIS.Core.Infra.EFCore
Task<bool> UpdateAsync(TEntity entity, Expression<Func<TEntity, TEntity>> updateFactory,
bool autoSave = false, CancellationToken cancellationToken = default);
/// <summary> EF跟踪方式 会去数据库查询完整的实体,再更新部分字段 </summary>
/// <summary> EF跟踪方式 会去数据库查询完整的实体,再更新部分字段 一定会产生更新sql </summary>
Task<TEntity> UpdatePartialFromQueryAsync(Guid id, Expression<Func<TEntity, TEntity>> updateFactory,
bool autoSave = false, CancellationToken cancellationToken = default);
/// <summary> 稽查用这个 EF跟踪方式 先查询出来所有实体,再更新部分字段 </summary>
/// <summary> 稽查用这个 EF跟踪方式 先查询出来所有实体,再更新部分字段 一定会产生更新sql</summary>
Task UpdatePartialFromQueryAsync(Expression<Func<TEntity, bool>> updateFilter,
Expression<Func<TEntity, TEntity>> updateFactory,
bool autoSave = false, bool ignoreQueryFilter = false, CancellationToken cancellationToken = default);
/// <summary> EF跟踪方式 会去数据库查询完整的实体,再更新部分字段 根据是否修改了字段ef 自动判断是否生成sql</summary>
Task<TEntity> UpdatePartialFromEFAutoAsync(Guid id, Expression<Func<TEntity, TEntity>> updateFactory,
bool autoSave = false, CancellationToken cancellationToken = default);
#endregion

View File

@ -8,6 +8,7 @@ using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.Extensions.Localization;
using System.Reflection;
namespace IRaCIS.Core.Infra.EFCore
{
@ -167,6 +168,36 @@ namespace IRaCIS.Core.Infra.EFCore
return searchEntity;
}
public async Task<TEntity> UpdatePartialFromEFAutoAsync(Guid id, Expression<Func<TEntity, TEntity>> updateFactory,
bool autoSave = false, CancellationToken cancellationToken = default)
{
var searchEntity = await _dbSet.FindAsync(id);
if (searchEntity == null)
{
throw new BusinessValidationFailedException(I18n.T("Repository_UpdateError"));
}
var list = ((MemberInitExpression)updateFactory.Body).Bindings.Select(mb => mb.Member.Name)
.Select(propName => typeof(TEntity).GetProperty(propName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)).ToList();
Func<TEntity, TEntity> func = updateFactory.Compile();
TEntity applyObj = func(searchEntity);
foreach (PropertyInfo prop in list)
{
object value = prop.GetValue(applyObj);
prop.SetValue(searchEntity, value);
}
await SaveChangesAsync(autoSave);
return searchEntity;
}
public async Task UpdatePartialFromQueryAsync(Expression<Func<TEntity, bool>> updateFilter,
Expression<Func<TEntity, TEntity>> updateFactory,
bool autoSave = false, bool ignoreQueryFilter = false, CancellationToken cancellationToken = default)
@ -191,6 +222,7 @@ namespace IRaCIS.Core.Infra.EFCore
/// <summary>EF跟踪方式 删除</summary>
public async Task<bool> DeleteAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default)
{

View File

@ -232,6 +232,10 @@ public static class StaticData
public const string TrialReadingTaskList_Export = "TrialReadingTaskList_Export";
public const string TrialTaskRandomOrderList_Export = "TrialTaskRandomOrderList_Export";
public const string TrialReReadingTaskList_Export = "TrialReReadingTaskList_Export";
public const string TrialMedicalReviewList_Export = "TrialMedicalReviewList_Export";