diff --git a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml index 62dcf536c..fb3f4d549 100644 --- a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml +++ b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml @@ -17316,17 +17316,17 @@ - 质疑 + ���� - 一致性核查 + һ���Ժ˲� - 复制 + ���� diff --git a/IRaCIS.Core.Application/Service/ReadingCalculate/General/ReadingCalculateService.cs b/IRaCIS.Core.Application/Service/ReadingCalculate/General/ReadingCalculateService.cs index 4f536da8e..46931c9cb 100644 --- a/IRaCIS.Core.Application/Service/ReadingCalculate/General/ReadingCalculateService.cs +++ b/IRaCIS.Core.Application/Service/ReadingCalculate/General/ReadingCalculateService.cs @@ -55,6 +55,7 @@ namespace IRaCIS.Core.Application.Service.ReadingCalculate {CriterionType.IVUS,typeof(IVUSCalculateService) }, {CriterionType.OCT,typeof(OCTCalculateService) }, {CriterionType.MRIPDFF,typeof(MRIPDFFCalculateService) }, + {CriterionType.MRIPDFFAdvance,typeof(MRIPDFFAdvanceCalculateService) }, {CriterionType.mRECISTHCC,typeof(MRECISTHCCCalculateService) }, }; diff --git a/IRaCIS.Core.Application/Service/ReadingCalculate/MRIPDFFAdvanceCalculateService.cs b/IRaCIS.Core.Application/Service/ReadingCalculate/MRIPDFFAdvanceCalculateService.cs new file mode 100644 index 000000000..2ab179580 --- /dev/null +++ b/IRaCIS.Core.Application/Service/ReadingCalculate/MRIPDFFAdvanceCalculateService.cs @@ -0,0 +1,561 @@ +using DocumentFormat.OpenXml.EMMA; +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.Infra.EFCore.Common; +using IRaCIS.Core.Infrastructure; +using MassTransit; +using Microsoft.AspNetCore.Mvc; +using System.Linq; + +namespace IRaCIS.Core.Application.Service.ReadingCalculate +{ + [ApiExplorerSettings(GroupName = "Reading")] + public class MRIPDFFAdvanceCalculateService(IRepository _readingTableQuestionAnswerRepository, + IRepository _visitTaskRepository, + IRepository _readingQuestionCriterionTrialRepository, + IRepository _readingTableQuestionTrialRepository, + IRepository _readingTableAnswerRowInfoRepository, + IRepository _readingGlobalTaskInfoRepository, + IRepository _readingQuestionTrialRepository, + IRepository _subjectVisitRepository, + IRepository _organInfoRepository, + IRepository _dictionaryRepository, + IRepository _readingTaskQuestionMarkRepository, + IRepository _dicomStudyRepository, + IRepository _noneDicomStudyRepository, + IRepository _tumorAssessmentRepository, + IGeneralCalculateService _generalCalculateService, + IRepository _readingTaskQuestionAnswerRepository, IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer) : BaseService, ICriterionCalculateService + { + + + private List siteVisitForTumorList = new List(); + + /// + /// 阅片导入 + /// + /// + public async Task ReadingImport() + { + } + + + /// + /// 获取阅片的计算数据 + /// + /// + /// + public async Task GetReadingCalculationData(GetReadingCalculationDataInDto inDto) + { + return new + { + }; + } + + #region 删除病灶获取起始病灶序号 + /// + /// 删除病灶获取起始病灶序号 + /// + /// + public async Task GetDeleteLesionStatrIndex(DeleteReadingRowAnswerInDto inDto) + { + return 1; + + + } + #endregion + + #region 获取阅片报告 + /// + /// 获取阅片报告 + /// + /// + /// + [HttpPost] + public async Task GetReadingReportEvaluation(GetReadingReportEvaluationInDto indto) + { + GetReadingReportEvaluationOutDto result = new GetReadingReportEvaluationOutDto(); + + result.CalculateResult = await this.GetReportVerify(new GetReportVerifyInDto() + { + VisitTaskId = indto.VisitTaskId + }); + + var visitTaskInfo = await _visitTaskRepository.Where(x => x.Id == indto.VisitTaskId).FirstNotNullAsync(); + + + result.ReadingTaskState = visitTaskInfo.ReadingTaskState; + var taskInfoList = await _generalCalculateService.GetReadingReportTaskList(indto.VisitTaskId); + + result.VisitTaskList = taskInfoList; + + var visitTaskIds = taskInfoList.Select(x => x.VisitTaskId).ToList(); + + var criterionId = visitTaskInfo.TrialReadingCriterionId; + var questionList = await _readingQuestionTrialRepository.Where(x => x.ReadingQuestionCriterionTrialId == criterionId && x.ShowQuestion != ShowQuestion.Hide).ToListAsync(); + var tableQuestionList = await _readingTableQuestionTrialRepository.Where(x => x.TrialCriterionId == criterionId).OrderBy(x => x.ShowOrder).ToListAsync(); + + var lesionsIndexs = await _readingTableAnswerRowInfoRepository.Where(x => visitTaskIds.Contains(x.VisitTaskId)).GroupBy(x => new { x.QuestionId }).Select(x => new lesionsIndexDto() + { + QuestionId = x.Key.QuestionId, + Rowindexs = x.Select(x => x.RowIndex).Distinct().OrderBy(x => x).ToList() + + }).ToListAsync(); + + var tableAnsweRowInfos = await _readingTableAnswerRowInfoRepository.Where(x => x.VisitTaskId == indto.VisitTaskId).ProjectTo(_mapper.ConfigurationProvider).ToListAsync(); + + var answers = await _readingTaskQuestionAnswerRepository.Where(x => visitTaskIds.Contains(x.VisitTaskId)).ToListAsync(); + var tableAnswers = await _readingTableQuestionAnswerRepository.Where(x => visitTaskIds.Contains(x.VisitTaskId)).ToListAsync(); + var globalanswerList = await _readingGlobalTaskInfoRepository.Where(x => visitTaskIds.Contains(x.TaskId) && x.GlobalVisitTask.TaskState == TaskState.Effect && x.Answer != string.Empty).Select(x => new Globalanswer() + { + TaskId = x.TaskId, + VisitTaskNum = x.GlobalVisitTask.VisitTaskNum, + QuestionId = x.QuestionId, + Answer = x.Answer + }).ToListAsync(); + var alltableAnsweRowInfos = await _readingTableAnswerRowInfoRepository.Where(x => visitTaskIds.Contains(x.VisitTaskId)).ToListAsync(); + var organIds = alltableAnsweRowInfos.Where(x => x.OrganInfoId != null).Select(x => x.OrganInfoId).Distinct().ToList(); + var organInfos = await _organInfoRepository.Where(x => organIds.Contains(x.Id)).ToListAsync(); + + var needChangeType = new List() { + QuestionMark.Organ, + QuestionMark.Location, + QuestionMark.Part, + }; + + // 第一级 + + List questions = await _generalCalculateService.GetReadingReportQuestion + ( + questionList, + taskInfoList, + globalanswerList, + answers, + tableAnsweRowInfos, + tableQuestionList, + alltableAnsweRowInfos, + tableAnswers, + organInfos, + needChangeType + ); + + + + result.TaskQuestions = questions; + + + + return result; + + + } + #endregion + + /// + /// 将上一次的访视病灶添加到这一次 + /// + /// + /// + public async Task AddTaskLesionAnswerFromLastTask(AddTaskLesionAnswerFromLastTaskInDto inDto) + { + var visitTaskId = inDto.VisitTaskId; + var taskinfo = await _visitTaskRepository.Where(x => x.Id == visitTaskId).FirstNotNullAsync(); + var isReadingTaskViewInOrder = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == taskinfo.TrialReadingCriterionId).Select(x => x.IsReadingTaskViewInOrder).FirstOrDefaultAsync(); + var baseLineVisitId = await _subjectVisitRepository.Where(x => x.SubjectId == taskinfo.SubjectId && x.IsBaseLine).Select(x => x.Id).FirstOrDefaultAsync(); + + if (!(await _readingTableQuestionAnswerRepository.AnyAsync(x => x.VisitTaskId == visitTaskId))) + { + + + + var dictionList = await _dictionaryRepository.Where(x => x.Parent.Code == "LiverSegmentation").OrderBy(x => x.ShowOrder).ToListAsync(); + + + var tableQuestion = await _readingQuestionTrialRepository.Where(x => x.ReadingQuestionCriterionTrialId == taskinfo.TrialReadingCriterionId && x.LesionType == LesionType.FatFraction).FirstNotNullAsync(); + + var tableQuestionList = await _readingTableQuestionTrialRepository.Where(x => x.ReadingQuestionId == tableQuestion.Id).ToListAsync(); + var LastVisitTaskId = await _visitTaskRepository.Where(x => x.ReadingCategory == ReadingCategory.Visit && + x.TrialReadingCriterionId == taskinfo.TrialReadingCriterionId && + x.IsAnalysisCreate == taskinfo.IsAnalysisCreate && + x.DoctorUserId == taskinfo.DoctorUserId && + x.IsSelfAnalysis == taskinfo.IsSelfAnalysis && + x.SubjectId == taskinfo.SubjectId && x.ReadingTaskState == ReadingTaskState.HaveSigned && x.VisitTaskNum < taskinfo.VisitTaskNum && x.TaskState == TaskState.Effect && x.ArmEnum == taskinfo.ArmEnum + ).OrderByDescending(x => x.VisitTaskNum).Select(x => x.Id).FirstOrDefaultAsync(); + + + List marks = await _readingTaskQuestionMarkRepository.Where(x => x.VisitTaskId == LastVisitTaskId && x.RowId != null).ProjectTo(_mapper.ConfigurationProvider).ToListAsync(); + + + marks.ForEach(x => { + + x.VisitTaskId = visitTaskId; + }); + + List rowlist = new List(); + List tableAnswerList = new List(); + + decimal num = 1; + foreach (var item in dictionList) + { + var guid = NewId.NextGuid(); + marks.ForEach(x => { + x.RowId = x.RowIndex == num ? guid : x.RowId; + }); + rowlist.Add(new ReadingTableAnswerRowInfo() + { + FristAddTaskId = visitTaskId, + IsCurrentTaskAdd = true, + BlindName = taskinfo.TaskBlindName, + OrderMark = tableQuestion.OrderMark, + VisitTaskId = visitTaskId, + TrialId = taskinfo.TrialId, + QuestionId = tableQuestion.Id, + RowIndex = num, + Id = guid, + }); + + tableAnswerList.Add(new ReadingTableQuestionAnswer() + { + QuestionId = tableQuestion.Id, + Answer = item.Code, + TableQuestionId = tableQuestionList.Where(x => x.QuestionMark == QuestionMark.liverSegmentation).Select(x => x.Id).FirstOrDefault(), + VisitTaskId = visitTaskId, + TrialId = taskinfo.TrialId, + RowIndex = num, + RowId = guid, + }); + + foreach (var otherQuestion in tableQuestionList.Where(x => !tableAnswerList.Any(y => y.RowId == guid && y.TableQuestionId == x.Id))) + { + tableAnswerList.Add(new ReadingTableQuestionAnswer() + { + Answer = otherQuestion.DefaultValue, + QuestionId = tableQuestion.Id, + TrialId = taskinfo.TrialId, + VisitTaskId = taskinfo.Id, + RowId = guid, + RowIndex = num, + TableQuestionId = otherQuestion.Id, + }); + } + + + num++; + } + await _readingTableAnswerRowInfoRepository.AddRangeAsync(rowlist); + await _readingTableQuestionAnswerRepository.AddRangeAsync(tableAnswerList); + + await _readingTaskQuestionMarkRepository.AddRangeAsync(_mapper.Map>(marks)); + await _readingTableQuestionAnswerRepository.SaveChangesAsync(); + } + + + return new AddTaskLesionAnswerFromLastTaskOutDto() + { + IsBaseLine = taskinfo.SourceSubjectVisitId == baseLineVisitId, + }; + + } + + /// + /// 测试计算 + /// + /// + /// + /// + [HttpPost] + public async Task TestCalculate(Guid visitTaskId, QuestionType type) + { + ReadingCalculateDto readingData = await _generalCalculateService.GetReadingCalculateDto(visitTaskId); + await ReadingCalculate(readingData, new List() { type }); + } + + /// + /// 计算任务 + /// + /// + /// + [HttpPost] + public async Task CalculateTask(CalculateTaskInDto inDto) + { + ReadingCalculateDto readingData = await _generalCalculateService.GetReadingCalculateDto(inDto.VisitTaskId); + readingData.IsChangeOtherTask = inDto.IsChangeOtherTask; + await ReadingCalculate(readingData); + } + + + + + /// + /// 自动计算 + /// + /// + /// + /// + public async Task ReadingCalculate(ReadingCalculateDto inDto, List? calculateType = null) + { + + await this.CalculateAvg(inDto); + inDto = await _generalCalculateService.GetReadingCalculateDto(inDto.VisitTaskId); + var needAddList = new List(); + List calculateList = new List() + { + // 脂肪平均 + new ReadingCalculateData (){QuestionType=QuestionType.TotalMeanFraction,GetStringFun=GetFatFractionAvg}, + + // 脂肪分级 + new ReadingCalculateData (){QuestionType=QuestionType.FattyLiverGrading,GetStringFun=GetFattyLiverGrading}, + }; + + + if (calculateType != null) + { + calculateList = calculateList.Where(x => calculateType.Contains(x.QuestionType)).ToList(); + } + + + + foreach (var calculate in calculateList) + { + var item = inDto.QuestionInfo.FirstOrDefault(x => x.QuestionType == calculate.QuestionType); + + if (item != null) + { + //计算答案 + + + #region 计算答案 + if (calculate.GetDecimalFun != null) + { + item.Answer = (await calculate.GetDecimalFun(inDto)).ToString(); + + } + else if (calculate.GetDecimalNullFun != null) + { + var value = await calculate.GetDecimalNullFun(inDto); + item.Answer = value == null ? "NA" : value.Value.ToString(); + } + else if (calculate.GetStringFun != null) + { + item.Answer = await calculate.GetStringFun(inDto); + } + #endregion + // 修改修约小数位数 + + List valueOfTypes = new List() { + + ValueOfType.Decimals, + ValueOfType.Percentage + }; + + if (inDto.DigitPlaces != -1 && calculate.GetDecimalFun != null && calculate.GetDecimalNullFun != null) + { + try + { + + if (valueOfTypes.Contains(item.ValueType)) + { + item.Answer = decimal.Round(decimal.Parse(item.Answer ?? "0"), inDto.DigitPlaces, MidpointRounding.AwayFromZero).ToString("F" + inDto.DigitPlaces.ToString()); + } + } + catch (Exception) + { + + } + } + + needAddList.Add(new ReadingTaskQuestionAnswer() + { + Answer = item.Answer, + ReadingQuestionTrialId = item.QuestionId, + }); + } + } + + + + var questionIds = needAddList.Select(x => x.ReadingQuestionTrialId).ToList(); + + await _readingTaskQuestionAnswerRepository.BatchDeleteNoTrackingAsync(x => questionIds.Contains(x.ReadingQuestionTrialId) && x.VisitTaskId == inDto.VisitTaskId); + needAddList.ForEach(x => + { + x.SubjectId = inDto.SubjectId; + x.ReadingQuestionCriterionTrialId = inDto.CriterionId; + x.VisitTaskId = inDto.VisitTaskId; + x.TrialId = inDto.TrialId; + x.SubjectId = inDto.SubjectId; + }); + + await _readingTaskQuestionAnswerRepository.AddRangeAsync(needAddList); + + await _readingTaskQuestionAnswerRepository.SaveChangesAsync(); + + } + + /// + /// 获取脂肪分数平均值 + /// + /// + /// + public async Task GetFatFractionAvg(ReadingCalculateDto inDto) + { + decimal result = 0; + + var rowInfo = inDto.QuestionInfo.Where(x => x.LesionType == LesionType.FatFraction) + .SelectMany(x => x.TableRowInfoList).ToList(); + + var tableQuestionList = rowInfo.Where(x=>x.TableQuestionList.Any(x=>x.QuestionMark== QuestionMark.IsMeasurable && x.Answer.EqEnum(YesOrNoOrNa.Yes))).SelectMany(x => x.TableQuestionList).ToList(); + + if (rowInfo.Any(x => x.TableQuestionList.Any(x => x.QuestionMark == QuestionMark.AverageValue && x.Answer.IsNullOrEmpty()))) + { + return string.Empty; + } + if (tableQuestionList.Count() == 0) + { + return "NE"; + } + result = tableQuestionList.Where(x => x.QuestionMark == QuestionMark.AverageValue).Average(x => x.Answer.IsNullOrEmptyReturn0()); + return decimal.Round(result, inDto.DigitPlaces, MidpointRounding.AwayFromZero).ToString("F" + inDto.DigitPlaces.ToString()); ; + + } + + /// + /// 获取脂肪肝分级 + /// + /// + /// + public async Task GetFattyLiverGrading(ReadingCalculateDto inDto) + { + var answer = inDto.QuestionInfo.Where(x => x.QuestionType == QuestionType.TotalMeanFraction).Select(x => x.Answer).FirstIsNullReturnEmpty(); + if (answer == "NE") + { + return FattyLiverClassification.NE.GetEnumInt(); + } + else if(answer == string.Empty) + { + return string.Empty; + } + + if (decimal.TryParse(answer, out var value)) + { + return value switch + { + < 5 => FattyLiverClassification.Level0.GetEnumInt(), + < 10 => FattyLiverClassification.Level1.GetEnumInt(), + < 25 => FattyLiverClassification.Level2.GetEnumInt(), + _ => FattyLiverClassification.Level3.GetEnumInt() + }; + } + + return FattyLiverClassification.NE.GetEnumInt(); + } + + /// + /// 计算平均值 + /// + /// + public async Task CalculateAvg(ReadingCalculateDto inDto) + { + // 脂肪分数的表格问题Id + var questionInfo = inDto.QuestionInfo.Where(x => x.LesionType == LesionType.FatFraction).FirstOrDefault(); + + List tableAnswers = new List(); + + + foreach (var item in questionInfo.TableRowInfoList) + { + var avg = item.TableQuestionList.Where(x => x.QuestionMark == QuestionMark.AverageValue).FirstOrDefault(); + var avgAnswer = string.Empty; + List questionMarks = new List() + { + QuestionMark.FirstMeasurement, + QuestionMark.SecondMeasurement, + QuestionMark.ThirdMeasurement, + QuestionMark.FourthMeasurement, + }; + var answers = item.TableQuestionList.Where(x => questionMarks.Contains(x.QuestionMark)).Select(x=>x.Answer).ToList(); + if (answers.Count() == 3 && !answers.Any(x => x.IsNullOrEmpty())) + { + var avgAnswernum= answers.Select(x=>x.IsNullOrEmptyReturn0()).Average(x=>x); + avgAnswer = decimal.Round(avgAnswernum, inDto.DigitPlaces, MidpointRounding.AwayFromZero).ToString("F" + inDto.DigitPlaces.ToString()); + } + if(item.TableQuestionList.Where(x => x.QuestionMark== QuestionMark.IsMeasurable).Select(x => x.Answer).FirstOrDefault().EqEnum(YesOrNoOrNa.No)) + { + avgAnswer = "NE"; + } + tableAnswers.Add(new ReadingTableQuestionAnswer() + { + Answer = avgAnswer, + VisitTaskId = inDto.VisitTaskId, + QuestionId = avg.QuestionId, + TableQuestionId = avg.TableQuestionId, + TrialId = inDto.TrialId, + RowIndex = avg.RowIndex, + RowId = avg.RowId, + + }); + + await _readingTableQuestionAnswerRepository.BatchDeleteNoTrackingAsync(x => x.VisitTaskId == inDto.VisitTaskId && x.RowId == item.RowId && x.TableQuestionId == avg.TableQuestionId); + } + + await _readingTableQuestionAnswerRepository.AddRangeAsync(tableAnswers); + await _readingTableQuestionAnswerRepository.SaveChangesAsync(); + + } + + + + public async Task GetReportVerify(GetReportVerifyInDto inDto) + { + return new GetReportVerifyOutDto() + { + + }; + } + + public async Task VerifyVisitTaskQuestions(VerifyVisitTaskQuestionsInDto inDto) + { + ReadingCalculateDto readingData = await _generalCalculateService.GetReadingCalculateDto(inDto.VisitTaskId); + + var markList = await _readingTaskQuestionMarkRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId).ToListAsync(); + var rowInfo = readingData.QuestionInfo.Where(x => x.LesionType == LesionType.FatFraction) + .SelectMany(x => x.TableRowInfoList).ToList(); + + var tableQuestionList = rowInfo.Where(x => x.TableQuestionList.Any(x => x.QuestionMark == QuestionMark.AverageValue && x.Answer.IsNotNullOrEmpty())).ToList(); + + if (tableQuestionList.Count() != 8) + { + throw new BusinessValidationFailedException(_localizer["MRIPDFF_AllNeedToBeMark"]); + } + + try + { + List questionMarkList = new List() { QuestionMark.FirstMeasurement, QuestionMark.SecondMeasurement, QuestionMark.ThirdMeasurement, QuestionMark.FourthMeasurement }; + 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(); + + + foreach (var item in notableQuestionList) + { + if (markList.Any(x => x.RowId == item.RowId && x.MeasureData.IsNotNullOrEmpty())) + { + throw new BusinessValidationFailedException(_localizer["MRIPDFF_NeedClearMark"]); + } + } + + } + } +} diff --git a/IRaCIS.Core.Domain.Share/Reading/ReadEnum.cs b/IRaCIS.Core.Domain.Share/Reading/ReadEnum.cs index 7cfec52a5..d9ff423a0 100644 --- a/IRaCIS.Core.Domain.Share/Reading/ReadEnum.cs +++ b/IRaCIS.Core.Domain.Share/Reading/ReadEnum.cs @@ -914,6 +914,12 @@ namespace IRaCIS.Core.Domain.Share /// MRIPDFF /// MRIPDFF = 21, + + /// + /// MRIPDFFAdvance + /// + + MRIPDFFAdvance = 22, } @@ -2519,6 +2525,11 @@ namespace IRaCIS.Core.Domain.Share /// 肝脏分段 /// liverSegmentation = 1106, + + /// + /// 第四次测量 + /// + FourthMeasurement = 1107, } ///