using IRaCIS.Core.Domain; using IRaCIS.Core.Domain._DomainEvent; using IRaCIS.Core.Domain.BaseModel; using IRaCIS.Core.Domain.Models; using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Infrastructure.Extention; using Microsoft.EntityFrameworkCore.ChangeTracking; using Newtonsoft.Json; using Org.BouncyCastle.Asn1.Cmp; namespace IRaCIS.Core.Infra.EFCore; public static class DBContext_Ext { public static void AddDomainEvents(this DbContext context) { var dbContext = (IRaCISDBContext)context; var changeTracker = context.ChangeTracker; //记录要保存到数据库的事件 var eventStoreList = new List(); #region 中心调研邮件通知 foreach (var entry in changeTracker.Entries()) { var trialSiteSurvey = entry.Entity; var originState = entry.Property(p => p.State).OriginalValue; //状态从待提交 变为CRC提交||SPM 提交 (驳回也会变为已提交,所以必须设置前置状态是待提交) if ((trialSiteSurvey.State == TrialSiteSurveyEnum.CRCSubmitted || trialSiteSurvey.State == TrialSiteSurveyEnum.SPMApproved) && originState == TrialSiteSurveyEnum.ToSubmit) { trialSiteSurvey.AddDomainEvent(new UserSiteSurveySubmitedEvent() { TrialSiteSurveyId = trialSiteSurvey.Id }); } //SPM CPM 提交的时候 else if (trialSiteSurvey.State == TrialSiteSurveyEnum.SPMApproved && originState == TrialSiteSurveyEnum.CRCSubmitted) { trialSiteSurvey.AddDomainEvent(new SiteSurveySPMSubmitedEvent() { TrialSiteSurveyId = trialSiteSurvey.Id }); } //PM 驳回 else if ((trialSiteSurvey.State == TrialSiteSurveyEnum.CRCSubmitted || trialSiteSurvey.State == TrialSiteSurveyEnum.ToSubmit) && originState == TrialSiteSurveyEnum.SPMApproved) { trialSiteSurvey.AddDomainEvent(new SiteSurverRejectedEvent() { TrialSiteSurveyId = trialSiteSurvey.Id, IsHaveSPMOrCPM = trialSiteSurvey.State == TrialSiteSurveyEnum.CRCSubmitted }); } //SPM 驳回 else if (trialSiteSurvey.State == TrialSiteSurveyEnum.ToSubmit && originState == TrialSiteSurveyEnum.CRCSubmitted) { trialSiteSurvey.AddDomainEvent(new SiteSurverRejectedEvent() { TrialSiteSurveyId = trialSiteSurvey.Id, IsHaveSPMOrCPM = true }); } //添加进记录 eventStoreList.AddRange(GetStoreEvents(trialSiteSurvey.DomainEvents)); } #endregion #region PD 入组发送邮件(不侵入之前的代码,有些判断过于复杂的,在代码里面有的,就手动 在跟踪的实体添加领域事件) foreach (var entry in changeTracker.Entries()) { var subjectVisit = entry.Entity; var originSubmitState = entry.Property(p => p.SubmitState).OriginalValue; var originAuditState = entry.Property(p => p.AuditState).OriginalValue; var originCheckState = entry.Property(p => p.CheckState).OriginalValue; var originCurrentActionUserId = entry.Property(p => p.CurrentActionUserId).OriginalValue; var originRequestBackState = entry.Property(p => p.RequestBackState).OriginalValue; //入组或者PD 才执行下面的逻辑 if ((subjectVisit.IsEnrollmentConfirm || subjectVisit.PDState == PDStateEnum.PDProgress)) { //质控状态变为待审核的时候 if (originSubmitState == SubmitStateEnum.ToSubmit && subjectVisit.SubmitState == SubmitStateEnum.Submitted && originAuditState == AuditStateEnum.None && subjectVisit.AuditState == AuditStateEnum.ToAudit ) { subjectVisit.AddDomainEvent(new CRCSubmitedAndQCToAuditEvent() { SubjectVisitId = subjectVisit.Id, IsPd = subjectVisit.PDState == PDStateEnum.PDProgress }); } //一致性核查通知PM发送邮件 if (originCheckState == CheckStateEnum.None && subjectVisit.CheckState == CheckStateEnum.ToCheck ) { subjectVisit.AddDomainEvent(new CheckStateChangedToAuditEvent() { IsPd = subjectVisit.PDState == PDStateEnum.PDProgress, SubjectVisitId = subjectVisit.Id }); } if (originCurrentActionUserId == null && subjectVisit.CurrentActionUserId != null) { var businessEnum = subjectVisit.IsEnrollmentConfirm ? EmailBusinessScenario.EligibilityVerification_PendingImageQC : EmailBusinessScenario.PDVerification_PendingImageQC; var delaySeconds = dbContext.TrialEmailNoticeConfig.Where(t => t.TrialId == subjectVisit.TrialId && t.BusinessScenarioEnum == businessEnum) .Select(t => t.EmailDelaySeconds).FirstOrDefault(); Console.WriteLine("qc领取任务:" + DateTime.Now.ToShortTimeString() + $"延时{delaySeconds}"); if (delaySeconds > 0) { subjectVisit.AddDomainEvent(new QCClaimTaskEvent() { IsPd = subjectVisit.PDState == PDStateEnum.PDProgress, SubjectVisitId = subjectVisit.Id, DelaySeconds = delaySeconds, CurrentActionUserId = (Guid)subjectVisit.CurrentActionUserId }); } } } // 重传影像 //CRC 申请 || PM审批的时候 if ((originRequestBackState == RequestBackStateEnum.NotRequest && subjectVisit.RequestBackState == RequestBackStateEnum.CRC_RequestBack) || (originRequestBackState == RequestBackStateEnum.CRC_RequestBack && subjectVisit.RequestBackState != RequestBackStateEnum.CRC_RequestBack)) { subjectVisit.AddDomainEvent(new CheckReuploadEvent() { RequestBackState = subjectVisit.RequestBackState, SubjectVisitId = subjectVisit.Id }); } //PM 直接退回任务 if ((originSubmitState == SubmitStateEnum.Submitted && subjectVisit.SubmitState == SubmitStateEnum.ToSubmit) && (originAuditState == AuditStateEnum.QCPassed && subjectVisit.AuditState == AuditStateEnum.None) && (originCheckState == CheckStateEnum.CVPassed && subjectVisit.CheckState == CheckStateEnum.None)) { subjectVisit.AddDomainEvent(new UnReadVisitTaskReReadingApproval() { SubjectVisitId = subjectVisit.Id }); } if (subjectVisit.DomainEvents.Count > 0) { //添加进记录 eventStoreList.AddRange(GetStoreEvents(subjectVisit.DomainEvents)); } } foreach (var entry in changeTracker.Entries()) { var qCChallenge = entry.Entity; var originReuploadEnum = entry.Property(p => p.ReuploadEnum).OriginalValue; var findSubjectVisit = dbContext.SubjectVisit.Where(t => t.Id == qCChallenge.SubjectVisitId) .Select(t => new { IsEnrollmentConfirm = t.IsEnrollmentConfirm, PDState = t.PDState, t.Id, t.TrialId }).FirstOrDefault().IfNullThrowException(); //入组或者PD 才执行下面的逻辑 if ((findSubjectVisit.IsEnrollmentConfirm || findSubjectVisit.PDState == PDStateEnum.PDProgress)) { if (entry.State == EntityState.Added) { qCChallenge.AddDomainEvent(new QCRepliedQCChallengeEvent() { IsPd = findSubjectVisit.PDState == PDStateEnum.PDProgress, QCChallengeId = qCChallenge.Id, SubjectVisitId = findSubjectVisit.Id, TrialId = findSubjectVisit.TrialId }); } } //重传影像 if ( //CRC 申请 (originReuploadEnum == QCChanllengeReuploadEnum.None && qCChallenge.ReuploadEnum == QCChanllengeReuploadEnum.CRCRequestReupload) || //同意申请 (originReuploadEnum == QCChanllengeReuploadEnum.CRCRequestReupload && qCChallenge.ReuploadEnum == QCChanllengeReuploadEnum.QCAgreeUpload)) { qCChallenge.AddDomainEvent(new QCChanllengeReuploadEvent() { SubjectVisitId = findSubjectVisit.Id, ReuploadEnum = qCChallenge.ReuploadEnum }); } if (qCChallenge.DomainEvents.Count > 0) { //添加进记录 eventStoreList.AddRange(GetStoreEvents(qCChallenge.DomainEvents)); } } foreach (var entry in changeTracker.Entries()) { var qCChallengeDialog = entry.Entity; var findSubjectVisit = dbContext.SubjectVisit.Where(t => t.Id == qCChallengeDialog.SubjectVisitId) .Select(t => new { IsEnrollmentConfirm = t.IsEnrollmentConfirm, PDState = t.PDState, t.Id, t.TrialId }).FirstOrDefault().IfNullThrowException(); //入组或者PD 才执行下面的逻辑 if ((findSubjectVisit.IsEnrollmentConfirm || findSubjectVisit.PDState == PDStateEnum.PDProgress)) { //CRC 针对质控质疑进行回复 if (entry.State == EntityState.Added && qCChallengeDialog.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator) { qCChallengeDialog.AddDomainEvent(new CRCRepliedQCChallengeEvent() { IsPd = findSubjectVisit.PDState == PDStateEnum.PDProgress, QCChallengeDialogId = qCChallengeDialog.Id, SubjectVisitId = findSubjectVisit.Id, TrialId = findSubjectVisit.TrialId }); } //QC 针对质控质疑进行回复 else if (entry.State == EntityState.Added && qCChallengeDialog.UserTypeEnum == UserTypeEnum.IQC) { qCChallengeDialog.AddDomainEvent(new QCRepliedQCChallengeEvent() { IsPd = findSubjectVisit.PDState == PDStateEnum.PDProgress, QCChallengeDialogId = qCChallengeDialog.Id, SubjectVisitId = findSubjectVisit.Id, TrialId = findSubjectVisit.TrialId }); } //添加进记录 eventStoreList.AddRange(GetStoreEvents(qCChallengeDialog.DomainEvents)); } } foreach (var entry in changeTracker.Entries()) { var checkChallengeDialog = entry.Entity; var findSubjectVisit = dbContext.SubjectVisit.Where(t => t.Id == checkChallengeDialog.SubjectVisitId) .Select(t => new { IsEnrollmentConfirm = t.IsEnrollmentConfirm, PDState = t.PDState, t.Id, t.TrialId }).FirstOrDefault().IfNullThrowException(); //入组或者PD 才执行下面的逻辑 if ((findSubjectVisit.IsEnrollmentConfirm || findSubjectVisit.PDState == PDStateEnum.PDProgress)) { //CRC 针对质控质疑进行回复 if (entry.State == EntityState.Added && checkChallengeDialog.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator) { checkChallengeDialog.AddDomainEvent(new CRCRepliedCheckChallengeEvent() { IsPd = findSubjectVisit.PDState == PDStateEnum.PDProgress, CheckChallengeDialogId = checkChallengeDialog.Id, SubjectVisitId = findSubjectVisit.Id, TrialId = findSubjectVisit.TrialId }); } else if (entry.State == EntityState.Added && checkChallengeDialog.UserTypeEnum == UserTypeEnum.ProjectManager) { checkChallengeDialog.AddDomainEvent(new PMRepliedCheckChallengeEvent() { IsPd = findSubjectVisit.PDState == PDStateEnum.PDProgress, CheckChallengeDialogId = checkChallengeDialog.Id, SubjectVisitId = findSubjectVisit.Id, TrialId = findSubjectVisit.TrialId }); } //添加进记录 eventStoreList.AddRange(GetStoreEvents(checkChallengeDialog.DomainEvents)); } } //医学审核任务 foreach (var entry in changeTracker.Entries()) { var taskMedicalReview = entry.Entity; if (entry.State == EntityState.Added) { var findVisitTask = dbContext.VisitTask.Where(t => t.Id == taskMedicalReview.VisitTaskId).Select(t => new { t.SourceSubjectVisitId, t.SouceReadModuleId }).FirstOrDefault().IfNullThrowException(); var findSubjectVisit = new EnrollmentConfirmAndPD(); if (findVisitTask.SourceSubjectVisitId != null) { findSubjectVisit = dbContext.SubjectVisit.Where(t => t.Id == findVisitTask.SourceSubjectVisitId) .Select(t => new EnrollmentConfirmAndPD { IsEnrollmentConfirm = t.IsEnrollmentConfirm, PDState = t.PDState }).FirstOrDefault(); } else { var subjectVisitId = dbContext.ReadModule.Where(t => t.Id == findVisitTask.SouceReadModuleId).Select(t => t.SubjectVisitId).FirstOrDefault(); findSubjectVisit = dbContext.SubjectVisit.Where(t => t.Id == subjectVisitId) .Select(t => new EnrollmentConfirmAndPD { IsEnrollmentConfirm = t.IsEnrollmentConfirm, PDState = t.PDState }).FirstOrDefault(); } //入组或者PD 才执行下面的逻辑 if (findSubjectVisit.IsEnrollmentConfirm || findSubjectVisit.PDState == PDStateEnum.PDProgress) { taskMedicalReview.AddDomainEvent(new UrgentMedicalReviewAddedEvent() { IsPD = findSubjectVisit.PDState == PDStateEnum.PDProgress, MedicalReviewId = taskMedicalReview.Id, VisitTaskId = taskMedicalReview.VisitTaskId }); //添加进记录 eventStoreList.AddRange(GetStoreEvents(taskMedicalReview.DomainEvents)); } } } //医学反馈 foreach (var entry in changeTracker.Entries()) { var readingMedicalReviewDialog = entry.Entity; var findVisitTask = dbContext.VisitTask.Where(t => t.Id == readingMedicalReviewDialog.VisitTaskId).Select(t => new { t.SourceSubjectVisitId, t.SouceReadModuleId }).FirstOrDefault().IfNullThrowException(); var findSubjectVisit = new EnrollmentConfirmAndPD(); if (findVisitTask.SourceSubjectVisitId != null) { findSubjectVisit = dbContext.SubjectVisit.Where(t => t.Id == findVisitTask.SourceSubjectVisitId) .Select(t => new EnrollmentConfirmAndPD { IsEnrollmentConfirm = t.IsEnrollmentConfirm, PDState = t.PDState }).FirstOrDefault(); } else { var subjectVisitId = dbContext.ReadModule.Where(t => t.Id == findVisitTask.SouceReadModuleId).Select(t => t.SubjectVisitId).FirstOrDefault(); findSubjectVisit = dbContext.SubjectVisit.Where(t => t.Id == subjectVisitId) .Select(t => new EnrollmentConfirmAndPD { IsEnrollmentConfirm = t.IsEnrollmentConfirm, PDState = t.PDState }).FirstOrDefault(); } //入组或者PD 才执行下面的逻辑 if (findSubjectVisit.IsEnrollmentConfirm || findSubjectVisit.PDState == PDStateEnum.PDProgress) { if (entry.State == EntityState.Added && readingMedicalReviewDialog.UserTypeEnumInt == (int)UserTypeEnum.MIM) { readingMedicalReviewDialog.AddDomainEvent(new UrgentMIMRepliedMedicalReview() { MedicalReviewId = readingMedicalReviewDialog.TaskMedicalReviewId, ReadingMedicalReviewDialogId = readingMedicalReviewDialog.Id }); } else if (entry.State == EntityState.Added && readingMedicalReviewDialog.UserTypeEnumInt == (int)UserTypeEnum.IndependentReviewer) { readingMedicalReviewDialog.AddDomainEvent(new UrgentIRRepliedMedicalReview() { IsPD = findSubjectVisit.PDState == PDStateEnum.PDProgress, MedicalReviewId = readingMedicalReviewDialog.TaskMedicalReviewId, ReadingMedicalReviewDialogId = readingMedicalReviewDialog.Id }); } //添加进记录 eventStoreList.AddRange(GetStoreEvents(readingMedicalReviewDialog.DomainEvents)); } } //任务 申请重阅ReReadingApplyState foreach (var entry in changeTracker.Entries()) { var visitTask = entry.Entity; var originReReadingApplyState = entry.Property(p => p.ReReadingApplyState).OriginalValue; if (originReReadingApplyState == ReReadingApplyState.Default && (visitTask.ReReadingApplyState == ReReadingApplyState.DocotorHaveApplyed || visitTask.ReReadingApplyState == ReReadingApplyState.TrialGroupHaveApplyed)) { var findSubjectVisit = new EnrollmentConfirmAndPD(); if (visitTask.SourceSubjectVisitId != null) { findSubjectVisit = dbContext.SubjectVisit.Where(t => t.Id == visitTask.SourceSubjectVisitId) .Select(t => new EnrollmentConfirmAndPD { IsEnrollmentConfirm = t.IsEnrollmentConfirm, PDState = t.PDState }).FirstOrDefault(); } else { var subjectVisitId = dbContext.ReadModule.Where(t => t.Id == visitTask.SouceReadModuleId).Select(t => t.SubjectVisitId).FirstOrDefault(); findSubjectVisit = dbContext.SubjectVisit.Where(t => t.Id == subjectVisitId) .Select(t => new EnrollmentConfirmAndPD { IsEnrollmentConfirm = t.IsEnrollmentConfirm, PDState = t.PDState }).FirstOrDefault(); } //入组或者PD 才执行下面的逻辑 if (findSubjectVisit.IsEnrollmentConfirm || findSubjectVisit.PDState == PDStateEnum.PDProgress) { visitTask.AddDomainEvent(new UrgentApplyedReReading() { VisitTaskId = visitTask.Id, ReReadingApplyState = visitTask.ReReadingApplyState }); } visitTask.AddDomainEvent(new HaveReadVisitTaskReReading() { SubjectId=visitTask.SubjectId, VisitTaskId = visitTask.Id, ReReadingApplyState = visitTask.ReReadingApplyState }); } if ((originReReadingApplyState == ReReadingApplyState.DocotorHaveApplyed || originReReadingApplyState == ReReadingApplyState.TrialGroupHaveApplyed) && (visitTask.ReReadingApplyState == ReReadingApplyState.Agree || visitTask.ReReadingApplyState == ReReadingApplyState.Reject)) { visitTask.AddDomainEvent(new HaveReadVisitTaskReReading() { SubjectId = visitTask.SubjectId, VisitTaskId = visitTask.Id, ReReadingApplyState = visitTask.ReReadingApplyState }); } if (visitTask.DomainEvents.Count > 0) { //添加进记录 eventStoreList.AddRange(GetStoreEvents(visitTask.DomainEvents)); } } #endregion #region 直接申请流程重传 foreach (var entry in changeTracker.Entries()) { var subjectVisitImageBackRecord = entry.Entity; var originApplyUserRole = entry.Property(p => p.ApplyUserRole).OriginalValue; var originImageBackState = entry.Property(p => p.ImageBackState).OriginalValue; if ( //申请的时候 (subjectVisitImageBackRecord.ImageBackState == ImageBackStateEnum.None && (subjectVisitImageBackRecord.ApplyUserRole == ImageBackApplyEnum.IQCRequestBack || subjectVisitImageBackRecord.ApplyUserRole == ImageBackApplyEnum.CRCRequestBack)) || //审核完成的时候 (originImageBackState == ImageBackStateEnum.None && subjectVisitImageBackRecord.ImageBackState != ImageBackStateEnum.None) ) { subjectVisitImageBackRecord.AddDomainEvent(new DirectApplyReupdloadEvent() { SubjectVisitId = subjectVisitImageBackRecord.SubjectVisitId, ApplyUserRole = subjectVisitImageBackRecord.ApplyUserRole, ImageBackState = subjectVisitImageBackRecord.ImageBackState }); } if (subjectVisitImageBackRecord.DomainEvents.Count > 0) { //添加进记录 eventStoreList.AddRange(GetStoreEvents(subjectVisitImageBackRecord.DomainEvents)); } } #endregion #region 阅片人筛选 var spmApproveEnrollIdList = new List(); var pmApplyEnrollIdList = new List(); Enroll lastEnroll = null; foreach (var entry in changeTracker.Entries()) { var enroll = entry.Entity; var originEnrollStatus = entry.Property(p => p.EnrollStatus).OriginalValue; if (originEnrollStatus == EnrollStatus.HasCommittedToCRO && enroll.EnrollStatus == EnrollStatus.InviteIntoGroup) { spmApproveEnrollIdList.Add(enroll.Id); lastEnroll = enroll; } if (originEnrollStatus == EnrollStatus.HasApplyDownloadResume && enroll.EnrollStatus == EnrollStatus.HasCommittedToCRO) { pmApplyEnrollIdList.Add(enroll.Id); lastEnroll = enroll; } } if (spmApproveEnrollIdList.Count > 0) { lastEnroll.AddDomainEvent(new ReviewerSPMApprovedEvent() { TrialId= lastEnroll.TrialId, EnrollIdList = spmApproveEnrollIdList }); eventStoreList.AddRange(GetStoreEvents(lastEnroll.DomainEvents)); } if (pmApplyEnrollIdList.Count > 0) { lastEnroll.AddDomainEvent(new ReviewerPMApplyEvent() { TrialId = lastEnroll.TrialId, EnrollIdList = spmApproveEnrollIdList }); eventStoreList.AddRange(GetStoreEvents(lastEnroll.DomainEvents)); } #endregion //跟随事务一起保存数据库 dbContext.EventStoreRecord.AddRange(eventStoreList); } private static List GetStoreEvents(IReadOnlyCollection domainEvents) { return domainEvents.Select(t => new EventStoreRecord() { Id = t.EventId, EventType = t.GetType().AssemblyQualifiedName, EventTypeName = t.GetType().Name, EventData = t.ToJsonStr() }).ToList(); } public class EnrollmentConfirmAndPD { public bool IsEnrollmentConfirm { get; set; } public PDStateEnum PDState { get; set; } } #region 暂时废弃 /// /// 暂时废弃,没有场景使用 /// /// public static void AddDomainCommands(this DbContext context) { var changeTracker = context.ChangeTracker; //遍历 ChangeTracker 中的实体 //foreach (var entry in changeTracker.Entries()) //{ // var userLog = entry.Entity; // if (entry.State == EntityState.Added) // { // // 受试者添加 触发访视自动添加 // var addCommand = new AddUserLogTriggerCommand { UserLog=userLog }; // userLog.AddDomainCommand(addCommand); // } //} //foreach (var entry in changeTracker.Entries()) //{ // var subject = entry.Entity; // if (entry.State == EntityState.Added) // { // // 受试者添加 触发访视自动添加 // var addedEvent = new AddSubjectTriggerCommand { SubjectId = subject.Id, TrialId = subject.TrialId, TrialSiteId = subject.TrialSiteId }; // subject.AddDomainCommand(addedEvent); // } //} } #endregion }