irc-netcore-api/IRaCIS.Core.Application/Service/TrialSiteUser/TrialService.cs

676 lines
34 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.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<Trial> _trialRepository,
IRepository<TrialIdentityUser> _trialIdentityUserRepository,
IRepository<CRO> _croRepository,
IRepository<EnrollDetail> _enrollDetailRepository,
IRepository<Dictionary> _dictionaryRepository,
IRepository<Enroll> _enrollRepository,
IRepository<Workload> _workloadRepository,
IRepository<Sponsor> _sponsorRepository,
IRepository<VisitStage> _visitStageRepository,
IRepository<TrialPaymentPrice> _trialPaymentPriceRepository,
IRepository<TrialDictionary> _trialDictionaryRepository,
IRepository<TrialBodyPart> _trialBodyPartRepository,
IOptionsMonitor<ServiceVerifyConfigOption> _verifyConfig,
IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer, IFusionCache _fusionCache) : BaseService, ITrialService
{
public bool TrialExpeditedChange { get; set; } = false;
/// <summary>
/// 分页获取临床项目列表 默认后台加急状态为3 查所有的
/// </summary>
/// <param name="inQuery"></param>
/// <returns></returns>
[HttpPost]
public async Task<PageOutput<TrialDetailDTO>> GetTrialList(TrialQueryDTO inQuery)
{
var multiModalityIdSelectCount = inQuery.ModalityIds.Count;
var multiCriteriaSelectCount = inQuery.CriterionIds.Count;
var multiReviewTypeSelectCount = inQuery.ReviewTypeIds.Count;
Expression<Func<Trial, bool>> trialDeclarationTypeExpression = x => true;
foreach (var item in inQuery.DeclarationTypeEnumList)
{
trialDeclarationTypeExpression = trialDeclarationTypeExpression.And(t => t.DeclarationTypes.Contains($"|{item}|"));
}
Expression<Func<Trial, bool>> 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)
.ProjectTo<TrialDetailDTO>(_mapper.ConfigurationProvider, new { userTypeEnumInt = _userInfo.UserTypeEnumInt, userId = _userInfo.UserRoleId, isEn_Us = _userInfo.IsEn_Us });
return await query.ToPagedListAsync(inQuery);
}
//过滤废除的项目
public async Task<List<TrialSelectDTO>> GetTrialSelect()
{
return await _trialRepository.AsQueryable()
.WhereIf(_userInfo.UserTypeEnumInt != (int)UserTypeEnum.SuperAdmin && _userInfo.UserTypeEnumInt != (int)UserTypeEnum.Admin && _userInfo.UserTypeEnumInt != (int)UserTypeEnum.OP, t => t.TrialIdentityUserList.Any(t => t.IdentityUserId == _userInfo.IdentityUserId) && t.IsDeleted == false)
.ProjectTo<TrialSelectDTO>(_mapper.ConfigurationProvider).ToListAsync();
}
/// <summary>
/// 获取项目基本信息
/// </summary>
/// <param name="projectId"></param>
/// <returns></returns>
[HttpGet("{projectId:guid}")]
public async Task<TrialDetailDTO> GetTrialInfoAndLockState(Guid projectId)
{
return (await _trialRepository.Where(o => o.Id == projectId).ProjectTo<TrialDetailDTO>(_mapper.ConfigurationProvider, new { isEn_Us = _userInfo.IsEn_Us }).FirstOrDefaultAsync()).IfNullThrowException();
}
[NonDynamicMethod]
public async Task<int> GetTrialMaxState(Guid trialId)
{
return await _enrollDetailRepository.Where(t => t.TrialId == trialId).MaxAsync(u => (int?)u.EnrollStatus) ?? 0;
}
[HttpGet("{trialId:guid}")]
public async Task<TrialAndTrialStateVieModel> GetTrialInfoAndMaxTrialState(Guid trialId)
{
return new TrialAndTrialStateVieModel()
{
TrialView = await GetTrialInfoAndLockState(trialId),
TrialMaxState = await GetTrialMaxState(trialId)
};
}
[HttpGet("{trialId:guid}")]
public async Task<int> GetTrialExpeditedState(Guid trialId)
{
var trial = (await _trialRepository.FirstOrDefaultAsync(u => u.Id == trialId)).IfNullThrowException();
return trial.Expedited;
}
/// <summary>
/// 添加项目
/// </summary>
/// <param name="trialAddModel"></param>
/// <returns></returns>
[NonDynamicMethod]
public virtual async Task<IResponseOutput<Trial>> 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<Trial>(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 _trialIdentityUserRepository.AddAsync(new TrialIdentityUser()
{
TrialId = trial.Id,
IdentityUserId = _userInfo.IdentityUserId,
JoinTime = DateTime.Now,
TrialUserRoleList = new List<TrialUserRole>(){
new TrialUserRole(){TrialId=trial.Id,UserId=_userInfo.UserRoleId} }
});
// 添加扩展信息表记录
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<BasicDicSelect>(_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;
}
}
/// <summary>
/// 标记项目删除
/// </summary>
/// <param name="trialId"></param>
/// <returns></returns>
[HttpDelete, Route("{trialId:guid}")]
public async Task<IResponseOutput> MarkTrialDelete(Guid trialId)
{
await _trialRepository.BatchUpdateNoTrackingAsync(t => t.Id == trialId, u => new Trial() { IsDeleted = true });
return ResponseOutput.Ok();
}
/// <summary> 真删除项目 方便清理测试数据 </summary>
/// <param name="trialId">临床试验项目Id</param>
[AllowAnonymous]
[HttpDelete, Route("{trialId:guid}")]
public async Task<IResponseOutput> 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<CheckChallengeDialog>(o => o.SubjectVisit.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<ClinicalDataTrialSet>(o => o.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<InspectionFile>(o => o.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<CriterionNidusSystem>(o => o.TrialReadingCriterion.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<DataInspection>(o => o.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<DicomStudy>(t => t.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<StudyMonitor>(t => t.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<DicomSeries>(t => t.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<DicomInstance>(t => t.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<EnrollReadingCategory>(t => t.Enroll.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<Enroll>(t => t.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<EnrollDetail>(t => t.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<NoneDicomStudyFile>(t => t.NoneDicomStudy.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<NoneDicomStudy>(t => t.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<OrganTrialInfo>(t => t.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<PaymentAdjustment>(t => t.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<PaymentDetail>(t => t.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<PreviousHistory>(t => t.SubjectVisit.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<PreviousOther>(t => t.SubjectVisit.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<PreviousPDF>(t => t.SubjectVisit.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<QCChallengeDialog>(t => t.QCChallenge.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<QCChallenge>(t => t.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<ReadingClinicalDataPDF>(t => t.ReadingClinicalData.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<ReadingClinicalData>(t => t.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<ReadingGlobalTaskInfo>(t => t.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<ReadingJudgeInfo>(t => t.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<ReadingMedicalReviewDialog>(t => t.TaskMedicalReview.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<ReadingMedicineQuestionAnswer>(t => t.TaskMedicalReview.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<ReadingMedicineTrialQuestion>(t => t.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<ReadingOncologyTaskInfo>(t => t.VisitTask.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<ReadingPeriodPlan>(t => t.ReadingPeriodSet.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<ReadingPeriodSet>(t => t.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<ReadingQuestionTrial>(t => t.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<ReadingTableAnswerRowInfo>(t => t.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<ReadingTableQuestionAnswer>(t => t.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<ReadingTableQuestionTrial>(t => t.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<ReadingTaskQuestionAnswer>(t => t.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<ReadingTaskRelation>(t => t.VisitTask.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<ReadModule>(t => t.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<ReadingTaskQuestionAnswer>(t => t.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<SubjectCanceDoctor>(t => t.Subject.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<SubjectUser>(t => t.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<Subject>(t => t.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<SubjectVisit>(t => t.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<TaskAllocationRule>(t => t.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<TaskConsistentRule>(t => t.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<TaskInfluence>(t => t.InfluenceTask.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<TaskMedicalReview>(t => t.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<TaskMedicalReviewRule>(t => t.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<TrialStateChange>(t => t.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<TrialPaymentPrice>(t => t.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<Trial>(o => o.Id == trialId);
await _repository.BatchDeleteNoTrackingAsync<TrialClinicalDataSetCriterion>(t => t.TrialReadingCriterion.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<TrialCriterionDictionaryCode>(t => t.TrialReadingCriterion.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<ReadingQuestionCriterionTrial>(t => t.TrialId == trialId);
await _trialDictionaryRepository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<TrialDocConfirmedUser>(t => t.TrialDocument.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<TrialDocument>(t => t.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<TrialDocNeedConfirmedUserType>(t => t.TrialDocument.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<TrialEmailNoticeUser>(t => t.TrialEmailNoticeConfig.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<TrialEmailNoticeConfig>(t => t.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<TrialExternalUser>(t => t.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<TrialPaymentPrice>(t => t.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<TrialQCQuestion>(t => t.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<TrialQCQuestionAnswer>(t => t.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<TrialRevenuesPrice>(t => t.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<TrialRevenuesPriceVerification>(t => t.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<TrialSign>(t => t.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<TrialSite>(t => t.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<TrialSiteSurvey>(t => t.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<TrialSiteUserSurvey>(t => t.TrialSiteSurvey.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<TrialSiteEquipmentSurvey>(t => t.TrialSiteSurvey.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<TrialUserRole>(t => t.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<TrialSiteUserRole>(t => t.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<VisitStage>(t => t.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<VisitPlanInfluenceStat>(t => t.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<VisitPlanInfluenceStudy>(t => t.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<VisitTaskReReading>(t => t.OriginalReReadingTask.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<VisitTask>(t => t.TrialId == trialId);
await _repository.BatchDeleteNoTrackingAsync<TrialStateChange>(t => t.TrialId == trialId);
#endregion
return ResponseOutput.Ok();
}
else
{
//---当前运行环境下,不允许删除项目数据。
return ResponseOutput.NotOk(_localizer["Trial_CannotDeleteProject"]);
}
}
[HttpPost]
public async Task<PageOutput<TrialDetailDTO>> 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<TrialDetailDTO>(_mapper.ConfigurationProvider, new { userTypeEnumInt = _userInfo.UserTypeEnumInt, userId = _userInfo.UserRoleId, isEn_Us = _userInfo.IsEn_Us });
return await query.ToPagedListAsync(inQuery, nameof(TrialDetailDTO.CreateTime));
}
/// <summary>
/// 根据项目Id 获取医生Id用于触发计算费用
/// </summary>
public async Task<List<Guid>> GetTrialEnrollmentReviewerIds(Guid trialId)
{
return await _enrollRepository.Where(u => u.TrialId == trialId &&
u.EnrollStatus >= EnrollStatus.DoctorReading).Select(u => u.DoctorId).Distinct().ToListAsync();
}
#region 医生用户接口
/// <summary> 分页获取医生参与的临床实验项目列表(查询条件)</summary>
/// <returns></returns>
[HttpPost]
public async Task<PageOutput<TrialDetailDTO>> 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.TrialIdentityUserList.Any(t => t.IdentityUserId == _userInfo.IdentityUserId))
.ProjectTo<TrialDetailDTO>(_mapper.ConfigurationProvider, new { userTypeEnumInt = _userInfo.UserTypeEnumInt, userId = _userInfo.UserRoleId, isEn_Us = _userInfo.IsEn_Us });
return await query.ToPagedListAsync(inQuery, nameof(TrialDetailDTO.CreateTime));
}
/// <summary>
/// 医生确认入组或拒绝入组
/// </summary>
/// <param name="trialId">项目Id</param>
/// <param name="status">9-拒绝入组10-确认入组</param>
/// <returns></returns>
[HttpPost("{trialId:guid}/{status:int}")]
[TrialGlobalLimit("AfterStopCannNotOpt")]
public async Task<IResponseOutput> 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
}
}