EI-Image-Viewer-Api/IRaCIS.Core.Application/_MediatR/Handlers/ConsistencyVerificationHand...

270 lines
15 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 AutoMapper;
using IRaCIS.Core.Application.MediatR.CommandAndQueries;
using IRaCIS.Core.Domain.Share;
using Newtonsoft.Json;
using MediatR;
using System.Linq.Expressions;
using System.Text;
namespace IRaCIS.Core.Application.MediatR.Handlers
{
public class ConsistencyVerificationHandler : IRequestHandler<ConsistencyVerificationRequest, string>
{
private readonly IRepository<DicomStudy> _studyRepository;
private readonly IUserInfo _userInfo;
private readonly IRepository<Subject> _subjectRepository;
private readonly IRepository<SubjectVisit> _subjectVisitRepository;
private readonly IRepository<TrialSite> _trialSiteRepository;
private readonly IMapper _mapper;
private readonly IRepository<NoneDicomStudy> _noneDicomStudyRepository;
/// <summary>
/// 构造函数注入
/// </summary>
public ConsistencyVerificationHandler(IRepository<DicomStudy> studyRepository, IUserInfo userInfo,
IRepository<Subject> subjectRepository, IRepository<SubjectVisit> subjectVisitRepository,
IRepository<TrialSite> trialSiteRepository, IRepository<NoneDicomStudy> noneDicomStudyRepository,
IMapper mapper)
{
_noneDicomStudyRepository = noneDicomStudyRepository;
_studyRepository = studyRepository;
_userInfo = userInfo;
_subjectRepository = subjectRepository;
_subjectVisitRepository = subjectVisitRepository;
_trialSiteRepository = trialSiteRepository;
_mapper = mapper;
}
async Task<string> IRequestHandler<ConsistencyVerificationRequest, string>.Handle(ConsistencyVerificationRequest request, CancellationToken cancellationToken)
{
var trialId = request.TrialId;
//处理Excel大小写
request.ETCList.ForEach(t => { t.Modality = t.Modality.ToUpper().Trim(); t.StudyDate = Convert.ToDateTime(t.StudyDate).ToString("yyyy-MM-dd"); t.SiteCode = t.SiteCode.ToUpper().Trim(); t.VisitName = t.VisitName.ToUpper().Trim(); t.SubjectCode = t.SubjectCode.ToUpper().Trim(); });
var etcList = request.ETCList;
//Expression<Func<SubjectVisit, bool>> subjectVisitLambda2 = x => x.TrialId == request.TrialId;
//subjectVisitLambda2= subjectVisitLambda2.And(x => x.CheckState == CheckStateEnum.ToCheck && x.AuditState == AuditStateEnum.QCPassed || (x.CheckState == CheckStateEnum.CVIng && x.AuditState == AuditStateEnum.QCPassed));
Expression<Func<SubjectVisit, bool>> subjectVisitLambda = x => x.TrialId == request.TrialId &&
(x.CheckState == CheckStateEnum.ToCheck && x.AuditState == AuditStateEnum.QCPassed || (x.CheckState == CheckStateEnum.CVIng && x.AuditState == AuditStateEnum.QCPassed));
var dicomQuery = from sv in _subjectVisitRepository.Where(subjectVisitLambda)
join trialSite in _trialSiteRepository.Where(t => t.TrialId == trialId) on sv.SiteId equals trialSite.SiteId
join subject in _subjectRepository.AsQueryable() on sv.SubjectId equals subject.Id
join study in _studyRepository.AsQueryable() on sv.Id equals study.SubjectVisitId
select new CheckDBModel()
{
SubjectVisitId = sv.Id,
SiteCode = trialSite.TrialSiteCode,
StudyDate = study.StudyTime == null ? string.Empty : ((DateTime)study.StudyTime).ToString("yyyy-MM-dd"),
StudyId = study.Id,
Modality = study.ModalityForEdit,
SubjectCode = subject.Code,
VisitName = sv.VisitName,
};
var noneDicomQuey = from sv in _subjectVisitRepository.Where(subjectVisitLambda)
join trialSite in _trialSiteRepository.Where(t => t.TrialId == trialId) on sv.SiteId equals trialSite.SiteId
join subject in _subjectRepository.AsQueryable() on sv.SubjectId equals subject.Id
join noneDicomStudy in _noneDicomStudyRepository.AsQueryable() on sv.Id equals noneDicomStudy.SubjectVisitId
select new CheckDBModel()
{
SubjectVisitId = sv.Id,
SiteCode = trialSite.TrialSiteCode,
StudyDate = noneDicomStudy.ImageDate.ToString("yyyy-MM-dd"),
StudyId = noneDicomStudy.Id,
Modality = noneDicomStudy.Modality,
SubjectCode = subject.Code,
VisitName = sv.VisitName,
};
var dbList = (await dicomQuery.ToListAsync()).Union(await noneDicomQuey.ToListAsync()).ToList();
//处理数据库 大小写
dbList.ForEach(t => { t.Modality = t.Modality.ToUpper().Trim(); t.SiteCode = t.SiteCode.ToUpper().Trim(); t.VisitName = t.VisitName.ToUpper().Trim(); t.SubjectCode = t.SubjectCode.ToUpper().Trim(); });
var dbCheckList = _mapper.Map<List<CheckViewModel>>(dbList);
////按照数据库数据检查批次分组 按照数据库的数据 一个个的检查批次对比
//var svGroup = dbList.GroupBy(t => new { t.SubjectVisitId, t.SiteCode, t.SubjectCode, t.VisitName })
// .Select(g => new { g.Key.SubjectCode, g.Key.VisitName, g.Key.SiteCode, g.Key.SubjectVisitId, StudyList = g.ToList() }).ToList();
//按照Excel数据检查批次分组 按照数据库的数据 一个个的检查批次对比
var svExcelGroup = etcList.GroupBy(t => new { t.SiteCode, t.SubjectCode, t.VisitName })
.Select(g => new { g.Key.SubjectCode, g.Key.VisitName, g.Key.SiteCode, ExcelStudyList = g.ToList() }).ToList();
foreach (var sv in svExcelGroup)
{
//Excel 的数据 在IRC 中可以找到该检查批次
if (dbCheckList.Any(t => t.SubjectCode == sv.SubjectCode && t.SiteCode == sv.SiteCode && t.VisitName == sv.VisitName))
{
var dbVisitStudyList = dbList.Where(t => t.SubjectCode == sv.SubjectCode && t.SiteCode == sv.SiteCode && t.VisitName == sv.VisitName).ToList();
//找到etc 当前visit site 和subject 一致的检查列表
var etcVisitStudyList = etcList.Where(t => t.SubjectCode == sv.SubjectCode && t.SiteCode == sv.SiteCode && t.VisitName == sv.VisitName).ToList();
StringBuilder dialogMsg = new StringBuilder();
dialogMsg.Append("您好,根据本系统自动识别该患者当前检查批次在IRC系统中已提交的影像检查情况如下");
var num = 0;
List<ParamInfoDto> paramInfoList = new List<ParamInfoDto>();
foreach (var item in dbVisitStudyList)
{
num++;
dialogMsg.AppendLine($"<br>{num}.{item.StudyDate}的{item.Modality}影像检查");
paramInfoList.Add(new ParamInfoDto()
{
Modality = item.Modality,
StudyDate = item.StudyDate,
});
}
var subjectVisitId = dbVisitStudyList.FirstOrDefault().SubjectVisitId;
var dbSV = (await _subjectVisitRepository.FirstOrDefaultAsync(t => t.Id == subjectVisitId)).IfNullThrowException();
#region 更换核对的顺序 以Excel 数据为准 注释
//// 该检查批次 在EDC Excel中没有任何数据
//if (etcVisitStudyList.Count == 0)
//{
// dialogMsg.AppendLine($"<br/>");
// dialogMsg.AppendLine($"<br><span style='color: #f00'>存在问题如下:</span>");
// num = 0;
// foreach (var item in sv.StudyList)
// {
// num++;
// dialogMsg.AppendLine($"<br>{num}.{item.StudyDate}的{item.Modality}影像检查(EDC 缺少) ");
// }
// dialogMsg.AppendLine($"<br/>");
// dialogMsg.AppendLine(@$"<br>说明:为高效解决/处理以上全部质疑问题麻烦您准确核实实际影像检查情况。请注意影像日期与实际检查的日期可能会不一致部分检查如PET -CT)可能同时存在多种模态影像。准确核实后,请回复该检查批次正确的影像检查情况。");
// dbSV.CheckResult = "当前检查批次在EDC表中未找到数据,请核对 SubjectCode、 SiteCode 、VisitName 是否和EDC系统保持一致";
// dbSV.CheckState = CheckStateEnum.CVIng;
// dbSV.ForwardState = ForwardStateEnum.ToForward;
// dbSV.CheckChallengeState = CheckChanllengeTypeEnum.PMWaitCRCReply;
// dbSV.CheckChallengeDialogList.Add(new CheckChallengeDialog()
// {
// SubjectVisitId = sv.SubjectVisitId,
// IsCRCNeedReply = true,
// TalkContent = dialogMsg.ToString(),
// ParamInfo = JsonConvert.SerializeObject(paramInfoList),
// UserTypeEnum = (UserTypeEnum)_userInfo.UserTypeEnumInt,
// CreateTime = DateTime.Now
// });
//}
//else
#endregion
{
//etc 和数据库 并集
var unionList = dbVisitStudyList.Union(etcVisitStudyList);
// 数据库存在
var dbExceptExcel = dbVisitStudyList.Except(etcVisitStudyList);
// excel 存在
var excelExceptDB = etcVisitStudyList.Except(dbCheckList);
//ETC 和系统的完全一致 两者没有差别
if (dbExceptExcel.Count() == 0 && excelExceptDB.Count() == 0)
{
dialogMsg.AppendLine($"<br/>");
dialogMsg.AppendLine($"核对EDC数据完全一致, 审核通过");
// dialogMsg.AppendLine(@$"<br>说明:为高效解决/处理以上全部质疑问题麻烦您准确核实实际影像检查情况。请注意影像日期与实际检查的日期可能会不一致部分检查如PET -CT)可能同时存在多种模态影像。准确核实后,请回复该检查批次正确的影像检查情况。");
dbSV.CheckState = CheckStateEnum.CVPassed;
dbSV.CheckUserId = _userInfo.Id;
dbSV.CheckPassedTime = DateTime.Now;
dbSV.CheckResult = "核对EDC数据完全一致";
dbSV.ManualPassReason = "自动核查通过";
//维护状态
dbSV.ReadingStatus = ReadingStatusEnum.TaskAllocate;
dbSV.RequestBackState = dbSV.RequestBackState == RequestBackStateEnum.CRC_RequestBack ? RequestBackStateEnum.PM_NotAgree : RequestBackStateEnum.NotRequest;
dbSV.CheckChallengeDialogList.Add(new CheckChallengeDialog()
{
SubjectVisitId = subjectVisitId,
ParamInfo = JsonConvert.SerializeObject(paramInfoList),
TalkContent = dialogMsg.ToString(),
UserTypeEnum = (UserTypeEnum)_userInfo.UserTypeEnumInt,
CreateTime = DateTime.Now
});
}
// ETC 和系统的有区别
else
{
dialogMsg.AppendLine($"<br/>");
dialogMsg.AppendLine($"<br><span style='color: #f00'>存在问题如下:</span>");
num = 0;
foreach (var item in dbExceptExcel)
{
num++;
dialogMsg.AppendLine($"<br>{num}.{item.StudyDate}的{item.Modality}影像检查(EDC 缺少) ");
}
foreach (var item in excelExceptDB)
{
num++;
dialogMsg.AppendLine($"<br>{num}.{item.StudyDate}的{item.Modality}影像检查(IRC 缺少) ");
}
dialogMsg.AppendLine($"<br/>");
dialogMsg.AppendLine(@$"<br>说明:为高效解决/处理以上全部质疑问题麻烦您准确核实实际影像检查情况。请注意影像日期与实际检查的日期可能会不一致部分检查如PET -CT)可能同时存在多种模态影像。准确核实后,请回复该检查批次正确的影像检查情况。");
dbSV.CheckResult = "根据导入的一致性核查数据,请确认本检查批次以下不一致检查项信息:" + String.Join(" | ", dbExceptExcel.Select(t => $"EDC 缺少:{t.StudyDate} {t.Modality} ")) + " | "
+ String.Join(" | ", excelExceptDB.Select(t => $"IRC 缺少:{t.StudyDate} {t.Modality}"));
//新增一致性核查质疑记录
dbSV.CheckState = CheckStateEnum.CVIng;
dbSV.CheckChallengeState = CheckChanllengeTypeEnum.PMWaitCRCReply;
//讲核查结果发送消息给IC
dbSV.CheckChallengeDialogList.Add(new CheckChallengeDialog()
{
SubjectVisitId = subjectVisitId,
IsCRCNeedReply = true,
TalkContent = dialogMsg.ToString(),
ParamInfo = JsonConvert.SerializeObject(paramInfoList),
UserTypeEnum = (UserTypeEnum)_userInfo.UserTypeEnumInt,
CreateTime = DateTime.Now
});
}
}
dbSV.CheckTime = DateTime.Now;
}
}
await _subjectVisitRepository.SaveChangesAsync();
return "OK";
}
}
}