irc-netcore-api/IRaCIS.Core.Application/Service/Reading/ClinicalData/ClinicalAnswerService.cs

566 lines
23 KiB
C#

//--------------------------------------------------------------------
// 此代码由T4模板自动生成 byzhouhang 20210918
// 生成时间 2023-06-15 15:06:06
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
//--------------------------------------------------------------------
using Microsoft.AspNetCore.Mvc;
using IRaCIS.Core.Application.Interfaces;
using IRaCIS.Core.Application.ViewModel;
using IRaCIS.Core.Application.Service.Reading.Dto;
using IRaCIS.Core.Infra.EFCore.Common;
using IRaCIS.Core.Domain.Share;
using MassTransit;
using IRaCIS.Core.Infrastructure;
using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Infrastructure.Extention;
namespace IRaCIS.Core.Application.Service
{
/// <summary>
/// 临床答案
/// </summary>
[ApiExplorerSettings(GroupName = "Reading")]
public class ClinicalAnswerService : BaseService
{
private readonly IRepository<TrialClinicalQuestion> _trialClinicalQuestionRepository;
private readonly IRepository<SystemClinicalQuestion> _systemClinicalQuestionRepository;
private readonly IRepository<SystemClinicalTableQuestion> _systemClinicalTableQuestionRepository;
private readonly IRepository<TrialClinicalTableQuestion> _trialClinicalTableQuestionRepository;
private readonly IRepository<ClinicalDataTrialSet> _clinicalDataTrialSetRepository;
private readonly IRepository<ClinicalForm> _clinicalFormRepository;
private readonly IRepository<Subject> _subjectRepository;
private readonly IRepository<ReadModuleCriterionFrom> _readModuleCriterionFromRepository;
private readonly IRepository<ReadModule> _readModuleRepository;
private readonly IRepository<ClinicalQuestionAnswer> _clinicalQuestionAnswerRepository;
private readonly IRepository<ClinicalTableAnswer> _clinicalTableAnswerRepository;
private readonly IRepository<ClinicalAnswerRowInfo> _clinicalAnswerRowInfoRepository;
private readonly IRepository<ReadingClinicalData> _readingClinicalDataRepository;
private readonly IRepository<SubjectVisit> _subjectVisitRepository;
private readonly IClinicalQuestionService _iClinicalQuestionService;
public ClinicalAnswerService(IRepository<TrialClinicalQuestion> trialClinicalQuestionRepository,
IRepository<SystemClinicalTableQuestion> systemClinicalTableQuestionRepository,
IRepository<TrialClinicalTableQuestion> trialClinicalTableQuestionRepository,
IRepository<ReadingClinicalData> readingClinicalDataRepository,
IRepository<ClinicalForm> clinicalFormRepository,
IRepository<Subject> subjectRepository,
IRepository<ReadModuleCriterionFrom> readModuleCriterionFromRepository,
IRepository<ReadModule> readModuleRepository,
IRepository<SubjectVisit> subjectVisitRepository,
IRepository<ClinicalTableAnswer> clinicalTableAnswerRepository,
IRepository<ClinicalQuestionAnswer> clinicalQuestionAnswerRepository,
IClinicalQuestionService iClinicalQuestionService,
IRepository<ClinicalAnswerRowInfo> clinicalAnswerRowInfoRepository,
IRepository<ClinicalDataTrialSet> clinicalDataTrialSetRepository,
IRepository<SystemClinicalQuestion> systemClinicalQuestionRepository
)
{
_subjectVisitRepository = subjectVisitRepository;
_readingClinicalDataRepository = readingClinicalDataRepository;
_clinicalAnswerRowInfoRepository = clinicalAnswerRowInfoRepository;
_clinicalQuestionAnswerRepository = clinicalQuestionAnswerRepository;
_systemClinicalTableQuestionRepository = systemClinicalTableQuestionRepository;
_trialClinicalQuestionRepository = trialClinicalQuestionRepository;
_trialClinicalTableQuestionRepository = trialClinicalTableQuestionRepository;
_systemClinicalQuestionRepository = systemClinicalQuestionRepository;
_clinicalDataTrialSetRepository = clinicalDataTrialSetRepository;
_clinicalFormRepository = clinicalFormRepository;
this._subjectRepository = subjectRepository;
this._readModuleCriterionFromRepository = readModuleCriterionFromRepository;
this._readModuleRepository = readModuleRepository;
_clinicalTableAnswerRepository = clinicalTableAnswerRepository;
_iClinicalQuestionService = iClinicalQuestionService;
}
/// <summary>
/// 自动添加CRC临床数据
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
public async Task AutoAddCRCClinical(AutoAddClinicalInDto inDto)
{
var dataTrialSetList = await _clinicalDataTrialSetRepository.Where(x =>x.TrialId == inDto.TrialId && x.UploadRole == UploadRole.CRC && x.IsConfirm)
.IgnoreAutoIncludes().ToListAsync();
var baseLine = await _subjectVisitRepository.Where(x => x.TrialId == inDto.TrialId)
.WhereIf(inDto.SubjectId!=null,x=>x.SubjectId==inDto.SubjectId)
.Select(x => new
{
x.SubjectId,
VisitId = x.Id,
x.IsBaseLine,
}).ToListAsync();
var clinicalDataList =await _readingClinicalDataRepository.Where(x =>x.TrialId==inDto.TrialId&&x.ClinicalDataTrialSet.UploadRole== UploadRole.CRC).IgnoreAutoIncludes().ToListAsync();
List<ReadingClinicalData> readingClinicalDatas = new List<ReadingClinicalData>();
baseLine.Select(x => x.SubjectId).Distinct().ForEach(n =>
{
var baseLineVisitId = baseLine.Where(x => x.IsBaseLine && x.SubjectId == n).Select(x => x.VisitId).First();
readingClinicalDatas.AddRange(
dataTrialSetList.Where(x => x.ClinicalDataLevel == ClinicalLevel.Subject).Where(x => clinicalDataList.Where(y => y.ClinicalDataTrialSetId == x.Id && y.SubjectId == n).Count() == 0)
.Select(x => new ReadingClinicalData()
{
ClinicalDataTrialSetId = x.Id,
IsVisit = true,
SubjectId = n,
ReadingId = baseLineVisitId,
TrialId = inDto.TrialId
}).ToList());
readingClinicalDatas.AddRange(
dataTrialSetList.Where(x => x.ClinicalDataLevel == ClinicalLevel.ImageRead).Where(x => clinicalDataList.Where(y => y.ClinicalDataTrialSetId == x.Id && y.SubjectId == n).Count() == 0)
.Select(x => new ReadingClinicalData()
{
ClinicalDataTrialSetId = x.Id,
IsVisit = false,
SubjectId = n,
ReadingId = default(Guid),
TrialId = inDto.TrialId
}).ToList());
readingClinicalDatas.AddRange(
dataTrialSetList.Where(x => x.ClinicalDataLevel == ClinicalLevel.OncologyRead).Where(x => clinicalDataList.Where(y => y.ClinicalDataTrialSetId == x.Id && y.SubjectId == n).Count() == 0)
.Select(x => new ReadingClinicalData()
{
ClinicalDataTrialSetId = x.Id,
IsVisit = false,
SubjectId = n,
ReadingId = default(Guid),
TrialId = inDto.TrialId
}).ToList());
});
baseLine.ForEach(n =>
{
readingClinicalDatas.AddRange(
dataTrialSetList.Where(x => x.ClinicalDataLevel == ClinicalLevel.SubjectVisit).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());
});
await _readingClinicalDataRepository.AddRangeAsync(readingClinicalDatas);
await _readingClinicalDataRepository.SaveChangesAsync();
}
/// <summary>
/// 获取CRC受试者临床数据
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task<List<GetCRCSubjectClinicalOutDto>> GetCRCSubjectClinicalList(GetCRCSubjectClinicalInDto inDto)
{
await AutoAddCRCClinical(new AutoAddClinicalInDto()
{
TrialId = inDto.TrialId
}) ;
var subjects = await _subjectRepository.Where(x => x.TrialId == inDto.TrialId).Select(x => new GetCRCSubjectClinicalResultDto()
{
SubjectId = x.Id,
SubjectCode = x.Code
}).ToListAsync();
var clinicalData=await _readingClinicalDataRepository.Where(x=>x.TrialId == inDto.TrialId&&x.ClinicalDataTrialSet.UploadRole==UploadRole.CRC&&x.ClinicalDataTrialSet.ClinicalDataLevel!= ClinicalLevel.SubjectVisit)
.Where(x=>!x.IsSign)
.Include(x=>x.ClinicalDataTrialSet).Select(x=>new GetCRCSubjectClinicalOutDto() {
SubjectId=x.SubjectId,
SubjectCode=x.Subject.Code,
TrialId=inDto.TrialId,
ClinicalDataTrialSetId = x.ClinicalDataTrialSet.Id,
ClinicalDataSetEnName= x.ClinicalDataTrialSet.ClinicalDataSetEnName,
ClinicalDataSetName = x.ClinicalDataTrialSet.ClinicalDataSetName,
}).OrderBy(x=>x.SubjectCode).ToListAsync();
// 一次查询报错 分两次写
clinicalData.ForEach(x =>
{
x.ClinicalDataSetEnName = x.ClinicalDataSetName.LanguageName(x.ClinicalDataSetEnName, _userInfo.IsEn_Us);
});
var clinicalFormData = await _clinicalFormRepository.Where(x => x.TrialId == inDto.TrialId).ToListAsync();
clinicalData.ForEach(n =>
{
n.ClinicalCount = clinicalFormData.Where(y => y.ClinicalDataTrialSetId == n.ClinicalDataTrialSetId && y.SubjectId == n.SubjectId).Count();
});
return clinicalData;
}
/// <summary>
/// 获取表单列表
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task<GetClinicalQuestionAnswerListOutDto> GetClinicalQuestionFormList(GetClinicalQuestionAnswerListInDto inDto)
{
var result = new GetClinicalQuestionAnswerListOutDto();
result.AnswerList = new List<Dictionary<string, string>>();
result.QuestionList=await _trialClinicalQuestionRepository.Where(x=>x.TrialClinicalId==inDto.ClinicalDataTrialSetId
&&x.ClinicalQuestionType!= ReadingQestionType.Group
&& x.ClinicalQuestionType != ReadingQestionType.Table).OrderBy(x=>x.ShowOrder)
.ProjectTo<TrialClinicalQuestionDto>(_mapper.ConfigurationProvider).ToListAsync();
var answers = await _clinicalQuestionAnswerRepository.Where(x => x.SubjectId == inDto.SubjectId && x.ClinicalDataTrialSetId == inDto.ClinicalDataTrialSetId)
.Select(x => new
{
x.ClinicalFormId,
x.ClinicalForm.CheckDate,
x.QuestionId,
x.Answer
})
.ToListAsync();
var ClinicalFormIds = answers.OrderBy(x=>x.CheckDate).Select(x => x.ClinicalFormId).Distinct().ToList();
ClinicalFormIds.ForEach(x =>
{
var dic = answers.Where(y => y.ClinicalFormId == x).ToDictionary(x => x.QuestionId.ToString(), x => x.Answer);
dic.Add("clinicalFormId", x.ToString());
result.AnswerList.Add(dic);
});
return result;
}
/// <summary>
/// 获取临床数据表单问题
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task<GetClinicalFormInfoOutDto> GetClinicalFormInfo(GetClinicalFormInfoInDto inDto)
{
var formInfo = await _clinicalFormRepository.Where(x => x.Id == inDto.ClinicalFormId).FirstNotNullAsync();
var questionAnswer = await _clinicalQuestionAnswerRepository.Where(x => x.ClinicalFormId == inDto.ClinicalFormId).Select(x => new ClinicalFormQuestionAnswer
{
QuestionId = x.QuestionId,
Answer = x.Answer
}).ToListAsync();
var tableAnswer = await _clinicalTableAnswerRepository.Where(x => x.ClinicalFormId == inDto.ClinicalFormId).Select(x => new ClinicalFormTableQuestionAnswer
{
TableQuestionId = x.TableQuestionId,
Answer = x.Answer,
QuestionId = x.QuestionId,
RowIndex = x.ClinicalAnswerRowInfo.RowIndex
}).ToListAsync();
var questions = await _trialClinicalQuestionRepository.Where(x => x.TrialClinicalId == formInfo.ClinicalDataTrialSetId)
.ProjectTo<ClinicalQuestionPreviewDto>(_mapper.ConfigurationProvider).ToListAsync();
var tableQuestions = await _trialClinicalQuestionRepository.Where(x => x.TrialClinicalId == formInfo.ClinicalDataTrialSetId)
.ProjectTo<ClinicalTablePreviewDto>(_mapper.ConfigurationProvider).ToListAsync();
var result = questions.Where(x => x.ClinicalQuestionType == ReadingQestionType.Group).ToList();
result.ForEach(x =>
{
_iClinicalQuestionService.FindChildQuestion(x, questions, tableQuestions, questionAnswer, tableAnswer);
});
return new GetClinicalFormInfoOutDto()
{
Question = result
};
}
/// <summary>
/// 提交临床数据表单
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task<IResponseOutput> SubmitClinicalForm(SubmitClinicalFormInDto inDto)
{
ClinicalForm clinicalForm = new ClinicalForm() { };
clinicalForm = new ClinicalForm()
{
ClinicalDataTrialSetId = inDto.ClinicalDataTrialSetId,
SubjectId = inDto.SubjectId,
TrialId= inDto.TrialId,
Id = inDto.ClinicalFormId ?? NewId.NextGuid(),
ReadingId = inDto.ReadingId,
VisitId = inDto.VisitId,
};
try
{
var checkDateQuestionId = await _trialClinicalQuestionRepository.Where(x => x.TrialClinicalId == inDto.ClinicalDataTrialSetId && x.IsCheckDate).Select(x => x.Id).FirstNotNullAsync();
clinicalForm.CheckDate = DateTime.Parse(inDto.QuestionAnswers.Where(x => x.QuestionId == checkDateQuestionId).Select(x => x.Answer).First());
}
catch (Exception)
{
}
List<ClinicalQuestionAnswer> clinicalQuestionAnswers = inDto.QuestionAnswers.Select(x => new ClinicalQuestionAnswer()
{
Answer=x.Answer,
ClinicalDataTrialSetId=inDto.ClinicalDataTrialSetId,
SubjectId=inDto.SubjectId,
ClinicalFormId= clinicalForm.Id,
QuestionId=x.QuestionId,
}).ToList();
List<ClinicalAnswerRowInfo> clinicalAnswerRowInfos = new List<ClinicalAnswerRowInfo>();
List<ClinicalTableAnswer> clinicalTableAnswers = new List<ClinicalTableAnswer>();
inDto.TableQuestionAnswerList.ForEach(x => {
var questionid = x.QuestionId;
for (int i = 0; i < x.TableQuestionAnswers.Count(); i++)
{
var rowInfo = new ClinicalAnswerRowInfo()
{
Id = NewId.NextGuid(),
SubjectId = inDto.SubjectId,
ClinicalFormId = clinicalForm.Id,
QuestionId = questionid,
RowIndex = i+1,
};
clinicalAnswerRowInfos.Add(rowInfo);
x.TableQuestionAnswers[i].ForEach(y => {
clinicalTableAnswers.Add(new ClinicalTableAnswer()
{
Answer=y.Answer,
ClinicalFormId= clinicalForm.Id,
QuestionId= questionid,
RowId= rowInfo.Id,
TableQuestionId=y.TableQuestionId,
SubjectId= inDto.SubjectId,
});
});
}
});
if (inDto.ClinicalFormId != null)
{
await _clinicalFormRepository.BatchDeleteNoTrackingAsync(x => x.Id == inDto.ClinicalFormId);
await _clinicalQuestionAnswerRepository.BatchDeleteNoTrackingAsync(x => x.ClinicalFormId == inDto.ClinicalFormId);
await _clinicalAnswerRowInfoRepository.BatchDeleteNoTrackingAsync(x => x.ClinicalFormId == inDto.ClinicalFormId);
await _clinicalTableAnswerRepository.BatchDeleteNoTrackingAsync(x => x.ClinicalFormId == inDto.ClinicalFormId);
}
await _clinicalFormRepository.AddAsync(clinicalForm);
await _clinicalQuestionAnswerRepository.AddRangeAsync(clinicalQuestionAnswers);
await _clinicalAnswerRowInfoRepository.AddRangeAsync(clinicalAnswerRowInfos);
await _clinicalTableAnswerRepository.AddRangeAsync(clinicalTableAnswers);
await _clinicalTableAnswerRepository.SaveChangesAsync();
return ResponseOutput.Ok(true);
}
/// <summary>
/// 获取CRC确认列表
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task<List<GetCRCConfirmListOutDto>> GetCRCConfirmList(GetCRCConfirmListInDto inDto)
{
List<GetCRCConfirmListOutDto> result = await _readModuleRepository.Where(x => x.TrialId == inDto.TrialId)
.Select(x => new GetCRCConfirmListOutDto()
{
SubjectId= x.SubjectId,
IsCRCConfirm = x.IsCRCConfirm,
LatestScanDate = x.SubjectVisit.LatestScanDate,
ReadingSetType = x.ReadingSetType,
IsPMConfirm = x.IsPMConfirm,
ReadModuleId = x.Id,
}).OrderBy(x => x.LatestScanDate).ToListAsync();
var formList = await _clinicalFormRepository.Where(x => x.TrialId == inDto.TrialId)
.Where(x => x.ClinicalDataTrialSet.UploadRole == UploadRole.CRC)
.Where(x => x.ClinicalDataTrialSet.ClinicalDataLevel == ClinicalLevel.ImageRead || x.ClinicalDataTrialSet.ClinicalDataLevel == ClinicalLevel.OncologyRead)
.Select(x => new CRCClinicalForm
{
CkeckDate = x.CheckDate,
ClinicalDataLevel = x.ClinicalDataTrialSet.ClinicalDataLevel,
ClinicalFormId = x.Id,
}).ToListAsync();
var confirmList = await _readModuleCriterionFromRepository.Where(x => x.TrialId == inDto.TrialId).ToListAsync();
result.ForEach(x =>
{
if (x.IsCRCConfirm)
{
x.ClinicalFormIdList = confirmList.Where(y => y.ReadModuleId == x.ReadModuleId).Select(y=>y.ClinicalFormId).ToList();
}
else
{
if (x.ReadingSetType == ReadingSetType.ImageReading)
{
x.ClinicalFormIdList = formList.Where(y => y.ClinicalDataLevel == ClinicalLevel.ImageRead&&y.CkeckDate<=x.LatestScanDate).Select(y => y.ClinicalFormId).ToList();
}
else
{
x.ClinicalFormIdList = formList.Where(y => y.ClinicalDataLevel == ClinicalLevel.OncologyRead&&y.CkeckDate <= x.LatestScanDate).Select(y => y.ClinicalFormId).ToList();
}
}
});
return result;
}
/// <summary>
/// CRC 确认临床数据
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task<IResponseOutput> CRCConfirmClinical(CRCConfirmClinicalInDto inDto)
{
var dataList =await this.GetCRCConfirmList(new GetCRCConfirmListInDto()
{
TrialId = inDto.TrialId
});
var presentData = dataList.Where(x => x.ReadModuleId == inDto.ReadModuleId).First();
var confirmlist= dataList.Where(x =>(x.LatestScanDate < presentData.LatestScanDate && x.ReadingSetType == presentData.ReadingSetType)
|| x.ReadModuleId == presentData.ReadModuleId).Where(x => !x.IsCRCConfirm).ToList();
List<ReadModuleCriterionFrom> needAddList = new List<ReadModuleCriterionFrom>()
{
};
confirmlist.ForEach(x =>
{
x.ClinicalFormIdList.ForEach(y =>
{
needAddList.Add(new ReadModuleCriterionFrom()
{
ClinicalFormId = y,
ReadModuleId = x.ReadModuleId,
SubjectId = x.SubjectId,
TrialId = inDto.TrialId,
});
});
});
var readModuleIds = confirmlist.Select(x => x.ReadModuleId).ToList();
await _readModuleRepository.UpdatePartialFromQueryAsync(x => readModuleIds.Contains(x.Id),x=>new ReadModule() {
IsCRCConfirm=true
});
await _readModuleCriterionFromRepository.AddRangeAsync(needAddList);
await _readModuleCriterionFromRepository.SaveChangesAsync();
return ResponseOutput.Ok(true);
}
/// <summary>
/// CRC 取消确认
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
[HttpPost]
public async Task<IResponseOutput> CRCCancelConfirmClinical(CRCCancelConfirmClinicalInDto inDto)
{
var dataList = await this.GetCRCConfirmList(new GetCRCConfirmListInDto()
{
TrialId = inDto.TrialId
});
var presentData = dataList.Where(x => x.ReadModuleId == inDto.ReadModuleId).First();
if (dataList.Any(x => x.IsPMConfirm && x.LatestScanDate > presentData.LatestScanDate && x.ReadingSetType == presentData.ReadingSetType))
{
throw new BusinessValidationFailedException("当前数据并非最后一条确认信息,无法取消!");
}
if(presentData.IsPMConfirm)
{
throw new BusinessValidationFailedException("PM已确认,无法取消!");
}
await _readModuleRepository.UpdatePartialFromQueryAsync(x => presentData.ReadModuleId==x.Id, x => new ReadModule()
{
IsCRCConfirm = false
});
await _readModuleCriterionFromRepository.BatchDeleteNoTrackingAsync(x=>x.ReadModuleId== presentData.ReadModuleId);
await _readModuleCriterionFromRepository.SaveChangesAsync();
return ResponseOutput.Ok(true);
}
/// <summary>
/// PM确认临床数据
/// </summary>
/// <param name="inDto"></param>
/// <returns></returns>
/// <exception cref="BusinessValidationFailedException"></exception>
[HttpPost]
public async Task<IResponseOutput> PMConfirmClinical(CRCConfirmClinicalInDto inDto)
{
var readModuleData = await _readModuleRepository.Where(x => x.Id == inDto.ReadModuleId).FirstNotNullAsync();
if (!readModuleData.IsCRCConfirm)
{
throw new BusinessValidationFailedException("CRC还未确认数据,PM无法确认");
}
await _readModuleRepository.UpdatePartialFromQueryAsync(x => inDto.ReadModuleId == x.Id, x => new ReadModule()
{
IsPMConfirm = false
});
await _readModuleRepository.SaveChangesAsync();
return ResponseOutput.Ok(true);
}
}
}