using IRaCIS.Application.Contracts; using IRaCIS.Application.Interfaces; using IRaCIS.Core.Application.Filter; using IRaCIS.Core.Application.Helper; using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Infrastructure; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Options; using Panda.DynamicWebApi.Attributes; using ZiggyCreatures.Caching.Fusion; namespace IRaCIS.Core.Application.Service { [ApiExplorerSettings(GroupName = "Trial")] public class TrialService(IRepository _trialRepository, IRepository _trialUserRepository, IRepository _croRepository, IRepository _enrollDetailRepository, IRepository _dictionaryRepository, IRepository _enrollRepository, IRepository _workloadRepository, IRepository _sponsorRepository, IRepository _visitStageRepository, IRepository _trialPaymentPriceRepository, IRepository _trialDictionaryRepository, IRepository _trialBodyPartRepository, IOptionsMonitor _verifyConfig, IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer, IFusionCache _fusionCache) : BaseService, ITrialService { public bool TrialExpeditedChange { get; set; } = false; /// /// 分页获取临床项目列表 默认后台加急状态为3 查所有的 /// /// /// [HttpPost] public async Task> GetTrialList(TrialQueryDTO inQuery) { var multiModalityIdSelectCount = inQuery.ModalityIds.Count; var multiCriteriaSelectCount = inQuery.CriterionIds.Count; var multiReviewTypeSelectCount = inQuery.ReviewTypeIds.Count; Expression> trialDeclarationTypeExpression = x => true; foreach (var item in inQuery.DeclarationTypeEnumList) { trialDeclarationTypeExpression = trialDeclarationTypeExpression.And(t => t.DeclarationTypes.Contains($"|{item}|")); } Expression> trialAttendedReviewerTypeExpression = x => true; foreach (var item in inQuery.AttendedReviewerTypeEnumList) { trialAttendedReviewerTypeExpression = trialAttendedReviewerTypeExpression.And(t => t.AttendedReviewerTypes.Contains($"|{item}|")); } var query = _trialRepository.AsQueryable() .WhereIf(!string.IsNullOrEmpty(inQuery.TrialStatusStr), o => o.TrialStatusStr.Contains(inQuery.TrialStatusStr)) .WhereIf(inQuery.SponsorId != null, o => o.SponsorId == inQuery.SponsorId) .WhereIf(inQuery.Expedited != null, o => o.Expedited == inQuery.Expedited) .WhereIf(!string.IsNullOrEmpty(inQuery.Code), o => o.TrialCode.Contains(inQuery.Code)) .WhereIf(!string.IsNullOrWhiteSpace(inQuery.Indication), o => o.Indication.Contains(inQuery.Indication)) .WhereIf(!string.IsNullOrEmpty(inQuery.ResearchProgramNo), o => o.ResearchProgramNo.Contains(inQuery.ResearchProgramNo)) .WhereIf(!string.IsNullOrWhiteSpace(inQuery.ExperimentName), o => o.ExperimentName.Contains(inQuery.ExperimentName)) .WhereIf(inQuery.PhaseId != null, o => o.PhaseId == inQuery.PhaseId) .WhereIf(inQuery.DeclarationTypeEnumList.Count > 0, trialDeclarationTypeExpression) .WhereIf(inQuery.AttendedReviewerTypeEnumList.Count > 0, trialAttendedReviewerTypeExpression) //.WhereIf(searchParam.AttendedReviewerType != null, o => o.AttendedReviewerType == searchParam.AttendedReviewerType) .WhereIf(inQuery.IndicationTypeId != null, o => o.IndicationTypeId == inQuery.IndicationTypeId) .WhereIf(inQuery.CROId != null, o => o.CROId == inQuery.CROId) .WhereIf(inQuery.BeginDate != null, o => o.CreateTime >= inQuery.BeginDate) .WhereIf(inQuery.EndDate != null, o => o.CreateTime <= inQuery.EndDate) .WhereIf(multiModalityIdSelectCount > 0, t => t.TrialDicList.Count(t => t.KeyName == StaticData.Modality) == multiModalityIdSelectCount) .WhereIf(multiCriteriaSelectCount > 0, t => t.TrialDicList.Count(t => t.KeyName == StaticData.Criterion) == multiCriteriaSelectCount) .WhereIf(multiReviewTypeSelectCount > 0, t => t.TrialDicList.Count(t => t.KeyName == StaticData.ReviewType) == multiReviewTypeSelectCount) .WhereIf(_userInfo.UserTypeEnumInt != (int)UserTypeEnum.SuperAdmin, t => t.TrialUserList.Any(t => t.UserId == _userInfo.UserRoleId && t.IsDeleted == false) && t.IsDeleted == false) .ProjectTo(_mapper.ConfigurationProvider, new { userTypeEnumInt = _userInfo.UserTypeEnumInt, userId = _userInfo.UserRoleId, isEn_Us = _userInfo.IsEn_Us }); return await query.ToPagedListAsync(inQuery); } //过滤废除的项目 public async Task> GetTrialSelect() { return await _trialRepository.AsQueryable() .WhereIf(_userInfo.UserTypeEnumInt != (int)UserTypeEnum.SuperAdmin && _userInfo.UserTypeEnumInt != (int)UserTypeEnum.Admin && _userInfo.UserTypeEnumInt != (int)UserTypeEnum.OP, t => t.TrialUserList.Any(t => t.UserId == _userInfo.UserRoleId) && t.IsDeleted == false) .ProjectTo(_mapper.ConfigurationProvider).ToListAsync(); } /// /// 获取项目基本信息 /// /// /// [HttpGet("{projectId:guid}")] public async Task GetTrialInfoAndLockState(Guid projectId) { return (await _trialRepository.Where(o => o.Id == projectId).ProjectTo(_mapper.ConfigurationProvider, new { isEn_Us = _userInfo.IsEn_Us }).FirstOrDefaultAsync()).IfNullThrowException(); } [NonDynamicMethod] public async Task GetTrialMaxState(Guid trialId) { return await _enrollDetailRepository.Where(t => t.TrialId == trialId).MaxAsync(u => (int?)u.EnrollStatus) ?? 0; } [HttpGet("{trialId:guid}")] public async Task GetTrialInfoAndMaxTrialState(Guid trialId) { return new TrialAndTrialStateVieModel() { TrialView = await GetTrialInfoAndLockState(trialId), TrialMaxState = await GetTrialMaxState(trialId) }; } [HttpGet("{trialId:guid}")] public async Task GetTrialExpeditedState(Guid trialId) { var trial = (await _trialRepository.FirstOrDefaultAsync(u => u.Id == trialId)).IfNullThrowException(); return trial.Expedited; } /// /// 添加项目 /// /// /// [NonDynamicMethod] public virtual async Task> AddOrUpdateTrial(TrialCommand trialAddModel) { //测试用户 只能创建非正式项目 if (_userInfo.IsTestUser && trialAddModel.TrialType != TrialType.NoneOfficial) { //---测试用户 只能创建非正式项目 throw new BusinessValidationFailedException(_localizer["Trial_TestUserCreateOnlyNonFormal"]); } if (trialAddModel.Id == Guid.Empty || trialAddModel.Id == null) { if (await _trialRepository.AnyAsync(u => u.TrialCode == trialAddModel.TrialCode)) { //---已经存在相同的项目编号。 throw new BusinessValidationFailedException(_localizer["Trial_DuplicateProjectNumber"]); } var dbMaxCode = await _trialRepository.Where(t => t.CreateTime.Year == DateTime.Now.Year && t.TrialType == trialAddModel.TrialType).Select(t => t.Code).DefaultIfEmpty().MaxAsync(); var currentYearMaxCodeNext = dbMaxCode + 1; //var test = _trialRepository.Where(t => t.CreateTime.Year == DateTime.Now.Year + 1).Select(t => t.Code).DefaultIfEmpty(1).ToList(); var trial = _mapper.Map(trialAddModel); //trial.Id = NewId.NextGuid(); var yearStr = DateTime.Now.Year.ToString(); trial.Code = currentYearMaxCodeNext; trial.TrialCode = (trial.TrialType == TrialType.NoneOfficial ? "T0" : yearStr.Substring(yearStr.Length - 2)) + trial.TrialCode + currentYearMaxCodeNext.ToString("D3"); trial.DeclarationTypes = $"|{string.Join('|', trialAddModel.DeclarationTypeEnumList.Select(x => ((int)x).ToString()).ToList())}|"; trial.AttendedReviewerTypes = $"|{string.Join('|', trialAddModel.AttendedReviewerTypeEnumList.Select(x => ((int)x).ToString()).ToList())}|"; //多选信息 trialAddModel.ModalityIds.ForEach(modalityId => trial.TrialDicList.Add(new TrialDictionary() { DictionaryId = modalityId, KeyName = StaticData.Modality, TrialId = trial.Id })); trialAddModel.CriterionIds.ForEach(criterionId => trial.TrialDicList.Add(new TrialDictionary() { DictionaryId = criterionId, KeyName = StaticData.Criterion, TrialId = trial.Id })); trialAddModel.ReviewTypeIds.ForEach(ReviewTypeId => trial.TrialDicList.Add(new TrialDictionary() { DictionaryId = ReviewTypeId, KeyName = StaticData.ReviewType, TrialId = trial.Id })); //添加项目后 项目状态变更为申请下载简历 trial.TrialEnrollStatus = (int)TrialEnrollStatus.ChooseDoctor; //trial.TrialStatusStr = StaticData.TrialInitializing; //状态变更详细表 trial.ClinicalTrialProjectDetails.Add(new TrialStatusDetail() { TrialId = trial.Id, TrialStatus = (int)TrialEnrollStatus.ChooseDoctor }); trial = await _trialRepository.AddAsync(trial); //如果是PM, 则需要将该人员添加到 运维人员表 //添加运维人员PM await _trialUserRepository.AddAsync(new TrialUserRole() { TrialId = trial.Id, UserId = _userInfo.UserRoleId, JoinTime = DateTime.Now }); // 添加扩展信息表记录 await _trialPaymentPriceRepository.AddAsync(new TrialPaymentPrice() { TrialId = trial.Id }); //添加访视 await _visitStageRepository.AddAsync(new VisitStage { TrialId = trial.Id, VisitNum = 0, BlindName = "B" + 0.ToString("D3"), VisitDay = 0, VisitName = "Baseline", IsBaseLine = true, VisitWindowLeft = -28, VisitWindowRight = 0 }); await _visitStageRepository.AddAsync(new VisitStage { TrialId = trial.Id, VisitNum = 1, BlindName = "B" + 10.ToString("D3"), VisitDay = 30, VisitName = "Visit 1", VisitWindowLeft = -5, VisitWindowRight = 5 }); var success = await _trialRepository.SaveChangesAsync(); //维护CRO Sponsor await DealSponsorAndCROAsync(trial); //维护部位到项目表 var searchList = await _dictionaryRepository.Where(t => t.Parent.Code == "BodyPart" && t.ParentId != null && t.IsEnable).ProjectTo(_mapper.ConfigurationProvider).ToListAsync(); var needAddBodyPartList = searchList.Select(t => new TrialBodyPart() { Code = t.Code, Name = t.Value, NameCN = t.ValueCN }).ToList(); foreach (var item in needAddBodyPartList) { item.TrialId = trial.Id; } await _trialBodyPartRepository.AddRangeAsync(needAddBodyPartList, true); await _fusionCache.SetAsync(CacheKeys.Trial(trial.Id.ToString()), StaticData.TrialState.TrialInitializing, TimeSpan.FromDays(7)); return ResponseOutput.Ok(trial); } else { var updateModel = trialAddModel; if (!await _trialRepository.AnyAsync(u => u.Id == trialAddModel.Id && (u.TrialStatusStr == StaticData.TrialState.TrialInitializing || u.TrialStatusStr == StaticData.TrialState.TrialOngoing))) { //---项目状态只有处于:初始化或者进行中时,才允许操作。 throw new BusinessValidationFailedException(_localizer["Trial_InvalidProjectStatus"]); } // 判断项目Id 是否已经存在 if (await _trialRepository.AnyAsync(u => u.TrialCode == updateModel.TrialCode && u.Id != updateModel.Id)) { //---已经存在相同的项目编号。 throw new BusinessValidationFailedException(_localizer["Trial_DuplicateProjectNumber"]); } var trial = await _trialRepository.FirstOrDefaultAsync(t => t.Id == updateModel.Id); //删除中间表 Title对应的记录 await _trialDictionaryRepository.BatchDeleteNoTrackingAsync(t => t.TrialId == updateModel.Id); //重新插入新的 Title记录 updateModel.ModalityIds.ForEach(modalityId => trial.TrialDicList.Add(new TrialDictionary() { DictionaryId = modalityId, KeyName = StaticData.Modality, TrialId = trial.Id })); updateModel.CriterionIds.ForEach(criterionId => trial.TrialDicList.Add(new TrialDictionary() { DictionaryId = criterionId, KeyName = StaticData.Criterion, TrialId = trial.Id })); updateModel.ReviewTypeIds.ForEach(ReviewTypeId => trial.TrialDicList.Add(new TrialDictionary() { DictionaryId = ReviewTypeId, KeyName = StaticData.ReviewType, TrialId = trial.Id })); if (updateModel.Expedited != trial.Expedited && updateModel.Expedited != null) { TrialExpeditedChange = true; await TrialExpeditedStatusChange(trial.Id, trial.Expedited, (int)updateModel.Expedited); } _mapper.Map(updateModel, trial); trial.DeclarationTypes = $"|{string.Join('|', updateModel.DeclarationTypeEnumList.Select(x => ((int)x).ToString()).ToList())}|"; trial.AttendedReviewerTypes = $"|{string.Join('|', updateModel.AttendedReviewerTypeEnumList.Select(x => ((int)x).ToString()).ToList())}|"; var success = await _trialRepository.SaveChangesAsync(); //维护CRO Sponsor await DealSponsorAndCROAsync(trial); return ResponseOutput.Ok(trial); } } private async Task DealSponsorAndCROAsync(Trial trial) { if (trial.SponsorId != null) { if (await _sponsorRepository.AnyAsync(t => t.Id == trial.SponsorId && t.IsTrialLevel)) { await _sponsorRepository.BatchUpdateNoTrackingAsync(t => t.Id == trial.SponsorId, u => new Sponsor() { TrialId = trial.Id }); } } if (trial.CROId != null) { if (await _croRepository.AnyAsync(t => t.Id == trial.CROId && t.IsTrialLevel)) { await _croRepository.BatchUpdateNoTrackingAsync(t => t.Id == trial.CROId, u => new CRO() { TrialId = trial.Id }); } } } // TODO: 需要优化,嵌套两层 switch case ? [NonDynamicMethod] private async Task TrialExpeditedStatusChange(Guid trialId, int oldState, int newState) { switch (oldState) { case (int)TrialExpedited.None: switch (newState) { case (int)TrialExpedited.ExpeditedIn24H: await _workloadRepository.BatchUpdateNoTrackingAsync(t => t.IsLock == false && t.TrialId == trialId, u => new Workload() { TimepointIn24H = u.Timepoint, AdjudicationIn24H = u.Adjudication, Timepoint = 0, Adjudication = 0 }); break; case (int)TrialExpedited.ExpeditedIn48H: await _workloadRepository.BatchUpdateNoTrackingAsync(t => t.IsLock == false && t.TrialId == trialId, u => new Workload() { TimepointIn48H = u.Timepoint, AdjudicationIn48H = u.Adjudication, Timepoint = 0, Adjudication = 0 }); break; } //_workloadRepository.Update(t => t.IsLock == false && t.TrialId == trialId, u => new Workload() //{ // Timepoint = 0, // Adjudication = 0 //}); break; case (int)TrialExpedited.ExpeditedIn24H: switch (newState) { case (int)TrialExpedited.None: await _workloadRepository.BatchUpdateNoTrackingAsync(t => t.IsLock == false && t.TrialId == trialId, u => new Workload() { Timepoint = u.TimepointIn24H, Adjudication = u.AdjudicationIn24H, TimepointIn24H = 0, AdjudicationIn24H = 0 }); break; case (int)TrialExpedited.ExpeditedIn48H: await _workloadRepository.BatchUpdateNoTrackingAsync(t => t.IsLock == false && t.TrialId == trialId, u => new Workload() { TimepointIn48H = u.TimepointIn24H, AdjudicationIn48H = u.AdjudicationIn24H, TimepointIn24H = 0, AdjudicationIn24H = 0 }); break; } //_workloadRepository.Update(t => t.IsLock == false && t.TrialId == trialId, u => new Workload() //{ // TimepointIn24H = 0, // AdjudicationIn24H = 0 //}); break; case (int)TrialExpedited.ExpeditedIn48H: switch (newState) { case (int)TrialExpedited.None: await _workloadRepository.BatchUpdateNoTrackingAsync(t => t.IsLock == false && t.TrialId == trialId, u => new Workload() { Timepoint = u.TimepointIn48H, Adjudication = u.AdjudicationIn48H, TimepointIn48H = 0, AdjudicationIn48H = 0 }); break; case (int)TrialExpedited.ExpeditedIn24H: await _workloadRepository.BatchUpdateNoTrackingAsync(t => t.IsLock == false && t.TrialId == trialId, u => new Workload() { TimepointIn24H = u.TimepointIn48H, AdjudicationIn24H = u.AdjudicationIn48H, TimepointIn48H = 0, AdjudicationIn48H = 0 }); break; } //_workloadRepository.Update(t => t.IsLock == false && t.TrialId == trialId, u => new Workload() //{ // TimepointIn48H = 0, // AdjudicationIn48H = 0 //}); break; } } /// /// 标记项目删除 /// /// /// [HttpDelete, Route("{trialId:guid}")] public async Task MarkTrialDelete(Guid trialId) { await _trialRepository.BatchUpdateNoTrackingAsync(t => t.Id == trialId, u => new Trial() { IsDeleted = true }); return ResponseOutput.Ok(); } /// 真删除项目 方便清理测试数据 /// 临床试验项目Id [AllowAnonymous] [HttpDelete, Route("{trialId:guid}")] public async Task DeleteTrial(Guid trialId, [FromServices] IRepository _repository) { var trial = (await _trialRepository.FirstOrDefaultAsync(u => u.Id == trialId, true)).IfNullThrowException(); if (_verifyConfig.CurrentValue.OpenTrialRelationDelete) { #region 真项目删除 await _repository.BatchDeleteNoTrackingAsync(o => o.SubjectVisit.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(o => o.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(o => o.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(o => o.TrialReadingCriterion.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(o => o.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.Enroll.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.NoneDicomStudy.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.SubjectVisit.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.SubjectVisit.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.SubjectVisit.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.QCChallenge.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.ReadingClinicalData.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TaskMedicalReview.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TaskMedicalReview.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.VisitTask.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.ReadingPeriodSet.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.VisitTask.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.Subject.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.InfluenceTask.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(o => o.Id == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialReadingCriterion.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialReadingCriterion.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId); await _trialDictionaryRepository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialDocument.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialDocument.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialEmailNoticeConfig.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialSiteSurvey.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialSiteSurvey.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.OriginalReReadingTask.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId); await _repository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId); #endregion return ResponseOutput.Ok(); } else { //---当前运行环境下,不允许删除项目数据。 return ResponseOutput.NotOk(_localizer["Trial_CannotDeleteProject"]); } } [HttpPost] public async Task> GetReviewerTrialListByEnrollmentStatus(TrialByStatusQueryDTO inQuery) { var query = _trialRepository.AsQueryable() .WhereIf(inQuery.Status == 5, t => t.EnrollList.Any(u => u.EnrollStatus == EnrollStatus.HasCommittedToCRO)) .WhereIf(inQuery.Status == 8, t => t.EnrollList.Any(u => u.EnrollStatus == EnrollStatus.InviteIntoGroup)) .WhereIf(inQuery.Status == 10, t => t.EnrollList.Any(u => u.EnrollStatus == EnrollStatus.DoctorReading)) .WhereIf(inQuery.Status == 14, t => t.EnrollList.Any(u => u.EnrollStatus == EnrollStatus.Finished)) .ProjectTo(_mapper.ConfigurationProvider, new { userTypeEnumInt = _userInfo.UserTypeEnumInt, userId = _userInfo.UserRoleId, isEn_Us = _userInfo.IsEn_Us }); return await query.ToPagedListAsync(inQuery, nameof(TrialDetailDTO.CreateTime)); } /// /// 根据项目Id 获取医生Id,用于触发计算费用 /// public async Task> GetTrialEnrollmentReviewerIds(Guid trialId) { return await _enrollRepository.Where(u => u.TrialId == trialId && u.EnrollStatus >= EnrollStatus.DoctorReading).Select(u => u.DoctorId).Distinct().ToListAsync(); } #region 医生用户接口 /// 分页获取医生参与的临床实验项目列表(查询条件) /// [HttpPost] public async Task> GetTrialListByReviewer(ReviewerTrialQueryDTO inQuery) { var query = _trialRepository .WhereIf(inQuery.EnrollStatus != null, o => (int)inQuery.EnrollStatus! == 10 ? o.EnrollList.Any(o => o.EnrollStatus >= EnrollStatus.ConfirmIntoGroup && o.EnrollStatus <= EnrollStatus.DoctorReading && o.DoctorId == _userInfo.UserRoleId) : o.EnrollList.Any(o => o.EnrollStatus == inQuery.EnrollStatus && o.DoctorId == _userInfo.UserRoleId)) .WhereIf(inQuery.Expedited != null, o => o.Expedited == inQuery.Expedited) .WhereIf(!string.IsNullOrEmpty(inQuery.Code), o => o.TrialCode.Contains(inQuery.Code)) .WhereIf(!string.IsNullOrWhiteSpace(inQuery.Indication), o => o.Indication.Contains(inQuery.Indication)) .WhereIf(_userInfo.UserTypeEnumInt != (int)UserTypeEnum.SuperAdmin, t => t.TrialUserList.Any(t => t.UserId == _userInfo.UserRoleId)) .ProjectTo(_mapper.ConfigurationProvider, new { userTypeEnumInt = _userInfo.UserTypeEnumInt, userId = _userInfo.UserRoleId, isEn_Us = _userInfo.IsEn_Us }); return await query.ToPagedListAsync(inQuery, nameof(TrialDetailDTO.CreateTime)); } /// /// 医生确认入组或拒绝入组 /// /// 项目Id /// 9-拒绝入组,10-确认入组 /// [HttpPost("{trialId:guid}/{status:int}")] [TrialGlobalLimit("AfterStopCannNotOpt")] public async Task UpdateEnrollStatus(Guid trialId, EnrollStatus status) { await _enrollDetailRepository.AddAsync(new EnrollDetail() { DoctorId = _userInfo.UserRoleId, TrialId = trialId, EnrollStatus = status, OptUserType = (int)SystemUserType.DoctorUser, }); return ResponseOutput.Result(await _enrollRepository.BatchUpdateNoTrackingAsync(u => u.TrialId == trialId && u.DoctorId == _userInfo.UserRoleId, e => new Enroll { EnrollStatus = status })); } #endregion } }