diff --git a/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingGlobalTaskService.cs b/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingGlobalTaskService.cs index 0c126a36a..aa1e0d22c 100644 --- a/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingGlobalTaskService.cs +++ b/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingGlobalTaskService.cs @@ -54,7 +54,7 @@ namespace IRaCIS.Core.Application.Service /// /// [HttpPost] - [TrialGlobalLimit( "AfterStopCannNotOpt" )] + [TrialGlobalLimit("AfterStopCannNotOpt")] public async Task 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 /// /// [HttpPost] - [TrialGlobalLimit( "AfterStopCannNotOpt" )] + [TrialGlobalLimit("AfterStopCannNotOpt")] public async Task 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, diff --git a/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingImageTaskService.cs b/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingImageTaskService.cs index 789a275ed..cd0794b3f 100644 --- a/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingImageTaskService.cs +++ b/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingImageTaskService.cs @@ -3271,7 +3271,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 }); diff --git a/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingOncologyTaskService.cs b/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingOncologyTaskService.cs index e6be23459..24955193a 100644 --- a/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingOncologyTaskService.cs +++ b/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingOncologyTaskService.cs @@ -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 }); diff --git a/IRaCIS.Core.Application/Service/Reading/ReadingPeriod/ReadModuleService.cs b/IRaCIS.Core.Application/Service/Reading/ReadingPeriod/ReadModuleService.cs index 458645a85..51e661adf 100644 --- a/IRaCIS.Core.Application/Service/Reading/ReadingPeriod/ReadModuleService.cs +++ b/IRaCIS.Core.Application/Service/Reading/ReadingPeriod/ReadModuleService.cs @@ -502,8 +502,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, @@ -888,7 +888,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() { diff --git a/IRaCIS.Core.Infra.EFCore/Common/AuditingData.cs b/IRaCIS.Core.Infra.EFCore/Common/AuditingData.cs index 599a4ff04..5b8859e06 100644 --- a/IRaCIS.Core.Infra.EFCore/Common/AuditingData.cs +++ b/IRaCIS.Core.Infra.EFCore/Common/AuditingData.cs @@ -188,7 +188,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 +1738,11 @@ namespace IRaCIS.Core.Infra.EFCore.Common var entity = item.Entity as IdentityUser; - - await InsertInspection(entity, type, x => new InspectionConvertDTO - { - IsDistinctionInterface = type == AuditOpt.Update ? true : false, - }); + + await InsertInspection(entity, type, x => new InspectionConvertDTO + { + IsDistinctionInterface = type == AuditOpt.Update ? true : false, + }); } // 项目参与人员 @@ -1777,7 +1777,7 @@ namespace IRaCIS.Core.Infra.EFCore.Common identityUser.Phone, identityUser.OrganizationName, }); - } + } } // 项目人员 @@ -1795,7 +1795,7 @@ namespace IRaCIS.Core.Infra.EFCore.Common //var user = await _dbContext.Users.Include(x => x.UserTypeRole).FirstOrDefaultAsync(x => x.Id == entity.UserId); await InsertInspection(entity, type, x => new InspectionConvertDTO { - IsDistinctionInterface = false, + IsDistinctionInterface = false, TrialId = x.TrialId, ObjectRelationParentId = x.TrialId, ExtraIndentification = extraIndentification, @@ -2027,7 +2027,7 @@ namespace IRaCIS.Core.Infra.EFCore.Common { extraIdentification = "/2"; } - + break; } @@ -3241,7 +3241,7 @@ namespace IRaCIS.Core.Infra.EFCore.Common u.ShowOrder } ).OrderBy(t => t.ShowOrder).ToList() - },_userInfo.AuditIdentification); + }, _userInfo.AuditIdentification); ////添加/修改病灶接口 只会对单个病灶进行操作 @@ -3502,18 +3502,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) { @@ -3528,6 +3534,7 @@ namespace IRaCIS.Core.Infra.EFCore.Common //同意重阅 case "VisitTask/ConfirmReReading": + if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.ProjectManager || _userInfo.UserTypeEnumInt == (int)UserTypeEnum.APM) { extraIdentification = "/" + 1; @@ -3549,51 +3556,86 @@ 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"; + } + } + + + } - //访视任务-- 非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 @@ -3710,7 +3752,7 @@ namespace IRaCIS.Core.Infra.EFCore.Common /// 表达式 /// 其他对象 /// - public async Task InsertInspection(T entityObj, string type, Expression> expression = null, object otherItem = null,string auditIdentification = "") where T : Entity + public async Task InsertInspection(T entityObj, string type, Expression> expression = null, object otherItem = null, string auditIdentification = "") where T : Entity { InspectionConvertDTO inspection = new InspectionConvertDTO(); @@ -3937,7 +3979,7 @@ namespace IRaCIS.Core.Infra.EFCore.Common /// 获取稽查记录的标识符 部分业务会进行特殊处理 /// /// - public string GetInspectionRecordIdentification(T entityObj, string type, bool IsDistinctionInterface = true, bool isSelfDefine = false,string auditIdentification="") + public string GetInspectionRecordIdentification(T entityObj, string type, bool IsDistinctionInterface = true, bool isSelfDefine = false, string auditIdentification = "") { //var entityType = _dbContext.Model.FindEntityType(entityObj.GetType()); //var tableName = entityType.GetTableName(); @@ -3956,11 +3998,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}"; } diff --git a/IRaCIS.Core.Infra.EFCore/Common/AuditingDto.cs b/IRaCIS.Core.Infra.EFCore/Common/AuditingDto.cs index 8bc888aff..f093bc9a4 100644 --- a/IRaCIS.Core.Infra.EFCore/Common/AuditingDto.cs +++ b/IRaCIS.Core.Infra.EFCore/Common/AuditingDto.cs @@ -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 { diff --git a/IRaCIS.Core.Infra.EFCore/Repository/ICommandRepository.cs b/IRaCIS.Core.Infra.EFCore/Repository/ICommandRepository.cs index 4de2f0c46..8675e78ff 100644 --- a/IRaCIS.Core.Infra.EFCore/Repository/ICommandRepository.cs +++ b/IRaCIS.Core.Infra.EFCore/Repository/ICommandRepository.cs @@ -35,15 +35,19 @@ namespace IRaCIS.Core.Infra.EFCore Task UpdateAsync(TEntity entity, Expression> updateFactory, bool autoSave = false, CancellationToken cancellationToken = default); - /// EF跟踪方式 会去数据库查询完整的实体,再更新部分字段 + /// EF跟踪方式 会去数据库查询完整的实体,再更新部分字段 一定会产生更新sql Task UpdatePartialFromQueryAsync(Guid id, Expression> updateFactory, bool autoSave = false, CancellationToken cancellationToken = default); - /// 稽查用这个 EF跟踪方式 先查询出来所有实体,再更新部分字段 + /// 稽查用这个 EF跟踪方式 先查询出来所有实体,再更新部分字段 一定会产生更新sql Task UpdatePartialFromQueryAsync(Expression> updateFilter, Expression> updateFactory, bool autoSave = false, bool ignoreQueryFilter = false, CancellationToken cancellationToken = default); + /// EF跟踪方式 会去数据库查询完整的实体,再更新部分字段 根据是否修改了字段ef 自动判断是否生成sql + Task UpdatePartialFromEFAutoAsync(Guid id, Expression> updateFactory, + bool autoSave = false, CancellationToken cancellationToken = default); + #endregion diff --git a/IRaCIS.Core.Infra.EFCore/Repository/Repository.cs b/IRaCIS.Core.Infra.EFCore/Repository/Repository.cs index 741686c83..d424e4077 100644 --- a/IRaCIS.Core.Infra.EFCore/Repository/Repository.cs +++ b/IRaCIS.Core.Infra.EFCore/Repository/Repository.cs @@ -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 UpdatePartialFromEFAutoAsync(Guid id, Expression> 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 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> updateFilter, Expression> updateFactory, bool autoSave = false, bool ignoreQueryFilter = false, CancellationToken cancellationToken = default) @@ -191,6 +222,7 @@ namespace IRaCIS.Core.Infra.EFCore + /// EF跟踪方式 删除 public async Task DeleteAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default) {