using IRaCIS.Application.Interfaces; using IRaCIS.Core.Application.Contracts; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using IRaCIS.Core.Domain.Share; using EasyCaching.Core; using IRaCIS.Core.Infrastructure; using Microsoft.AspNetCore.Authorization; using IRaCIS.Core.Application.Auth; using Panda.DynamicWebApi.Attributes; using IRaCIS.Core.Infra.EFCore.Common; using IRaCIS.Core.Application.Service.Reading.Dto; using IRaCIS.Core.Application.Interfaces; using IRaCIS.Core.Application.ViewModel; using MassTransit; using IRaCIS.Core.Application.Filter; using static IRaCIS.Core.Domain.Share.StaticData; namespace IRaCIS.Core.Application { [ApiExplorerSettings(GroupName = "Trial")] public class TrialConfigService : BaseService, ITrialConfigService { private readonly IRepository _trialRepository; private readonly IRepository _trialQCQuestionRepository; private readonly IRepository _readingQuestionCriterionTrialRepository; private readonly IRepository _readingQuestionTrialRepository; private readonly IRepository _readingQuestionCriterionSystemRepository; private readonly IRepository _clinicalDataTrialSetRepository; private readonly IRepository _readingCriterionPageRepository; private readonly IEasyCachingProvider _provider; private readonly IOrganInfoService _iOrganInfoService; private readonly IRepository _taskAllocationRuleRepository; private readonly IRepository _readingCriterionDictionaryRepository; private readonly IReadingQuestionService iReadingQuestionService; private readonly IRepository _readingTaskQuestionAnswer; private readonly IRepository _visitTaskRepository; private readonly IRepository _readingTableQuestionAnswerRepository; private readonly IRepository _readingTableAnswerRowInfoRepository; private readonly IRepository _readingTableQuestionTrialRepository; public TrialConfigService(IRepository trialRepository, IRepository trialQCQuestionRepository, IRepository readingQuestionCriterionTrialRepository, IRepository readingQuestionTrialRepository, IRepository readingQuestionCriterionSystemRepository, IRepository clinicalDataTrialSetRepository, IRepository readingCriterionPageRepository, IRepository taskAllocationRuleRepository, IRepository readingCriterionDictionaryRepository, IReadingQuestionService iReadingQuestionService, IEasyCachingProvider provider, IOrganInfoService iOrganInfoService, IRepository visitTaskRepository, IRepository readingTableQuestionTrialRepository, IRepository readingTableQuestionAnswerRepository, IRepository readingTableAnswerRowInfoRepository, IRepository readingTaskQuestionAnswer ) { _trialRepository = trialRepository; _taskAllocationRuleRepository = taskAllocationRuleRepository; this._readingCriterionDictionaryRepository = readingCriterionDictionaryRepository; this.iReadingQuestionService = iReadingQuestionService; this._trialQCQuestionRepository = trialQCQuestionRepository; this._readingQuestionCriterionTrialRepository = readingQuestionCriterionTrialRepository; this._readingQuestionTrialRepository = readingQuestionTrialRepository; this._readingQuestionCriterionSystemRepository = readingQuestionCriterionSystemRepository; this._clinicalDataTrialSetRepository = clinicalDataTrialSetRepository; this._provider = provider; this._iOrganInfoService = iOrganInfoService; this._readingTableQuestionTrialRepository = readingTableQuestionTrialRepository; this._readingCriterionPageRepository = readingCriterionPageRepository; this._visitTaskRepository = visitTaskRepository; this._readingTableQuestionAnswerRepository = readingTableQuestionAnswerRepository; this._readingTableAnswerRowInfoRepository = readingTableAnswerRowInfoRepository; this._readingTaskQuestionAnswer = readingTaskQuestionAnswer; } /// /// 阅片信息签名验证接口 /// /// /// /// [HttpPost] public async Task TrialReadingInfoSignVerify(TrialReadingInfoSignInDto inDto) { var trialCriterion = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == inDto.TrialReadingCriterionId).FirstOrDefaultAsync(); var existsJudge = await _readingQuestionTrialRepository.Where(x => x.ReadingQuestionCriterionTrialId == trialCriterion.Id && x.IsJudgeQuestion && x.JudgeType == JudgeTypeEnum.None) .WhereIf(trialCriterion.FormType == FormType.SinglePage, x => x.ReadingCriterionPageId == null) .WhereIf(trialCriterion.FormType == FormType.MultiplePage, x => x.ReadingCriterionPageId != null) .AnyAsync(); if (existsJudge&& trialCriterion.IsArbitrationReading) { throw new BusinessValidationFailedException("有裁判问题未配置产生裁判阅片任务的条件,操作失败!"); } return ResponseOutput.Ok(true); } /// /// 获取项目已经确认的标准 /// /// [HttpPost] public async Task> GetTrialConfirmCriterionList(GetTrialConfirmCriterionListInDto inDto) { List result = await _readingQuestionCriterionTrialRepository.Where(x => x.TrialId == inDto.TrialId && x.IsConfirm) .Select(x => new GetTrialConfirmCriterionOutDto() { TrialCriterionId = x.Id, CriterionName = x.CriterionName }).ToListAsync(); return result; } /// /// 阅片信息签名 /// /// /// [NonDynamicMethod] public async Task TrialReadingInfoSign(TrialReadingInfoSignInDto inDto) { var trialCriterion = await _readingQuestionCriterionTrialRepository.Where(x => x.Id==inDto.TrialReadingCriterionId).FirstOrDefaultAsync(); var existsJudge = await _readingQuestionTrialRepository.Where(x => x.ReadingQuestionCriterionTrialId == trialCriterion.Id && x.IsJudgeQuestion && x.JudgeType == JudgeTypeEnum.None) .WhereIf(trialCriterion.FormType == FormType.SinglePage, x => x.ReadingCriterionPageId == null) .WhereIf(trialCriterion.FormType == FormType.MultiplePage, x => x.ReadingCriterionPageId != null) .AnyAsync(); if (existsJudge&& trialCriterion.IsArbitrationReading) { throw new BusinessValidationFailedException("有裁判问题未配置产生裁判阅片任务的条件,操作失败!"); } await _readingQuestionCriterionTrialRepository.UpdatePartialFromQueryAsync(x => x.Id == inDto.TrialReadingCriterionId, x => new ReadingQuestionCriterionTrial() { ReadingInfoSignTime = DateTime.Now }); var result = await _trialRepository.SaveChangesAsync(); return ResponseOutput.Ok(result); } /// /// 获取项目阅片信息 /// /// /// [HttpPost] public async Task GetCriterionReadingInfo(GetTrialReadingInfoInDto inDto) { GetTrialReadingInfoOutDto trialInfo= await _readingQuestionCriterionTrialRepository.Where(x=>x.Id==inDto.TrialReadingCriterionId).ProjectTo(_mapper.ConfigurationProvider).FirstNotNullAsync(); if (trialInfo.ReadingTool == null) { trialInfo.ReadingTool = ReadingTool.Dicom; } return trialInfo; } /// /// 同步项目标准字典信息 /// /// /// [HttpPost] public async Task AsyncTrialCriterionDictionary(AsyncTrialCriterionDictionaryInDto inDto) { var trialCriterion = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == inDto.TrialReadingCriterionId).FirstNotNullAsync(); if (trialCriterion.ReadingQuestionCriterionSystemId != null) { await _readingCriterionDictionaryRepository.BatchDeleteNoTrackingAsync(x => x.CriterionId == trialCriterion.Id); var criterionDictionaryList = await _readingCriterionDictionaryRepository.Where(x => x.CriterionId == trialCriterion.ReadingQuestionCriterionSystemId.Value) .ToListAsync(); criterionDictionaryList.ForEach(x => { x.Id = NewId.NextGuid(); x.Dictionary = null; x.IsSystemCriterion = false; x.CriterionId = inDto.TrialReadingCriterionId; }); if (trialCriterion.SynchronizeOriginalTime == null ) { // 同步器官 await _iOrganInfoService.SynchronizeSystemOrganToTrial(new SynchronizeSystemOrganToTrialInDto() { TrialReadingCriterionId = inDto.TrialReadingCriterionId, SystemCriterionId = trialCriterion.ReadingQuestionCriterionSystemId }); // 同步问题 await iReadingQuestionService.SynchronizeCriterion(new SynchronizeCriterionInDto() { TrialReadingCriterionId = inDto.TrialReadingCriterionId, }); // 清除多余答案 var questionQuery = _readingQuestionTrialRepository.Where(x => x.ReadingQuestionCriterionTrialId == inDto.TrialReadingCriterionId).AsQueryable(); var tableQuestionQuery = _readingTableQuestionTrialRepository.Where(x => x.TrialCriterionId == inDto.TrialReadingCriterionId).AsQueryable(); await _readingTaskQuestionAnswer.BatchDeleteNoTrackingAsync(x => questionQuery.Count(y => y.Id == x.ReadingQuestionTrialId) == 0) ; await _readingTableAnswerRowInfoRepository.BatchDeleteNoTrackingAsync(x => questionQuery.Count(y => y.Id == x.QuestionId)==0); await _readingTableQuestionAnswerRepository.BatchDeleteNoTrackingAsync(x => tableQuestionQuery.Count(y => y.Id == x.TableQuestionId)==0); var systemCriterion = await _readingQuestionCriterionSystemRepository.Where(x => x.Id == trialCriterion.ReadingQuestionCriterionSystemId).FirstNotNullAsync(); await _readingQuestionCriterionTrialRepository.BatchUpdateNoTrackingAsync(x => x.Id == inDto.TrialReadingCriterionId, x => new ReadingQuestionCriterionTrial() { IsOncologyReading = systemCriterion.IsOncologyReading, IseCRFShowInDicomReading=systemCriterion.IseCRFShowInDicomReading, }); } await _readingCriterionDictionaryRepository.AddRangeAsync(criterionDictionaryList); await _readingQuestionCriterionTrialRepository.BatchUpdateNoTrackingAsync(x => x.Id == inDto.TrialReadingCriterionId, x => new ReadingQuestionCriterionTrial() { SynchronizeOriginalTime = DateTime.Now }); await _readingCriterionDictionaryRepository.SaveChangesAsync(); } return ResponseOutput.Ok(true); } /// /// 修改全局阅片配置信息 /// /// /// [HttpPost] [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })] public async Task SetGlobalReadingInfo(SetGlobalReadingInfoInDto inDto) { //await _readingQuestionCriterionTrialRepository.UpdatePartialFromQueryAsync(inDto.TrialReadingCriterionId, x => new ReadingQuestionCriterionTrial() //{ // IsGlobalReading = inDto.IsGlobalReading //}); await _readingCriterionDictionaryRepository.BatchDeleteNoTrackingAsync(x => x.CriterionId == inDto.TrialReadingCriterionId && x.ParentCode == ReadingCommon.CriterionDictionary.GlobalAssess); await _readingCriterionDictionaryRepository.AddRangeAsync(inDto.GlobalAssessList.Select(x => new ReadingCriterionDictionary { CriterionId = inDto.TrialReadingCriterionId, DictionaryId = x.DictionaryId, IsBaseLineUse=x.IsBaseLineUse, IsFollowVisitUse=x.IsFollowVisitUse, IsSystemCriterion = false, ParentCode = ReadingCommon.CriterionDictionary.GlobalAssess })); var result= await _readingCriterionDictionaryRepository.SaveChangesAsync(); return ResponseOutput.Ok(result); } /// /// 获取全局阅片信息 /// /// /// [HttpPost] public async Task GetGlobalReadingInfo(GetOncologySetInDto inDto) { var trialCriterion = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == inDto.TrialReadingCriterionId).FirstNotNullAsync(); GetGlobalReadingOutDto result = new GetGlobalReadingOutDto() { IsGlobalReading = trialCriterion.IsGlobalReading, IsSystemCriterion= trialCriterion.ReadingQuestionCriterionSystemId!=null, IsSign=trialCriterion.ReadingInfoSignTime!=null, GlobalAssessTypes = await _readingCriterionDictionaryRepository.Where(x => x.CriterionId == inDto.TrialReadingCriterionId && x.ParentCode == ReadingCommon.CriterionDictionary.GlobalAssess ) .Select(x => new CriterionDictionaryInfo() { Id = x.Id, DictionaryId = x.DictionaryId, ChildGroup = x.Dictionary.ChildGroup, IsBaseLineUse = x.IsBaseLineUse, IsFollowVisitUse = x.IsFollowVisitUse, Code = x.Dictionary.Code, Description = x.Dictionary.Description, ShowOrder = x.Dictionary.ShowOrder, ParentCode = x.Dictionary.Parent.Code, Value = x.Dictionary.Value, ValueCN = x.Dictionary.ValueCN }).OrderBy(x => x.ParentCode).ThenBy(x => x.ShowOrder).ToListAsync() }; return result; } /// /// 获取项目肿瘤学配置 /// /// /// [HttpPost] public async Task GetOncologySet(GetOncologySetInDto inDto) { var trialCriterion = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == inDto.TrialReadingCriterionId).FirstNotNullAsync(); return new GetOncologySetOutDto { EvaluationReason = trialCriterion.EvaluationReason.IsNullOrEmpty()? ReadingCommon.EvaluationReason : trialCriterion.EvaluationReason, OncologyAssessIds = await _readingCriterionDictionaryRepository.Where(x => x.CriterionId == inDto.TrialReadingCriterionId && x.ParentCode == ReadingCommon.CriterionDictionary.OncologyAssess).Select(x => x.DictionaryId).ToListAsync(), IsSystemCriterion= trialCriterion.ReadingQuestionCriterionSystemId!=null, IsSign = trialCriterion.ReadingInfoSignTime != null, }; } /// /// 设置项目肿瘤学配置 /// /// /// [HttpPost] [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })] public async Task SetOncologySet(SetOncologySetInDto inDto) { await _readingQuestionCriterionTrialRepository.UpdatePartialFromQueryAsync(inDto.TrialReadingCriterionId, x => new ReadingQuestionCriterionTrial() { EvaluationResult = inDto.EvaluationResult, EvaluationReason = inDto.EvaluationReason, IsShowDetail=inDto.IsShowDetail, }); await _readingCriterionDictionaryRepository.BatchDeleteNoTrackingAsync(x => x.CriterionId == inDto.TrialReadingCriterionId && x.ParentCode == ReadingCommon.CriterionDictionary.OncologyAssess); await _readingCriterionDictionaryRepository.AddRangeAsync(inDto.OncologyAssessIds.Select(x => new ReadingCriterionDictionary { CriterionId = inDto.TrialReadingCriterionId, DictionaryId = x, IsSystemCriterion = false, ParentCode = ReadingCommon.CriterionDictionary.OncologyAssess })); var result = await _readingQuestionCriterionTrialRepository.SaveChangesAsync(); return ResponseOutput.Ok(result); } /// /// 获取项目裁判信息 /// /// /// [HttpPost] public async Task<(List,object)> GetTrialReadingJudgeList(GetTrialReadingInfoInDto inDto) { var trialCriterion = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == inDto.TrialReadingCriterionId).FirstOrDefaultAsync(); var judgeQuestionList= await _readingQuestionTrialRepository .WhereIf(trialCriterion.FormType==FormType.SinglePage,x=>x.ReadingCriterionPageId==null) .WhereIf(trialCriterion.FormType == FormType.MultiplePage, x => x.ReadingCriterionPageId != null) .Where(x => x.ReadingQuestionCriterionTrial.IsConfirm && x.IsJudgeQuestion && x.TrialId == inDto.TrialId&&x.ReadingQuestionCriterionTrialId== trialCriterion.Id) .Select(x => new TrialJudgeQuestion() { AnswerCombination = x.AnswerCombination, AnswerGroup = x.AnswerGroup, JudgeType = x.JudgeType, QuestionId = x.Id, PageName=x.ReadingCriterionPage.PageName, QuestionName = x.QuestionName.LanguageName(x.QuestionEnName, _userInfo.IsEn_Us), ReadingQuestionCriterionTrialId = x.ReadingQuestionCriterionTrialId }).ToListAsync(); return (judgeQuestionList, new { IsSign= trialCriterion.ReadingInfoSignTime!= null, }); } /// /// 获取项目标准分页信息 /// /// /// [HttpPost] public async Task> GetReadingCriterionPageList(GetTrialReadingInfoInDto inDto) { return await _readingCriterionPageRepository.Where(x => x.TrialId == inDto.TrialId).ProjectTo(_mapper.ConfigurationProvider).ToListAsync(); } /// /// 获取项目阅片标准信息 /// /// /// [HttpPost] public async Task GetTrialReadingCriterionInfo(GetTrialReadingInfoInDto inDto) { GetTrialReadingCriterionInfoOutDto result = new GetTrialReadingCriterionInfoOutDto(); result.ReadingCriterionPageList = await _readingCriterionPageRepository.Where(x => x.TrialId == inDto.TrialId).ProjectTo(_mapper.ConfigurationProvider).OrderBy(x=>x.ShowOrder).ToListAsync(); var trialCriterion = await _readingQuestionCriterionTrialRepository.Where(x => x.Id==inDto.TrialReadingCriterionId).FirstOrDefaultAsync(); result.ReadingInfoSignTime = trialCriterion.ReadingInfoSignTime; result.DigitPlaces = trialCriterion.DigitPlaces; result.TrialCriterionId = trialCriterion.Id; result.FormType = trialCriterion.FormType; result.IsFromSystem = trialCriterion.ReadingQuestionCriterionSystemId != null; result.IsMustGlobalReading = trialCriterion.IsMustGlobalReading; result.IsSystemCriterion = trialCriterion.ReadingQuestionCriterionSystemId != null; result.TrialQuestionList = await _readingQuestionTrialRepository.Where(x => x.ReadingQuestionCriterionTrial.IsConfirm && x.TrialId == inDto.TrialId&&x.ReadingQuestionCriterionTrialId == result.TrialCriterionId &&x.ReadingCriterionPageId==null) .ProjectTo(_mapper.ConfigurationProvider).OrderBy(x => x.ShowOrder).ToListAsync(); return result; } /// /// 设置项目阅片标准 /// /// [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })] public async Task SetTrialReadingCriterion(SetTrialReadingCriterionInDto inDto) { if (inDto.IsSignSave) { var criterionFormType = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == inDto.TrialReadingCriterionId).Select(x => x.FormType).FirstOrDefaultAsync(); var count = _readingQuestionTrialRepository.Where(x => x.ReadingQuestionCriterionTrialId == inDto.TrialReadingCriterionId) .WhereIf(criterionFormType == FormType.SinglePage, x => x.ReadingCriterionPageId == null) .WhereIf(criterionFormType == FormType.MultiplePage, x => x.ReadingCriterionPageId != null).Count(); if (count == 0) { throw new BusinessValidationFailedException("当前标准下未配置问题"); } } await _readingQuestionCriterionTrialRepository.UpdatePartialFromQueryAsync(inDto.TrialReadingCriterionId, x => new ReadingQuestionCriterionTrial() { FormType = inDto.FormType, }); var result = await _trialRepository.SaveChangesAsync(); return ResponseOutput.Ok(result); } /// /// 设置项目阅片信息 /// /// /// [HttpPost] [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })] public async Task SetCriterionReadingInfo(SetCriterionReadingInfoInDto inDto) { ArbitrationRule arbitration = ArbitrationRule.NA; if (inDto.IsArbitrationReading) { arbitration = inDto.IsReadingPeriod ? ArbitrationRule.Reading : ArbitrationRule.Visit; } await _readingQuestionCriterionTrialRepository.UpdatePartialFromQueryAsync(inDto.TrialReadingCriterionId, x => new ReadingQuestionCriterionTrial() { ReadingTool=inDto.ReadingTool, IsReadingPeriod=inDto.IsReadingPeriod, //DigitPlaces=inDto.DigitPlaces, IsReadingTaskViewInOrder =inDto.IsReadingTaskViewInOrder, ReadingTaskViewEnum = inDto.ReadingTaskViewEnum, DigitPlaces= inDto.DigitPlaces, //IsImageIabeled = inDto.IsImageIabeled, IsReadingShowSubjectInfo = inDto.IsReadingShowSubjectInfo, IsReadingShowPreviousResults = inDto.IsReadingShowPreviousResults, GlobalUpdateType=inDto.GlobalUpdateType, ImagePlatform=inDto.ImagePlatform, IseCRFShowInDicomReading=inDto.IseCRFShowInDicomReading, ArbitrationRule= arbitration, ReadingType = inDto.ReadingType, IsGlobalReading = inDto.IsGlobalReading, IsArbitrationReading = inDto.IsArbitrationReading, IsOncologyReading = inDto.IsOncologyReading, }); var result = await _readingQuestionCriterionTrialRepository.SaveChangesAsync(); return ResponseOutput.Ok(result); } /// /// 获取签名文本 /// /// /// [HttpGet("{signCode}")] public async Task GetSignText(string signCode) { var signRawText = await _repository.Where(t => t.Code == signCode).Select(t => new { t.Code, t.Value, t.ValueCN, t.Id, ParentValue = t.Parent.Value, ParentValueCN = t.Parent.ValueCN }).FirstOrDefaultAsync(); if (signRawText == null) { return ResponseOutput.NotOk("该操作需要电子签名确认,但未在系统中找到该场景的签名模板。"); } return ResponseOutput.Ok(new { SignCodeId = signRawText.Id, SignCode = signRawText.Code, SignText = _userInfo.IsEn_Us? signRawText.ParentValue.Replace("xxx", signRawText.Value) : signRawText.ParentValueCN.Replace("xxx", signRawText.ValueCN), //SignTextCN = signRawText.ParentValueCN.Replace("xxx", signRawText.Value) }); } //验证 仅仅在 Initializing/Ongoing 才可以操作 private async Task VerifyOnlyInOngoingOrInitialIzingOptAsync(Guid trialId) { if (!await _trialRepository.AnyAsync(t => t.Id == trialId && (t.TrialStatusStr == StaticData.TrialState.TrialInitializing || t.TrialStatusStr == StaticData.TrialState.TrialOngoing))) { throw new BusinessValidationFailedException("该项目已结束或停止,不允许修改配置。"); } } /// /// 验证签名确认 /// /// /// /// [HttpPost] public async Task VerifyTrialConfigSignatureConfirm(SignConfirmDTO signConfirmDTO) { var trialConfig = (await _trialRepository .Select(t => new { TrialId = t.Id, t.QCProcessEnum, t.IsImageConsistencyVerification }) .FirstOrDefaultAsync(t => t.TrialId == signConfirmDTO.TrialId)) .IfNullThrowException(); var showOrderList = await _repository.Where(t => t.TrialId == signConfirmDTO.TrialId).Select(t => new { t.ShowOrder, ParentShowOrder = (int?)t.ParentQCQuestion.ShowOrder }).ToListAsync(); if (trialConfig.QCProcessEnum == TrialQCProcess.DoubleAudit || trialConfig.QCProcessEnum == TrialQCProcess.SingleAudit) { if (showOrderList.Count == 0) { throw new BusinessValidationFailedException("当前未添加影像质控审核问题。请先添加影像质控审核问题,再进行确认。"); } } if (showOrderList.Count() != showOrderList.Select(t => t.ShowOrder).Distinct().Count()) { throw new BusinessValidationFailedException("影像质控审核问题显示序号不能重复。"); } if (showOrderList.Where(t => t.ParentShowOrder != null).Any(t => t.ParentShowOrder > t.ShowOrder)) { throw new BusinessValidationFailedException("父问题的显示序号要比子问题的显示序号小,请确认。"); } if (await _trialRepository.AnyAsync(t => t.Id == signConfirmDTO.TrialId && t.QCQuestionConfirmedUserId != null && t.QCQuestionConfirmedUserId != _userInfo.Id)) { throw new BusinessValidationFailedException("影像质控审核问题已被其他人员确认,不允许再次确认。"); } return ResponseOutput.Ok(); } /// /// 签名确认 包括项目的三组配置 + QC问题确认 后修改状态 (适用于不会回退的,项目废除、状态修改, 存在回退 不在这里弄,提供单独接口修改状态) /// /// [Authorize(Policy = IRaCISPolicy.PM_APM)] public async Task TrialConfigSignatureConfirm(SignConfirmDTO signConfirmDTO) { await VerifyOnlyInOngoingOrInitialIzingOptAsync(signConfirmDTO.TrialId); if (signConfirmDTO.SignCode == ((int)SignEnum.TrialLogicConfim).ToString()) { await _trialRepository.UpdatePartialFromQueryAsync(t => t.Id == signConfirmDTO.TrialId, u => new Trial() { IsTrialBasicLogicConfirmed = true }); } else if (signConfirmDTO.SignCode == ((int)SignEnum.TrialProcessConfim).ToString()) { await _trialRepository.UpdatePartialFromQueryAsync(t => t.Id == signConfirmDTO.TrialId, u => new Trial() { IsTrialProcessConfirmed = true }); } else if (signConfirmDTO.SignCode == ((int)SignEnum.TrialUrgentConfim).ToString()) { await _trialRepository.UpdatePartialFromQueryAsync(t => t.Id == signConfirmDTO.TrialId, u => new Trial() { IsTrialUrgentConfirmed = true }); } else if (signConfirmDTO.SignCode == ((int)SignEnum.TrialQCQuestionConfirm).ToString()) { var trialConfig = (await _trialRepository .Select(t => new { TrialId = t.Id, t.QCProcessEnum, t.IsImageConsistencyVerification }) .FirstOrDefaultAsync(t => t.TrialId == signConfirmDTO.TrialId)) .IfNullThrowException(); var showOrderList = await _repository.Where(t => t.TrialId == signConfirmDTO.TrialId).Select(t => new { t.ShowOrder, ParentShowOrder = (int?)t.ParentQCQuestion.ShowOrder }).ToListAsync(); if (trialConfig.QCProcessEnum == TrialQCProcess.DoubleAudit || trialConfig.QCProcessEnum == TrialQCProcess.SingleAudit) { if (showOrderList.Count == 0) { throw new BusinessValidationFailedException("当前未添加影像质控审核问题。请先添加影像质控审核问题,再进行确认。"); } } if (showOrderList.Count() != showOrderList.Select(t => t.ShowOrder).Distinct().Count()) { throw new BusinessValidationFailedException("影像质控审核问题显示序号不能重复。"); } if (showOrderList.Where(t => t.ParentShowOrder != null).Any(t => t.ParentShowOrder > t.ShowOrder)) { throw new BusinessValidationFailedException("父问题的显示序号要比子问题的显示序号小,请确认。"); } if (await _trialRepository.AnyAsync(t => t.Id == signConfirmDTO.TrialId && t.QCQuestionConfirmedUserId != null && t.QCQuestionConfirmedUserId != _userInfo.Id)) { throw new BusinessValidationFailedException("影像质控审核问题已被其他人员确认,不允许再次确认。"); } await _trialQCQuestionRepository.UpdatePartialFromQueryAsync(t => t.TrialId == signConfirmDTO.TrialId, x => new TrialQCQuestion { IsConfirm = true }); await _trialRepository.UpdatePartialFromQueryAsync(t => t.Id == signConfirmDTO.TrialId, u => new Trial() { QCQuestionConfirmedTime = DateTime.Now, QCQuestionConfirmedUserId = _userInfo.Id, IsQCQuestionConfirmed = true }); await _trialRepository.SaveChangesAsync(); } return ResponseOutput.Ok(); } /// /// 配置 基础逻辑信息 /// /// /// [HttpPut] [Authorize(Policy = IRaCISPolicy.PM_APM)] [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "BeforeOngoingCantOpt", "AfterStopCannNotOpt" })] public async Task ConfigTrialBasicInfo(BasicTrialConfig trialConfig) { await VerifyOnlyInOngoingOrInitialIzingOptAsync(trialConfig.TrialId); var trialInfo = (await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialConfig.TrialId)).IfNullThrowException(); trialConfig.Modalitys = $"|{String.Join('|', trialConfig.ModalityList)}|"; _mapper.Map(trialConfig, trialInfo); trialInfo.UpdateTime = DateTime.Now; return ResponseOutput.Ok(await _repository.SaveChangesAsync()); } /// /// 配置流程 /// /// /// [HttpPut] [Authorize(Policy = IRaCISPolicy.PM_APM)] [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "BeforeOngoingCantOpt", "AfterStopCannNotOpt" })] public async Task ConfigTrialProcessInfo(TrialProcessConfig trialConfig) { if (!await _trialRepository.Where(t => t.Id == trialConfig.TrialId).IgnoreQueryFilters().AnyAsync(t => t.TrialStatusStr == StaticData.TrialState.TrialInitializing)) { return ResponseOutput.NotOk("该项目当前状态不是初始化,不允许进行该操作。"); } var trialInfo = await _trialRepository.Where(t => t.Id == trialConfig.TrialId, true).Include(t => t.TrialDicList.Where(u => u.KeyName == StaticData.Criterion)).FirstOrDefaultAsync(); if (trialInfo == null) return Null404NotFound(trialInfo); _mapper.Map(trialConfig, trialInfo); //if (trialInfo.IsGlobalReading && (trialInfo.IsArbitrationReading ?? false)) //{ // trialInfo.ArbitrationRule = ArbitrationRule.Reading; //} //if (!trialInfo.IsGlobalReading && (trialInfo.IsArbitrationReading ?? false)) //{ // trialInfo.ArbitrationRule = ArbitrationRule.Visit; //} trialInfo.UpdateTime = DateTime.Now; // 修改临床数据 var noconfirmids = await _clinicalDataTrialSetRepository.Where(x => x.TrialId == trialConfig.TrialId && !trialConfig.ClinicalDataTrialSetIds.Contains(x.Id)).Select(x => x.Id).ToListAsync(); foreach (var item in trialConfig.ClinicalDataTrialSetIds) { await _clinicalDataTrialSetRepository.UpdatePartialFromQueryAsync(item, x => new ClinicalDataTrialSet() { IsConfirm = true }); } foreach (var item in noconfirmids) { await _clinicalDataTrialSetRepository.UpdatePartialFromQueryAsync(item, x => new ClinicalDataTrialSet() { IsConfirm = false }); } // 修改阅片标准 var cancelConfirmCriterionIds = await _readingQuestionCriterionTrialRepository.Where(x => x.TrialId == trialConfig.TrialId && x.IsConfirm && !trialConfig.TrialCriterionIds.Contains(x.Id)).Select(x => x.Id).ToListAsync(); await _readingQuestionCriterionTrialRepository.UpdatePartialFromQueryAsync(x => cancelConfirmCriterionIds.Contains(x.Id), x => new ReadingQuestionCriterionTrial() { IsConfirm = false }); await _readingQuestionCriterionTrialRepository.UpdatePartialFromQueryAsync(x => trialConfig.TrialCriterionIds.Contains(x.Id), x => new ReadingQuestionCriterionTrial() { IsConfirm = true }); ; return ResponseOutput.Ok(await _repository.SaveChangesAsync()); } /// /// 配置加急信息 /// /// /// [HttpPut] [Authorize(Policy = IRaCISPolicy.PM_APM)] [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "BeforeOngoingCantOpt", "AfterStopCannNotOpt" })] public async Task ConfigTrialUrgentInfo(TrialUrgentConfig trialConfig) { await VerifyOnlyInOngoingOrInitialIzingOptAsync(trialConfig.TrialId); var trialInfo = (await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialConfig.TrialId)).IfNullThrowException(); //项目紧急 当前所有已提交,但未完成的访视,设置为加急。后续提交的访视也设置为加急 (在提交的时候,回去判断 项目加急,Subject加急,是否入组确认,是否Pd,从而设置访视是否加急) if (trialConfig.IsUrgent) { await _repository.BatchUpdateAsync(t => t.TrialId == trialInfo.Id && t.SubmitState == SubmitStateEnum.Submitted && t.ForwardState < ForwardStateEnum.Forwarded, s => new SubjectVisit() { IsUrgent = trialConfig.IsUrgent }); } else //之前设置为加急的访视状态不变。后续提交的访视,为不加急。 { } _mapper.Map(trialConfig, trialInfo); trialInfo.UpdateTime = DateTime.Now; return ResponseOutput.Ok(await _repository.SaveChangesAsync()); } [HttpGet("{trialId:guid}")] public async Task IfTrialCanOngoing(Guid trialId) { var canOPt = await _trialRepository.AnyAsync(trial => trial.Id == trialId && trial.IsTrialBasicLogicConfirmed && trial.IsTrialProcessConfirmed && trial.IsTrialUrgentConfirmed && trial.VisitPlanConfirmed); return ResponseOutput.Ok(canOPt, msg: canOPt ? "" : "该项目的项目配置(基础配置、流程配置、加急配置) 、访视管理,有配置未确认,不能设置项目状态为启动。"); } /// /// 更新项目状态 /// /// /// /// /// [HttpPut("{trialId:guid}/{trialStatusStr}/{reason?}")] [UnitOfWork] [Authorize(Policy = IRaCISPolicy.PM)] [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })] public async Task UpdateTrialState(Guid trialId, string trialStatusStr, string? reason) { var trial = (await _trialRepository.Where(t => t.Id == trialId, true).IgnoreQueryFilters().FirstOrDefaultAsync()).IfNullThrowException(); if (trialStatusStr == StaticData.TrialState.TrialOngoing) { if (trial.IsTrialBasicLogicConfirmed && trial.IsTrialProcessConfirmed && trial.IsTrialUrgentConfirmed && trial.VisitPlanConfirmed) { } else { return ResponseOutput.NotOk("无法变更项目状态。该项目的项目配置、访视管理中,有未确认项"); } } if ((trialStatusStr == StaticData.TrialState.TrialStopped || trialStatusStr == StaticData.TrialState.TrialCompleted) && trial.TrialStatusStr != StaticData.TrialState.TrialOngoing) { return ResponseOutput.NotOk("项目没有进入启动状态,不能设置为停止或完成状态"); } //if (trialStatusStr != StaticData.TrialState.TrialOngoing) //{ // trial.TrialFinishTime = DateTime.Now; //} trial.TrialStateChangeList.Add(new TrialStateChange() { OriginState = trial.TrialStatusStr, NowState = trialStatusStr, Reason = reason ?? String.Empty, TrialId = trialId }); trial.TrialStatusStr = trialStatusStr; //Paused、 添加工总量 算医生读片中 if (trialStatusStr.Contains(StaticData.TrialState.TrialCompleted)) { await _repository.BatchUpdateAsync(u => u.TrialId == trialId, e => new Enroll { EnrollStatus = EnrollStatus.Finished }); await _trialRepository.BatchUpdateNoTrackingAsync(u => u.Id == trialId, s => new Trial { TrialFinishedTime = DateTime.UtcNow.AddHours(8) }); } await _provider.SetAsync(trialId.ToString(), trialStatusStr, TimeSpan.FromDays(7)); await _repository.SaveChangesAsync(); return ResponseOutput.Ok(); } /// /// 项目状态 变更历史 /// /// /// [HttpGet("{trialId:guid}")] public async Task> GetTrialStateChangeList(Guid trialId) { return await _repository.Where(t => t.TrialId == trialId).ProjectTo(_mapper.ConfigurationProvider).ToListAsync(); } /// /// 废除项目 /// /// /// /// [HttpPut("{trialId:guid}/{isAbandon:bool}")] [Authorize(Policy = IRaCISPolicy.PM)] [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "BeforeOngoingCantOpt", "AfterStopCannNotOpt" })] public async Task AbandonTrial(Guid trialId, /*Guid? signId,*/ bool isAbandon) { await _trialRepository.UpdatePartialFromQueryAsync(trialId, u => new Trial() { IsDeleted = isAbandon, TrialFinishTime = isAbandon ? DateTime.Now : null }, true); return ResponseOutput.Ok(); } /// /// 获取 配置的所有信息 没有分多个接口 /// /// /// [HttpGet("{trialId:guid}")] public async Task GetTrialConfigInfo(Guid trialId) { return await _trialRepository.Where(t => t.Id == trialId).ProjectTo(_mapper.ConfigurationProvider) .FirstOrDefaultAsync().IfNullThrowException(); } /// /// 配置项目任务信息 /// /// /// [HttpPut] [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "BeforeOngoingCantOpt", "AfterStopCannNotOpt" })] //[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })] public async Task ConfigTrialTaskInfo(TrialTaskConfig trialConfig) { var trialInfo = (await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialConfig.TrialId)).IfNullThrowException(); _mapper.Map(trialConfig, trialInfo); return ResponseOutput.Ok(await _trialRepository.SaveChangesAsync()); } /// /// 配置项目读片查看规则 /// /// /// [HttpPut] [TypeFilter(typeof(TrialResourceFilter),Arguments = new object[] { "BeforeOngoingCantOpt", "AfterStopCannNotOpt" })] //[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })] public async Task ConfigTrialReadingTaskViewRule(TrialReadingTaskViewConfig trialConfig) { var trialInfo = (await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialConfig.TrialId)).IfNullThrowException(); _mapper.Map(trialConfig, trialInfo); return ResponseOutput.Ok(await _trialRepository.SaveChangesAsync()); } } }