diff --git a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml index 93adc7873..e51bf5247 100644 --- a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml +++ b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml @@ -3202,7 +3202,7 @@ - 自动添加CRC临床数据 + 自动添加CRC临床数据 (不包括检查级别) diff --git a/IRaCIS.Core.Application/Service/ImageAndDoc/StudyService.cs b/IRaCIS.Core.Application/Service/ImageAndDoc/StudyService.cs index 57e7a8cec..c74549364 100644 --- a/IRaCIS.Core.Application/Service/ImageAndDoc/StudyService.cs +++ b/IRaCIS.Core.Application/Service/ImageAndDoc/StudyService.cs @@ -139,7 +139,11 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc } - + /// + /// 上传临床数据 + /// + /// + /// [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })] public async Task AddOrUpdateArchiveStudy(NewArchiveStudyCommand incommand) { diff --git a/IRaCIS.Core.Application/Service/ImageAndDoc/_MapConfig.cs b/IRaCIS.Core.Application/Service/ImageAndDoc/_MapConfig.cs index a935d98b6..abe17f113 100644 --- a/IRaCIS.Core.Application/Service/ImageAndDoc/_MapConfig.cs +++ b/IRaCIS.Core.Application/Service/ImageAndDoc/_MapConfig.cs @@ -59,7 +59,8 @@ namespace IRaCIS.Core.Application.Service ; CreateMap() - .ForMember(o => o.UploadedTime, t => t.MapFrom(u => u.CreateTime)) + .ForMember(o => o.IsCompleteClinicalData, t => t.MapFrom(u => !u.ReadingClinicalDataList.Any(x=>x.ReadingClinicalDataPDFList.Count()==0))) + .ForMember(o => o.UploadedTime, t => t.MapFrom(u => u.CreateTime)) .ForMember(o => o.Uploader, t => t.MapFrom(u => u.Uploader.LastName + " / " + u.Uploader.FirstName)) .ForMember(o => o.StudyId, t => t.MapFrom(u => u.Id)) .ForMember(o => o.IsHaveUploadFailed, t => t.MapFrom(u => u.DicomStudyMonitorList.Any(t=>t.FailedFileCount>0))) diff --git a/IRaCIS.Core.Application/Service/QC/DTO/QARecordViewModel.cs b/IRaCIS.Core.Application/Service/QC/DTO/QARecordViewModel.cs index 225e6e396..72234ea6f 100644 --- a/IRaCIS.Core.Application/Service/QC/DTO/QARecordViewModel.cs +++ b/IRaCIS.Core.Application/Service/QC/DTO/QARecordViewModel.cs @@ -256,7 +256,8 @@ namespace IRaCIS.Core.Application.Contracts.DTO public class TrialVisitQADTO { public bool ExistsManual { get; set; } - public SubjectClinicalDataDto SubjectClinicalData { get; set; } = new SubjectClinicalDataDto(); + public bool IsHaveStudyClinicalData { get; set; } + public SubjectClinicalDataDto SubjectClinicalData { get; set; } = new SubjectClinicalDataDto(); public List NoneDicomStudyList { get; set; } = new List(); @@ -387,7 +388,10 @@ namespace IRaCIS.Core.Application.Contracts.DTO public string ModalityForEdit { get; set; } = string.Empty; public bool IsHaveUploadFailed { get; set; } - } + + public bool IsCompleteClinicalData { get; set; } + + } public class QASeriesInfoDto { diff --git a/IRaCIS.Core.Application/Service/QC/DTO/QCListViewModel.cs b/IRaCIS.Core.Application/Service/QC/DTO/QCListViewModel.cs index 77fe44405..5e6cab450 100644 --- a/IRaCIS.Core.Application/Service/QC/DTO/QCListViewModel.cs +++ b/IRaCIS.Core.Application/Service/QC/DTO/QCListViewModel.cs @@ -123,8 +123,11 @@ namespace IRaCIS.Core.Application.Contracts public bool IsEnrollementQualificationConfirm { get; set; } public bool IsPDProgressView { get; set; } + public bool IsHaveStudyClinicalData { get; set; } - public string OutEnrollmentVisitName { get; set; } = String.Empty; + + + public string OutEnrollmentVisitName { get; set; } = String.Empty; public string BodyPartTypes { get; set; } = String.Empty; diff --git a/IRaCIS.Core.Application/Service/QC/QCListService.cs b/IRaCIS.Core.Application/Service/QC/QCListService.cs index b85b2b380..d2d7dc7b3 100644 --- a/IRaCIS.Core.Application/Service/QC/QCListService.cs +++ b/IRaCIS.Core.Application/Service/QC/QCListService.cs @@ -8,6 +8,7 @@ using IRaCIS.Application.Interfaces; using IRaCIS.Application.Contracts; using IRaCIS.Core.Application.ViewModel; using IRaCIS.Core.Application.Service.Reading.Dto; +using static Org.BouncyCastle.Math.EC.ECCurve; namespace IRaCIS.Core.Application.Image.QA { @@ -16,7 +17,8 @@ namespace IRaCIS.Core.Application.Image.QA { private readonly IRepository _subjectVisitRepository; private readonly IRepository _trialRepository; - private readonly IRepository _clinicalDataTrialSet; + private readonly IRepository _clinicalDataTrialSetRepository; + private readonly IRepository _clinicalDataTrialSet; private readonly IRepository _trialQCQuestionAnswerRepository; private readonly IRepository _trialQCQuestionRepository; private readonly IRepository _consistencyCheckFileRepository; @@ -26,7 +28,8 @@ namespace IRaCIS.Core.Application.Image.QA public QCListService( IRepository subjectVisitRepository, IRepository trialRepository, - IRepository clinicalDataTrialSet, + IRepository clinicalDataTrialSetRepository, + IRepository clinicalDataTrialSet, IRepository trialQCQuestionAnswerRepository, IRepository trialQCQuestionRepository, IReadingImageTaskService IReadingImageTaskService, @@ -39,7 +42,8 @@ namespace IRaCIS.Core.Application.Image.QA this._trialQCQuestionRepository = trialQCQuestionRepository; this._consistencyCheckFileRepository = consistencyCheckFileRepository; _trialRepository = trialRepository; - this._clinicalDataTrialSet = clinicalDataTrialSet; + this._clinicalDataTrialSetRepository = clinicalDataTrialSetRepository; + this._clinicalDataTrialSet = clinicalDataTrialSet; } @@ -77,8 +81,8 @@ namespace IRaCIS.Core.Application.Image.QA var pageList = await query.ToPagedListAsync(visitSearchDTO.PageIndex, visitSearchDTO.PageSize, visitSearchDTO.SortField, visitSearchDTO.Asc, string.IsNullOrWhiteSpace(visitSearchDTO.SortField), defalutSortArray); var config = await _repository.Where(t => t.Id == visitSearchDTO.TrialId).ProjectTo(_mapper.ConfigurationProvider).FirstOrDefaultAsync().IfNullThrowException(); - config.IsHaveSubjectClinicalData = await _clinicalDataTrialSet.AnyAsync(x => x.TrialId == visitSearchDTO.TrialId && x.IsConfirm && (x.ClinicalDataLevel == ClinicalLevel.Subject || x.ClinicalDataLevel == ClinicalLevel.Study) && x.UploadRole == UploadRole.CRC); - config.IsHaveVisitClinicalData = await _clinicalDataTrialSet.AnyAsync(x => x.TrialId == visitSearchDTO.TrialId && x.IsConfirm && (x.ClinicalDataLevel == ClinicalLevel.SubjectVisit|| x.ClinicalDataLevel == ClinicalLevel.Study) && x.UploadRole == UploadRole.CRC); + config.IsHaveSubjectClinicalData = await _clinicalDataTrialSet.AnyAsync(x => x.TrialId == visitSearchDTO.TrialId && x.IsConfirm && (x.ClinicalDataLevel == ClinicalLevel.Subject ) && x.UploadRole == UploadRole.CRC); + config.IsHaveVisitClinicalData = await _clinicalDataTrialSet.AnyAsync(x => x.TrialId == visitSearchDTO.TrialId && x.IsConfirm && (x.ClinicalDataLevel == ClinicalLevel.SubjectVisit) && x.UploadRole == UploadRole.CRC); return (pageList, config); } @@ -610,8 +614,10 @@ namespace IRaCIS.Core.Application.Image.QA return new TrialVisitQADTO { - QCQuestionAnswerList = qacheckList, - StudyList = temp.StudyList, + QCQuestionAnswerList = qacheckList, + + IsHaveStudyClinicalData = await _clinicalDataTrialSetRepository.AnyAsync(x => x.IsConfirm && x.TrialId == sv.TrialId && x.ClinicalDataLevel == ClinicalLevel.Study), + StudyList = temp.StudyList, ExistsManual= (await _IReadingImageTaskService.GetManualList(new GetManualListInDto() { TrialId = sv.TrialId })).Count() > 0, SeriesList = temp.SeriesList, RelationInfo = await GetVisitQCSubjectInfo(subjectVisitId), @@ -760,12 +766,17 @@ namespace IRaCIS.Core.Application.Image.QA [HttpGet("{subjectVisitId:guid}")] public async Task<(List,object)> GetSubjectVisitUploadedStudyList(Guid subjectVisitId) { + + var visit = await _subjectVisitRepository.Where(x => x.Id == subjectVisitId).FirstNotNullAsync(); var list= await _repository.Where(s => s.SubjectVisitId == subjectVisitId).IgnoreQueryFilters().ProjectTo(_mapper.ConfigurationProvider).OrderBy(t=>t.StudyCode).ToListAsync(); var config = await _repository.Where(t => t.Id == subjectVisitId).Select(t=>t.Trial).ProjectTo(_mapper.ConfigurationProvider).FirstOrDefaultAsync().IfNullThrowException(); - return (list, config); + config.IsHaveStudyClinicalData = await _clinicalDataTrialSetRepository.AnyAsync(x => x.IsConfirm && x.TrialId == visit.TrialId && x.ClinicalDataLevel == ClinicalLevel.Study); + + + return (list, config); } diff --git a/IRaCIS.Core.Application/Service/Reading/ClinicalData/ClinicalAnswerService.cs b/IRaCIS.Core.Application/Service/Reading/ClinicalData/ClinicalAnswerService.cs index 761800f5b..1bfd22237 100644 --- a/IRaCIS.Core.Application/Service/Reading/ClinicalData/ClinicalAnswerService.cs +++ b/IRaCIS.Core.Application/Service/Reading/ClinicalData/ClinicalAnswerService.cs @@ -16,6 +16,7 @@ using IRaCIS.Core.Domain.Models; using IRaCIS.Core.Infrastructure.Extention; using IRaCIS.Core.Application.Service.Reading.Interface; using IRaCIS.Core.Application.Contracts; +using OfficeOpenXml.FormulaParsing.Excel.Functions.Information; namespace IRaCIS.Core.Application.Service { @@ -41,6 +42,7 @@ namespace IRaCIS.Core.Application.Service private readonly IRepository _subjectRepository; private readonly IRepository _readModuleCriterionFromRepository; private readonly IRepository _readModuleRepository; + private readonly IRepository _dicomStudyRepository; private readonly IRepository _clinicalQuestionAnswerRepository; private readonly IRepository _clinicalTableAnswerRepository; @@ -64,6 +66,7 @@ namespace IRaCIS.Core.Application.Service IReadingClinicalDataService iReadingClinicalDataService, IRepository readModuleCriterionFromRepository, IRepository readModuleRepository, + IRepository dicomStudyRepository, IRepository subjectVisitRepository, IRepository clinicalTableAnswerRepository, IRepository clinicalQuestionAnswerRepository, @@ -87,6 +90,7 @@ namespace IRaCIS.Core.Application.Service this._subjectRepository = subjectRepository; this._readModuleCriterionFromRepository = readModuleCriterionFromRepository; this._readModuleRepository = readModuleRepository; + this._dicomStudyRepository = dicomStudyRepository; _clinicalTableAnswerRepository = clinicalTableAnswerRepository; _iClinicalQuestionService = iClinicalQuestionService; } @@ -111,11 +115,56 @@ namespace IRaCIS.Core.Application.Service } /// - /// 自动添加CRC临床数据 + /// 删除检查级别临床数据 /// /// /// - public async Task AutoAddCRCClinical(AutoAddClinicalInDto inDto) + public async Task DeleteStudyClinical(DeleteStudyClinicalInDto inDto) + { + await _readingClinicalDataRepository.BatchDeleteNoTrackingAsync(x => x.StudyId == inDto.StudyId); + + } + + /// + /// 添加检查级别临床数据 + /// + /// + /// + public async Task AddStudyClinical(AddStudyClinicalInDto inDto) + { + var studyInfo = await _dicomStudyRepository.Where(x => x.Id == inDto.StudyId).FirstNotNullAsync(); + + List clinicals = await _clinicalDataTrialSetRepository.Where(x => + x.TrialId == studyInfo.TrialId && x.IsConfirm&&x.ClinicalDataLevel== ClinicalLevel.Study).ToListAsync(); + + List datas = new List(); + + clinicals.ForEach(x => + { + datas.Add(new ReadingClinicalData() + { + ClinicalDataTrialSetId = x.Id, + IsVisit = true, + SubjectId = studyInfo.SubjectId, + ReadingId = studyInfo.SubjectVisitId, + TrialId = studyInfo.TrialId, + StudyId = studyInfo.Id + + }); + + }); + + await _readingClinicalDataRepository.AddRangeAsync(datas); + await _readingClinicalDataRepository.SaveChangesAsync(); + + } + + /// + /// 自动添加CRC临床数据 (不包括检查级别) + /// + /// + /// + public async Task AutoAddCRCClinical(AutoAddClinicalInDto inDto) { var dataTrialSetList = await _clinicalDataTrialSetRepository.Where(x =>x.TrialId == inDto.TrialId && x.UploadRole == UploadRole.CRC && x.IsConfirm) .IgnoreAutoIncludes().ToListAsync(); @@ -194,16 +243,16 @@ namespace IRaCIS.Core.Application.Service TrialId = inDto.TrialId }).ToList()); - readingClinicalDatas.AddRange( - dataTrialSetList.Where(x => x.ClinicalDataLevel == ClinicalLevel.Study).Where(x => clinicalDataList.Where(y => y.ClinicalDataTrialSetId == x.Id && y.ReadingId == n.VisitId).Count() == 0) - .Select(x => new ReadingClinicalData() - { - ClinicalDataTrialSetId = x.Id, - IsVisit = true, - SubjectId = n.SubjectId, - ReadingId = n.VisitId, - TrialId = inDto.TrialId - }).ToList()); + //readingClinicalDatas.AddRange( + // dataTrialSetList.Where(x => x.ClinicalDataLevel == ClinicalLevel.Study).Where(x => clinicalDataList.Where(y => y.ClinicalDataTrialSetId == x.Id && y.ReadingId == n.VisitId).Count() == 0) + // .Select(x => new ReadingClinicalData() + // { + // ClinicalDataTrialSetId = x.Id, + // IsVisit = true, + // SubjectId = n.SubjectId, + // ReadingId = n.VisitId, + // TrialId = inDto.TrialId + // }).ToList()); }); diff --git a/IRaCIS.Core.Application/Service/Reading/ClinicalData/ReadingClinicalDataService.cs b/IRaCIS.Core.Application/Service/Reading/ClinicalData/ReadingClinicalDataService.cs index b144be19e..920e01a7d 100644 --- a/IRaCIS.Core.Application/Service/Reading/ClinicalData/ReadingClinicalDataService.cs +++ b/IRaCIS.Core.Application/Service/Reading/ClinicalData/ReadingClinicalDataService.cs @@ -9,6 +9,7 @@ using Microsoft.Extensions.DependencyInjection; using System.Linq.Expressions; using IRaCIS.Core.Infrastructure; using System.Linq.Dynamic.Core; +using Microsoft.Extensions.Logging; namespace IRaCIS.Application.Services { @@ -82,7 +83,7 @@ namespace IRaCIS.Application.Services { var existsQuery = _readingClinicalDataRepository .WhereIf(indto.Id != null, x => x.Id != indto.Id) - .Where(x => x.ClinicalDataTrialSetId == indto.ClinicalDataTrialSetId && x.ReadingId == indto.ReadingId); + .Where(x => x.ClinicalDataTrialSetId == indto.ClinicalDataTrialSetId && x.ReadingId == indto.ReadingId&&x.StudyId==indto.StudyId); @@ -178,19 +179,33 @@ namespace IRaCIS.Application.Services #region 临床数据CRC 相关 - /// - /// 获取CRC上传的文件 - /// - /// - /// - [HttpPost] + + /// + /// 获取CRC上传的文件 + /// + /// + /// + [HttpPost] public async Task> GetCRCClinicalData(GetCRCClinicalDataInDto inDto) { - List cRCClinicalDataList = await _readingClinicalDataRepository.Where(x => x.ReadingId == inDto.SubjectVisitId) - .WhereIf(inDto.IsBaseline, x => x.ClinicalDataTrialSet.ClinicalDataLevel == ClinicalLevel.Subject || x.ClinicalDataTrialSet.ClinicalDataLevel == ClinicalLevel.SubjectVisit|| x.ClinicalDataTrialSet.ClinicalDataLevel == ClinicalLevel.Study) - .WhereIf(!inDto.IsBaseline, x => x.ClinicalDataTrialSet.ClinicalDataLevel == ClinicalLevel.SubjectVisit || x.ClinicalDataTrialSet.ClinicalDataLevel == ClinicalLevel.Study) - .Where(x => x.ClinicalDataTrialSet.TrialId == inDto.TrialId && x.ClinicalDataTrialSet.UploadRole == UploadRole.CRC) - .Select(x => new GetCRCClinicalDataOutDto() + + var query = _readingClinicalDataRepository.AsQueryable(); + if (inDto.StudyId != null) + { + query = query.Where(x => x.StudyId == inDto.StudyId.Value); + } + else + { + query = query.Where(x => x.ReadingId == inDto.SubjectVisitId) + .WhereIf(inDto.IsBaseline, x => x.ClinicalDataTrialSet.ClinicalDataLevel == ClinicalLevel.Subject || x.ClinicalDataTrialSet.ClinicalDataLevel == ClinicalLevel.SubjectVisit) + .WhereIf(!inDto.IsBaseline, x => x.ClinicalDataTrialSet.ClinicalDataLevel == ClinicalLevel.SubjectVisit) + .Where(x => x.ClinicalDataTrialSet.TrialId == inDto.TrialId && x.ClinicalDataTrialSet.UploadRole == UploadRole.CRC); + + } + + + List cRCClinicalDataList = await query + .Select(x => new GetCRCClinicalDataOutDto() { Id = x.Id, ClinicalDataSetName = x.ClinicalDataTrialSet.ClinicalDataSetName.LanguageName(x.ClinicalDataTrialSet.ClinicalDataSetEnName, _userInfo.IsEn_Us) , diff --git a/IRaCIS.Core.Application/Service/Reading/Dto/ClinicalAnswerDto.cs b/IRaCIS.Core.Application/Service/Reading/Dto/ClinicalAnswerDto.cs index fb669cb58..c09cbbf25 100644 --- a/IRaCIS.Core.Application/Service/Reading/Dto/ClinicalAnswerDto.cs +++ b/IRaCIS.Core.Application/Service/Reading/Dto/ClinicalAnswerDto.cs @@ -12,7 +12,19 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto { public Guid ReadingClinicalDataId { get; set; } } - public class AutoAddClinicalInDto + + + public class DeleteStudyClinicalInDto + { + public Guid StudyId { get; set; } + } + + public class AddStudyClinicalInDto + { + public Guid StudyId { get; set; } + } + + public class AutoAddClinicalInDto { public Guid? SubjectId { get; set; } diff --git a/IRaCIS.Core.Application/Service/Reading/Dto/ReadingClinicalDataDto.cs b/IRaCIS.Core.Application/Service/Reading/Dto/ReadingClinicalDataDto.cs index 39262facc..a3f213303 100644 --- a/IRaCIS.Core.Application/Service/Reading/Dto/ReadingClinicalDataDto.cs +++ b/IRaCIS.Core.Application/Service/Reading/Dto/ReadingClinicalDataDto.cs @@ -15,6 +15,8 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto public Guid? Id { get; set; } + public Guid? StudyId { get; set; } + /// /// 项目ID /// @@ -143,16 +145,17 @@ namespace IRaCIS.Core.Application.Service.Reading.Dto public class GetCRCClinicalDataInDto { - [NotDefault] public Guid SubjectVisitId { get; set; } - [NotDefault] public Guid TrialId { get; set; } - [NotDefault] public Guid SubjectId { get; set; } public bool IsBaseline { get; set; } + + public Guid? StudyId { get; set; } + + } /// diff --git a/IRaCIS.Core.Application/Service/Reading/Interface/IClinicalAnswerService.cs b/IRaCIS.Core.Application/Service/Reading/Interface/IClinicalAnswerService.cs index 0553e985a..c3decdd72 100644 --- a/IRaCIS.Core.Application/Service/Reading/Interface/IClinicalAnswerService.cs +++ b/IRaCIS.Core.Application/Service/Reading/Interface/IClinicalAnswerService.cs @@ -11,7 +11,13 @@ namespace IRaCIS.Core.Application.Service.Reading.Interface { Task CRCSignClinicalData(CRCSignClinicalDataInDto inDto); - Task AutoAddCRCClinical(AutoAddClinicalInDto inDto); + + Task DeleteStudyClinical(DeleteStudyClinicalInDto inDto); + + Task AddStudyClinical(AddStudyClinicalInDto inDto); + + + Task AutoAddCRCClinical(AutoAddClinicalInDto inDto); Task PMConfirmClinical(CRCConfirmClinicalInDto inDto); diff --git a/IRaCIS.Core.Application/Service/ReadingCalculate/General/ReadingCalculateService.cs b/IRaCIS.Core.Application/Service/ReadingCalculate/General/ReadingCalculateService.cs index 348d0815e..d8b7d3d82 100644 --- a/IRaCIS.Core.Application/Service/ReadingCalculate/General/ReadingCalculateService.cs +++ b/IRaCIS.Core.Application/Service/ReadingCalculate/General/ReadingCalculateService.cs @@ -95,6 +95,7 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate public async Task CalculateTask(CalculateTaskInDto inDto) { + _userInfo.IsNotNeedInspection = true; var service = await this.GetService(inDto.VisitTaskId); if (service != null) { diff --git a/IRaCIS.Core.Application/Service/ReadingCalculate/LuganoCalculateService.cs b/IRaCIS.Core.Application/Service/ReadingCalculate/LuganoCalculateService.cs index 6b82c2a7e..f21b84499 100644 --- a/IRaCIS.Core.Application/Service/ReadingCalculate/LuganoCalculateService.cs +++ b/IRaCIS.Core.Application/Service/ReadingCalculate/LuganoCalculateService.cs @@ -2279,16 +2279,25 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate var differenceValue = presentSpd - baseLineSpleenLength; var differenceLowValue = presentSpd - lowSpleenLength; - decimal percentage = 0; - if (baseLineSpleenLength != 0) - { - percentage = differenceValue * 100 / (baseLineSpleenLength-130); - } + - // 1、基线 垂直径> 130 mm - //2、与基线相比脾垂直径变化值≥10 mm - //与基线相比脾肿大增加的百分比 > 50% - if (baseLineSpleenLength > 130 && differenceValue >= 10 && percentage > 50) + decimal getPercentage() + { + decimal percentage = 0; + if (baseLineSpleenLength != 0) + { + percentage = differenceValue * 100 / (baseLineSpleenLength - 130); + } + return percentage; + } + + + + // 1、基线 垂直径> 130 mm + //2、与基线相比脾垂直径变化值≥10 mm + // 当前垂直径>130 mm + //与基线相比脾肿大增加的百分比 > 50% + if (baseLineSpleenLength > 130 && differenceValue >= 10 && spleenLength>130 && getPercentage() > 50) { result = SpleenAssessment.Increase; } @@ -2312,9 +2321,10 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate { result = SpleenAssessment.Normal; } - //1、基线期 状态为“肿大” - //与基线相比脾肿大增加的百分比 < -50% - else if (baseLineState.EqEnum(SpleenAssessment.Swelling) && percentage < -50) + //1、基线期 状态为“肿大” + // 当前垂直径>130 mm + //与基线相比脾肿大增加的百分比 < -50% + else if (baseLineState.EqEnum(SpleenAssessment.Swelling) && spleenLength > 130 && getPercentage() < -50) { result = SpleenAssessment.Remission; } @@ -2616,7 +2626,33 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate /// public async Task GetPET5PSRemark(ReadingCalculateDto inDto) { - return string.Empty; + List needSearchTypes = new List() + { + QuestionType.PET5PS, + QuestionType.PSScoreRemarks, + }; + + var dataBaseDataList = await _readingTaskQuestionAnswerRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId && needSearchTypes.Contains(x.ReadingQuestionTrial.QuestionType)).Select(x => new + { + x.Answer, + x.ReadingQuestionTrial.QuestionType + }).ToListAsync(); ; + + + // 数据库中PET5PS + var pET5PS = dataBaseDataList.Where(x => x.QuestionType == QuestionType.PET5PS).Select(x => x.Answer).FirstIsNullReturnEmpty(); + + // 如果PET5PS没变 就不重新计算 + if (pET5PS == (await GetPET5PS(inDto)).ToString()) + { + return dataBaseDataList.Where(x => x.QuestionType == QuestionType.PSScoreRemarks).Select(x => x.Answer).FirstIsNullReturnEmpty(); + + } + else + { + return string.Empty; + } + } #endregion diff --git a/IRaCIS.Core.Application/Triggers/SubjectVisitTrigger.cs b/IRaCIS.Core.Application/Triggers/SubjectVisitTrigger.cs index 979c1f779..6c4336d22 100644 --- a/IRaCIS.Core.Application/Triggers/SubjectVisitTrigger.cs +++ b/IRaCIS.Core.Application/Triggers/SubjectVisitTrigger.cs @@ -1,4 +1,5 @@ using EntityFrameworkCore.Triggered; +using IRaCIS.Core.Application.Service.Reading.Interface; using IRaCIS.Core.Domain.Share; namespace IRaCIS.Core.Application.Triggers @@ -9,13 +10,14 @@ namespace IRaCIS.Core.Application.Triggers public class SubjectVisitTrigger : IAfterSaveTrigger, IAfterSaveTrigger, IAfterSaveTrigger { private readonly IRepository _subjectVisitRepository; - private readonly IRepository _repository; + private readonly IClinicalAnswerService _iClinicalAnswerService; + private readonly IRepository _repository; - public SubjectVisitTrigger(IRepository subjectVisitRepository,IRepository repository) + public SubjectVisitTrigger(IRepository subjectVisitRepository, IClinicalAnswerService iClinicalAnswerService,IRepository repository) { _subjectVisitRepository = subjectVisitRepository; - - _repository = repository; + this._iClinicalAnswerService = iClinicalAnswerService; + _repository = repository; } //注意删除不能用扩展方法,必须用EF跟踪的实体 否则不能取到 SubjectVisitId @@ -65,13 +67,33 @@ namespace IRaCIS.Core.Application.Triggers await UpdateSubjectVisitSubmitStateAsync(subjectVisitId); + //添加检查级别临床数据 + + // 检查类型 ModalityForEdit + // 检查模态 Modalities + var modalities = context.Entity.Modalities; + if (modalities.Contains("PT") && modalities.Contains("CT")) + { + await _iClinicalAnswerService.AddStudyClinical(new Service.Reading.Dto.AddStudyClinicalInDto() + { + StudyId = studyId, + }); + } + + } if (context.ChangeType == ChangeType.Deleted) { await UpdateSubjectVisitImageDateAsync(subjectVisitId); await UpdateSubjectVisitSubmitStateAsync(subjectVisitId); - } + + //删除检查级别临床数据 + await _iClinicalAnswerService.DeleteStudyClinical(new Service.Reading.Dto.DeleteStudyClinicalInDto() + { + StudyId = context.Entity.Id, + }); + } } diff --git a/IRaCIS.Core.Domain/Image/DicomStudy.cs b/IRaCIS.Core.Domain/Image/DicomStudy.cs index a42a79b81..f06517ea9 100644 --- a/IRaCIS.Core.Domain/Image/DicomStudy.cs +++ b/IRaCIS.Core.Domain/Image/DicomStudy.cs @@ -88,10 +88,14 @@ namespace IRaCIS.Core.Domain.Models [ForeignKey("CreateUserId")] public User Uploader { get; set; } + [JsonIgnore] + + public List ReadingClinicalDataList { get; set; } - //软删除 - public bool IsDeleted { get; set; } + + //软删除 + public bool IsDeleted { get; set; } public DateTime? DeletedTime { get; set; } diff --git a/IRaCIS.Core.Domain/Reading/ClinicalData/ReadingClinicalData.cs b/IRaCIS.Core.Domain/Reading/ClinicalData/ReadingClinicalData.cs index bdcb87f34..423d169e8 100644 --- a/IRaCIS.Core.Domain/Reading/ClinicalData/ReadingClinicalData.cs +++ b/IRaCIS.Core.Domain/Reading/ClinicalData/ReadingClinicalData.cs @@ -24,6 +24,8 @@ namespace IRaCIS.Core.Domain.Models /// public Guid ReadingId { get; set; } + public Guid? StudyId { get; set; } + /// /// 受试者ID /// @@ -75,9 +77,11 @@ namespace IRaCIS.Core.Domain.Models public ClinicalDataTrialSet ClinicalDataTrialSet { get; set; } + [JsonIgnore] + public DicomStudy? DicomStudy { get; set; } - [JsonIgnore] + [JsonIgnore] [ForeignKey("TrialId")] public Trial Trial { get; set; } diff --git a/IRaCIS.Core.Infra.EFCore/AuthUser/IUserInfo.cs b/IRaCIS.Core.Infra.EFCore/AuthUser/IUserInfo.cs index eb4448cec..b2970b619 100644 --- a/IRaCIS.Core.Infra.EFCore/AuthUser/IUserInfo.cs +++ b/IRaCIS.Core.Infra.EFCore/AuthUser/IUserInfo.cs @@ -51,10 +51,12 @@ namespace IRaCIS.Core.Domain.Share Guid? BatchId { get; set; } + bool IsNotNeedInspection { get; set; } - /// - /// 字符串形式 标识时区 - /// - string TimeZoneId { get; } + + /// + /// 字符串形式 标识时区 + /// + string TimeZoneId { get; } } } diff --git a/IRaCIS.Core.Infra.EFCore/AuthUser/UserInfo.cs b/IRaCIS.Core.Infra.EFCore/AuthUser/UserInfo.cs index 61521c667..d101ec1b7 100644 --- a/IRaCIS.Core.Infra.EFCore/AuthUser/UserInfo.cs +++ b/IRaCIS.Core.Infra.EFCore/AuthUser/UserInfo.cs @@ -298,7 +298,12 @@ namespace IRaCIS.Core.Domain.Share get; set; } - } + + /// + /// 是否不需要记录稽查 + /// + public bool IsNotNeedInspection { get; set; } = false; + } public static class ClaimAttributes { diff --git a/IRaCIS.Core.Infra.EFCore/Common/AuditingData.cs b/IRaCIS.Core.Infra.EFCore/Common/AuditingData.cs index 0ad3d6c38..5b6274db0 100644 --- a/IRaCIS.Core.Infra.EFCore/Common/AuditingData.cs +++ b/IRaCIS.Core.Infra.EFCore/Common/AuditingData.cs @@ -2697,120 +2697,136 @@ namespace IRaCIS.Core.Infra.EFCore.Common //保存影像质量 多条记录,只记录一条稽查 if (entitys.Any(x => x.Entity.GetType() == typeof(ReadingTaskQuestionAnswer))) { - // 保存影像质量 、 修改整体肿瘤评估结果 、 非dicom 保存访视阅片结果 、附加评估 - if (_userInfo.RequestUrl == "ReadingImageTask/changeDicomReadingQuestionAnswer" - || _userInfo.RequestUrl == "ReadingImageTask/saveImageQuality" - || _userInfo.RequestUrl.Contains("SaveTaskQuestion") - || _userInfo.RequestUrl == "ReadingImageTask/saveVisitTaskQuestions" - || _userInfo.RequestUrl == "ReadingImageTask/changeCalculationAnswer" - || _userInfo.RequestUrl == "ReadingImageTask/submitTaskAdditionalQuestion") + //判断是否不需要记录稽查 + if (_userInfo.IsNotNeedInspection) { - var type = AuditOpt.Add; - - List unitDataList = (await _dbContext.Dictionary.Where(x => x.Parent.Code == "ValueUnit").Where(x => x.Code != "0").ToListAsync()).Select(x => new UnitData() - { - - Unit = (ValueUnit)int.Parse(x.Code), - UnitName = x.Value.ToString(), - }).ToList(); - var extraIdentification = string.Empty; - - //具体的答案 - var taskQuestionAnswerList = entitys.Where(x => x.Entity.GetType() == typeof(ReadingTaskQuestionAnswer)).Select(t => t.Entity as ReadingTaskQuestionAnswer).ToList(); - - //获取问题名称 组合成数组 - var quesionList = await _dbContext.ReadingQuestionTrial.Where(t => taskQuestionAnswerList.Select(k => k.ReadingQuestionTrialId).Contains(t.Id)).IgnoreQueryFilters().Select(t => new - { - t.QuestionName, - t.QuestionEnName, - QuestionId = t.Id, - t.DictionaryCode, - t.Unit, - t.ShowOrder, - AnswerType = t.Type, - }).OrderBy(t => t.ShowOrder).ToListAsync(); - - - var firstEntity = taskQuestionAnswerList.First(); - - var cloneEntity = firstEntity.Clone(); - - - - //保证Id 唯一 - cloneEntity.Id = IdentifierHelper.CreateGuid(firstEntity.ReadingQuestionCriterionTrialId.ToString(), firstEntity.ReadingQuestionTrialId.ToString(), firstEntity.VisitTaskId.ToString()); - - - dynamic tableQuesionAndAnswerList = null; - //自定义特有标识 - if (await _dbContext.ReadingQuestionCriterionTrial.AnyAsync(t => t.Id == firstEntity.ReadingQuestionCriterionTrialId && t.CriterionType == CriterionType.SelfDefine)) - { - extraIdentification = "/Self"; - - //还会把病灶问题答案更新 - - var tableQuestionAnswerList = entitys.Where(x => x.Entity.GetType() == typeof(ReadingTableQuestionAnswer)).Select(t => t.Entity as ReadingTableQuestionAnswer).ToList(); - - - //获取表格问题名称 组合成数组 - var tableQuesionList = await _dbContext.ReadingTableQuestionTrial.Where(t => tableQuestionAnswerList.Select(k => k.TableQuestionId).Contains(t.Id)).Select(t => - new - { - TrialReadingCriterionId = t.ReadingQuestionTrial.ReadingQuestionCriterionTrialId, //标准Id - Type = t.ReadingQuestionTrial.QuestionName, //病灶类型 - t.ReadingQuestionTrial.Unit, - t.ReadingQuestionTrial.CustomUnit, - t.DictionaryCode, - t.QuestionName, - t.QuestionEnName, - QuestionId = t.Id, - t.ShowOrder, - AnswerType = t.Type, - }) - .OrderBy(t => t.ShowOrder).ToListAsync(); - - tableQuesionAndAnswerList = tableQuestionAnswerList.Join(tableQuesionList, t => t.TableQuestionId, u => u.QuestionId, (t, u) => - new - { - //如果问题类型是附件 特殊处理 方便前端解析 - Answer = u.AnswerType == "upload" ? "❄❅❆❇❈❉❊" + t.Answer : t.Answer, - u.QuestionName, - u.QuestionEnName, - u.DictionaryCode, - u.ShowOrder, - t.RowId - } - ).OrderBy(t => t.RowId).ThenBy(t => t.ShowOrder).ToList(); - - - - } - - await InsertInspection(cloneEntity, type, x => new InspectionConvertDTO() - { - VisitTaskId = x.VisitTaskId, - - ObjectRelationParentId = x.VisitTaskId, - - TrialReadingCriterionId = x.ReadingQuestionCriterionTrialId, - - ExtraIndentification = extraIdentification, - - }, new - { - QuestionAnswerList = taskQuestionAnswerList.Join(quesionList, - t => t.ReadingQuestionTrialId, - u => u.QuestionId, - (t, u) => - new { Answer = u.AnswerType == "upload" ? "❄❅❆❇❈❉❊" + t.Answer : t.Answer + unitDataList.Where(y => y.Unit == u.Unit).Select(x => x.UnitName).FirstIsNullReturnEmpty() - , u.DictionaryCode, u.QuestionName, u.QuestionEnName, u.ShowOrder }).OrderBy(t => t.ShowOrder).ToList() - , - TableQuestionAndAnswerList = tableQuesionAndAnswerList - } - ); - + _userInfo.IsNotNeedInspection = false; } + else + { + // 保存影像质量 、 修改整体肿瘤评估结果 、 非dicom 保存访视阅片结果 、附加评估 + if (_userInfo.RequestUrl == "ReadingImageTask/changeDicomReadingQuestionAnswer" + || _userInfo.RequestUrl == "ReadingImageTask/saveImageQuality" + || _userInfo.RequestUrl.Contains("SaveTaskQuestion") + || _userInfo.RequestUrl == "ReadingImageTask/saveVisitTaskQuestions" + || _userInfo.RequestUrl == "ReadingImageTask/changeCalculationAnswer" + || _userInfo.RequestUrl == "ReadingImageTask/submitTaskAdditionalQuestion") + { + var type = AuditOpt.Add; + + List unitDataList = (await _dbContext.Dictionary.Where(x => x.Parent.Code == "ValueUnit").Where(x => x.Code != "0").ToListAsync()).Select(x => new UnitData() + { + + Unit = (ValueUnit)int.Parse(x.Code), + UnitName = x.Value.ToString(), + }).ToList(); + var extraIdentification = string.Empty; + + //具体的答案 + var taskQuestionAnswerList = entitys.Where(x => x.Entity.GetType() == typeof(ReadingTaskQuestionAnswer)).Select(t => t.Entity as ReadingTaskQuestionAnswer).ToList(); + + //获取问题名称 组合成数组 + var quesionList = await _dbContext.ReadingQuestionTrial.Where(t => taskQuestionAnswerList.Select(k => k.ReadingQuestionTrialId).Contains(t.Id)).IgnoreQueryFilters().Select(t => new + { + t.QuestionName, + t.QuestionEnName, + QuestionId = t.Id, + t.DictionaryCode, + t.Unit, + t.ShowOrder, + AnswerType = t.Type, + }).OrderBy(t => t.ShowOrder).ToListAsync(); + + + var firstEntity = taskQuestionAnswerList.First(); + + var cloneEntity = firstEntity.Clone(); + + + + //保证Id 唯一 + cloneEntity.Id = IdentifierHelper.CreateGuid(firstEntity.ReadingQuestionCriterionTrialId.ToString(), firstEntity.ReadingQuestionTrialId.ToString(), firstEntity.VisitTaskId.ToString()); + + + dynamic tableQuesionAndAnswerList = null; + //自定义特有标识 + if (await _dbContext.ReadingQuestionCriterionTrial.AnyAsync(t => t.Id == firstEntity.ReadingQuestionCriterionTrialId && t.CriterionType == CriterionType.SelfDefine)) + { + extraIdentification = "/Self"; + + //还会把病灶问题答案更新 + + var tableQuestionAnswerList = entitys.Where(x => x.Entity.GetType() == typeof(ReadingTableQuestionAnswer)).Select(t => t.Entity as ReadingTableQuestionAnswer).ToList(); + + + //获取表格问题名称 组合成数组 + var tableQuesionList = await _dbContext.ReadingTableQuestionTrial.Where(t => tableQuestionAnswerList.Select(k => k.TableQuestionId).Contains(t.Id)).Select(t => + new + { + TrialReadingCriterionId = t.ReadingQuestionTrial.ReadingQuestionCriterionTrialId, //标准Id + Type = t.ReadingQuestionTrial.QuestionName, //病灶类型 + t.ReadingQuestionTrial.Unit, + t.ReadingQuestionTrial.CustomUnit, + t.DictionaryCode, + t.QuestionName, + t.QuestionEnName, + QuestionId = t.Id, + t.ShowOrder, + AnswerType = t.Type, + }) + .OrderBy(t => t.ShowOrder).ToListAsync(); + + tableQuesionAndAnswerList = tableQuestionAnswerList.Join(tableQuesionList, t => t.TableQuestionId, u => u.QuestionId, (t, u) => + new + { + //如果问题类型是附件 特殊处理 方便前端解析 + Answer = u.AnswerType == "upload" ? "❄❅❆❇❈❉❊" + t.Answer : t.Answer, + u.QuestionName, + u.QuestionEnName, + u.DictionaryCode, + u.ShowOrder, + t.RowId + } + ).OrderBy(t => t.RowId).ThenBy(t => t.ShowOrder).ToList(); + + + + } + + await InsertInspection(cloneEntity, type, x => new InspectionConvertDTO() + { + VisitTaskId = x.VisitTaskId, + + ObjectRelationParentId = x.VisitTaskId, + + TrialReadingCriterionId = x.ReadingQuestionCriterionTrialId, + + ExtraIndentification = extraIdentification, + + }, new + { + QuestionAnswerList = taskQuestionAnswerList.Join(quesionList, + t => t.ReadingQuestionTrialId, + u => u.QuestionId, + (t, u) => + new { + Answer = u.AnswerType == "upload" ? "❄❅❆❇❈❉❊" + t.Answer : t.Answer + unitDataList.Where(y => y.Unit == u.Unit).Select(x => x.UnitName).FirstIsNullReturnEmpty() + , + u.DictionaryCode, + u.QuestionName, + u.QuestionEnName, + u.ShowOrder + }).OrderBy(t => t.ShowOrder).ToList() + , + TableQuestionAndAnswerList = tableQuesionAndAnswerList + } + ); + + + } + } + } diff --git a/IRaCIS.Core.Infra.EFCore/EntityConfigration/StudyConfigration.cs b/IRaCIS.Core.Infra.EFCore/EntityConfigration/StudyConfigration.cs index 78c26fcd7..0b2031707 100644 --- a/IRaCIS.Core.Infra.EFCore/EntityConfigration/StudyConfigration.cs +++ b/IRaCIS.Core.Infra.EFCore/EntityConfigration/StudyConfigration.cs @@ -24,6 +24,13 @@ namespace IRaCIS.Core.Infra.EFCore.EntityConfigration .HasForeignKey(s => new { s.TrialId, s.SiteId }) .HasPrincipalKey(c => new { c.TrialId, c.SiteId }); - } + + builder + .HasMany(s => s.ReadingClinicalDataList) + .WithOne(c => c.DicomStudy) + .HasForeignKey(s => new { s.StudyId }) + .HasPrincipalKey(c => new { c.Id }); + + } } }