using Microsoft.AspNetCore.Mvc; using IRaCIS.Core.Application.Service.Reading.Dto; using MassTransit; using IRaCIS.Core.Domain.Models; using IRaCIS.Core.Application.Interfaces; using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Infrastructure; using System.Linq; using System.Linq.Expressions; using System; using MathNet.Numerics.Optimization.LineSearch; namespace IRaCIS.Application.Services { /// <summary> /// 临床数据配置 /// </summary> [ApiExplorerSettings(GroupName = "Reading")] public class ClinicalDataSetService : BaseService { public IClinicalQuestionService _iClinicalQuestionService; public IRepository<SubjectVisit> _subjectVisitRepository; private readonly IRepository<ClinicalDataTrialSet> _clinicalDataTrialSetRepository; private readonly IRepository<TrialClinicalDataSetCriterion> _trialClinicalDataSetCriterionRepository; private readonly IRepository<ReadingQuestionCriterionTrial> _iReadingQuestionCriterionTrialRepository; private readonly IRepository<ClinicalDataSystemSet> _clinicalDataSystemSetRepository; private readonly IRepository<PreviousPDF> _previousPDFRepository; private readonly IRepository<Dictionary> _dictionaryRepository; private readonly IRepository<Trial> _trialRepository; private readonly IRepository<TrialClinicalQuestion> _trialClinicalQuestionRepository; private readonly IRepository<SystemClinicalQuestion> _systemClinicalQuestionRepository; public ClinicalDataSetService(IRepository<SubjectVisit> subjectVisitRepository, IClinicalQuestionService iClinicalQuestionService, IRepository<ClinicalDataTrialSet> ClinicalDataTrialSetRepository, IRepository<TrialClinicalDataSetCriterion> trialClinicalDataSetCriterionRepository, IRepository<ReadingQuestionCriterionTrial> iReadingQuestionCriterionTrialRepository, IRepository<ClinicalDataSystemSet> ClinicalDataSystemSetRepository, IRepository<PreviousPDF> previousPDFRepository, IRepository<Dictionary> dictionaryRepository, IRepository<TrialClinicalQuestion> trialClinicalQuestionRepository, IRepository<SystemClinicalQuestion> systemClinicalQuestionRepository, IRepository<Trial> trialRepository ) { _iClinicalQuestionService = iClinicalQuestionService; _subjectVisitRepository = subjectVisitRepository; _trialClinicalQuestionRepository = trialClinicalQuestionRepository; _systemClinicalQuestionRepository = systemClinicalQuestionRepository; _clinicalDataTrialSetRepository = ClinicalDataTrialSetRepository; this._trialClinicalDataSetCriterionRepository = trialClinicalDataSetCriterionRepository; this._iReadingQuestionCriterionTrialRepository = iReadingQuestionCriterionTrialRepository; _clinicalDataSystemSetRepository = ClinicalDataSystemSetRepository; this._previousPDFRepository = previousPDFRepository; this._dictionaryRepository = dictionaryRepository; this._trialRepository = trialRepository; } /// <summary> /// 应用系统临床数据 /// </summary> /// <param name="inDto"></param> /// <returns></returns> /// <exception cref="BusinessValidationFailedException"></exception> [HttpPost] public async Task<IResponseOutput> ApplySystemClinical(ApplySystemClinicalInDto inDto) { var isNeedVerify = await _clinicalDataSystemSetRepository.AnyAsync(x => x.Id == inDto.SystemClinicalId && (x.ClinicalDataLevel == ClinicalLevel.ImageRead || x.ClinicalDataLevel == ClinicalLevel.OncologyRead) && x.ClinicalUploadType == ClinicalUploadType.Structuring && x.UploadRole == UploadRole.CRC ); if (_systemClinicalQuestionRepository.Where(x => x.SystemClinicalId == inDto.SystemClinicalId).Count() == 0) { throw new BusinessValidationFailedException(_localizer["ClinicalComment_dataNotConfigured"]); } if (isNeedVerify&&_systemClinicalQuestionRepository.Where(x => x.SystemClinicalId == inDto.SystemClinicalId && x.IsCheckDate).Count() != 1) { throw new BusinessValidationFailedException(_localizer["ClinicalDataSet_Apply"]); } await _clinicalDataSystemSetRepository.UpdatePartialFromQueryAsync(x => x.Id == inDto.SystemClinicalId, x => new ClinicalDataSystemSet() { IsApply = true }); await _clinicalDataSystemSetRepository.SaveChangesAsync(); return ResponseOutput.Ok(true); } /// <summary> /// 应用项目临床数据 /// </summary> /// <param name="inDto"></param> /// <returns></returns> /// <exception cref="BusinessValidationFailedException"></exception> [HttpPost] public async Task<IResponseOutput> ApplyTrialClinical(ApplyTrialClinicalInDto inDto) { var isNeedVerify = await _clinicalDataTrialSetRepository.AnyAsync(x => x.Id == inDto.TrialClinicalId && (x.ClinicalDataLevel == ClinicalLevel.ImageRead|| x.ClinicalDataLevel==ClinicalLevel.OncologyRead) && x.ClinicalUploadType == ClinicalUploadType.Structuring && x.UploadRole == UploadRole.CRC ); if (_trialClinicalQuestionRepository.Where(x => x.TrialClinicalId == inDto.TrialClinicalId).Count() == 0) { throw new BusinessValidationFailedException(_localizer["ClinicalComment_dataNotConfigured"]); } if (isNeedVerify&&_trialClinicalQuestionRepository.Where(x => x.TrialClinicalId == inDto.TrialClinicalId && x.IsCheckDate).Count() != 1) { throw new BusinessValidationFailedException(_localizer["ClinicalDataSet_Apply"]); } await _clinicalDataTrialSetRepository.UpdatePartialFromQueryAsync(x => x.Id == inDto.TrialClinicalId, x => new ClinicalDataTrialSet() { IsApply = true }); await _clinicalDataTrialSetRepository.SaveChangesAsync(); return ResponseOutput.Ok(true); } #region 系统 /// <summary> /// 新增或者修改(系统) /// </summary> /// <param name="indto"></param> /// <returns></returns> [HttpPost] public async Task<IResponseOutput> AddOrUpdateClinicalDataSystemSet(ClinicalDataSystemSetAddOrEdit indto) { if (indto.ClinicalUploadType == ClinicalUploadType.Table || indto.ClinicalUploadType == ClinicalUploadType.PDF) { indto.IsApply = true; } var dictionary = await _dictionaryRepository.Where(x => x.Parent.Code == "ClinicalDataType" && x.Code == indto.ClinicalDataSetEnum.ToString()).FirstNotNullAsync(); indto.ClinicalDataSetName = dictionary.ValueCN; indto.ClinicalDataSetEnName = dictionary.Value; var existsQuery = _clinicalDataSystemSetRepository .WhereIf(indto.Id != null, x => x.Id != indto.Id) .Where(x => x.ClinicalDataSetName == indto.ClinicalDataSetName||x.ClinicalDataSetEnName==indto.ClinicalDataSetEnName); if (await existsQuery.AnyAsync()) { //---存在同类型的临床数据,操作失败 return ResponseOutput.NotOk(_localizer["ClinicalDataSet_DupTypeFail"]); } indto.CriterionEnumListStr= $"|{String.Join('|', indto.CriterionEnumList)}|"; var entity = await _clinicalDataSystemSetRepository.InsertOrUpdateAsync(indto); //entity.SystemClinicalDataCriterionList = indto.SystemCriterionIdList.Select(t => new SystemClinicalDataCriterion() //{ // SystemClinicalDataSetId = entity.Id, // SystemReadingCriterionId = t //}).ToList(); //if (indto.Id != null) //{ // await _systemClinicalDataCriterionRepository.BatchDeleteNoTrackingAsync(t => t.SystemClinicalDataSetId == entity.Id); // await _systemClinicalDataCriterionRepository.AddRangeAsync(entity.SystemClinicalDataCriterionList); //} await _clinicalDataSystemSetRepository.SaveChangesAsync(); return ResponseOutput.Ok(entity.Id.ToString()); } /// <summary> /// 获取系统临床数据(系统) /// </summary> /// <returns></returns> [HttpPost] public async Task<List<ClinicalDataSystemSetView>> GetSystemClinicalDataSystemSetList(GetTrialClinicalDataSystemIndto inDto) { return await _clinicalDataSystemSetRepository.AsQueryable() .WhereIf(inDto.ClinicalDataLevel != null, x => x.ClinicalDataLevel == inDto.ClinicalDataLevel) .WhereIf(inDto.ClinicalUploadType != null, x => x.ClinicalUploadType == inDto.ClinicalUploadType) .WhereIf(inDto.ClinicalDataSetName != String.Empty, x => x.ClinicalDataSetName.Contains(inDto.ClinicalDataSetName)) .ProjectTo<ClinicalDataSystemSetView>(_mapper.ConfigurationProvider).ToListAsync(); } /// <summary> /// 删除(系统) /// </summary> /// <param name="id"></param> /// <returns></returns> [HttpDelete("{id:guid}")] public async Task<IResponseOutput> DeleteClinicalSystemSetData(Guid id) { await _clinicalDataSystemSetRepository.DeleteFromQueryAsync(x => x.Id == id, true); return ResponseOutput.Result(true); } #endregion #region 项目 /// <summary> /// 新增或者修改(项目) /// </summary> /// <param name="indto"></param> /// <returns></returns> [HttpPost] public async Task<IResponseOutput> AddOrUpdateClinicalDataTrialSet(ClinicalDataTrialSetAddOrEdit indto) { if (indto.ClinicalUploadType == ClinicalUploadType.Table || indto.ClinicalUploadType == ClinicalUploadType.PDF) { indto.IsApply = true; } var existsQuery = _clinicalDataTrialSetRepository .WhereIf(indto.Id != null, x => x.Id != indto.Id) .Where(x => (x.ClinicalDataSetName == indto.ClinicalDataSetName||x.ClinicalDataSetEnName==indto.ClinicalDataSetEnName) && x.TrialId == indto.TrialId); if (await existsQuery.AnyAsync()) { //---存在同类型的临床数据,操作失败 return ResponseOutput.NotOk(_localizer["ClinicalDataSet_DupTypeFail"]); } if (indto.Id != null && indto.IsApply == null) { indto.IsApply = await _clinicalDataTrialSetRepository.Where(x => x.Id == indto.Id).Select(x => x.IsApply).FirstOrDefaultAsync(); } //indto.CriterionEnumListStr = $"|{String.Join('|', indto.CriterionEnumList)}|"; //var entity = _mapper.Map<TEntity>(from); indto.CreateTime = DateTime.Now; var entity = await _clinicalDataTrialSetRepository.InsertOrUpdateAsync(indto); entity.TrialClinicalDataSetCriteriaList = indto.TrialCriterionIdList.Select(t => new TrialClinicalDataSetCriterion() { TrialClinicalDataSetId = entity.Id, TrialReadingCriterionId = t }).ToList(); if (indto.Id != null) { await _trialClinicalDataSetCriterionRepository.DeleteFromQueryAsync(t => t.TrialClinicalDataSetId == entity.Id); await _repository.AddRangeAsync<TrialClinicalDataSetCriterion>(entity.TrialClinicalDataSetCriteriaList); } await _clinicalDataTrialSetRepository.SaveChangesAsync(); return ResponseOutput.Ok(entity.Id.ToString()); } /// <summary> /// 获取项目的临床数据 /// </summary> /// <param name="inDto"></param> /// <returns></returns> [HttpPost] [UnitOfWork] public async Task<List<ClinicalDataTrialSetView>> GetTrialClinicalDataTrialSetList(GetTrialClinicalDataTrialIndto inDto) { await this.AddTrialClinicalDataTrialSet(inDto.TrialId); Expression<Func<ClinicalDataTrialSet, bool>> predicate = null; if (inDto.CriterionIds != null) { List<string> criterionTypes = (await _iReadingQuestionCriterionTrialRepository.Where(x => inDto.CriterionIds.Contains(x.Id)).Select(x => x.CriterionType).ToListAsync()) .Select(x => ((int)x).ToString()).ToList(); predicate = x =>x.SystemClinicalDataSetId == null; foreach (var item in criterionTypes) { Expression<Func<ClinicalDataTrialSet, bool>> typeExpression = x =>x.ClinicalDataSystemSet==null|| x.ClinicalDataSystemSet.CriterionEnumListStr.Contains(item); predicate = predicate.Or(typeExpression); } } var trialClinicalDataList = await _clinicalDataTrialSetRepository.AsQueryable() .Where(x => x.TrialId == inDto.TrialId) .WhereIf(inDto.CriterionIds != null, predicate) .WhereIf(inDto.ClinicalDataLevel != null, x => x.ClinicalDataLevel == inDto.ClinicalDataLevel) .WhereIf(inDto.ClinicalUploadType != null, x => x.ClinicalUploadType == inDto.ClinicalUploadType) .WhereIf(inDto.ClinicalDataSetName != String.Empty, x => x.ClinicalDataSetName.Contains(inDto.ClinicalDataSetName)) .ProjectTo<ClinicalDataTrialSetView>(_mapper.ConfigurationProvider, new { CriterionIds = inDto.CriterionIds }).ToListAsync(); return trialClinicalDataList; } /// <summary> /// 删除(项目) /// </summary> /// <param name="id"></param> /// <returns></returns> [HttpDelete("{id:guid}")] public async Task<IResponseOutput> DeleteClinicalTrialSetData(Guid id) { await _clinicalDataTrialSetRepository.DeleteFromQueryAsync(x => x.Id == id, true); return ResponseOutput.Result(true); } #endregion #region 系统和项目标准下拉 界面上配置和临床数据关联 废弃 //[HttpPost] //public async Task<List<SystemCriterionSelectDto>> GetSystemCriterionSelectList(SystemCriterionSelectQuery inQuery) //{ // return await _repository.Where<ReadingQuestionCriterionSystem>() // .WhereIf(!string.IsNullOrEmpty(inQuery.CriterionName), t => t.CriterionName.Contains(inQuery.CriterionName)) // .WhereIf(inQuery.IsEnable != null, t => t.IsEnable == inQuery.IsEnable) // .WhereIf(inQuery.IsCompleteConfig != null, t => t.IsCompleteConfig == inQuery.IsCompleteConfig) // .Select(t => new SystemCriterionSelectDto() // { // Id = t.Id, // CriterionName = t.CriterionName, // IsCompleteConfig = t.IsCompleteConfig, // IsEnable = t.IsEnable // }).ToListAsync(); //} //[HttpPost] //public async Task<List<TrialCriterionSelectDto>> GetTrialCriterionSelectList(TrialCriterionSelectQuery inQuery) //{ // return await _repository.Where<ReadingQuestionCriterionTrial>(t => t.TrialId == inQuery.TrialId) // .WhereIf(!string.IsNullOrEmpty(inQuery.CriterionName), t => t.CriterionName.Contains(inQuery.CriterionName)) // .WhereIf(inQuery.IsEnable != null, t => t.IsEnable == inQuery.IsEnable) // .WhereIf(inQuery.IsCompleteConfig != null, t => t.IsCompleteConfig == inQuery.IsCompleteConfig) // .Select(t => new TrialCriterionSelectDto() // { // Id = t.Id, // CriterionName = t.CriterionName, // IsCompleteConfig = t.IsCompleteConfig, // IsEnable = t.IsEnable // }).ToListAsync(); //} #endregion #region 将系统配置添加到项目配置 /// <summary> /// 将系统配置添加到项目配置 /// </summary> /// <param name="trialId"></param> /// <returns></returns> private async Task AddTrialClinicalDataTrialSet(Guid trialId) { #region MyRegion //不存在的时候,就将系统数据同步到项目临床数据配置 if (!await _clinicalDataTrialSetRepository.AnyAsync(x => x.TrialId == trialId && x.SystemClinicalDataSetId != null)) { var systemClinicalDataList = await _clinicalDataSystemSetRepository.Where(x=>x.IsApply).AsQueryable().ToListAsync(); var systemIds = systemClinicalDataList.Select(x => x.Id).ToList(); var trialSystemClinicalDataSetIds = await _clinicalDataTrialSetRepository.Where(x => x.TrialId == trialId && x.SystemClinicalDataSetId != null).Select(x => x.SystemClinicalDataSetId.Value).ToListAsync(); var needAddids = systemIds.Except(trialSystemClinicalDataSetIds).ToList(); var systemDataList = systemClinicalDataList.Where(x => needAddids.Contains(x.Id)).ToList(); var readingCriterionList = _repository.Where<ReadingQuestionCriterionTrial>(t => t.TrialId == trialId).Where(t => t.ReadingQuestionCriterionSystemId != null) .Select(t => new { t.ReadingQuestionCriterionSystemId, TrialReadingCriterionId = t.Id ,t.CriterionType}).ToList(); List<ClinicalDataTrialSet> dataSets = systemDataList.Select(x => new ClinicalDataTrialSet() { Id = NewId.NextGuid(), SystemClinicalDataSetId = x.Id, ClinicalDataSetName = x.ClinicalDataSetName, ClinicalDataLevel = x.ClinicalDataLevel, ClinicalUploadType = x.ClinicalUploadType, ClinicalDataSetEnName=x.ClinicalDataSetEnName, UploadRole = x.UploadRole, FileName = x.FileName, Path = x.Path, TrialId = trialId, IsApply = x.IsApply, //项目不采用 标准枚举字符串的方式 //CriterionEnumListStr=x.CriterionEnumListStr TrialClinicalDataSetCriteriaList = readingCriterionList.Where(t => x.CriterionEnumList.Contains( (int )t.CriterionType)).Select(c => new TrialClinicalDataSetCriterion() { TrialReadingCriterionId = c.TrialReadingCriterionId }).ToList() }).ToList(); await _clinicalDataTrialSetRepository.AddRangeAsync(dataSets); var result = await _clinicalDataTrialSetRepository.SaveChangesAsync(); await _iClinicalQuestionService.SynchronizationQuestion(dataSets.Select(x => new SynchronizationQuestionDto() { SystemClinicalId = x.SystemClinicalDataSetId.Value, TrialClinicalId = x.Id, }).ToList()); } #endregion #region OLd //var syncClinicalDataTime = await _trialRepository.Where(x => x.Id == trialId).Select(x => x.SyncClinicalDataTime).FirstOrDefaultAsync(); //if (syncClinicalDataTime == null) //{ // var systemClinicalDataList = await _clinicalDataSystemSetRepository.AsQueryable().Include(t => t.SystemClinicalDataCriterionList).ToListAsync(); // var systemIds = systemClinicalDataList.Select(x => x.Id).ToList(); // var trialSystemClinicalDataSetIds = await _clinicalDataTrialSetRepository.Where(x => x.TrialId == trialId && x.SystemClinicalDataSetId != null).Select(x => x.SystemClinicalDataSetId.Value).ToListAsync(); // var needAddids = systemIds.Except(trialSystemClinicalDataSetIds).ToList(); // var systemDataList = systemClinicalDataList.Where(x => needAddids.Contains(x.Id)).ToList(); // var readingCriterionList = _repository.Where<ReadingQuestionCriterionTrial>(t => t.TrialId == trialId).Where(t => t.ReadingQuestionCriterionSystemId != null) // .Select(t => new { t.ReadingQuestionCriterionSystemId, TrialReadingCriterionId = t.Id }).ToList(); // List<ClinicalDataTrialSet> dataSets = systemDataList.Select(x => new ClinicalDataTrialSet() // { // Id = NewId.NextGuid(), // SystemClinicalDataSetId = x.Id, // ClinicalDataSetName = x.ClinicalDataSetName, // ClinicalDataLevel = x.ClinicalDataLevel, // ClinicalUploadType = x.ClinicalUploadType, // UploadRole = x.UploadRole, // FileName = x.FileName, // Path = x.Path, // TrialId = trialId, // TrialClinicalDataCriterionList = readingCriterionList.Where(t => x.SystemClinicalDataCriterionList.Select(c => (Guid?)c.SystemReadingCriterionId).ToList().Contains(t.ReadingQuestionCriterionSystemId)).Select(c => // new TrialClinicalDataCriterion() { TrialReadingCriterionId = c.TrialReadingCriterionId }).ToList() // }).ToList(); // #region 临床数据标准 // // dataSets.ForEach(x => // //x.TrialClinicalDataCriterionList = systemClinicalDataList.Where(t => t.Id == x.SystemClinicalDataSetId) // // .Select(t => new TrialClinicalDataCriterion() { TrialReadingCriterionId = x.cl }).ToList() // // ); // #endregion // await _clinicalDataTrialSetRepository.AddRangeAsync(dataSets); // //var needUpdateitemList = await _clinicalDataTrialSetRepository.Where(x => x.TrialId == trialId && needUpdateIds.Contains(x.SystemClinicalDataSetId.Value)).ToListAsync(); // //foreach (var item in needUpdateitemList) // //{ // // var systemData = systemClinicalDataList.FirstOrDefault(x => x.Id == item.SystemClinicalDataSetId); // // await _clinicalDataTrialSetRepository.UpdatePartialNoQueryAsync(item.Id,x=>new ClinicalDataTrialSet() { // // ClinicalDataSetName = systemData.ClinicalDataSetName, // // ClinicalDataLevel = systemData.ClinicalDataLevel, // // ClinicalUploadType = systemData.ClinicalUploadType, // // UploadRole = systemData.UploadRole, // // FileName = systemData.FileName, // // Path = systemData.Path, // // }); // //} // await _trialRepository.BatchUpdateNoTrackingAsync(x => x.Id == trialId, x => new Trial() // { // SyncClinicalDataTime = DateTime.Now, // }); // var result = await _clinicalDataTrialSetRepository.SaveChangesAsync(); //} #endregion } #endregion } }