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 IRaCIS.Core.Application.Service.Reading.Dto; using MassTransit; using System.ComponentModel.DataAnnotations; using System.Reflection; using IRaCIS.Core.Infra.EFCore.Common; using IRaCIS.Core.Application.Contracts; using IRaCIS.Core.Application.Service.Inspection.DTO; using Panda.DynamicWebApi.Attributes; using Microsoft.Extensions.DependencyInjection; namespace IRaCIS.Application.Services { /// /// 阅片临床数据 /// [ApiExplorerSettings(GroupName = "Reading")] public class ReadingClinicalDataService : BaseService, IReadingClinicalDataService { private readonly IRepository _readingClinicalDataRepository; private readonly IRepository _clinicalDataTrialSetRepository; private readonly IRepository _visitTaskRepository; private readonly IRepository _previousPDFRepository; private readonly IRepository _subjectVisitRepository; private readonly IRepository _previousHistoryRepository; private readonly IRepository _previousOtherRepository; private readonly IRepository _previousSurgeryRepository; private readonly IServiceProvider iServiceProvider; private readonly IRepository _subjectRepository; private readonly IRepository _readModuleRepository; private readonly IRepository _readingClinicalDataPDFRepository; public ReadingClinicalDataService(IRepository readingClinicalDataRepository, IRepository clinicalDataTrialSetRepository, IRepository previousPDFRepository, IRepository subjectVisitRepository, IRepository previousHistoryRepository, IRepository previousOtherRepository, IRepository previousSurgeryRepository, IServiceProvider IServiceProvider, IRepository subjectRepository, IRepository readModuleRepository, IRepository readingClinicalDataPDFRepository, IRepository visitTaskRepository) { this._readingClinicalDataRepository = readingClinicalDataRepository; this._clinicalDataTrialSetRepository = clinicalDataTrialSetRepository; this._previousPDFRepository = previousPDFRepository; this._subjectVisitRepository = subjectVisitRepository; this._previousHistoryRepository = previousHistoryRepository; this._previousOtherRepository = previousOtherRepository; this._previousSurgeryRepository = previousSurgeryRepository; this.iServiceProvider = IServiceProvider; this._subjectRepository = subjectRepository; this._readModuleRepository = readModuleRepository; this._readingClinicalDataPDFRepository = readingClinicalDataPDFRepository; this._visitTaskRepository = visitTaskRepository; } /// /// 新增或者修改 /// /// /// [HttpPost] public async Task AddOrUpdateReadingClinicalData(AddOrUpdateReadingClinicalDataDto indto) { var existsQuery = _readingClinicalDataRepository .WhereIf(indto.Id != null, x => x.Id != indto.Id) .Where(x => x.ClinicalDataTrialSetId == indto.ClinicalDataTrialSetId && x.ReadingId == indto.ReadingId); if (await existsQuery.AnyAsync()) { return ResponseOutput.NotOk("存在同类型的临床数据"); } var clinicalDataTrialSet = (await _clinicalDataTrialSetRepository.Where(x => x.Id == indto.ClinicalDataTrialSetId).FirstOrDefaultAsync()).IfNullThrowException(); if (indto.Id == null) { var entity = _mapper.Map(indto); entity.ReadingClinicalDataPDFList = indto.AddFileList.Select(x => new ReadingClinicalDataPDF() { TrialId = entity.TrialId, SubjectId = indto.SubjectId, FileName = x.FileName, Path = x.Path, ClinicalDataTrialSetId = indto.ClinicalDataTrialSetId, IsVisit = indto.IsVisit, ClinicalDataLevel = clinicalDataTrialSet.ClinicalDataLevel, ReadingId = indto.ReadingId }).ToList(); entity.ReadingClinicalDataState = ReadingClinicalDataStatus.HaveUploaded; entity.IsBlind = null; entity.IsComplete = null; await _readingClinicalDataRepository.AddAsync(entity, true); var success = await _readingClinicalDataRepository.SaveChangesAsync(); return ResponseOutput.Ok(entity.Id); } else { var entity = (await _readingClinicalDataRepository.Where(t => t.Id == indto.Id, true).FirstOrDefaultAsync()).IfNullThrowException(); _mapper.Map(indto, entity); await _readingClinicalDataPDFRepository.DeleteFromQueryAsync(x => indto.DeleteFileIds.Contains(x.Id)); await _readingClinicalDataRepository.SaveChangesAsync(); var addFileList = indto.AddFileList.Select(x => new ReadingClinicalDataPDF() { TrialId = entity.TrialId, SubjectId = indto.SubjectId, FileName = x.FileName, Path = x.Path, ClinicalDataTrialSetId = indto.ClinicalDataTrialSetId, IsVisit = indto.IsVisit, ClinicalDataLevel = clinicalDataTrialSet.ClinicalDataLevel, ReadingId = indto.ReadingId, ReadingClinicalDataId = entity.Id, }).ToList(); entity.ReadingClinicalDataState = ReadingClinicalDataStatus.HaveUploaded; await _readingClinicalDataPDFRepository.AddRangeAsync(addFileList); var success = await _readingClinicalDataRepository.SaveChangesAsync(); return ResponseOutput.Ok(entity.Id); } } /// /// 获取CRC上传的文件 /// /// /// [HttpPost] public async Task> GetCRCClinicalData(GetCRCClinicalDataInDto inDto) { await this.AddCRCClinicalData(inDto); List cRCClinicalDataList = await _readingClinicalDataRepository.Where(x => x.ReadingId == inDto.SubjectVisitId) .Where(x => x.ClinicalDataTrialSet.TrialId == inDto.TrialId && x.ClinicalDataTrialSet.UploadRole == UploadRole.CRC && x.ClinicalDataTrialSet.ClinicalDataLevel != ClinicalLevel.ImageRead && x.ClinicalDataTrialSet.ClinicalDataLevel != ClinicalLevel.OncologyRead && x.ClinicalDataTrialSet.IsConfirm) .Select(x => new GetCRCClinicalDataOutDto() { Id = x.Id, ClinicalDataSetName = x.ClinicalDataTrialSet.ClinicalDataSetName, ClinicalUploadType = x.ClinicalDataTrialSet.ClinicalUploadType, ClinicalDataTrialSetId = x.ClinicalDataTrialSet.Id, FileName = x.ClinicalDataTrialSet.FileName, UploadRole = x.ClinicalDataTrialSet.UploadRole, Path = x.ClinicalDataTrialSet.Path, IsBlind=x.IsBlind, IsComplete=x.IsComplete }).ToListAsync(); List clinicalData = (await this.GetReadingClinicalDataList(new GetReadingClinicalDataListIndto() { SubjectId = inDto.SubjectId, ReadingId = inDto.SubjectVisitId, TrialId = inDto.TrialId, })).Item1; var previousHistoryList = await _previousHistoryRepository.Where(x => x.SubjectVisitId == inDto.SubjectVisitId).ProjectTo(_mapper.ConfigurationProvider).ToListAsync(); var previousOtherList = await _previousOtherRepository.Where(x => x.SubjectVisitId == inDto.SubjectVisitId).ProjectTo(_mapper.ConfigurationProvider).ToListAsync(); var previousSurgeryList = await _previousSurgeryRepository.Where(x => x.SubjectVisitId == inDto.SubjectVisitId).ProjectTo(_mapper.ConfigurationProvider).ToListAsync(); foreach (var item in cRCClinicalDataList) { item.PDFFileList = clinicalData.Where(y => y.ClinicalDataTrialSetId == item.ClinicalDataTrialSetId).SelectMany(x => x.FileList).ToList(); item.ClinicalTableData = new ClinicalDataTable() { PreviousHistoryList = previousHistoryList.Where(x => x.ClinicalDataTrialSetId == item.ClinicalDataTrialSetId).ToList(), PreviousOtherList = previousOtherList.Where(x => x.ClinicalDataTrialSetId == item.ClinicalDataTrialSetId).ToList(), PreviousSurgeryList = previousSurgeryList.Where(x => x.ClinicalDataTrialSetId == item.ClinicalDataTrialSetId).ToList(), }; } return cRCClinicalDataList; } /// /// 添加CRC数据类型 /// /// private async Task AddCRCClinicalData(GetCRCClinicalDataInDto inDto) { var cRCClinicalDataIds = await _clinicalDataTrialSetRepository.Where(x => x.TrialId == inDto.TrialId && x.UploadRole == UploadRole.CRC && x.ClinicalDataLevel != ClinicalLevel.ImageRead && x.ClinicalDataLevel != ClinicalLevel.OncologyRead && x.IsConfirm).Select(x => x.Id).ToListAsync(); var needAddIds = cRCClinicalDataIds.Where(x => _readingClinicalDataRepository.Where(y => y.ReadingId == inDto.SubjectVisitId && x == y.ClinicalDataTrialSetId).Count() == 0).ToList(); List readingClinicals = needAddIds.Select(x => new ReadingClinicalData() { ClinicalDataTrialSetId = x, IsVisit = true, SubjectId = inDto.SubjectId, ReadingId = inDto.SubjectVisitId, TrialId = inDto.TrialId }).ToList(); await _readingClinicalDataRepository.AddRangeAsync(readingClinicals); await _readingClinicalDataRepository.SaveChangesAsync(); } ///// ///// 设置临床数据是否盲化 ///// ///// //[HttpPost] //public async Task SetReadingClinicalDataIsBlind(SetReadingClinicalDataIsBlind inDto) //{ // await _readingClinicalDataRepository.UpdatePartialFromQueryAsync(inDto.Id, x=>new ReadingClinicalData() { // IsBlind=inDto.IsBlind, // }); // return ResponseOutput.Ok(await _readingClinicalDataRepository.SaveChangesAsync()); //} /// /// 删除 /// /// /// [HttpDelete("{id:guid}")] public async Task DeleteReadingClinicalData(Guid id) { await _readingClinicalDataRepository.DeleteFromQueryAsync(x => x.Id == id, true); await _readingClinicalDataPDFRepository.DeleteFromQueryAsync(x => x.ReadingClinicalDataId == id, true); return ResponseOutput.Result(true); } /// /// 获取下拉菜单 /// /// /// [HttpPost] public async Task> GetTrialClinicalDataSelect(GetTrialClinicalDataSelectIndto inDto) { var userTypes = new List() { (int)UserTypeEnum.ProjectManager, (int)UserTypeEnum.SPM, (int)UserTypeEnum.CPM, (int)UserTypeEnum.IndependentReviewer, }; if (userTypes.Contains(_userInfo.UserTypeEnumInt)) { inDto.UploadRole = UploadRole.PM; } ReadModule readModule = null; if (inDto.ReadingId != null) { readModule = await _readModuleRepository.Where(x => x.Id ==inDto.ReadingId).FirstOrDefaultAsync(); } Dictionary keyValuePairs = new Dictionary(); keyValuePairs.Add(ModuleTypeEnum.Global, ClinicalLevel.ImageRead); keyValuePairs.Add(ModuleTypeEnum.Oncology, ClinicalLevel.OncologyRead); var usedIdsQuery = _readingClinicalDataRepository.Where(x => x.ReadingId == inDto.ReadingId && x.Id != inDto.ReadingClinicalDataId).Select(x => x.ClinicalDataTrialSetId); List clinicalList = await _clinicalDataTrialSetRepository.Where(x => x.TrialId == inDto.TrialId && x.IsConfirm) .WhereIf(inDto.UploadRole != null, x => x.UploadRole == inDto.UploadRole) .Where(x => !usedIdsQuery.Contains(x.Id)) .WhereIf(inDto.IsVisit && inDto.IsBaseLine, x => x.ClinicalDataLevel == ClinicalLevel.Subject || x.ClinicalDataLevel == ClinicalLevel.SubjectVisit) .WhereIf(inDto.IsVisit && !inDto.IsBaseLine, x => x.ClinicalDataLevel == ClinicalLevel.SubjectVisit) .WhereIf(!inDto.IsVisit, x => x.ClinicalDataLevel == ClinicalLevel.ImageRead||x.ClinicalDataLevel==ClinicalLevel.OncologyRead) .WhereIf(readModule!=null, x => x.ClinicalDataLevel == keyValuePairs[readModule.ModuleType]) .Select(x => new GetTrialClinicalDataSelectOutDto() { ClinicalDataLevel = x.ClinicalDataLevel, ClinicalDataSetName = x.ClinicalDataSetName, ClinicalUploadType = x.ClinicalUploadType, FileName = x.FileName, Path = x.Path, Id = x.Id }).ToListAsync(); return clinicalList; } /// /// 影像阅片临床数据签名 /// // [HttpPost] public async Task ReadClinicalDataSign(ReadingClinicalDataSignIndto inDto) { await _readingClinicalDataRepository.UpdatePartialFromQueryAsync(x => x.Id == inDto.ReadingClinicalDataId, x => new ReadingClinicalData() { IsSign = true, ReadingClinicalDataState=ReadingClinicalDataStatus.HaveSigned }); var result = await _readingClinicalDataRepository.SaveChangesAsync(); var readingId = await _readingClinicalDataRepository.Where(x => x.Id == inDto.ReadingClinicalDataId).Select(x => x.ReadingId).FirstOrDefaultAsync(); await this.iServiceProvider.GetService().AddOncologyTask(readingId); return ResponseOutput.Result(result); } /// /// 获取访视 阅片或任务临床数据 /// /// /// [HttpPost] public async Task<(List, object)> GetReadingOrTaskClinicalDataList(GetReadingOrTaskClinicalDataListInDto inDto) { var readingNameOrTaskBlindName = string.Empty; if (inDto.ReadingId == null) { var visitTask = await _visitTaskRepository.FirstOrDefaultAsync(x => x.Id == inDto.VisitTaskId); inDto.ReadingId = visitTask.SouceReadModuleId ?? visitTask.SourceSubjectVisitId; readingNameOrTaskBlindName = visitTask.TaskBlindName; } if (readingNameOrTaskBlindName.IsNullOrEmpty()) { readingNameOrTaskBlindName = await _subjectVisitRepository.Where(x => x.Id == inDto.ReadingId).Select(x => x.VisitName).FirstOrDefaultAsync(); if (readingNameOrTaskBlindName.IsNullOrEmpty()) { readingNameOrTaskBlindName = await _readModuleRepository.Where(x => x.Id == inDto.ReadingId).Select(x => x.ModuleName).FirstOrDefaultAsync(); } } var result = await GetClinicalDataList(inDto); var previousHistoryList = await _previousHistoryRepository.Where(x => x.SubjectVisitId == inDto.ReadingId).ProjectTo(_mapper.ConfigurationProvider).ToListAsync(); var previousOtherList = await _previousOtherRepository.Where(x => x.SubjectVisitId == inDto.ReadingId).ProjectTo(_mapper.ConfigurationProvider).ToListAsync(); var previousSurgeryList = await _previousSurgeryRepository.Where(x => x.SubjectVisitId == inDto.ReadingId).ProjectTo(_mapper.ConfigurationProvider).ToListAsync(); foreach (var item in result) { item.ClinicalTableData = new ClinicalDataTable() { PreviousHistoryList = previousHistoryList.Where(x => x.ClinicalDataTrialSetId == item.ClinicalDataTrialSetId).ToList(), PreviousOtherList = previousOtherList.Where(x => x.ClinicalDataTrialSetId == item.ClinicalDataTrialSetId).ToList(), PreviousSurgeryList = previousSurgeryList.Where(x => x.ClinicalDataTrialSetId == item.ClinicalDataTrialSetId).ToList(), }; } return (result, new { SubjectCode = await _subjectRepository.Where(x => x.Id == inDto.SubjectId).Select(x => x.Code).FirstOrDefaultAsync(), ReadingNameOrTaskBlindName = readingNameOrTaskBlindName, }); } [NonDynamicMethod] public async Task> GetClinicalDataList(GetReadingOrTaskClinicalDataListInDto inDto) { if (inDto.ReadingId == null) { var visitTask = await _visitTaskRepository.FirstOrDefaultAsync(x => x.Id == inDto.VisitTaskId); inDto.ReadingId = visitTask.SouceReadModuleId ?? visitTask.SourceSubjectVisitId; } var resultQuery = _readingClinicalDataRepository.Where(x => x.SubjectId == inDto.SubjectId) .WhereIf(inDto.ReadingClinicalDataId != null, x => x.Id == inDto.ReadingClinicalDataId) .Where(x => x.ReadingId == inDto.ReadingId || (x.SubjectId == inDto.SubjectId && x.ClinicalDataTrialSet.ClinicalDataLevel == ClinicalLevel.Subject)) .Select(x => new GetReadingClinicalDataListOutDto() { ClinicalDataLevel = x.ClinicalDataTrialSet.ClinicalDataLevel, SubjectId = x.SubjectId, ClinicalDataSetName = x.ClinicalDataTrialSet.ClinicalDataSetName, ClinicalDataTrialSetId = x.ClinicalDataTrialSetId, IsSign = x.IsSign, ClinicalUploadType = x.ClinicalDataTrialSet.ClinicalUploadType, Id = x.Id, UploadRole = x.ClinicalDataTrialSet.UploadRole, IsCRCUpload = x.ClinicalDataTrialSet.UploadRole == UploadRole.CRC, FileList = x.ReadingClinicalDataPDFList.Select(y => new GetFileDto() { Id = y.Id, FileName = y.FileName, Path = y.Path, CreateTime = y.CreateTime, }).ToList() }); var result = await resultQuery.ToListAsync(); result = result.Where(x => !(x.ClinicalUploadType == ClinicalUploadType.PDF && x.FileList.Count() == 0)).ToList(); return result; } /// /// 获取阅片临床数据列表 /// /// /// [HttpPost] public async Task<(List,object)> GetReadingClinicalDataList(GetReadingClinicalDataListIndto inDto) { GetTrialClinicalDataSelectIndto getTrialClinicalDataSelectIndto = new GetTrialClinicalDataSelectIndto() { ReadingId = inDto.ReadingId, TrialId = inDto.TrialId, IsBaseLine = inDto.IsBaseLine, SubjectId = inDto.SubjectId, IsVisit = inDto.IsVisit, }; var clinicalDataList = await this.GetTrialClinicalDataSelect(getTrialClinicalDataSelectIndto); if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.ClinicalResearchCoordinator || _userInfo.UserTypeEnumInt == (int)UserTypeEnum.IQC) { inDto.UploadRole = UploadRole.CRC; } var isBaseLine = await _subjectVisitRepository.AnyAsync(x => x.Id == inDto.ReadingId && x.IsBaseLine); var result =await this.GetReadingClinicalList(inDto); var previousHistoryList = await _previousHistoryRepository.Where(x => x.SubjectVisitId == inDto.ReadingId).ProjectTo(_mapper.ConfigurationProvider).ToListAsync(); var previousOtherList = await _previousOtherRepository.Where(x => x.SubjectVisitId == inDto.ReadingId).ProjectTo(_mapper.ConfigurationProvider).ToListAsync(); var previousSurgeryList = await _previousSurgeryRepository.Where(x => x.SubjectVisitId == inDto.ReadingId).ProjectTo(_mapper.ConfigurationProvider).ToListAsync(); foreach (var item in result) { item.ClinicalTableData = new ClinicalDataTable() { PreviousHistoryList = previousHistoryList.Where(x => x.ClinicalDataTrialSetId == item.ClinicalDataTrialSetId).ToList(), PreviousOtherList = previousOtherList.Where(x => x.ClinicalDataTrialSetId == item.ClinicalDataTrialSetId).ToList(), PreviousSurgeryList = previousSurgeryList.Where(x => x.ClinicalDataTrialSetId == item.ClinicalDataTrialSetId).ToList(), }; } return (result, new { IsCanAddClinicalData= clinicalDataList.Count()>0, }) ; } [HttpPut] public async Task PMClinicalDataConfirm(PMClinicalDataConfirmCommand command) { await _readingClinicalDataRepository.UpdatePartialFromQueryAsync(t => t.Id == command.Id, u => new ReadingClinicalData() { IsBlind=command.IsBlind, IsComplete=command.IsComplete, ReadingClinicalDataState=ReadingClinicalDataStatus.HaveChecked }); await _readingClinicalDataRepository.SaveChangesAsync(); return ResponseOutput.Ok(); } /// /// 获取临床数据集合 /// /// [NonDynamicMethod] public async Task> GetReadingClinicalList(GetReadingClinicalDataListIndto inDto) { var resultQuery = _readingClinicalDataRepository.Where(x => x.SubjectId == inDto.SubjectId) .Where(x => x.ReadingId == inDto.ReadingId) .WhereIf(inDto.UploadRole == UploadRole.CRC, x => x.ClinicalDataTrialSet.UploadRole == UploadRole.CRC) .Select(x => new GetReadingClinicalDataListOutDto() { ClinicalDataLevel = x.ClinicalDataTrialSet.ClinicalDataLevel, SubjectId = x.SubjectId, ClinicalDataSetName = x.ClinicalDataTrialSet.ClinicalDataSetName, ClinicalDataTrialSetId = x.ClinicalDataTrialSetId, IsSign = x.IsSign, ClinicalUploadType = x.ClinicalDataTrialSet.ClinicalUploadType, Id = x.Id, UploadRole = x.ClinicalDataTrialSet.UploadRole, IsCRCUpload = x.ClinicalDataTrialSet.UploadRole == UploadRole.CRC, IsBlind=x.IsBlind, IsComplete=x.IsComplete, ReadingClinicalDataState=x.ReadingClinicalDataState, FileList = x.ReadingClinicalDataPDFList.Select(y => new GetFileDto() { Id = y.Id, FileName = y.FileName, Path = y.Path, CreateTime = y.CreateTime, }).ToList() }); var result = await resultQuery.ToListAsync(); result = result.Where(x => !(x.UploadRole == UploadRole.CRC && x.ClinicalUploadType == ClinicalUploadType.PDF && x.FileList.Count() == 0)).ToList(); return result; } /// /// 获取单个阅片临床数据的所有文件 /// /// /// [HttpPost] public async Task> GetReadingClinicalDataPDFList(GetReadingClinicalDataPDFListIndto inDto) { var result = await _readingClinicalDataPDFRepository.Where(x => x.ReadingClinicalDataId == inDto.ReadingClinicalDataId).ProjectTo(_mapper.ConfigurationProvider) .ToPagedListAsync(inDto.PageIndex, inDto.PageSize, inDto.SortField == null ? nameof(GetReadingClinicalDataPDFListOutDto.FileName) : inDto.SortField, inDto.Asc); return result; } /// /// 删除PDF单个文件 /// /// /// [HttpDelete("{id:guid}")] public async Task DeleteReadingClinicalDataPDF(Guid id) { await _readingClinicalDataPDFRepository.DeleteFromQueryAsync(x => x.Id == id, true); return ResponseOutput.Result(true); } } }