using AutoMapper; using IRaCIS.Core.Application.MediatR.CommandAndQueries; using IRaCIS.Core.Domain.Share; using MediatR; using System.Linq.Expressions; using System.Text; namespace IRaCIS.Core.Application.MediatR.Handlers { public class ConsistencyVerificationHandler : IRequestHandler { private readonly IRepository _studyRepository; private readonly IUserInfo _userInfo; private readonly IRepository _subjectRepository; private readonly IRepository _subjectVisitRepository; private readonly IRepository _trialSiteRepository; private readonly IMapper _mapper; private readonly IRepository _noneDicomStudyRepository; /// /// 构造函数注入 /// public ConsistencyVerificationHandler(IRepository studyRepository, IUserInfo userInfo, IRepository subjectRepository, IRepository subjectVisitRepository, IRepository trialSiteRepository, IRepository noneDicomStudyRepository, IMapper mapper) { _noneDicomStudyRepository = noneDicomStudyRepository; _studyRepository = studyRepository; _userInfo = userInfo; _subjectRepository = subjectRepository; _subjectVisitRepository = subjectVisitRepository; _trialSiteRepository = trialSiteRepository; _mapper = mapper; } async Task IRequestHandler.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> 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> 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.Modalities, 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()); //处理数据库 大小写 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>(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(); foreach (var sv in svGroup) { //找到etc 当前visit site 和subject 一致的检查列表 var etcVisitStudyList = etcList.Where(t => t.SubjectCode == sv.SubjectCode && t.SiteCode == sv.SiteCode && t.VisitName == sv.VisitName).ToList(); var dbVisitStudyList = dbCheckList.Where(t => t.SubjectCode == sv.SubjectCode && t.SiteCode == sv.SiteCode && t.VisitName == sv.VisitName).ToList(); StringBuilder dialogMsg = new StringBuilder(); dialogMsg.Append("您好,根据本系统自动识别,该受试者当前访视已提交的影像检查情况如下:"); var num = 0; foreach (var item in sv.StudyList) { num++; dialogMsg.AppendLine($"
{num}.{item.StudyDate}的{item.Modality}影像检查"); } var dbSV = (await _subjectVisitRepository.FirstOrDefaultAsync(t => t.Id == sv.SubjectVisitId)).IfNullThrowException(); if (etcVisitStudyList.Count == 0) { dialogMsg.AppendLine($"
"); dialogMsg.AppendLine($"
存在问题如下:"); num = 0; foreach (var item in sv.StudyList) { num++; dialogMsg.AppendLine($"
{num}.{item.StudyDate}  {item.Modality} 在导入文件中不存在"); } dialogMsg.AppendLine($"
"); dialogMsg.AppendLine(@$"
说明:为高效解决/处理以上全部质疑问题,麻烦您准确核实实际影像检查情况。请注意影像日期与实际检查的日期可能会不一致,部分检查(如PET -CT)可能同时存在多种模态影像。准确核实后,请回复该访视正确的影像检查情况。"); dbSV.CheckResult = "当前访视在EDC表中未找到数据,请核对 SubjectCode、 SiteCode 、VisitName 是否和ETC系统保持一致"; 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(), UserTypeEnum = (UserTypeEnum)_userInfo.UserTypeEnumInt,CreateTime=DateTime.Now }); } else { //etc 和数据库 并集 var unionList = dbVisitStudyList.Union(etcVisitStudyList); // 数据库存在 var dbExceptExcel = dbVisitStudyList.Except(etcVisitStudyList); // excel 存在 var excelExceptDB = etcVisitStudyList.Except(dbCheckList); //两者没有差别 if (dbExceptExcel.Count() == 0 && excelExceptDB.Count()==0) { dialogMsg.AppendLine($"
"); dialogMsg.AppendLine($"核对EDC数据,完全一致, 审核通过"); // dialogMsg.AppendLine(@$"
说明:为高效解决/处理以上全部质疑问题,麻烦您准确核实实际影像检查情况。请注意影像日期与实际检查的日期可能会不一致,部分检查(如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 = sv.SubjectVisitId, TalkContent = dialogMsg.ToString(), UserTypeEnum = (UserTypeEnum)_userInfo.UserTypeEnumInt, CreateTime = DateTime.Now }); } else { dialogMsg.AppendLine($"
"); dialogMsg.AppendLine($"
存在问题如下:"); num = 0; foreach (var item in dbExceptExcel) { num++; dialogMsg.AppendLine($"
{num}.EDC 缺少{item.StudyDate}的{item.Modality}影像检查 "); } foreach (var item in excelExceptDB) { num++; dialogMsg.AppendLine($"
{num}.IRC 缺少{item.StudyDate}的{item.Modality}影像检查 "); } dialogMsg.AppendLine($"
"); dialogMsg.AppendLine(@$"
说明:为高效解决/处理以上全部质疑问题,麻烦您准确核实实际影像检查情况。请注意影像日期与实际检查的日期可能会不一致,部分检查(如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; //讲核查结果发送消息给CRC dbSV.CheckChallengeDialogList.Add(new CheckChallengeDialog() { SubjectVisitId = sv.SubjectVisitId, IsCRCNeedReply = true, TalkContent = dialogMsg.ToString(), UserTypeEnum = (UserTypeEnum)_userInfo.UserTypeEnumInt, CreateTime = DateTime.Now }); } } dbSV.CheckTime = DateTime.Now; } await _subjectVisitRepository.SaveChangesAsync(); return "OK"; } } }