using IRaCIS.Application.Interfaces; using IRaCIS.Application.Contracts; using IRaCIS.Core.Infra.EFCore; using IRaCIS.Core.Application.Filter; using IRaCIS.Core.Domain.Share; using Microsoft.AspNetCore.Mvc; using IRaCIS.Core.Application.Service.Inspection.Interface; using IRaCIS.Core.Infrastructure; using Newtonsoft.Json; using IRaCIS.Core.Domain.Common; namespace IRaCIS.Application.Services { [ApiExplorerSettings(GroupName = "Trial")] public class SubjectService : BaseService, ISubjectService { private readonly IRepository _subjectRepository; private readonly IInspectionService _inspectionService; private readonly IRepository _subjectVisitRepository; public SubjectService(IRepository subjectRepository, IInspectionService inspectionService,IRepository subjectVisitRepository) { _subjectRepository = subjectRepository; _inspectionService = inspectionService; _subjectVisitRepository = subjectVisitRepository; } /// /// 添加或更新受试者信息[New] /// /// state:1-访视中,2-出组。0-全部 /// [TrialAudit(AuditType.SubjectAudit, AuditOptType.AddOrUpdateSubject)] [TypeFilter(typeof(TrialResourceFilter))] public async Task> AddOrUpdateSubject([FromBody] SubjectCommand subjectCommand) { var svlist = new List(); if (await _repository.AnyAsync(t => t.Id == subjectCommand.TrialId && !t.VisitPlanConfirmed)) { return ResponseOutput.NotOk("The trial visit plan has not been confirmed yet.Please contact the project manager to confirm the visit plan before adding subject."); } var verifyExp1 = new EntityVerifyExp() { VerifyExp = u => u.Code == subjectCommand.Code && u.TrialId == subjectCommand.TrialId, VerifyMsg = "A subjects with the same subject ID already existed in this trial." }; bool isadd = false; Subject mapedSubject = null; if (subjectCommand.Id == null) //insert { isadd = true; mapedSubject= await _subjectRepository.InsertFromDTOAsync(subjectCommand, false, verifyExp1); //添加受试者的时候,获取访视计划列表,添加到受试者访视表。 var visitPlan = await _repository.Where(t => t.TrialId == subjectCommand.TrialId).ToListAsync(); svlist = _mapper.Map>(visitPlan); var IsEnrollementQualificationConfirm = await _repository.Where(t => t.Id == mapedSubject.TrialId).Select(u => u.IsEnrollementQualificationConfirm).FirstOrDefaultAsync(); svlist.ForEach(t => { t.SubjectId = mapedSubject.Id; t.TrialId = subjectCommand.TrialId; t.SiteId = subjectCommand.SiteId; t.IsEnrollmentConfirm = t.IsBaseLine ? IsEnrollementQualificationConfirm : false; }); await _subjectVisitRepository.AddRangeAsync(svlist); } else //update { mapedSubject = await _subjectRepository.UpdateFromDTOAsync(subjectCommand, false,false, verifyExp1/*, verifyExp2*/); } await _repository.SaveChangesAsync(); var createtime = DateTime.Now.AddSeconds(1); // 添加稽查记录 if (isadd) { List datas = new List(); // 移到仓储了 //datas.Add(new DataInspection() //{ // TrialId = subjectCommand.TrialId, // SiteId = subjectCommand.SiteId, // SubjectId = mapedSubject.Id, // SubjectCode = subjectCommand.Code, // IsSign=false, // CreateTime = createtime, // Identification = "Init|Subject|Status|Subject", // JsonDetail= JsonConvert.SerializeObject(new { // Status= "新增", // }) //}); JsonSerializerSettings settings = new JsonSerializerSettings(); settings.PreserveReferencesHandling = PreserveReferencesHandling.Objects; settings.ReferenceLoopHandling = ReferenceLoopHandling.Serialize; //var jsonData = JsonConvert.SerializeObject(info, settings); var visittime = createtime.AddSeconds(1); foreach (var item in svlist) { // 添加访视 datas.Add(new DataInspection() { TrialId = subjectCommand.TrialId, SiteId = subjectCommand.SiteId, SubjectId = mapedSubject.Id, SubjectCode = subjectCommand.Code, SubjectVisitId = item.Id, SubjectVisitName = item.VisitName, BlindName = item.BlindName, IsSign = false, CreateTime = visittime, Identification = "Add|Visit|Info|Visit-Image Upload", JsonDetail = item.ToJcJson() }); // 初始化访视 datas.Add(new DataInspection() { TrialId = subjectCommand.TrialId, SiteId = subjectCommand.SiteId, SubjectId = mapedSubject.Id, SubjectCode = subjectCommand.Code, SubjectVisitId = item.Id, BlindName = item.BlindName, SubjectVisitName = item.VisitName, IsSign = false, CreateTime = visittime.AddSeconds(1), Identification = "Init|Visit|Status|Visit-Image Upload", JsonDetail = item.ToJcJson() }); } await _inspectionService.AddListInspectionRecordAsync(datas); } return ResponseOutput.Ok(mapedSubject.Id.ToString()); } [HttpPut("{trialId:guid}")] [UnitOfWork] public async Task UpdateSubjectStatus(SubjectStatusChangeCommand subjectStatusChangeCommand) { var dbBeforeSubject = await _subjectRepository.UpdateFromDTOAsync(subjectStatusChangeCommand, true); //如果是出组了 if (subjectStatusChangeCommand.Status == SubjectStatus.OutOfVisit) { if (subjectStatusChangeCommand.FinalSubjectVisitId != null) { if (await _subjectVisitRepository.AnyAsync(t => t.SubjectId == subjectStatusChangeCommand.SubjectId && t.IsFinalVisit && t.Id != subjectStatusChangeCommand.FinalSubjectVisitId)) { throw new BusinessValidationFailedException( "该受试者已经有访视设置为末次访视,不允许将该访视设置为末次访视"); } var sv = await _subjectVisitRepository.FirstOrDefaultAsync(t => t.Id == subjectStatusChangeCommand.FinalSubjectVisitId).IfNullThrowException(); if (await _subjectVisitRepository.AnyAsync(t => t.SubjectId == subjectStatusChangeCommand.SubjectId && t.VisitNum > sv.VisitNum && t.SubmitState == SubmitStateEnum.ToSubmit)) { throw new BusinessValidationFailedException( "该受试者此访视后有影像上传,该访视不允许设置为末次访视"); } sv.IsFinalVisit = true; //末次访视后的 访视设置为不可用 await _subjectVisitRepository.BatchUpdateAsync(t => t.SubjectId == subjectStatusChangeCommand.SubjectId && t.VisitNum > sv.VisitNum, u => new SubjectVisit() { VisitExecuted = VisitExecutedEnum.Unavailable }); } //将受试者未执行的 设置为不可用 await _subjectVisitRepository.BatchUpdateAsync(t => t.SubjectId == dbBeforeSubject.Id && t.VisitExecuted == VisitExecutedEnum.UnExecuted, u => new SubjectVisit() { VisitExecuted = VisitExecutedEnum.Unavailable }); } await _repository.SaveChangesAsync(); return ResponseOutput.Ok(); } [HttpDelete("{id:guid}/{trialId:guid}")] [TrialAudit(AuditType.SubjectAudit, AuditOptType.DeleteSubject)] [TypeFilter(typeof(TrialResourceFilter))] public async Task DeleteSubject(Guid id) { if (await _subjectVisitRepository.AnyAsync(u => u.SubjectId == id && u.VisitExecuted == VisitExecutedEnum.Executed)) { return ResponseOutput.NotOk("This subject has executed a visit with uploading study images,and couldn't be deleted."); } var isSuccess = await _subjectRepository.BatchDeleteAsync(u => u.Id == id); await _subjectVisitRepository.TrackingBatchDeleteAsync(u => u.SubjectId == id); var subvisit = await _subjectVisitRepository.Where(x => x.SubjectId == id).ToListAsync(); List datas = new List(); foreach (var item in subvisit) { datas.Add(new DataInspection() { SiteId = item.SiteId, SubjectId = item.SubjectId, TrialId = item.TrialId, SubjectVisitId = item.Id, Identification = "Delete|Visit|Data|Visit-Image Upload", JsonDetail = JsonConvert.SerializeObject(item) }); }; await _inspectionService.AddListInspectionRecordAsync(datas); return ResponseOutput.Result(isSuccess); } /// 分页获取受试者列表[New] /// /// state:1-访视中,2-出组。0-全部 [HttpPost] public async Task, TrialSubjectConfig>> GetSubjectList(SubjectQueryParam param) { var subjectQuery = _subjectRepository.Where(u => u.TrialId == param.TrialId) .WhereIf(!string.IsNullOrWhiteSpace(param.Code), t => t.Code.Contains(param.Code)) .WhereIf(!string.IsNullOrWhiteSpace(param.Name), t => t.ShortName.Contains(param.Name)) .WhereIf(!string.IsNullOrWhiteSpace(param.Sex), t => t.Sex.Contains(param.Sex)) .WhereIf(param.Status != null, t => t.Status == param.Status) .WhereIf(param.SiteId != null, t => t.SiteId == param.SiteId) // CRC 只负责他管理site的受试者 .WhereIf(_userInfo.UserTypeEnumInt == (int)UserTypeEnum.ClinicalResearchCoordinator, t => t.TrialSite.CRCUserList.Any(t => t.UserId == _userInfo.Id)) .ProjectTo(_mapper.ConfigurationProvider); var pageList = await subjectQuery.ToPagedListAsync(param.PageIndex, param.PageSize, param.SortField == string.Empty ? "Code" : param.SortField, param.Asc); var trialConfig = await _repository.Where(t => t.Id == param.TrialId).ProjectTo(_mapper.ConfigurationProvider).FirstOrDefaultAsync().IfNullThrowException(); return ResponseOutput.Ok(pageList, trialConfig); } /// /// 计划外访视 获取受试者选择下拉框列表 /// [HttpGet("{siteId:guid}/{trialId:guid}")] public List GetSubjectListBySiteId(Guid siteId, Guid trialId) { var query = _subjectRepository.Where(t => t.SiteId == siteId && t.TrialId == trialId && t.Status == SubjectStatus.OnVisit).Select(u => new SubjectSelect() { Code = u.Code, FirstName = u.FirstName, LastName = u.LastName, Sex = u.Sex, SubjectId = u.Id, Age = u.Age, MRN = u.MedicalNo, Status = u.Status, FirstGiveMedicineTime = u.FirstGiveMedicineTime }); return query.ToList(); } [Obsolete] [HttpGet("{trialId:guid}/{subjectId:guid}/{finalSubjectVisitId:guid}")] public async Task VerifySubjectFinalVisit(Guid subjectId, Guid finalSubjectVisitId) { if (await _repository.AnyAsync(t => t.SubjectId == subjectId && t.IsFinalVisit)) { return ResponseOutput.NotOk("该受试者已经有访视设置为末次访视,不允许将该访视设置为末次访视"); } var sv = (await _repository.FirstOrDefaultAsync(t => t.Id == finalSubjectVisitId)).IfNullThrowException(); if (await _repository.AnyAsync(t => t.SubjectId == subjectId && t.VisitNum > sv.VisitNum && t.SubmitState == SubmitStateEnum.ToSubmit)) { return ResponseOutput.NotOk("该受试者此访视后有影像上传,该访视不允许设置为末次访视"); } return ResponseOutput.Ok(); } } }