irc-netcore-api/IRaCIS.Core.Application/Service/ReadingCalculate/General/GeneralCalculateService.cs

1027 lines
51 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using Amazon.Runtime.Internal.Transform;
using DocumentFormat.OpenXml.Drawing.Spreadsheet;
using IRaCIS.Core.Application.Helper;
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 MassTransit;
using MassTransit.Saga;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using MiniExcelLibs;
using System.Collections.Immutable;
using System.Data;
using System.IO;
using System.Text;
namespace IRaCIS.Core.Application.Service.ReadingCalculate
{
public class GeneralCalculateService(IRepository<ReadingTableQuestionAnswer> _readingTableQuestionAnswerRepository,
IRepository<VisitTask> _visitTaskRepository,
IRepository<Segmentation> _segmentationRepository,
IRepository<Segment> _segmentRepository,
IRepository<SegmentBinding> _segmentBindingRepository,
IRepository<ReadingTaskQuestionMark> _readingTaskQuestionMarkRepository,
IRepository<ReadingNoneDicomMark> _readingNoneDicomMarkRepository,
IRepository<ReadingNoneDicomMarkBinding> _readingNoneDicomMarkBindingRepository,
IRepository<ReadingQuestionCriterionTrial> _readingQuestionCriterionTrialRepository,
ILogger<GeneralCalculateService> _logger,
IRepository<ReadingTableQuestionTrial> _readingTableQuestionTrialRepository,
IRepository<ReadingTableAnswerRowInfo> _readingTableAnswerRowInfoRepository,
IRepository<ReadingQuestionTrial> _readingQuestionTrialRepository,
IRepository<SubjectVisit> _subjectVisitRepository,
IRepository<TumorAssessment_RECIST1Point1> _tumorAssessmentRepository,
IRepository<ReadingTaskQuestionAnswer> _readingTaskQuestionAnswerRepository,
IRepository<InspectionFile> _inspectionFileRepository,
IOSSService oSSService, IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer) : BaseService, IGeneralCalculateService
{
/// <summary>
/// 构造阅片报告问题
/// </summary>
/// <param name="questionList"></param>
/// <param name="taskInfoList"></param>
/// <param name="globalanswerList"></param>
/// <param name="answers"></param>
/// <param name="tableAnsweRowInfos"></param>
/// <param name="tableQuestionList"></param>
/// <param name="alltableAnsweRowInfos"></param>
/// <param name="tableAnswers"></param>
/// <param name="organInfos"></param>
/// <param name="needChangeType"></param>
/// <returns></returns>
public async Task<List<ReadingReportDto>> GetReadingReportQuestion(
List<ReadingQuestionTrial>? questionList,
List<VisitTaskInfo> taskInfoList,
List<Globalanswer>? globalanswerList,
List<ReadingTaskQuestionAnswer>? answers,
List<TableAnsweRowInfo>? tableAnsweRowInfos,
List<ReadingTableQuestionTrial> tableQuestionList,
List<ReadingTableAnswerRowInfo> alltableAnsweRowInfos,
List<ReadingTableQuestionAnswer> tableAnswers,
List<OrganInfo> organInfos,
List<QuestionMark?> needChangeType
)
{
#region 构造问题
List<ReadingReportDto> questions = _mapper.Map<List<ReadingReportDto>>(questionList.Where(x => x.Type == ReadingQestionType.Group).OrderBy(x => x.ShowOrder));
// 分组
foreach (var item in questions)
{
item.QuestionName = item.QuestionName.LanguageName(item.QuestionEnName, _userInfo.IsEn_Us);
item.GroupName = item.GroupName.LanguageName(item.GroupEnName, _userInfo.IsEn_Us);
item.ReportLayType = ReportLayType.Group;
item.Childrens = _mapper.Map<List<ReadingReportDto>>(questionList.Where(x => x.GroupId == item.QuestionId).OrderBy(x => x.ShowOrder));
// 问题
foreach (var question in item.Childrens)
{
question.QuestionName = question.QuestionName.LanguageName(question.QuestionEnName, _userInfo.IsEn_Us);
question.ReportLayType = ReportLayType.Question;
foreach (var task in taskInfoList)
{
var globalAnswer = globalanswerList.Where(x => x.TaskId == task.VisitTaskId && x.QuestionId == question.QuestionId).OrderByDescending(x => x.VisitTaskNum).FirstOrDefault();
var answer = answers.Where(x => x.VisitTaskId == task.VisitTaskId && x.ReadingQuestionTrialId == question.QuestionId).FirstOrDefault();
question.Answer.Add(new TaskQuestionAnswer()
{
Answer = answer == null ? string.Empty : answer.Answer,
IsGlobalChange = globalAnswer == null ? false : true,
GlobalChangeAnswer = globalAnswer == null ? string.Empty : globalAnswer.Answer,
TaskName = task.TaskName,
VisitTaskId = task.VisitTaskId,
});
}
// 构造表格行数据
var rowlist = tableAnsweRowInfos.Where(x => x.QuestionId == question.QuestionId).OrderBy(x => x.RowIndex).ToList();
question.Childrens = rowlist.Select(x => new ReadingReportDto()
{
QuestionName = question.OrderMark + x.RowIndex.GetLesionMark(),
SplitOrMergeLesionName = x.MergeName.IsNullOrEmpty() ? x.SplitName : x.MergeName,
SplitOrMergeType = x.SplitOrMergeType,
LesionType = question.LesionType,
IsShowInDicom = question.IsShowInDicom,
IsCanEditPosition = x.IsCanEditPosition,
RowIndex = x.RowIndex,
BlindName = x.BlindName,
ReportLayType = ReportLayType.Lesions,
}).ToList();
foreach (var row in question.Childrens)
{
// tableQuestion
row.Childrens = _mapper.Map<List<ReadingReportDto>>(tableQuestionList.Where(x => x.ReadingQuestionId == question.QuestionId));
foreach (var tableQuestion in row.Childrens)
{
tableQuestion.QuestionName = tableQuestion.QuestionName.LanguageName(tableQuestion.QuestionEnName, _userInfo.IsEn_Us);
tableQuestion.LesionType = question.LesionType;
tableQuestion.RowId = row.RowId;
tableQuestion.IsShowInDicom = question.IsShowInDicom;
tableQuestion.RowIndex = row.RowIndex;
tableQuestion.ReportLayType = ReportLayType.TableQuestion;
foreach (var task in taskInfoList)
{
var rowinfo = alltableAnsweRowInfos.Where(x => x.VisitTaskId == task.VisitTaskId && x.QuestionId == tableQuestion.QuestionId && x.RowIndex == tableQuestion.RowIndex).FirstOrDefault();
var taskQuestionAnswer = new TaskQuestionAnswer()
{
Answer = tableAnswers.Where(x => x.VisitTaskId == task.VisitTaskId && x.QuestionId == tableQuestion.QuestionId && x.RowIndex == tableQuestion.RowIndex && x.TableQuestionId == tableQuestion.TableQuestionId).Select(x => x.Answer).FirstIsNullReturnEmpty(),
TaskName = task.TaskName,
VisitTaskId = task.VisitTaskId,
};
if (rowinfo != null && rowinfo.OrganInfoId != null)
{
var organInfo = organInfos.Where(x => x.Id == rowinfo.OrganInfoId).FirstOrDefault();
if (organInfo != null && needChangeType.Contains(tableQuestion.QuestionMark))
{
if (_userInfo.IsEn_Us)
{
switch (tableQuestion.QuestionMark)
{
case QuestionMark.Organ:
taskQuestionAnswer.Answer = organInfo.TULOCEN;
break;
case QuestionMark.Location:
if (organInfo.IsCanEditPosition)
{
}
else
{
taskQuestionAnswer.Answer = organInfo.TULATEN;
}
break;
case QuestionMark.Part:
taskQuestionAnswer.Answer = organInfo.PartEN;
break;
}
}
else
{
switch (tableQuestion.QuestionMark)
{
case QuestionMark.Organ:
taskQuestionAnswer.Answer = organInfo.TULOC;
break;
case QuestionMark.Location:
if (organInfo.IsCanEditPosition)
{
}
else
{
taskQuestionAnswer.Answer = organInfo.TULAT;
}
break;
case QuestionMark.Part:
taskQuestionAnswer.Answer = organInfo.Part;
break;
}
}
}
}
tableQuestion.Answer.Add(taskQuestionAnswer);
}
}
}
}
;
}
#endregion
return questions;
}
/// <summary>
/// 复制既往新病灶答案
/// </summary>
/// <returns></returns>
public async Task CopyHistoryAnswer(VisitTask taskinfo, List<ReadingTableAnswerRowInfo> tableRowList, List<ReadingTableQuestionAnswer> tableAnswerList)
{
if (_userInfo.RequestUrl == "ReadingImageTask/resetReadingTask")
{
return;
}
// 如果有表格问题或者外层问题答案就不复制了
if ((await _readingTableQuestionAnswerRepository.AnyAsync(x => x.VisitTaskId == taskinfo.Id))
|| (await _readingTaskQuestionAnswerRepository.AnyAsync(x => x.VisitTaskId == taskinfo.Id)))
{
return;
}
if (taskinfo.IsCopyLesionAnswer)
{
var historyTaskId = 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.SignTime)
.Select(x => x.Id).FirstOrDefaultAsync();
// 1.标记信息复制有问题 2. 标记
if (historyTaskId != Guid.Empty)
{
var criterionType = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == taskinfo.TrialReadingCriterionId).Select(x => x.CriterionType).FirstOrDefaultAsync();
var historyTableRowList = await _readingTableAnswerRowInfoRepository.Where(x => x.VisitTaskId == historyTaskId).Include(x => x.ReadingQuestionTrial).ToListAsync();
var historyTableAnswerList = await _readingTableQuestionAnswerRepository.Where(x => x.VisitTaskId == historyTaskId).ToListAsync();
var answerList = await _readingTaskQuestionAnswerRepository.Where(x => x.VisitTaskId == historyTaskId).ToListAsync();
var questionMarkList = await _readingTaskQuestionMarkRepository.Where(x => x.VisitTaskId == historyTaskId).ToListAsync();
var noneDicomMarkList = await _readingNoneDicomMarkRepository.Where(x => x.VisitTaskId == historyTaskId).ToListAsync();
var noneDicomMarkBindingList = await _readingNoneDicomMarkBindingRepository.Where(x => x.VisitTaskId == historyTaskId).ToListAsync();
Dictionary<Guid, Guid> lesionRelationship = new Dictionary<Guid, Guid>() { };
// 这里后续还要添加病灶 比如现在是访视三 要把失效任务访视三的 在访视三的病灶添加过来
// 同时自定义的 除了根据器官判断还需要根据 复制前值的答案相不相等
foreach (var item in tableRowList)
{
if (item.SplitOrMergeType == SplitOrMergeType.Merged)
{
continue;
}
// 自定义标准(SelfDefine)的病灶IdentityRowId不可靠 除了根据器官判断还需要根据复制前值的答案是否相等 优先用答案匹配
var historyRow = historyTableRowList
.WhereIf(criterionType == CriterionType.SelfDefine,x => IsSameCustomRowAnswer(item, x, tableAnswerList, historyTableAnswerList))
.Where(x =>
x.QuestionId == item.QuestionId &&
x.RowIndex == item.RowIndex &&
x.IdentityRowId == item.IdentityRowId &&
x.IdentityRowId != null &&
x.OrganInfoId == item.OrganInfoId
).FirstOrDefault();
if (historyRow != null)
{
lesionRelationship.Add(historyRow.Id, item.Id);
item.StudyId = historyRow.StudyId;
item.SeriesId = historyRow.SeriesId;
item.InstanceId = historyRow.InstanceId;
item.OtherStudyId = historyRow.OtherStudyId;
item.OtherSeriesId = historyRow.OtherSeriesId;
item.OtherInstanceId = historyRow.OtherInstanceId;
item.MeasureData = historyRow.MeasureData.Replace(historyTaskId.ToString(), taskinfo.Id.ToString());
item.OtherMeasureData = historyRow.OtherMeasureData.Replace(historyTaskId.ToString(), taskinfo.Id.ToString());
tableAnswerList.Where(x => x.RowId == item.Id).ForEach(x =>
{
x.Answer = x.Answer.IsNullOrEmpty() ?
historyTableAnswerList.Where(y => y.RowId == historyRow.Id && y.TableQuestionId == x.TableQuestionId).Select(x => x.Answer).FirstOrDefault() ?? string.Empty :
x.Answer;
});
}
}
// 将失效任务在当前访视新增的病灶添加过来
// 例如现在是访视三,把失效任务访视三中在访视三新增的病灶(FristAddTaskId == historyTaskId)添加过来
var historyAddRowList = historyTableRowList.Where(x => x.FristAddTaskId == historyTaskId && x.SplitOrMergeType != SplitOrMergeType.Merged).ToList();
var historyRowIdSet = historyTableRowList.Select(x => x.Id).ToHashSet();
foreach (var historyRow in historyAddRowList)
{
// 判断当前任务是否已经存在该病灶 失效任务新增的病灶IdentityRowId是新建的不会与当前任务重复
bool isExist = tableRowList.Any(x => x.QuestionId == historyRow.QuestionId && x.IdentityRowId != null && x.IdentityRowId == historyRow.IdentityRowId);
if (isExist)
{
continue;
}
// 通过CopyTableAnswerRowInfo映射复制行字段
var copyRow = _mapper.Map<CopyTableAnswerRowInfo>(historyRow);
copyRow.Id = NewId.NextGuid();
copyRow.VisitTaskId = taskinfo.Id;
copyRow.MeasureData = historyRow.MeasureData.Replace(historyTaskId.ToString(), taskinfo.Id.ToString());
copyRow.IsCurrentTaskAdd = true;
copyRow.FristAddTaskId = taskinfo.Id;
var newRow = _mapper.Map<ReadingTableAnswerRowInfo>(copyRow);
// CopyTableAnswerRowInfo没有Other和PET/CT融合字段 单独复制
newRow.OtherMeasureData = historyRow.OtherMeasureData.Replace(historyTaskId.ToString(), taskinfo.Id.ToString());
newRow.OtherInstanceId = historyRow.OtherInstanceId;
newRow.OtherSeriesId = historyRow.OtherSeriesId;
newRow.OtherStudyId = historyRow.OtherStudyId;
newRow.OtherMarkTool = historyRow.OtherMarkTool;
newRow.OtherPicturePath = historyRow.OtherPicturePath;
newRow.OtherNumberOfFrames = historyRow.OtherNumberOfFrames;
newRow.PTSeriesId = historyRow.PTSeriesId;
newRow.CTSeriesId = historyRow.CTSeriesId;
tableRowList.Add(newRow);
if (!lesionRelationship.ContainsKey(historyRow.Id))
{
lesionRelationship.Add(historyRow.Id, newRow.Id);
}
// 复制该病灶的表格答案
historyTableAnswerList.Where(x => x.RowId == historyRow.Id).ForEach(x =>
{
tableAnswerList.Add(new ReadingTableQuestionAnswer()
{
Id = NewId.NextGuid(),
Answer = x.Answer,
QuestionId = x.QuestionId,
VisitTaskId = taskinfo.Id,
TrialId = x.TrialId,
RowIndex = x.RowIndex,
TableQuestionId = x.TableQuestionId,
RowId = newRow.Id,
});
});
}
// 处理新增病灶的分割合并关系 新增病灶已经在tableRowList里 通过SplitRowId/MergeRowId是否指向失效任务的行来识别
tableRowList.ForEach(x =>
{
if (x.SplitRowId != null && historyRowIdSet.Contains(x.SplitRowId.Value))
{
x.SplitRowId = lesionRelationship.ContainsKey(x.SplitRowId.Value) ? lesionRelationship[x.SplitRowId.Value] : (Guid?)null;
}
if (x.MergeRowId != null && historyRowIdSet.Contains(x.MergeRowId.Value))
{
x.MergeRowId = lesionRelationship.ContainsKey(x.MergeRowId.Value) ? lesionRelationship[x.MergeRowId.Value] : (Guid?)null;
}
});
// 复制外层问题
answerList.ForEach(x =>
{
x.Id = NewId.NextGuid();
x.VisitTaskId = taskinfo.Id;
});
await _readingTaskQuestionAnswerRepository.AddRangeAsync(answerList);
// 处理标记
Dictionary<Guid, Guid> dicomKeys = new Dictionary<Guid, Guid>();
foreach (var item in questionMarkList)
{
item.Id = NewId.NextGuid();
item.VisitTaskId = taskinfo.Id;
item.FristAddTaskId = taskinfo.Id;
if (item.MarkId != null)
{
if (dicomKeys.ContainsKey(item.MarkId.Value))
{
item.MarkId = dicomKeys[item.MarkId.Value];
item.MeasureData = item.MeasureData.Replace(historyTaskId.ToString(), taskinfo.Id.ToString()).Replace(item.MarkId.Value.ToString(), dicomKeys[item.MarkId.Value].ToString());
}
else
{
var newguid = NewId.NextGuid();
item.MeasureData = item.MeasureData.Replace(historyTaskId.ToString(), taskinfo.Id.ToString()).Replace(item.MarkId.Value.ToString(), newguid.ToString());
dicomKeys.Add(item.MarkId.Value, newguid);
item.MarkId = dicomKeys[item.MarkId.Value];
}
}
}
await _readingTaskQuestionMarkRepository.AddRangeAsync(questionMarkList);
// 处理非Dicom标记
Dictionary<Guid, Guid> noneKeys = new Dictionary<Guid, Guid>();
foreach (var item in noneDicomMarkList)
{
var newid = NewId.NextGuid();
item.VisitTaskId = taskinfo.Id;
if (item.MarkId != null)
{
if (noneKeys.ContainsKey(item.MarkId.Value))
{
item.MarkId = noneKeys[item.MarkId.Value];
item.MeasureData = item.MeasureData.Replace(historyTaskId.ToString(), taskinfo.Id.ToString()).Replace(item.MarkId.Value.ToString(), noneKeys[item.MarkId.Value].ToString());
}
else
{
var newguid = NewId.NextGuid();
item.MeasureData = item.MeasureData.Replace(historyTaskId.ToString(), taskinfo.Id.ToString()).Replace(item.MarkId.Value.ToString(), newguid.ToString());
noneKeys.Add(item.MarkId.Value, newguid);
item.MarkId = noneKeys[item.MarkId.Value];
}
}
#region 处理非DICOM绑定
// 处理非DICOM绑定
foreach (var binding in noneDicomMarkBindingList.Where(z => z.MarkId == item.MarkId))
{
binding.Id = NewId.NextGuid();
binding.VisitTaskId = taskinfo.Id;
if (binding.MarkId != null)
{
binding.NoneDicomMarkId = newid;
if (noneKeys.ContainsKey(binding.MarkId.Value))
{
binding.MarkId = noneKeys[binding.MarkId.Value];
}
}
}
#endregion
item.Id = NewId.NextGuid();
}
#region 分割
Dictionary<Guid, Guid> segmentationRelationship = new Dictionary<Guid, Guid>() { };
var segmentationList = _segmentationRepository.Where(t => t.VisitTaskId == historyTaskId).ToList();
foreach (var item in segmentationList)
{
var newSegmentationId = NewId.NextSequentialGuid();
segmentationRelationship.Add(item.Id, newSegmentationId);
item.Id = newSegmentationId;
item.VisitTaskId = taskinfo.Id;
}
Dictionary<Guid, Guid> segmentRelationship = new Dictionary<Guid, Guid>() { };
var segmentList = _segmentRepository.Where(t => t.VisitTaskId == historyTaskId).ToList();
foreach (var item in segmentList)
{
var newSegmentationId = NewId.NextSequentialGuid();
segmentRelationship.Add(item.Id, newSegmentationId);
if (segmentationRelationship.ContainsKey(item.SegmentationId))
{
item.SegmentationId = segmentationRelationship[item.SegmentationId];
}
item.Id = newSegmentationId;
item.VisitTaskId = taskinfo.Id;
}
var segmentBindingList = _segmentBindingRepository.Where(x => x.VisitTaskId == historyTaskId).ToList();
foreach (var item in segmentBindingList)
{
if (segmentationRelationship.ContainsKey(item.SegmentationId))
{
item.SegmentationId = segmentationRelationship[item.SegmentationId];
}
if (segmentRelationship.ContainsKey(item.SegmentId))
{
item.SegmentId = segmentRelationship[item.SegmentId];
}
if (item.RowId != null && lesionRelationship.ContainsKey(item.RowId.Value))
{
item.RowId = lesionRelationship[item.RowId.Value];
}
item.Id = NewId.NextSequentialGuid();
item.VisitTaskId = taskinfo.Id;
}
_ = _segmentationRepository.AddRangeAsync(segmentationList).Result;
_ = _segmentRepository.AddRangeAsync(segmentList).Result;
_ = _segmentBindingRepository.AddRangeAsync(segmentBindingList).Result;
#endregion
await _readingNoneDicomMarkRepository.AddRangeAsync(noneDicomMarkList);
await _readingNoneDicomMarkBindingRepository.AddRangeAsync(noneDicomMarkBindingList);
}
}
}
/// <summary>
/// 从上传文件中获取Datatable
/// </summary>
/// <returns></returns>
public async Task<FileToDataTableDto> GetDataTableFromUpload(IFormFile file, string pathCode, Guid trialId)
{
FileToDataTableDto result = new FileToDataTableDto();
result.DataTable = new DataTable();
var fileFolder = "Upload\\";
if (!Directory.Exists(fileFolder))
{
Directory.CreateDirectory(fileFolder);
}
var fileName = DateTime.Now.ToString("yyyyMMddHHmmss") +
Path.GetExtension(file.FileName);
var filePath = Path.Combine(fileFolder, fileName);
var fileStream = new MemoryStream();
try
{
using (var stream = new FileStream(filePath, FileMode.Create))
{
file.CopyTo(stream);
await stream.CopyToAsync(fileStream);
result.SheetNames = stream.GetSheetNames();
stream.Position = 0;
result.DataTable = stream.QueryAsDataTable(useHeaderRow: false);
}
}
catch (Exception)
{
File.Delete(filePath);
}
try
{
var ossRelativePath = await oSSService.UploadToOSSAsync(fileStream, $"{trialId}/InspectionUpload/" + pathCode, file.FileName, uploadInfo: new FileUploadRecordAddOrEdit() { TrialId = trialId, BatchDataType = BatchDataType.ReadingImportTemplete });
await _inspectionFileRepository.AddAsync(new InspectionFile() { FileName = file.FileName, RelativePath = ossRelativePath, TrialId = trialId });
}
catch (Exception)
{
}
File.Delete(filePath);
// 创建一个要删除的行集合
var rowsToRemove = new System.Collections.Generic.List<DataRow>();
// 遍历DataTable的每一行
foreach (DataRow row in result.DataTable.Rows)
{
bool allEmpty = true;
// 遍历每一列,检查值
foreach (var item in row.ItemArray)
{
if (item != null && !item.ToString().IsNullOrEmpty())
{
allEmpty = false;
break; // 只要有一个不为空,跳出循环
}
}
// 如果所有列都是空字符串,则添加到待删除的行集合中
if (allEmpty)
{
rowsToRemove.Add(row);
}
}
// 移除标记为待删除的行
foreach (var row in rowsToRemove)
{
result.DataTable.Rows.Remove(row);
}
return result;
}
/// <summary>
/// 添加计算错误日志
/// </summary>
/// <param name="inDto"></param>
/// <param name="lesionName"></param>
/// <param name="lesionType"></param>
/// <returns></returns>
public async Task LogRecord(ReadingCalculateDto inDto, string lesionName, LesionType lesionType)
{
// 这里是记录日志 不需要国际化
var criterionInfo = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == inDto.TrialReadingCriterionId).Include(x => x.Trial).FirstNotNullAsync();
var taskInfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).Include(x => x.Subject).Include(x => x.DoctorUser).FirstNotNullAsync();
//错误级别日志:项目、标准、受试者、阅片人、任务。输出其它既往新病灶数据:
StringBuilder builder = new StringBuilder();
builder.AppendLine($"");
builder.AppendLine($"【项目】:【{criterionInfo.Trial.TrialCode}】");
builder.AppendLine($"【项目Id】:【{criterionInfo.TrialId}】");
builder.AppendLine($"【标准】:【{criterionInfo.CriterionName}】");
builder.AppendLine($"【标准Id】:【{criterionInfo.Id}】");
builder.AppendLine($"【受试者】:【{taskInfo.Subject.ShortName}】");
builder.AppendLine($"【受试者Id】:【{taskInfo.Subject.Id}】");
builder.AppendLine($"【阅片人】:【{taskInfo.DoctorUser.FullName}】");
builder.AppendLine($"【阅片人Id】:【{taskInfo.DoctorUser.Id}】");
builder.AppendLine($"【任务】:【{taskInfo.TaskBlindName}】");
builder.AppendLine($"【任务Id】:【{taskInfo.Id}】");
builder.AppendLine($"【病灶类型】:【{lesionName}】");
var lesionInfo = inDto.QuestionInfo.Where(x => x.LesionType == lesionType).FirstOrDefault();
if (lesionInfo != null)
{
lesionInfo.TableRowInfoList.OrderBy(x => x.RowIndex).ForEach(x =>
{
builder.AppendLine(@$"【病灶编号】:【{x.RowIndex.ToString()}】,
【病灶长径】:【{x.TableQuestionList.Where(y => y.QuestionMark == QuestionMark.MajorAxis).Select(y => y.Answer).FirstIsNullReturnEmpty()}】,
【病灶短径】:【{x.TableQuestionList.Where(y => y.QuestionMark == QuestionMark.ShortAxis).Select(y => y.Answer).FirstIsNullReturnEmpty()}】,
【病灶状态】:【{x.TableQuestionList.Where(y => y.QuestionMark == QuestionMark.State).Select(y => y.Answer).FirstIsNullReturnEmpty()}】");
});
}
_logger.LogError(builder.ToString());
}
/// <summary>
/// 获取ReadingCalculateDto
/// </summary>
/// <param name="visitTaskId"></param>
/// <returns></returns>
public async Task<ReadingCalculateDto> GetReadingCalculateDto(Guid visitTaskId)
{
var visitTask = await _visitTaskRepository.Where(x => x.Id == visitTaskId).Include(x => x.SourceSubjectVisit).FirstNotNullAsync();
var criterionInfo = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == visitTask.TrialReadingCriterionId).FirstNotNullAsync();
var subjectVisit = await _subjectVisitRepository.Where(x => x.Id == (visitTask.SourceSubjectVisitId ?? default(Guid))).FirstOrDefaultAsync();
var baseLineVisitId = await _subjectVisitRepository.Where(x => x.SubjectId == visitTask.SubjectId && x.IsBaseLine).Select(x => x.Id).FirstOrDefaultAsync();
var rowInfoList = await _readingTableAnswerRowInfoRepository.Where(x => x.VisitTaskId == visitTaskId).Include(x => x.FristAddTask).ToListAsync();
var baseLinetaskId = await _visitTaskRepository.Where(x => x.SourceSubjectVisitId == baseLineVisitId && x.TaskState == TaskState.Effect
&& x.TrialReadingCriterionId == visitTask.TrialReadingCriterionId
&& x.ArmEnum == visitTask.ArmEnum).Select(x => x.Id).FirstOrDefaultAsync();
List<QuestionInfo> questionInfos = await _readingQuestionTrialRepository.Where(x => x.ReadingQuestionCriterionTrialId == visitTask.TrialReadingCriterionId).Select(x => new QuestionInfo()
{
LesionType = x.LesionType,
QuestionId = x.Id,
QuesionName = x.QuestionName.LanguageName(x.QuestionEnName, _userInfo.IsEn_Us),
OrderMark = x.OrderMark,
QuestionType = x.QuestionType,
ValueType = x.ValueType,
}).ToListAsync();
var questionAnswers = await _readingTaskQuestionAnswerRepository.Where(x => x.VisitTaskId == visitTaskId).Select(x => new
{
x.ReadingQuestionTrialId,
x.Answer,
x.PCWGInterimAnswer,
}).ToListAsync();
var tableQuestion = await _readingTableQuestionAnswerRepository.Where(x => x.VisitTaskId == visitTaskId).Include(x => x.ReadingTableQuestionTrial).Select(x => new TableQuestionInfo()
{
Answer = x.Answer,
AnswerId = x.Id,
QuestionMark = x.ReadingTableQuestionTrial.QuestionMark,
TableQuestionId = x.TableQuestionId,
QuestionId = x.QuestionId,
QuestionType = x.ReadingQuestionTrial.QuestionType,
RowIndex = x.RowIndex,
RowId = x.RowId,
}).ToListAsync();
foreach (var item in questionInfos)
{
item.Answer = questionAnswers.Where(y => y.ReadingQuestionTrialId == item.QuestionId).Select(x => x.Answer).FirstOrDefault() ?? string.Empty;
item.PCWGInterimAnswer = questionAnswers.Where(y => y.ReadingQuestionTrialId == item.QuestionId).Select(x => x.PCWGInterimAnswer).FirstOrDefault();
var thisItemRowInfo = rowInfoList.Where(x => x.QuestionId == item.QuestionId).ToList();
var thisItemTableQuestions = tableQuestion.Where(x => x.QuestionId == item.QuestionId).ToList();
item.TableRowInfoList = thisItemRowInfo.Select(x => new TableRowInfo()
{
RowId = x.Id,
RowIndex = x.RowIndex,
MeasureData = x.MeasureData,
OtherMeasureData = x.OtherMeasureData,
FristAddTaskNum = x.FristAddTask.VisitTaskNum,
TableQuestionList = tableQuestion.Where(y => y.QuestionId == item.QuestionId && y.RowId == x.Id).ToList(),
}).ToList();
}
ReadingCalculateDto readingData = new ReadingCalculateDto()
{
SubjectId = visitTask.SubjectId,
TaskBlindName = visitTask.TaskBlindName,
IsConvertedTask = await _visitTaskRepository.Where(x => x.Id == visitTaskId).Select(x => x.IsConvertedTask).FirstOrDefaultAsync(),
BeforeConvertedTaskId = visitTask.BeforeConvertedTaskId,
VisitTaskId = visitTaskId,
SubjectVisitId = visitTask.SourceSubjectVisitId!.Value,
QuestionInfo = questionInfos,
CriterionId = visitTask.TrialReadingCriterionId,
TrialId = visitTask.TrialId,
IsAnalysisCreate = visitTask.IsAnalysisCreate,
IsSelfAnalysis = visitTask.IsSelfAnalysis,
IsBaseLine = subjectVisit!.IsBaseLine,
DoctorUserId = visitTask.DoctorUserId,
TrialReadingCriterionId = visitTask.TrialReadingCriterionId,
BaseLineTaskId = baseLinetaskId,
ArmEnum = visitTask.ArmEnum,
VisitName = subjectVisit.VisitName,
BlindName = subjectVisit.BlindName,
VisitTaskNum = visitTask.VisitTaskNum,
DigitPlaces = criterionInfo.DigitPlaces ?? 2,
};
return readingData;
}
/// <summary>
/// 添加转化任务病灶信息
/// </summary>
/// <param name="visitTaskId"></param>
/// <param name="beforeConvertedTaskId"></param>
/// <returns></returns>
public async Task AddConvertedTaskFocus(Guid visitTaskId, Guid beforeConvertedTaskId)
{
var originalTask = await _visitTaskRepository.Where(x => x.Id == visitTaskId).Include(x => x.TrialReadingCriterion).FirstNotNullAsync();
var taskAnswer = await _readingTaskQuestionAnswerRepository.Where(x => x.VisitTaskId == beforeConvertedTaskId && x.ReadingQuestionTrial.QuestionType != QuestionType.AdjustReason && x.ReadingQuestionTrial.Type != "calculation").IgnoreAutoIncludes().AsNoTracking().ToListAsync();
taskAnswer.ForEach(x =>
{
x.VisitTaskId = visitTaskId;
x.Id = NewId.NextGuid();
});
var tableRowAnswers = await _readingTableAnswerRowInfoRepository.Where(x => x.VisitTaskId == beforeConvertedTaskId).AsNoTracking().ProjectTo<CopyTableAnswerRowInfo>(_mapper.ConfigurationProvider).IgnoreAutoIncludes().ToListAsync();
tableRowAnswers.ForEach(x =>
{
x.VisitTaskId = visitTaskId;
x.IsCurrentTaskAdd = false;
x.FristAddTaskId = x.FristAddTaskId == beforeConvertedTaskId ? visitTaskId : x.FristAddTaskId;
x.Id = NewId.NextGuid();
});
tableRowAnswers.ForEach(x =>
{
x.SplitRowId = tableRowAnswers.Where(y => y.OriginalId == x.SplitRowId).Select(y => y.Id).FirstOrDefault();
x.MergeRowId = tableRowAnswers.Where(y => y.OriginalId == x.MergeRowId).Select(y => y.Id).FirstOrDefault();
});
var tableAnswer = await _readingTableQuestionAnswerRepository.Where(x => x.VisitTaskId == beforeConvertedTaskId).IgnoreAutoIncludes().AsNoTracking().ToListAsync();
tableAnswer.ForEach(x =>
{
x.Id = NewId.NextGuid();
x.VisitTaskId = visitTaskId;
x.RowId = tableRowAnswers.Where(y => y.OriginalId == x.RowId).Select(x => x.Id).FirstOrDefault();
});
var addrowInfo = _mapper.Map<List<ReadingTableAnswerRowInfo>>(tableRowAnswers);
switch (originalTask.TrialReadingCriterion.CriterionType)
{
case CriterionType.IRECIST1Point1:
//非靶病灶全部数据复制,不可更改。支持如果状态为:显著增大需要自动改为: 显著增大(iUPD)
var stateQuestionId = await _readingTableQuestionTrialRepository.Where(x => x.TrialCriterionId == originalTask.TrialReadingCriterionId
&& x.ReadingQuestionTrial.LesionType == LesionType.NonTargetLesions && x.QuestionMark == QuestionMark.State).Select(x => x.Id).FirstOrDefaultAsync();
tableAnswer.ForEach(x =>
{
if (x.TableQuestionId == stateQuestionId && x.Answer.EqEnum(NoTargetState.Increase))
{
x.Answer = NoTargetState.IUPD.GetEnumInt();
}
});
// 新转换为其它既往新病灶: 状态为消失、疑似、无法评估的新病灶自动转换为:其它既往新病灶,且不可以编辑
// 找到新病灶问题
var newLesionQuestion = await _readingQuestionTrialRepository.Where(x => x.ReadingQuestionCriterionTrialId == originalTask.TrialReadingCriterionId && x.LesionType == LesionType.NewLesions).FirstOrDefaultAsync();
// 找到其他既往新病灶
var otherLesionQuestion = await _readingQuestionTrialRepository.Where(x => x.ReadingQuestionCriterionTrialId == originalTask.TrialReadingCriterionId && x.LesionType == LesionType.OtherPreviousNewLesion).FirstOrDefaultAsync();
if (newLesionQuestion != null && otherLesionQuestion != null)
{
// 找到表格问题
var newLesionTableQuestionList = await _readingTableQuestionTrialRepository.Where(x => x.ReadingQuestionId == newLesionQuestion.Id).ToListAsync();
// 找到表格问题
var otherLesionTableQuestionList = await _readingTableQuestionTrialRepository.Where(x => x.ReadingQuestionId == otherLesionQuestion.Id).ToListAsync();
// 找到病灶状态
var newstateQuestionId = newLesionTableQuestionList.Where(x => x.QuestionMark == QuestionMark.State).Select(x => x.Id).FirstOrDefault();
var stateAnswers = new List<string>() {
NewLesionState.Loss.GetEnumInt(),
NewLesionState.Suspected.GetEnumInt(),
NewLesionState.UnableEvaluate.GetEnumInt()
};
var needRowIds = tableAnswer.Where(x => x.TableQuestionId == newstateQuestionId && stateAnswers.Contains(x.Answer)).Select(x => x.RowId).Distinct().ToList();
var index = 0;
addrowInfo.ForEach(x =>
{
if (needRowIds.Contains(x.Id))
{
index++;
x.RowIndex = index;
x.RowMark = otherLesionQuestion.OrderMark + x.RowIndex.GetLesionMark();
var fristAddTaskId = x.FristAddTaskId.Clone();
x.FromMark = fristAddTaskId == beforeConvertedTaskId ? string.Empty : x.RowMark;
x.FristAddTaskId = fristAddTaskId == beforeConvertedTaskId ? visitTaskId : fristAddTaskId;
x.QuestionId = otherLesionQuestion.Id;
x.OrderMark = otherLesionQuestion.OrderMark;
x.ReportMark = x.RowMark;
}
});
tableAnswer.ForEach(x =>
{
if (needRowIds.Contains(x.RowId))
{
var row = addrowInfo.Where(y => y.Id == x.RowId).FirstOrDefault();
if (row != null)
{
x.RowIndex = row.RowIndex;
}
x.QuestionId = otherLesionQuestion.Id;
var newLesionTableQuestion = newLesionTableQuestionList.Where(y => y.Id == x.TableQuestionId).FirstOrDefault();
if (newLesionTableQuestion != null)
{
x.TableQuestionId = otherLesionTableQuestionList.Where(y => y.QuestionMark == newLesionTableQuestion.QuestionMark).Select(x => x.Id).FirstOrDefault();
}
}
});
}
break;
}
await _readingTaskQuestionAnswerRepository.AddRangeAsync(taskAnswer);
await _readingTableAnswerRowInfoRepository.AddRangeAsync(addrowInfo);
await _readingTableQuestionAnswerRepository.AddRangeAsync(tableAnswer);
await _readingTableQuestionAnswerRepository.SaveChangesAsync();
}
/// <summary>
/// 获取阅片报告任务List
/// </summary>
/// <param name="visitTaskId"></param>
/// <returns></returns>
public async Task<List<VisitTaskInfo>> GetReadingReportTaskList(Guid visitTaskId)
{
var visitTaskInfo = await _visitTaskRepository.Where(x => x.Id == visitTaskId).Include(x => x.TrialReadingCriterion).FirstNotNullAsync();
var isAdditionalQuestionId = await _readingQuestionTrialRepository.Where(x => x.ReadingQuestionCriterionTrialId == visitTaskInfo.TrialReadingCriterionId && x.IsAdditional).IgnoreQueryFilters().Select(x => x.Id).ToListAsync();
var taskquery = _visitTaskRepository
.Where(x => (x.SubjectId == visitTaskInfo.SubjectId
&& (x.TaskState == TaskState.Effect || x.TaskState == TaskState.Freeze)
&& x.IsAnalysisCreate == visitTaskInfo.IsAnalysisCreate
&& x.DoctorUserId == visitTaskInfo.DoctorUserId
&& x.IsSelfAnalysis == visitTaskInfo.IsSelfAnalysis
&& x.VisitTaskNum <= visitTaskInfo.VisitTaskNum
&& x.ArmEnum == visitTaskInfo.ArmEnum
&& x.TrialReadingCriterionId == visitTaskInfo.TrialReadingCriterionId
&& x.ReadingCategory == ReadingCategory.Visit && x.ReadingTaskState == ReadingTaskState.HaveSigned) || x.Id == visitTaskId
);
if (visitTaskInfo.ReadingTaskState == ReadingTaskState.HaveSigned)
{
taskquery = _visitTaskRepository.Where(x => visitTaskInfo.ReportRelatedTaskIdList.Contains(x.Id) || x.Id == visitTaskInfo.Id);
}
if (visitTaskInfo.TrialReadingCriterion.IsReadingTaskViewInOrder != ReadingOrder.InOrder)
{
taskquery = _visitTaskRepository.Where(x => x.Id == visitTaskInfo.Id);
}
var taskInfoList = await taskquery.OrderBy(x => x.VisitTaskNum).Select(x => new VisitTaskInfo()
{
BlindName = x.TaskBlindName,
IsBaseLine = x.SourceSubjectVisit.IsBaseLine,
VisitTaskId = x.Id,
TaskState = x.TaskState,
TaskName = x.TaskName,
LatestScanDate = x.SourceSubjectVisit != null ? x.SourceSubjectVisit.LatestScanDate : null,
VisitTaskNum = x.VisitTaskNum,
IsConvertedTask = x.IsConvertedTask,
BeforeConvertedTaskId = x.BeforeConvertedTaskId,
//CrterionDictionaryGroup = x.CrterionDictionaryGroup,
IsCurrentTask = x.Id == visitTaskId,
}).OrderBy(x => x.VisitTaskNum).ThenByDescending(x => x.TaskState).ToListAsync();
taskInfoList.ForEach(x =>
{
x.CrterionDictionaryGroup = ReadingCommon.GetCrterionDictionaryGroup(x.IsConvertedTask);
});
var taskIds = taskInfoList.Select(x => x.VisitTaskId).ToList();
var isHaveAdditionalTaskIds = await _readingTaskQuestionAnswerRepository.Where(x => taskIds.Contains(x.VisitTaskId) && isAdditionalQuestionId.Contains(x.ReadingQuestionTrialId)).Select(x => x.VisitTaskId).Distinct().ToListAsync();
taskInfoList.ForEach(x =>
{
x.IsHaveAdditionalQuestion = isHaveAdditionalTaskIds.Contains(x.VisitTaskId);
});
return taskInfoList;
}
/// <summary>
/// 自定义病灶判断是否是同一个病灶 除了根据器官判断还需要根据复制前值的答案是否相等
/// </summary>
/// <param name="currentRow"></param>
/// <param name="historyRow"></param>
/// <param name="currentAnswerList"></param>
/// <param name="historyAnswerList"></param>
/// <returns></returns>
private bool IsSameCustomRowAnswer(ReadingTableAnswerRowInfo currentRow, ReadingTableAnswerRowInfo historyRow,
List<ReadingTableQuestionAnswer> currentAnswerList, List<ReadingTableQuestionAnswer> historyAnswerList)
{
// 复制前值的答案即当前任务从上一次有效访视复制过来的答案自定义阅片只有IsCopy的问题会复制值非空的就是复制前值
var currentAnswers = currentAnswerList.Where(x => x.RowId == currentRow.Id && !x.Answer.IsNullOrEmpty())
.GroupBy(x => x.TableQuestionId).ToDictionary(x => x.Key, x => x.First().Answer);
var historyAnswers = historyAnswerList.Where(x => x.RowId == historyRow.Id && !x.Answer.IsNullOrEmpty())
.GroupBy(x => x.TableQuestionId).ToDictionary(x => x.Key, x => x.First().Answer);
// 没有复制前值可以比较时 只根据器官判断
if (currentAnswers.Count == 0)
{
return true;
}
return currentAnswers.All(x => historyAnswers.TryGetValue(x.Key, out var historyAnswer) && historyAnswer == x.Value);
}
}
}