using IRaCIS.Application.Interfaces; using IRaCIS.Core.Infra.EFCore; using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Application.Filter; using Microsoft.AspNetCore.Mvc; using IRaCIS.Core.Application.Service.WorkLoad.DTO; using Microsoft.AspNetCore.Authorization; using IRaCIS.Core.Application.Auth; namespace IRaCIS.Application.Services { [ApiExplorerSettings(GroupName = "Enroll")] public class EnrollService : BaseService, IEnrollService { private readonly IRepository _trialRepository; private readonly IRepository _trialDetailRepository; private readonly IRepository _TrialPaymentPriceRepository; private readonly IRepository _enrollRepository; private readonly IRepository _doctorRepository; private readonly IRepository _enrollDetailRepository; private readonly IRepository _workloadRepository; private readonly IMailVerificationService _mailVerificationService; //private readonly IRepository _trialUserRepository; public EnrollService(IRepository clinicalTrialProjectRepository, IRepository clinicalProjectDetailRepository, IRepository intoGroupRepository, IRepository doctorRepository, IRepository TrialPaymentPriceRepository, IRepository intoGroupDetailRepository, IRepository workloadRepository, IMailVerificationService mailVerificationService) { _trialRepository = clinicalTrialProjectRepository; _TrialPaymentPriceRepository = TrialPaymentPriceRepository; _doctorRepository = doctorRepository; _trialDetailRepository = clinicalProjectDetailRepository; _enrollRepository = intoGroupRepository; _enrollDetailRepository = intoGroupDetailRepository; _workloadRepository = workloadRepository; _mailVerificationService = mailVerificationService; //_trialUserRepository = trialUserRepository; } /// /// 添加或更新项目医生项目价格 /// [HttpPost] public async Task AddOrUpdateEnroll(EnrollCommand addOrUpdateModel) { var trialDoctoritem = await _enrollRepository.FirstOrDefaultAsync(u => u.Id == addOrUpdateModel.Id); if (trialDoctoritem == null)//insert { await _enrollRepository.InsertFromDTOAsync(addOrUpdateModel); } else//update { await _enrollRepository.UpdateFromDTOAsync(addOrUpdateModel); } var success = await _enrollRepository.SaveChangesAsync(); return ResponseOutput.Result(success); } /// /// 获取医生项目列表 /// /// /// [HttpPost] public async Task> GetTrialDoctorList(EnrollGetQuery challengeQuery) { var costStatisticsQueryable = from enroll in _enrollRepository.Where(t => t.TrialId == challengeQuery.TrialId) join dociorc in _doctorRepository.Where() on enroll.DoctorId equals dociorc.Id join price in _TrialPaymentPriceRepository.Where() on enroll.TrialId equals price.TrialId select new EnrollViewModel() { ChineseName = dociorc.ChineseName, AdjustmentMultiple = enroll.AdjustmentMultiple, FirstName = dociorc.FirstName, LastName = dociorc.LastName, DoctorId = dociorc.Id, TrialId = challengeQuery.TrialId, Id = enroll.Id, Training = enroll.Training, RefresherTraining = enroll.RefresherTraining, Timepoint = enroll.Timepoint, Timepoint48H = enroll.Timepoint48H, Timepoint24H = enroll.Timepoint24H, Adjudication = enroll.Adjudication, Adjudication48H = enroll.Adjudication48H, Adjudication24H = enroll.Adjudication24H, Global = enroll.Global, Code = dociorc.Code, ReviewerCode = dociorc.ReviewerCode, Downtime = enroll.Downtime, }; return await costStatisticsQueryable.ToPagedListAsync(challengeQuery.PageIndex, challengeQuery.PageSize, "ChineseName"); //var query2 = _repository.Where(x => x.TrialId == challengeQuery.TrialId) // .WhereIf(challengeQuery.TrialId != null, t => t.TrialId == challengeQuery.TrialId) // .WhereIf(challengeQuery.DoctorId != null, t => t.DoctorId == challengeQuery.DoctorId) // .ProjectTo(_mapper.ConfigurationProvider); //var pageList = await query2.ToListAsync(); // return new PageOutput(challengeQuery.pageIndex, challengeQuery.pageSize, //costStatisticsQueryable); } #region Reviewer 入组审核流程(select-submit-approve-confirm) /// 为项目筛选医生 提交 【select】 /// 项目Id /// 医生Id数组 /// [HttpPost("{trialId:guid}")] [TypeFilter(typeof(TrialResourceFilter))] [Authorize(Policy = IRaCISPolicy.PM_APM_SPM_CPM)] public async Task SelectReviewers(Guid trialId, Guid[] doctorIdArray) { var trial = await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialId); if (trial == null) return Null404NotFound(trial); //_trialRepository.Attach(trial); //更新项目状态 trial.TrialEnrollStatus = (int)TrialEnrollStatus.HasApplyDownLoadResume; //_trialRepository.Update(trial); //添加项目状态变化记录 var trialDetail = new TrialStatusDetail() { TrialId = trial.Id, TrialStatus = (int)TrialEnrollStatus.HasApplyDownLoadResume, }; await _trialDetailRepository.AddAsync(trialDetail); // 入组表 入组状态跟踪表 foreach (var doctorId in doctorIdArray) { await _enrollRepository.AddAsync(new Enroll() { DoctorId = doctorId, TrialId = trialId, EnrollStatus = EnrollStatus.HasApplyDownloadResume, }); await _enrollDetailRepository.AddAsync(new EnrollDetail() { DoctorId = doctorId, TrialId = trialId, EnrollStatus = EnrollStatus.HasApplyDownloadResume, OptUserType = (int)SystemUserType.AdminUser, }); } return ResponseOutput.Result(await _enrollRepository.SaveChangesAsync()); } /// /// 入组流程-向CRO提交医生[Submit] /// [HttpPost("{trialId:guid}/{commitState:int}")] [TypeFilter(typeof(TrialResourceFilter))] [Authorize(Policy = IRaCISPolicy.PM_APM_SPM_CPM)] public async Task SubmitReviewer(Guid trialId, Guid[] doctorIdArray, int commitState) { var trial = await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialId); if (trial != null) { if (commitState == 1) //确认提交CRO { //更新项目状态 trial.TrialEnrollStatus = (int)TrialEnrollStatus.HasCommitCRO; //添加项目详细记录 var trialDetail = new TrialStatusDetail() { TrialId = trial.Id, TrialStatus = (int)TrialEnrollStatus.HasCommitCRO }; await _trialDetailRepository.AddAsync(trialDetail); //更新入组表 跟踪了 所以不用下面的_enrollRepository.Update(intoGroupItem); var intoGroupList = await _enrollRepository.Where(t => t.TrialId == trialId, true).ToListAsync(); foreach (var intoGroupItem in intoGroupList) { if (doctorIdArray.Contains(intoGroupItem.DoctorId)) { intoGroupItem.EnrollStatus = EnrollStatus.HasCommittedToCRO; //_enrollRepository.Update(intoGroupItem); await _enrollDetailRepository.AddAsync(new EnrollDetail() { TrialDetailId = trialDetail.Id, DoctorId = intoGroupItem.DoctorId, TrialId = trialId, EnrollStatus = EnrollStatus.HasCommittedToCRO, OptUserType = (int)SystemUserType.AdminUser, //后台用户 }); } } } else if (commitState == 0)//回退上一步 { //更新入组表 var intoGroupList = await _enrollRepository.Where(t => t.TrialId == trialId, true).ToListAsync(); foreach (var intoGroupItem in intoGroupList) { if (doctorIdArray.Contains(intoGroupItem.DoctorId)) { intoGroupItem.EnrollStatus = EnrollStatus.HasApplyDownloadResume; //_enrollRepository.Update(intoGroupItem); var deleteItem = await _enrollDetailRepository.FirstOrDefaultAsync(t => t.TrialId == trialId && t.DoctorId == intoGroupItem.DoctorId && t.EnrollStatus == EnrollStatus.HasCommittedToCRO); await _enrollDetailRepository.DeleteAsync(deleteItem); } } } return ResponseOutput.Result(await _enrollRepository.SaveChangesAsync()); } return ResponseOutput.NotOk($"Cannot find trial {trialId}"); } /// /// 入组流程-CRO确定医生名单 [ Approve] /// [HttpPost("{trialId:guid}/{auditState:int}")] [TypeFilter(typeof(TrialResourceFilter))] [Authorize(Policy = IRaCISPolicy.PM_APM_SPM_CPM)] public async Task ApproveReviewer(Guid trialId, Guid[] doctorIdArray, int auditState) { var trial = await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialId); if (trial == null) return Null404NotFound(trial); if (auditState == 1) //确认入组 { //var existItem = _trialRepository.FindSingleOrDefault(u => u.Id == trialId && u.TrialStatus >= (int)TrialEnrollStatus.HasConfirmedDoctorNames); //if (existItem == null) //{ // trial.TrialStatus = (int)TrialEnrollStatus.HasConfirmedDoctorNames; // trial.TrialStatusStr = "Approved"; //} //_trialRepository.Update(trial); //更新项目状态 trial.TrialEnrollStatus = (int)TrialEnrollStatus.HasConfirmedDoctorNames; //添加项目详细记录 var trialDetail = new TrialStatusDetail() { TrialId = trialId, TrialStatus = (int)TrialEnrollStatus.HasConfirmedDoctorNames }; await _trialDetailRepository.AddAsync(trialDetail); //更新入组表 跟踪方式,不用下面的_enrollRepository.Update(intoGroupItem); var intoGroupList = _enrollRepository.Where(t => t.TrialId == trialId, true).ToList(); foreach (var intoGroupItem in intoGroupList) { if (doctorIdArray.Contains(intoGroupItem.DoctorId)) { intoGroupItem.EnrollStatus = EnrollStatus.InviteIntoGroup; //_enrollRepository.Update(intoGroupItem); await _enrollDetailRepository.AddAsync(new EnrollDetail() { DoctorId = intoGroupItem.DoctorId, TrialId = trialId, EnrollStatus = EnrollStatus.InviteIntoGroup, OptUserType = (int)SystemUserType.AdminUser, //后台用户 }); } } } else if (auditState == 0)//回退上一步 { //更新入组表 var intoGroupList = _enrollRepository.Where(t => t.TrialId == trialId, true).ToList(); foreach (var intoGroupItem in intoGroupList) { if (doctorIdArray.Contains(intoGroupItem.DoctorId)) { intoGroupItem.EnrollStatus = EnrollStatus.HasCommittedToCRO; //_enrollRepository.Update(intoGroupItem); var deleteItem = await _enrollDetailRepository.FirstOrDefaultAsync(t => t.TrialId == trialId && t.DoctorId == intoGroupItem.DoctorId && t.EnrollStatus == EnrollStatus.InviteIntoGroup); await _enrollDetailRepository.DeleteAsync(deleteItem); } } } return ResponseOutput.Result(await _enrollRepository.SaveChangesAsync()); } /// /// 入组流程-后台确认医生入组[Confirm] /// [HttpPost] [TypeFilter(typeof(TrialResourceFilter))] [Authorize(Policy = IRaCISPolicy.PM_APM_SPM_CPM)] [UnitOfWork] public async Task ConfirmReviewer(ConfirmReviewerCommand confirmReviewerCommand, [FromServices] IRepository _trialUserRepository, [FromServices] IRepository _taskAllocationRuleRepository) { //var trial = _trialRepository.FirstOrDefault(t => t.Id == trialId); //var existItem = _trialRepository.FindSingleOrDefault(u => u.Id == trialId && u.TrialStatus >= (int)TrialEnrollStatus.HasConfirmedDoctorNames); //trial.TrialStatusStr = "Reading"; ////trial.TrialStatus = (int)TrialStatus.HasConfirmedDoctorNames; //_trialRepository.Update(trial); var trialId = confirmReviewerCommand.TrialId; var trial = await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialId); if (trial == null) return Null404NotFound(trial); //更新入组表 var intoGroupList = await _enrollRepository.Where(t => t.TrialId == trialId,true).ToListAsync(); if (confirmReviewerCommand.ConfirmState == 1) //确认入组 { foreach (var intoGroupItem in intoGroupList) { if (confirmReviewerCommand.DoctorIdArray.Contains(intoGroupItem.DoctorId)) { intoGroupItem.EnrollStatus = EnrollStatus.ConfirmIntoGroup; intoGroupItem.EnrollTime = DateTime.Now; var userId= await _mailVerificationService.DoctorJoinTrialEmail(trialId, intoGroupItem.DoctorId, confirmReviewerCommand.BaseUrl, confirmReviewerCommand.RouteUrl); if( !await _trialUserRepository.AnyAsync(t=>t.TrialId==trialId && t.UserId== userId, true)) { await _trialUserRepository.AddAsync(new TrialUser() { TrialId = trialId, UserId = userId }); await _enrollRepository.BatchUpdateNoTrackingAsync(t => t.Id == intoGroupItem.Id, u => new Enroll() { DoctorUserId = userId }); await _taskAllocationRuleRepository.AddAsync(new TaskAllocationRule() { TrialId = trialId, DoctorUserId = userId,EnrollId= intoGroupItem.Id }); } await _enrollDetailRepository.AddAsync(new EnrollDetail() { DoctorId = intoGroupItem.DoctorId, TrialId = trialId, EnrollStatus = EnrollStatus.ConfirmIntoGroup, OptUserType = (int)SystemUserType.AdminUser, //后台用户 }); } } } else if (confirmReviewerCommand.ConfirmState == 0)//回退上一步 { foreach (var intoGroupItem in intoGroupList) { if (confirmReviewerCommand.DoctorIdArray.Contains(intoGroupItem.DoctorId)) { intoGroupItem.EnrollStatus = EnrollStatus.InviteIntoGroup; intoGroupItem.EnrollTime = null; var deleteItem = await _enrollDetailRepository.FirstOrDefaultAsync(t => t.TrialId == trialId && t.DoctorId == intoGroupItem.DoctorId && t.EnrollStatus == EnrollStatus.ConfirmIntoGroup); await _enrollDetailRepository.DeleteAsync(deleteItem); } } } return ResponseOutput.Result(await _enrollRepository.SaveChangesAsync()); } /// /// optType 0表示回退,回退之后,列表没这条数据了, 1表示出组,需要填写出组时间 /// /// /// /// /// /// [HttpPost("{trialId:guid}/{doctorId:guid}/{optType:int}")] [TypeFilter(typeof(TrialResourceFilter))] [Authorize(Policy = IRaCISPolicy.PM_APM_SPM_CPM)] public async Task EnrollBackOrOut(Guid trialId, Guid doctorId, int optType, DateTime? outEnrollTime) { var intoGroupItem = await _enrollRepository.FirstOrDefaultAsync(t => t.TrialId == trialId && t.DoctorId == doctorId); if (optType == 0) { var sum = _workloadRepository.Where(t => t.TrialId == trialId && t.DoctorId == doctorId && t.DataFrom == (int)WorkLoadFromStatus.FinalConfirm) .Sum(u => u.Adjudication + u.AdjudicationIn24H + u.AdjudicationIn48H + u.Timepoint + u.TimepointIn24H + u.TimepointIn48H + u.RefresherTraining + u.Training + u.Global + u.Downtime); if (sum != 0) { return ResponseOutput.NotOk("Reviewers with workload cannot go back"); } intoGroupItem.EnrollStatus = EnrollStatus.InviteIntoGroup; intoGroupItem.EnrollTime = null; var deleteItem = await _enrollDetailRepository.FirstOrDefaultAsync(t => t.TrialId == trialId && t.DoctorId == intoGroupItem.DoctorId && t.EnrollStatus == EnrollStatus.ConfirmIntoGroup); await _enrollDetailRepository.DeleteAsync(deleteItem); } else if (optType == 1) { intoGroupItem.OutEnrollTime = outEnrollTime; } return ResponseOutput.Result(await _enrollRepository.SaveChangesAsync()); } #endregion } }