diff --git a/IRaCIS.Core.API/Controllers/UploadDownLoadController.cs b/IRaCIS.Core.API/Controllers/UploadDownLoadController.cs index 9739b774d..c10e0bfae 100644 --- a/IRaCIS.Core.API/Controllers/UploadDownLoadController.cs +++ b/IRaCIS.Core.API/Controllers/UploadDownLoadController.cs @@ -10,7 +10,7 @@ using IRaCIS.Core.Application.Contracts.Dicom.DTO; using IRaCIS.Core.Application.Filter; using IRaCIS.Core.Application.Helper; using IRaCIS.Core.Application.MediatR.CommandAndQueries; -using IRaCIS.Core.Application.Service.Verify; +using IRaCIS.Core.Application.Service; using IRaCIS.Core.Domain.Models; using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Infra.EFCore; @@ -370,7 +370,7 @@ namespace IRaCIS.Core.API.Controllers [Authorize(Policy = IRaCISPolicy.CRC)] public async Task UploadVisitClinicalData(Guid subjectVisitId, [FromServices] IRepository _repository) { - await QCCommonVerify.VerifyIsCRCSubmmitAsync(_repository, _userInfo, subjectVisitId); + await QCCommon.VerifyIsCRCSubmmitAsync(_repository, _userInfo, subjectVisitId); var sv = _repository.Where(t => t.Id == subjectVisitId).Select(t => new { t.TrialId, t.SiteId, t.SubjectId }).FirstOrDefault().IfNullThrowException(); @@ -409,7 +409,7 @@ namespace IRaCIS.Core.API.Controllers { var startTime = DateTime.Now; - await QCCommonVerify.VerifyIsCRCSubmmitAsync(_repository, _userInfo, subjectVisitId); + await QCCommon.VerifyIsCRCSubmmitAsync(_repository, _userInfo, subjectVisitId); var sv = (await _repository.Where(t => t.Id == subjectVisitId).Select(t => new { t.TrialId, t.SiteId, t.SubjectId }).FirstOrDefaultAsync()).IfNullThrowConvertException(); diff --git a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml index c30551941..65876cf38 100644 --- a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml +++ b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml @@ -417,7 +417,7 @@ 获取登陆用户的系统通知列表 只是过滤了用户类型 和已经发布的 - + 验证CRC 是否已提交 已提交 就不允许进行任何操作,如果是IQC 那么还验证是否是当前任务领取人 diff --git a/IRaCIS.Core.Application/Service/Common/DictionaryService.cs b/IRaCIS.Core.Application/Service/Common/DictionaryService.cs index 425b137e9..f2ef89ff2 100644 --- a/IRaCIS.Core.Application/Service/Common/DictionaryService.cs +++ b/IRaCIS.Core.Application/Service/Common/DictionaryService.cs @@ -42,7 +42,6 @@ namespace IRaCIS.Application.Services var systemBasicDataQueryable = _dicRepository.Where(t => t.ParentId == null) .WhereIf(!string.IsNullOrEmpty(basicDicQuery.Code), t => t.Code.Contains(basicDicQuery.Code!)) - .WhereIf(!string.IsNullOrEmpty(basicDicQuery.KeyName), t => t.KeyName.Contains(basicDicQuery.KeyName!)) .WhereIf(basicDicQuery.ConfigTypeId != null, t => t.ConfigTypeId == basicDicQuery.ConfigTypeId!) .WhereIf(basicDicQuery.IsConfig != null, t => t.IsConfig == basicDicQuery.IsConfig) diff --git a/IRaCIS.Core.Application/Service/ImageAndDoc/StudyService.cs b/IRaCIS.Core.Application/Service/ImageAndDoc/StudyService.cs index 925bc15d7..8d11b8234 100644 --- a/IRaCIS.Core.Application/Service/ImageAndDoc/StudyService.cs +++ b/IRaCIS.Core.Application/Service/ImageAndDoc/StudyService.cs @@ -34,96 +34,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc } - private Expression> GetDicomStudySubjectVisitFilter(string[]? VisitPlanArray) - { - Expression> svExpression = x => true; - bool isNeedVisitSearch = VisitPlanArray != null && VisitPlanArray?.Length > 0; - - if (isNeedVisitSearch) - { - var inPlanArray = VisitPlanArray!.Where(t => !t.Contains('.')).Select(t => decimal.Parse(t)).ToArray(); - var isSelectOutPlan = VisitPlanArray!.Any(t => t.Contains('.')); - - - if (inPlanArray.Length > 0) - { - svExpression = svExpression.And(t => inPlanArray.Contains(t.SubjectVisit.VisitNum)); - } - - - if (isSelectOutPlan) - { - svExpression = svExpression.Or(t => t.SubjectVisit.InPlan == false); - - } - - - } - - return svExpression; - } - - - private Expression> GetNoneDicomStudySubjectVisitFilter(string[]? VisitPlanArray) - { - Expression> svExpression = x => true; - - bool isNeedVisitSearch = VisitPlanArray != null && VisitPlanArray?.Length > 0; - - if (isNeedVisitSearch) - { - var inPlanArray = VisitPlanArray!.Where(t => !t.Contains('.')).Select(t => decimal.Parse(t)).ToArray(); - var isSelectOutPlan = VisitPlanArray!.Any(t => t.Contains('.')); - - - if (inPlanArray.Length > 0) - { - svExpression = svExpression.And(t => inPlanArray.Contains(t.SubjectVisit.VisitNum)); - } - - - if (isSelectOutPlan) - { - svExpression = svExpression.Or(t => t.SubjectVisit.InPlan == false); - - } - - - } - - return svExpression; - } - - private Expression> GetStudyMonitorSubjectVisitFilter(string[]? VisitPlanArray) - { - Expression> svExpression = x => true; - - bool isNeedVisitSearch = VisitPlanArray != null && VisitPlanArray?.Length > 0; - - if (isNeedVisitSearch) - { - var inPlanArray = VisitPlanArray!.Where(t => !t.Contains('.')).Select(t => decimal.Parse(t)).ToArray(); - var isSelectOutPlan = VisitPlanArray!.Any(t => t.Contains('.')); - - - if (inPlanArray.Length > 0) - { - svExpression = svExpression.And(t => inPlanArray.Contains(t.SubjectVisit.VisitNum)); - } - - - if (isSelectOutPlan) - { - svExpression = svExpression.Or(t => t.SubjectVisit.InPlan == false); - - } - - - } - - return svExpression; - } @@ -131,7 +42,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc public async Task> GetDicomAndNoneDicomStudyList(StudyQuery studyQuery) { - var svExpression = GetDicomStudySubjectVisitFilter(studyQuery.VisitPlanArray); + var svExpression = QCCommon.GetDicomStudySubjectVisitFilter(studyQuery.VisitPlanArray); var dicomStudyQuery = _repository.Where(t => t.TrialId == studyQuery.TrialId) .WhereIf(_userInfo.UserTypeEnumInt == (int)UserTypeEnum.ClinicalResearchCoordinator || _userInfo.UserTypeEnumInt == (int)UserTypeEnum.CRA, t => t.TrialSite.CRCUserList.Any(t => t.UserId == _userInfo.Id)) @@ -178,7 +89,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc //.ProjectTo(_mapper.ConfigurationProvider); - var svExpression2 = GetNoneDicomStudySubjectVisitFilter(studyQuery.VisitPlanArray); + var svExpression2 = QCCommon.GetNoneDicomStudySubjectVisitFilter(studyQuery.VisitPlanArray); var nodeDicomStudyQuery = _repository.Where(t => t.TrialId == studyQuery.TrialId) @@ -240,7 +151,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc [HttpPost] public async Task> GetDicomAndNoneDicomStudyMonitorList(StudyQuery studyQuery) { - var svExpression = GetStudyMonitorSubjectVisitFilter(studyQuery.VisitPlanArray); + var svExpression = QCCommon.GetStudyMonitorSubjectVisitFilter(studyQuery.VisitPlanArray); var StudyMonitorQuery = _repository.Where(t => t.TrialId == studyQuery.TrialId) .WhereIf(_userInfo.UserTypeEnumInt == (int)UserTypeEnum.ClinicalResearchCoordinator || _userInfo.UserTypeEnumInt == (int)UserTypeEnum.CRA, t => t.TrialSite.CRCUserList.Any(t => t.UserId == _userInfo.Id)) //.WhereIf(!string.IsNullOrEmpty(studyQuery.VisitPlanInfo), studyQuery.VisitPlanInfo.Contains('.') ? t => t.SubjectVisit.VisitNum.ToString().Contains(".") : t => t.SubjectVisit.VisitNum == decimal.Parse(studyQuery.VisitPlanInfo)) diff --git a/IRaCIS.Core.Application/Service/QC/ClinicalDataService.cs b/IRaCIS.Core.Application/Service/QC/ClinicalDataService.cs index 4d0b274d1..3404bc925 100644 --- a/IRaCIS.Core.Application/Service/QC/ClinicalDataService.cs +++ b/IRaCIS.Core.Application/Service/QC/ClinicalDataService.cs @@ -4,8 +4,7 @@ // 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。 //-------------------------------------------------------------------- using Microsoft.AspNetCore.Mvc; -using IRaCIS.Core.Application.Service.Verify; - +using IRaCIS.Core.Application.Service; namespace IRaCIS.Core.Application.Contracts { @@ -97,7 +96,7 @@ namespace IRaCIS.Core.Application.Contracts [HttpPost("{trialId:guid}")] public async Task> AddOrUpdatePreviousHistory(PreviousHistoryAddOrEdit addOrEditPreviousHistory) { - await QCCommonVerify.VerifyIsCRCSubmmitAsync(_repository, _userInfo, addOrEditPreviousHistory.SubjectVisitId); + await QCCommon.VerifyIsCRCSubmmitAsync(_repository, _userInfo, addOrEditPreviousHistory.SubjectVisitId); var entity = await _previousHistoryRepository.InsertOrUpdateAsync(addOrEditPreviousHistory, true); return ResponseOutput.Ok(entity.Id); @@ -107,7 +106,7 @@ namespace IRaCIS.Core.Application.Contracts [HttpDelete("{trialId:guid}/{subjectVisitId:guid}/{previousHistoryId:guid}")] public async Task DeletePreviousHistory(Guid previousHistoryId,Guid subjectVisitId) { - await QCCommonVerify.VerifyIsCRCSubmmitAsync(_repository, _userInfo, subjectVisitId); + await QCCommon.VerifyIsCRCSubmmitAsync(_repository, _userInfo, subjectVisitId); await _previousHistoryRepository.DeleteFromQueryAsync(t => t.Id == previousHistoryId,true); return ResponseOutput.Ok(); } @@ -124,7 +123,7 @@ namespace IRaCIS.Core.Application.Contracts [HttpPost("{trialId:guid}")] public async Task> AddOrUpdatePreviousOther(PreviousOtherAddOrEdit addOrEditPreviousOther) { - await QCCommonVerify.VerifyIsCRCSubmmitAsync(_repository, _userInfo, addOrEditPreviousOther.SubjectVisitId); + await QCCommon.VerifyIsCRCSubmmitAsync(_repository, _userInfo, addOrEditPreviousOther.SubjectVisitId); var entity = await _previousOtherRepository.InsertOrUpdateAsync(addOrEditPreviousOther, true); return ResponseOutput.Ok(entity.Id); @@ -134,7 +133,7 @@ namespace IRaCIS.Core.Application.Contracts [HttpDelete("{trialId:guid}/{subjectVisitId:guid}/{previousOtherId:guid}")] public async Task DeletePreviousOther(Guid previousOtherId, Guid subjectVisitId) { - await QCCommonVerify.VerifyIsCRCSubmmitAsync(_repository, _userInfo, subjectVisitId); + await QCCommon.VerifyIsCRCSubmmitAsync(_repository, _userInfo, subjectVisitId); await _previousOtherRepository.DeleteFromQueryAsync(t => t.Id == previousOtherId,true); return ResponseOutput.Ok(); @@ -152,7 +151,7 @@ namespace IRaCIS.Core.Application.Contracts [HttpPost("{trialId:guid}")] public async Task> AddOrUpdatePreviousSurgery(PreviousSurgeryAddOrEdit addOrEditPreviousSurgery) { - await QCCommonVerify.VerifyIsCRCSubmmitAsync(_repository, _userInfo, addOrEditPreviousSurgery.SubjectVisitId); + await QCCommon.VerifyIsCRCSubmmitAsync(_repository, _userInfo, addOrEditPreviousSurgery.SubjectVisitId); var entity = await _previousSurgeryRepository.InsertOrUpdateAsync(addOrEditPreviousSurgery, true); return ResponseOutput.Ok(entity.Id); } @@ -161,7 +160,7 @@ namespace IRaCIS.Core.Application.Contracts [HttpDelete("{trialId:guid}/{subjectVisitId:guid}/{previousSurgeryId:guid}")] public async Task DeletePreviousSurgery(Guid previousSurgeryId, Guid subjectVisitId) { - await QCCommonVerify.VerifyIsCRCSubmmitAsync(_repository, _userInfo, subjectVisitId); + await QCCommon.VerifyIsCRCSubmmitAsync(_repository, _userInfo, subjectVisitId); var success = await _previousSurgeryRepository.DeleteFromQueryAsync(t => t.Id == previousSurgeryId,true); return ResponseOutput.Ok(); } @@ -178,7 +177,7 @@ namespace IRaCIS.Core.Application.Contracts public async Task AddOrUpdatePreviousPDF(PreviousPDFAddOrEdit addOrEditPreviousPDF) { - await QCCommonVerify.VerifyIsCRCSubmmitAsync(_repository, _userInfo, addOrEditPreviousPDF.SubjectVisitId); + await QCCommon.VerifyIsCRCSubmmitAsync(_repository, _userInfo, addOrEditPreviousPDF.SubjectVisitId); var entity = await _previousPdfRepository.InsertOrUpdateAsync(addOrEditPreviousPDF, true); return ResponseOutput.Ok(entity.Id); @@ -187,7 +186,7 @@ namespace IRaCIS.Core.Application.Contracts [HttpDelete("{trialId:guid}/{subjectVisitId:guid}/{previousPDFId:guid}")] public async Task DeletePreviousPDF(Guid previousPDFId, Guid subjectVisitId) { - await QCCommonVerify.VerifyIsCRCSubmmitAsync(_repository, _userInfo, subjectVisitId); + await QCCommon.VerifyIsCRCSubmmitAsync(_repository, _userInfo, subjectVisitId); await _previousPdfRepository.DeleteFromQueryAsync(t => t.Id == previousPDFId,true); return ResponseOutput.Ok(); diff --git a/IRaCIS.Core.Application/Service/QC/NoneDicomStudyService.cs b/IRaCIS.Core.Application/Service/QC/NoneDicomStudyService.cs index 69e811038..9680bf73a 100644 --- a/IRaCIS.Core.Application/Service/QC/NoneDicomStudyService.cs +++ b/IRaCIS.Core.Application/Service/QC/NoneDicomStudyService.cs @@ -7,7 +7,7 @@ using Microsoft.AspNetCore.Mvc; using IRaCIS.Core.Application.Filter; using Nito.AsyncEx; using System.ComponentModel.DataAnnotations; -using IRaCIS.Core.Application.Service.Verify; +using IRaCIS.Core.Application.Service; namespace IRaCIS.Core.Application.Contracts { @@ -50,9 +50,9 @@ namespace IRaCIS.Core.Application.Contracts public async Task> AddOrUpdateNoneDicomStudy(NoneDicomStudyAddOrEdit addOrEditNoneDicomStudy) { - await QCCommonVerify.VerifyIsCRCSubmmitAsync(_repository, _userInfo, addOrEditNoneDicomStudy.SubjectVisitId); + await QCCommon.VerifyIsCRCSubmmitAsync(_repository, _userInfo, addOrEditNoneDicomStudy.SubjectVisitId); - await QCCommonVerify.VerifyStudyImageDataAsync(_repository, addOrEditNoneDicomStudy.SubjectId, addOrEditNoneDicomStudy.SubjectVisitId, addOrEditNoneDicomStudy.ImageDate); + await QCCommon.VerifyStudyImageDataAsync(_repository, addOrEditNoneDicomStudy.SubjectId, addOrEditNoneDicomStudy.SubjectVisitId, addOrEditNoneDicomStudy.ImageDate); NoneDicomStudy? optEntity = null; @@ -95,7 +95,7 @@ namespace IRaCIS.Core.Application.Contracts //提交了 但是IQC同意的时候 是可以删除的 | 普通提交后也不能删除 - await QCCommonVerify.VerifyIsCRCSubmmitAsync(_repository,_userInfo, subjectVisitId); + await QCCommon.VerifyIsCRCSubmmitAsync(_repository,_userInfo, subjectVisitId); await _noneDicomStudyRepository.DeleteFromQueryAsync(noneDicomStudyId); @@ -115,7 +115,7 @@ namespace IRaCIS.Core.Application.Contracts public async Task DeleteNoneDicomStudyFile(Guid noneDicomStudyFileId, Guid subjectVisitId) { //提交了 但是IQC同意的时候 是可以删除的 | 普通提交后也不能删除 - await QCCommonVerify.VerifyIsCRCSubmmitAsync(_repository, _userInfo, subjectVisitId); + await QCCommon.VerifyIsCRCSubmmitAsync(_repository, _userInfo, subjectVisitId); var success = await _noneDicomStudyFileRepository.DeleteFromQueryAsync(t => t.Id == noneDicomStudyFileId, true); diff --git a/IRaCIS.Core.Application/Service/QC/QCCommon.cs b/IRaCIS.Core.Application/Service/QC/QCCommon.cs new file mode 100644 index 000000000..70cd3cdc4 --- /dev/null +++ b/IRaCIS.Core.Application/Service/QC/QCCommon.cs @@ -0,0 +1,264 @@ +using IRaCIS.Core.Domain.Share; +using IRaCIS.Core.Infrastructure; +using System.Linq.Expressions; + +namespace IRaCIS.Core.Application.Service +{ + public static class QCCommon + { + /// + /// 验证CRC 是否已提交 已提交 就不允许进行任何操作,如果是IQC 那么还验证是否是当前任务领取人 + /// + /// + /// + /// + /// + /// + public static async Task VerifyIsCRCSubmmitAsync(IRepository _repository, IUserInfo _userInfo, Guid? subjectVisitId=null) + { + //添加的时候不验证 + if (subjectVisitId != null) + { + if (await _repository.AnyAsync(t => t.Id == subjectVisitId && t.SubmitState == SubmitStateEnum.Submitted && + (!t.QCChallengeList.Any(u => u.ReuploadEnum == QCChanllengeReuploadEnum.QCAgreeUpload)))) + { + throw new BusinessValidationFailedException("CRC 已提交影像,不能进行操作。"); + } + } + + //IQC 的时候 验证是不是当前领取人 + if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.IQC) + { + + await VerifyIsCanQCAsync(_repository, _userInfo, null, subjectVisitId); + + } + + } + + public static async Task VerifyIsCanQCAsync(IRepository _repository,IUserInfo _userInfo, SubjectVisit? subjectVisit=null, Guid? subjectVisitId=null) + { + if (subjectVisitId != null) + { + subjectVisit = (await _repository.FirstOrDefaultAsync(t => t.Id == subjectVisitId)).IfNullThrowException(); + } + + if (subjectVisit!.CurrentActionUserId != _userInfo.Id) + { + throw new BusinessValidationFailedException("您不是该质控任务当前领取人,没有操作权限!"); + } + } + + + + public static async Task VerifyStudyImageDataAsync(IRepository _repository, Guid subjectId, Guid subjectVisitId,DateTime imageDate) + { + var visitList = await _repository.Where(t => t.SubjectId == subjectId).Select(t => new { t.VisitNum, t.EarliestScanDate, t.LatestScanDate, t.Id }).ToListAsync(); + + var currentVisitNum = await _repository.Where(t => t.Id == subjectVisitId).Select(t => t.VisitNum).FirstOrDefaultAsync(); + + + + //小于当前访视 最近的最晚拍片 + var before = visitList.Where(u => u.VisitNum < currentVisitNum).Max(k => k.LatestScanDate); + + if (before != null && before > imageDate) + { + throw new BusinessValidationFailedException($"当前访视检查时间{imageDate.ToString("yyyy-MM-dd")}不能早于前序访视检查时间{before?.ToString("yyyy-MM-dd")},请核对检查数据是否有误"); + } + + + //大于当前访视 最近的最早拍片日期 + var after = visitList.Where(u => u.VisitNum > currentVisitNum).Min(k => k.EarliestScanDate); + + if (after != null && after < imageDate) + { + throw new BusinessValidationFailedException($"当前访视检查时间{imageDate.ToString("yyyy-MM-dd")}不能晚于该访视之后的检查时间{after?.ToString("yyyy-MM-dd")},请核对检查数据是否有误"); + + } + } + + + + #region 处理方式多选过滤条件 + + public static Expression> GetSubjectVisitFilter(string[]? VisitPlanArray) + { + Expression> svExpression = x => true; + + bool isNeedVisitSearch = VisitPlanArray != null && VisitPlanArray?.Length > 0; + + if (isNeedVisitSearch) + { + var inPlanArray = VisitPlanArray!.Where(t => !t.Contains('.')).Select(t => decimal.Parse(t)).ToArray(); + var isSelectOutPlan = VisitPlanArray!.Any(t => t.Contains('.')); + + + if (inPlanArray.Length > 0) + { + svExpression = svExpression.And(t => inPlanArray.Contains(t.VisitNum)); + + if (isSelectOutPlan) + { + svExpression = svExpression.Or(t => t.InPlan == false); + + } + } + else if (isSelectOutPlan) + { + svExpression = t => t.InPlan == false; + } + + + + + } + + return svExpression; + } + + + public static Expression> GetQCChallengeFilter(string[]? VisitPlanArray) + { + Expression> svExpression = x => true; + + bool isNeedVisitSearch = VisitPlanArray != null && VisitPlanArray?.Length > 0; + + if (isNeedVisitSearch) + { + var inPlanArray = VisitPlanArray!.Where(t => !t.Contains('.')).Select(t => decimal.Parse(t)).ToArray(); + var isSelectOutPlan = VisitPlanArray!.Any(t => t.Contains('.')); + + + if (inPlanArray.Length > 0) + { + svExpression = svExpression.And(t => inPlanArray.Contains(t.SubjectVisit.VisitNum)); + + if (isSelectOutPlan) + { + svExpression = svExpression.Or(t => t.SubjectVisit.InPlan == false); + + } + } + else if (isSelectOutPlan) + { + svExpression = t => t.SubjectVisit.InPlan == false; + } + + + + } + + return svExpression; + } + + + public static Expression> GetDicomStudySubjectVisitFilter(string[]? VisitPlanArray) + { + Expression> svExpression = x => true; + + bool isNeedVisitSearch = VisitPlanArray != null && VisitPlanArray?.Length > 0; + + if (isNeedVisitSearch) + { + var inPlanArray = VisitPlanArray!.Where(t => !t.Contains('.')).Select(t => decimal.Parse(t)).ToArray(); + var isSelectOutPlan = VisitPlanArray!.Any(t => t.Contains('.')); + + + if (inPlanArray.Length > 0) + { + svExpression = svExpression.And(t => inPlanArray.Contains(t.SubjectVisit.VisitNum)); + + if (isSelectOutPlan) + { + svExpression = svExpression.Or(t => t.SubjectVisit.InPlan == false); + + } + } + else if (isSelectOutPlan) + { + svExpression = t => t.SubjectVisit.InPlan == false; + } + + + + + } + + return svExpression; + } + + + public static Expression> GetNoneDicomStudySubjectVisitFilter(string[]? VisitPlanArray) + { + Expression> svExpression = x => true; + + bool isNeedVisitSearch = VisitPlanArray != null && VisitPlanArray?.Length > 0; + + if (isNeedVisitSearch) + { + var inPlanArray = VisitPlanArray!.Where(t => !t.Contains('.')).Select(t => decimal.Parse(t)).ToArray(); + var isSelectOutPlan = VisitPlanArray!.Any(t => t.Contains('.')); + + + if (inPlanArray.Length > 0) + { + svExpression = svExpression.And(t => inPlanArray.Contains(t.SubjectVisit.VisitNum)); + + if (isSelectOutPlan) + { + svExpression = svExpression.Or(t => t.SubjectVisit.InPlan == false); + + } + } + else if (isSelectOutPlan) + { + svExpression = t => t.SubjectVisit.InPlan == false; + } + + + + + } + + return svExpression; + } + + public static Expression> GetStudyMonitorSubjectVisitFilter(string[]? VisitPlanArray) + { + Expression> svExpression = x => true; + + bool isNeedVisitSearch = VisitPlanArray != null && VisitPlanArray?.Length > 0; + + if (isNeedVisitSearch) + { + var inPlanArray = VisitPlanArray!.Where(t => !t.Contains('.')).Select(t => decimal.Parse(t)).ToArray(); + var isSelectOutPlan = VisitPlanArray!.Any(t => t.Contains('.')); + + + if (inPlanArray.Length > 0) + { + svExpression = svExpression.And(t => inPlanArray.Contains(t.SubjectVisit.VisitNum)); + + if (isSelectOutPlan) + { + svExpression = svExpression.Or(t => t.SubjectVisit.InPlan == false); + + } + } + + else if (isSelectOutPlan) + { + svExpression = t => t.SubjectVisit.InPlan == false; + } + + + + } + + return svExpression; + } + + #endregion + } +} diff --git a/IRaCIS.Core.Application/Service/QC/QCCommonVerify.cs b/IRaCIS.Core.Application/Service/QC/QCCommonVerify.cs deleted file mode 100644 index a9540b5b5..000000000 --- a/IRaCIS.Core.Application/Service/QC/QCCommonVerify.cs +++ /dev/null @@ -1,83 +0,0 @@ -using IRaCIS.Core.Domain.Share; -using IRaCIS.Core.Infrastructure; - - -namespace IRaCIS.Core.Application.Service.Verify -{ - public static class QCCommonVerify - { - /// - /// 验证CRC 是否已提交 已提交 就不允许进行任何操作,如果是IQC 那么还验证是否是当前任务领取人 - /// - /// - /// - /// - /// - /// - public static async Task VerifyIsCRCSubmmitAsync(IRepository _repository, IUserInfo _userInfo, Guid? subjectVisitId=null) - { - //添加的时候不验证 - if (subjectVisitId != null) - { - if (await _repository.AnyAsync(t => t.Id == subjectVisitId && t.SubmitState == SubmitStateEnum.Submitted && - (!t.QCChallengeList.Any(u => u.ReuploadEnum == QCChanllengeReuploadEnum.QCAgreeUpload)))) - { - throw new BusinessValidationFailedException("CRC 已提交影像,不能进行操作。"); - } - } - - //IQC 的时候 验证是不是当前领取人 - if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.IQC) - { - - await VerifyIsCanQCAsync(_repository, _userInfo, null, subjectVisitId); - - } - - } - - public static async Task VerifyIsCanQCAsync(IRepository _repository,IUserInfo _userInfo, SubjectVisit? subjectVisit=null, Guid? subjectVisitId=null) - { - if (subjectVisitId != null) - { - subjectVisit = (await _repository.FirstOrDefaultAsync(t => t.Id == subjectVisitId)).IfNullThrowException(); - } - - if (subjectVisit!.CurrentActionUserId != _userInfo.Id) - { - throw new BusinessValidationFailedException("您不是该质控任务当前领取人,没有操作权限!"); - } - } - - - - public static async Task VerifyStudyImageDataAsync(IRepository _repository, Guid subjectId, Guid subjectVisitId,DateTime imageDate) - { - var visitList = await _repository.Where(t => t.SubjectId == subjectId).Select(t => new { t.VisitNum, t.EarliestScanDate, t.LatestScanDate, t.Id }).ToListAsync(); - - var currentVisitNum = await _repository.Where(t => t.Id == subjectVisitId).Select(t => t.VisitNum).FirstOrDefaultAsync(); - - - - //小于当前访视 最近的最晚拍片 - var before = visitList.Where(u => u.VisitNum < currentVisitNum).Max(k => k.LatestScanDate); - - if (before != null && before > imageDate) - { - throw new BusinessValidationFailedException($"当前访视检查时间{imageDate.ToString("yyyy-MM-dd")}不能早于前序访视检查时间{before?.ToString("yyyy-MM-dd")},请核对检查数据是否有误"); - } - - - //大于当前访视 最近的最早拍片日期 - var after = visitList.Where(u => u.VisitNum > currentVisitNum).Min(k => k.EarliestScanDate); - - if (after != null && after < imageDate) - { - throw new BusinessValidationFailedException($"当前访视检查时间{imageDate.ToString("yyyy-MM-dd")}不能晚于该访视之后的检查时间{after?.ToString("yyyy-MM-dd")},请核对检查数据是否有误"); - - } - } - - - } -} diff --git a/IRaCIS.Core.Application/Service/QC/QCListService.cs b/IRaCIS.Core.Application/Service/QC/QCListService.cs index 2aa036270..96a99de98 100644 --- a/IRaCIS.Core.Application/Service/QC/QCListService.cs +++ b/IRaCIS.Core.Application/Service/QC/QCListService.cs @@ -2,8 +2,7 @@ using Microsoft.AspNetCore.Mvc; using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Application.Contracts.DTO; -using System.Linq.Expressions; -using IRaCIS.Core.Infrastructure; +using IRaCIS.Core.Application.Service; namespace IRaCIS.Core.Application.Image.QA { @@ -23,70 +22,7 @@ namespace IRaCIS.Core.Application.Image.QA } - #region 处理方式多选过滤条件 - private Expression> GetSubjectVisitFilter(string[]? VisitPlanArray) - { - Expression> svExpression = x => true; - - bool isNeedVisitSearch = VisitPlanArray != null && VisitPlanArray?.Length > 0; - - if (isNeedVisitSearch) - { - var inPlanArray = VisitPlanArray!.Where(t => !t.Contains('.')).Select(t => decimal.Parse(t)).ToArray(); - var isSelectOutPlan = VisitPlanArray!.Any(t => t.Contains('.')); - - - if (inPlanArray.Length > 0) - { - svExpression = svExpression.And(t => inPlanArray.Contains(t.VisitNum)); - } - - - if (isSelectOutPlan) - { - svExpression = svExpression.Or(t => t.InPlan == false); - - } - - - } - - return svExpression; - } - - - private Expression> GetQCChallengeFilter(string[]? VisitPlanArray) - { - Expression> svExpression = x => true; - - bool isNeedVisitSearch = VisitPlanArray != null && VisitPlanArray?.Length > 0; - - if (isNeedVisitSearch) - { - var inPlanArray = VisitPlanArray!.Where(t => !t.Contains('.')).Select(t => decimal.Parse(t)).ToArray(); - var isSelectOutPlan = VisitPlanArray!.Any(t => t.Contains('.')); - - - if (inPlanArray.Length > 0) - { - svExpression = svExpression.And(t => inPlanArray.Contains(t.SubjectVisit.VisitNum)); - } - - if (isSelectOutPlan) - { - svExpression = svExpression.Or(t => t.SubjectVisit.InPlan == false); - - } - - - } - - return svExpression; - } - - - #endregion #region CRC上传、质疑页面 /// @@ -97,7 +33,7 @@ namespace IRaCIS.Core.Application.Image.QA [HttpPost] public async Task<(PageOutput, TrialSubjectAndSVConfig)> GetCRCVisitList(CRCVisitSearchDTO visitSearchDTO) { - var svExpression = GetSubjectVisitFilter(visitSearchDTO.VisitPlanArray); + var svExpression = QCCommon.GetSubjectVisitFilter(visitSearchDTO.VisitPlanArray); var query = _repository.Where(x => x.TrialId == visitSearchDTO.TrialId) .WhereIf(visitSearchDTO.SiteId != null, t => t.SiteId == visitSearchDTO.SiteId) @@ -168,7 +104,7 @@ namespace IRaCIS.Core.Application.Image.QA // }; #endregion - var svExpression = GetQCChallengeFilter(challengeQuery.VisitPlanArray); + var svExpression = QCCommon.GetQCChallengeFilter(challengeQuery.VisitPlanArray); var query2 = _repository.Where(x => x.TrialId == challengeQuery.TrialId) //.WhereIf(challengeQuery.ChallengeState != null, t => t.SubjectVisit.ChallengeState == challengeQuery.ChallengeState) @@ -257,7 +193,7 @@ namespace IRaCIS.Core.Application.Image.QA // }; #endregion - var svExpression = GetQCChallengeFilter(challengeQuery.VisitPlanArray); + var svExpression = QCCommon.GetQCChallengeFilter(challengeQuery.VisitPlanArray); var query = _repository.Where(x => x.TrialId == challengeQuery.TrialId) //.WhereIf(challengeQuery.ChallengeState != null, t => t.SubjectVisit.ChallengeState == challengeQuery.ChallengeState) @@ -446,7 +382,7 @@ namespace IRaCIS.Core.Application.Image.QA #endregion - var svExpression = GetSubjectVisitFilter(visitSearchDTO.VisitPlanArray); + var svExpression = QCCommon.GetSubjectVisitFilter(visitSearchDTO.VisitPlanArray); var query = _subjectVisitRepository.Where(x => x.TrialId == visitSearchDTO.TrialId) .WhereIf(visitSearchDTO.ChallengeState != null, t => t.ChallengeState == visitSearchDTO.ChallengeState) .WhereIf(visitSearchDTO.SiteId != null, t => t.SiteId == visitSearchDTO.SiteId) @@ -535,7 +471,7 @@ namespace IRaCIS.Core.Application.Image.QA // }; #endregion - var svExpression = GetSubjectVisitFilter(checkQuery.VisitPlanArray); + var svExpression = QCCommon.GetSubjectVisitFilter(checkQuery.VisitPlanArray); var query = _subjectVisitRepository.Where(x => x.TrialId == checkQuery.TrialId) .Where(x => x.AuditState == AuditStateEnum.QCPassed) //一致性核查中的,或者还没一致性核查的 @@ -581,7 +517,7 @@ namespace IRaCIS.Core.Application.Image.QA { //var trialConfig = _trialReposioty.Select(t => new { TrialId = t.Id, t.QCProcessEnum, t.IsImageConsistencyVerification }).FirstOrDefault(t => t.TrialId == forwardQuery.TrialId); - var svExpression = GetSubjectVisitFilter(forwardQuery.VisitPlanArray); + var svExpression = QCCommon.GetSubjectVisitFilter(forwardQuery.VisitPlanArray); var query = _subjectVisitRepository.Where(x => x.TrialId == forwardQuery.TrialId) .Where(t => t.CheckState == CheckStateEnum.CVPassed) diff --git a/IRaCIS.Core.Application/Service/Visit/SubjectVisitService.cs b/IRaCIS.Core.Application/Service/Visit/SubjectVisitService.cs index 6d9bb4aee..a8afa86e8 100644 --- a/IRaCIS.Core.Application/Service/Visit/SubjectVisitService.cs +++ b/IRaCIS.Core.Application/Service/Visit/SubjectVisitService.cs @@ -44,6 +44,12 @@ namespace IRaCIS.Core.Application.Services IsVerify = svCommand.IsFinalVisit }; + var verifyExp3 = new EntityVerifyExp() + { + VerifyExp = t => t.SubjectId == svCommand.SubjectId && t.VisitName==svCommand.VisitName, + VerifyMsg = "该受试者的访视计划中已经包含一个具有相同访视名称的访视。" + + }; svCommand.BlindName = "B" + ((int)(svCommand.VisitNum * 10)).ToString("D3"); svCommand.VisitExecuted = svCommand.IsLostVisit ? VisitExecutedEnum.Executed : svCommand.VisitExecuted; @@ -63,12 +69,12 @@ namespace IRaCIS.Core.Application.Services } } - dbBeforeEntity = await _subjectVisitRepository.InsertFromDTOAsync(svCommand, false, verifyExp1, verifyExp2); + dbBeforeEntity = await _subjectVisitRepository.InsertFromDTOAsync(svCommand, false, verifyExp1, verifyExp2,verifyExp3); } else { - dbBeforeEntity = await _subjectVisitRepository.UpdateFromDTOAsync(svCommand, false, false, verifyExp1, verifyExp2); + dbBeforeEntity = await _subjectVisitRepository.UpdateFromDTOAsync(svCommand, false, false, verifyExp1, verifyExp2, verifyExp3); if (svCommand.PDState != dbBeforeEntity.PDState && dbBeforeEntity.SubmitState == SubmitStateEnum.Submitted) { diff --git a/IRaCIS.Core.Domain.Share/Common/VerifyType.cs b/IRaCIS.Core.Domain.Share/Common/VerifyType.cs index 6592b44d1..9018cf6f2 100644 --- a/IRaCIS.Core.Domain.Share/Common/VerifyType.cs +++ b/IRaCIS.Core.Domain.Share/Common/VerifyType.cs @@ -9,5 +9,22 @@ namespace IRaCIS.Core.Domain.Share Phone = 1 } - + + + public enum DicDataTypeEnum + { + //字典下拉配置 + Config = 0, + + //下拉框 + Select = 1, + + //枚举 + Enum=2, + + //Bool + + Bool=3 + + } } diff --git a/IRaCIS.Core.Domain/Common/Dictionary.cs b/IRaCIS.Core.Domain/Common/Dictionary.cs index ad4f3365e..2aab8b731 100644 --- a/IRaCIS.Core.Domain/Common/Dictionary.cs +++ b/IRaCIS.Core.Domain/Common/Dictionary.cs @@ -12,6 +12,13 @@ namespace IRaCIS.Core.Domain.Models public List DoctorDicRelationList { get; set; } = new List(); + public string ChildGroup { get; set; } + + public int ChildCodeEnum { get; set; } + + + public DicDataTypeEnum DataTypeEnum { get; set; } + [Column("Value")] public string Value { get; set; } = string.Empty; @@ -25,7 +32,6 @@ namespace IRaCIS.Core.Domain.Models public int ShowOrder { get; set; } - public string ChildGroup { get; set; } public Guid UpdateUserId { get; set; } public DateTime UpdateTime { get; set; } @@ -52,11 +58,6 @@ namespace IRaCIS.Core.Domain.Models [ForeignKey("ParentId")] public Dictionary Parent { get; set; } - public int ChildCodeEnum { get; set; } - - - [StringLength(50)] - public string KeyName { get; set; } = string.Empty; [NotMapped]