467 lines
20 KiB
C#
467 lines
20 KiB
C#
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<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;
|
||
|
||
|
||
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;
|
||
|
||
}
|
||
|
||
|
||
|
||
/// <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))]
|
||
[Authorize(Policy = IRaCISPolicy.PM_APM_SPM_CPM)]
|
||
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 = (int)EnrollStatus.HasApplyDownloadResume,
|
||
});
|
||
|
||
await _enrollDetailRepository.AddAsync(new EnrollDetail()
|
||
{
|
||
DoctorId = doctorId,
|
||
TrialId = trialId,
|
||
EnrollStatus = (int)EnrollStatus.HasApplyDownloadResume,
|
||
OptUserType = (int)SystemUserType.AdminUser,
|
||
});
|
||
}
|
||
|
||
return ResponseOutput.Result(await _enrollRepository.SaveChangesAsync());
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// 入组流程-向CRO提交医生[Submit]
|
||
/// </summary>
|
||
|
||
[HttpPost("{trialId:guid}/{commitState:int}")]
|
||
[TypeFilter(typeof(TrialResourceFilter))]
|
||
[Authorize(Policy = IRaCISPolicy.PM_APM_SPM_CPM)]
|
||
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 = (int)EnrollStatus.HasCommittedToCRO;
|
||
//_enrollRepository.Update(intoGroupItem);
|
||
|
||
await _enrollDetailRepository.AddAsync(new EnrollDetail()
|
||
{
|
||
TrialDetailId = trialDetail.Id,
|
||
DoctorId = intoGroupItem.DoctorId,
|
||
TrialId = trialId,
|
||
EnrollStatus = (int)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 = (int)EnrollStatus.HasApplyDownloadResume;
|
||
|
||
//_enrollRepository.Update(intoGroupItem);
|
||
|
||
|
||
var deleteItem = await _enrollDetailRepository.FirstOrDefaultAsync(t =>
|
||
t.TrialId == trialId && t.DoctorId == intoGroupItem.DoctorId &&
|
||
t.EnrollStatus == (int)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))]
|
||
[Authorize(Policy = IRaCISPolicy.PM_APM_SPM_CPM)]
|
||
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 = (int)EnrollStatus.InviteIntoGroup;
|
||
//_enrollRepository.Update(intoGroupItem);
|
||
|
||
await _enrollDetailRepository.AddAsync(new EnrollDetail()
|
||
{
|
||
DoctorId = intoGroupItem.DoctorId,
|
||
TrialId = trialId,
|
||
EnrollStatus = (int)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 = (int)EnrollStatus.HasCommittedToCRO;
|
||
|
||
//_enrollRepository.Update(intoGroupItem);
|
||
|
||
var deleteItem = await _enrollDetailRepository.FirstOrDefaultAsync(t =>
|
||
t.TrialId == trialId && t.DoctorId == intoGroupItem.DoctorId &&
|
||
t.EnrollStatus == (int)EnrollStatus.InviteIntoGroup);
|
||
|
||
await _enrollDetailRepository.DeleteAsync(deleteItem);
|
||
}
|
||
}
|
||
|
||
|
||
}
|
||
return ResponseOutput.Result(await _enrollRepository.SaveChangesAsync());
|
||
|
||
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// 入组流程-后台确认医生入组[Confirm]
|
||
/// </summary>
|
||
|
||
[HttpPost]
|
||
[TypeFilter(typeof(TrialResourceFilter))]
|
||
[Authorize(Policy = IRaCISPolicy.PM_APM_SPM_CPM)]
|
||
[UnitOfWork]
|
||
public async Task<IResponseOutput> ConfirmReviewer(ConfirmReviewerCommand confirmReviewerCommand)
|
||
{
|
||
//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 = (int)EnrollStatus.ConfirmIntoGroup;
|
||
intoGroupItem.EnrollTime = DateTime.Now;
|
||
|
||
await _mailVerificationService.DoctorJoinTrialEmail(trialId, intoGroupItem.DoctorId, confirmReviewerCommand.BaseUrl, confirmReviewerCommand.RouteUrl);
|
||
await _enrollDetailRepository.AddAsync(new EnrollDetail()
|
||
{
|
||
DoctorId = intoGroupItem.DoctorId,
|
||
TrialId = trialId,
|
||
EnrollStatus = (int)EnrollStatus.ConfirmIntoGroup,
|
||
OptUserType = (int)SystemUserType.AdminUser, //后台用户
|
||
});
|
||
}
|
||
}
|
||
|
||
}
|
||
else if (confirmReviewerCommand.ConfirmState == 0)//回退上一步
|
||
{
|
||
foreach (var intoGroupItem in intoGroupList)
|
||
{
|
||
if (confirmReviewerCommand.DoctorIdArray.Contains(intoGroupItem.DoctorId))
|
||
{
|
||
intoGroupItem.EnrollStatus = (int)EnrollStatus.InviteIntoGroup;
|
||
intoGroupItem.EnrollTime = null;
|
||
|
||
|
||
var deleteItem = await _enrollDetailRepository.FirstOrDefaultAsync(t =>
|
||
t.TrialId == trialId && t.DoctorId == intoGroupItem.DoctorId &&
|
||
t.EnrollStatus == (int)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))]
|
||
[Authorize(Policy = IRaCISPolicy.PM_APM_SPM_CPM)]
|
||
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 = (int)EnrollStatus.InviteIntoGroup;
|
||
intoGroupItem.EnrollTime = null;
|
||
|
||
var deleteItem = await _enrollDetailRepository.FirstOrDefaultAsync(t =>
|
||
t.TrialId == trialId && t.DoctorId == intoGroupItem.DoctorId &&
|
||
t.EnrollStatus == (int)EnrollStatus.ConfirmIntoGroup);
|
||
|
||
await _enrollDetailRepository.DeleteAsync(deleteItem);
|
||
|
||
}
|
||
else if (optType == 1)
|
||
{
|
||
intoGroupItem.OutEnrollTime = outEnrollTime;
|
||
}
|
||
return ResponseOutput.Result(await _enrollRepository.SaveChangesAsync());
|
||
}
|
||
#endregion
|
||
|
||
}
|
||
}
|