EI-Image-Viewer-Api/IRaCIS.Core.Application/Service/WorkLoad/EnrollService.cs

513 lines
22 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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;
using System.Text.RegularExpressions;
namespace IRaCIS.Application.Services
{
[ApiExplorerSettings(GroupName = "Enroll")]
public class EnrollService : BaseService, IEnrollService
{
private readonly IRepository<Trial> _trialRepository;
private readonly IRepository<TrialStatusDetail> _trialDetailRepository;
private readonly IRepository<TrialPaymentPrice> _TrialPaymentPriceRepository;
private readonly IRepository<Enroll> _enrollRepository;
private readonly IRepository<Doctor> _doctorRepository;
private readonly IRepository<EnrollDetail> _enrollDetailRepository;
private readonly IRepository<Workload> _workloadRepository;
private readonly IMailVerificationService _mailVerificationService;
//private readonly IRepository<TrialUser> _trialUserRepository;
public EnrollService(IRepository<Trial> clinicalTrialProjectRepository,
IRepository<TrialStatusDetail> clinicalProjectDetailRepository,
IRepository<Enroll> intoGroupRepository,
IRepository<Doctor> doctorRepository,
IRepository<TrialPaymentPrice> TrialPaymentPriceRepository,
IRepository<EnrollDetail> intoGroupDetailRepository,
IRepository<Workload> workloadRepository,
IMailVerificationService mailVerificationService)
{
_trialRepository = clinicalTrialProjectRepository;
_TrialPaymentPriceRepository = TrialPaymentPriceRepository;
_doctorRepository = doctorRepository;
_trialDetailRepository = clinicalProjectDetailRepository;
_enrollRepository = intoGroupRepository;
_enrollDetailRepository = intoGroupDetailRepository;
_workloadRepository = workloadRepository;
_mailVerificationService = mailVerificationService;
//_trialUserRepository = trialUserRepository;
}
/// <summary>
/// 添加或更新项目医生项目价格
/// </summary>
[HttpPost]
public async Task<IResponseOutput> 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);
}
/// <summary>
/// 获取医生项目列表
/// </summary>
/// <param name="challengeQuery"></param>
/// <returns></returns>
[HttpPost]
public async Task<PageOutput<EnrollViewModel>> 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<EnrollViewModel>(x => x.TrialId == challengeQuery.TrialId)
// .WhereIf(challengeQuery.TrialId != null, t => t.TrialId == challengeQuery.TrialId)
// .WhereIf(challengeQuery.DoctorId != null, t => t.DoctorId == challengeQuery.DoctorId)
// .ProjectTo<Enroll>(_mapper.ConfigurationProvider);
//var pageList = await query2.ToListAsync();
// return new PageOutput<EnrollViewModel>(challengeQuery.pageIndex, challengeQuery.pageSize,
//costStatisticsQueryable);
}
#region Reviewer 入组审核流程select-submit-approve-confirm
/// <summary> 为项目筛选医生 提交 【select】 </summary>
/// <param name="trialId">项目Id</param>
/// <param name="doctorIdArray">医生Id数组</param>
/// <returns></returns>
[HttpPost("{trialId:guid}")]
[TypeFilter(typeof(TrialResourceFilter),Arguments = new object[] { "AfterStopCannNotOpt" })]
[Authorize(Policy = IRaCISPolicy.PM_APM_SPM_CPM_SMM_CMM)]
public async Task<IResponseOutput> 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,
DoctorUserId = _repository.Where<User>(t => t.DoctorId == doctorId).Select(t => t.Id).FirstOrDefault()
}); ;
await _enrollDetailRepository.AddAsync(new EnrollDetail()
{
DoctorId = doctorId,
TrialId = trialId,
EnrollStatus = EnrollStatus.HasApplyDownloadResume,
OptUserType = (int)SystemUserType.AdminUser,
});
}
return ResponseOutput.Result(await _enrollRepository.SaveChangesAsync());
}
/// <summary>
/// 入组流程-向CRO提交医生[Submit]
/// </summary>
[HttpPost("{trialId:guid}/{commitState:int}")]
[TypeFilter(typeof(TrialResourceFilter),Arguments = new object[] { "AfterStopCannNotOpt" })]
[Authorize(Policy = IRaCISPolicy.PM_APM_SPM_CPM_SMM_CMM)]
public async Task<IResponseOutput> 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}");
}
/// <summary>
/// 入组流程-CRO确定医生名单 [ Approve]
/// </summary>
[HttpPost("{trialId:guid}/{auditState:int}")]
[TypeFilter(typeof(TrialResourceFilter),Arguments = new object[] { "AfterStopCannNotOpt" })]
[Authorize(Policy = IRaCISPolicy.PM_APM_SPM_CPM_SMM_CMM)]
public async Task<IResponseOutput> 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());
}
/// <summary>
/// 入组流程-后台确认医生入组[Confirm]
/// </summary>
[HttpPost]
[TypeFilter(typeof(TrialResourceFilter),Arguments = new object[] { "AfterStopCannNotOpt" })]
[Authorize(Policy = IRaCISPolicy.PM_APM_SPM_CPM_SMM_CMM)]
[UnitOfWork]
public async Task<IResponseOutput> ConfirmReviewer(ConfirmReviewerCommand confirmReviewerCommand,
[FromServices] IRepository<TrialUser> _trialUserRepository,
[FromServices] IRepository<TaskAllocationRule> _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();
//验证邮件
var emaiList = await _doctorRepository.Where(t => intoGroupList.Select(t => t.DoctorId).Contains(t.Id))
.Select(t => new { t.EMail, t.FirstName, t.LastName }).ToListAsync();
var errorList = emaiList.Where(t => !Regex.IsMatch(t.EMail, @"^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$"))
.ToList();
if (errorList.Count() > 0)
{
return ResponseOutput.NotOk(string.Join(',', errorList.Select(c => c.LastName+" / "+c.FirstName)) +"邮箱格式存在问题") ;
}
if (confirmReviewerCommand.ConfirmState == 1) //确认入组
{
foreach (var intoGroupItem in intoGroupList)
{
if (confirmReviewerCommand.DoctorIdArray.Contains(intoGroupItem.DoctorId))
{
//当邮件发送没有问题的时候,才修改状态 如果有问题,就当前不做处理
try
{
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, JoinTime = DateTime.Now });
}
await _enrollRepository.BatchUpdateNoTrackingAsync(t => t.Id == intoGroupItem.Id, u => new Enroll() { DoctorUserId = userId });
if (!await _taskAllocationRuleRepository.AnyAsync(t => t.TrialId == trialId && t.DoctorUserId == userId && t.EnrollId == intoGroupItem.Id, true))
{
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, //后台用户
});
intoGroupItem.EnrollStatus = EnrollStatus.ConfirmIntoGroup;
intoGroupItem.EnrollTime = DateTime.Now;
}
catch (Exception )
{
intoGroupItem.EnrollStatus = EnrollStatus.ConfirmIntoGroupFailed;
}
}
}
}
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());
}
/// <summary>
/// optType 0表示入组列表没这条数据了 1表示出组需要填写出组时间 废弃
/// </summary>
/// <param name="trialId"></param>
/// <param name="doctorId"></param>
/// <param name="optType"></param>
/// <param name="outEnrollTime"></param>
/// <returns></returns>
[HttpPost("{trialId:guid}/{doctorId:guid}/{optType:int}")]
[TypeFilter(typeof(TrialResourceFilter),Arguments = new object[] { "AfterStopCannNotOpt" })]
[Authorize(Policy = IRaCISPolicy.PM_APM_SPM_CPM)]
[Obsolete]
public async Task<IResponseOutput> 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
}
}