diff --git a/IRC.Core.SCP/Service/CStoreSCPService.cs b/IRC.Core.SCP/Service/CStoreSCPService.cs index a81e11ec1..261ca563b 100644 --- a/IRC.Core.SCP/Service/CStoreSCPService.cs +++ b/IRC.Core.SCP/Service/CStoreSCPService.cs @@ -24,39 +24,7 @@ using IRaCIS.Core.Infrastructure; namespace IRaCIS.Core.SCP.Service { - /// - /// 后台托管服务的方式运行 - /// - //public class CStoreSCPHostedService : IHostedService - //{ - // private readonly ILogger _logger; - // private readonly IDicomServerFactory _dicomServerFactory; - // private IDicomServer? _server; - // public CStoreSCPHostedService(ILogger logger, IDicomServerFactory dicomServerFactory) - // { - // _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - // _dicomServerFactory = dicomServerFactory ?? throw new ArgumentNullException(nameof(dicomServerFactory)); - // } - - // public async Task StartAsync(CancellationToken cancellationToken) - // { - // _logger.LogInformation("Starting DICOM server"); - // _server = _dicomServerFactory.Create(104); - // _logger.LogInformation("DICOM server is running"); - // } - - // public Task StopAsync(CancellationToken cancellationToken) - // { - // if (_server != null) - // { - // _server.Stop(); - // _server.Dispose(); - // _server = null; - // } - // return Task.CompletedTask; - // } - //} public class DicomSCPServiceOption { public List CalledAEList { get; set; } @@ -75,6 +43,11 @@ namespace IRaCIS.Core.SCP.Service private SCPImageUpload _upload { get; set; } + private Guid _trialId { get; set; } + + private Guid _trialSiteId { get; set; } + + private static readonly DicomTransferSyntax[] _acceptedTransferSyntaxes = new DicomTransferSyntax[] { @@ -121,15 +94,37 @@ namespace IRaCIS.Core.SCP.Service _serviceProvider = (IServiceProvider)this.UserState; - var option = _serviceProvider.GetService>().CurrentValue; + var _trialDicomAERepository = _serviceProvider.GetService>(); - var calledAEList = option.CalledAEList; - if (!calledAEList.Contains(association.CalledAE)) + var trialDicomAEList = _trialDicomAERepository.Select(t => new { t.CalledAE, t.TrialId }).ToList(); + var trialCalledAEList = trialDicomAEList.Select(t => t.CalledAE).ToList(); - //if (association.CalledAE != "STORESCP") + var findCalledAE = trialDicomAEList.Where(t => t.CalledAE == association.CalledAE).FirstOrDefault(); + + var isCanReceiveIamge = false; + + if (findCalledAE!=null) + { + _trialId = findCalledAE.TrialId; + + var _trialSiteDicomAERepository = _serviceProvider.GetService>(); + + + var findTrialSiteAE = _trialSiteDicomAERepository.Where(t=>t.CallingAE==association.CallingAE ).FirstOrDefault(); + + if (findTrialSiteAE!=null) + { + _trialSiteId= findTrialSiteAE.TrialSiteId; + + isCanReceiveIamge = true; + } + } + + + if (!trialCalledAEList.Contains(association.CalledAE) || isCanReceiveIamge==false) { Log.Logger.Warning($"拒绝CalledAE:{association.CalledAE}的连接"); @@ -152,6 +147,8 @@ namespace IRaCIS.Core.SCP.Service } } + + return SendAssociationAcceptAsync(association); } @@ -167,7 +164,7 @@ namespace IRaCIS.Core.SCP.Service _upload.EndTime = DateTime.Now; _upload.StudyCount = _SCPStudyIdList.Count; - await _SCPImageUploadRepository.AddAsync(_upload,true); + await _SCPImageUploadRepository.AddAsync(_upload, true); await SendAssociationReleaseResponseAsync(); } @@ -175,11 +172,9 @@ namespace IRaCIS.Core.SCP.Service private async Task DataMaintenanceAsaync() { - Log.Logger.Warning($"CallingAE:{Association.CallingAE} CalledAE:{Association.CalledAE}传输结束:开始维护数据,处理检查Modality 以及自动创建访视,绑定检查"); + Log.Logger.Warning($"CallingAE:{Association.CallingAE} CalledAE:{Association.CalledAE}传输结束:开始维护数据,处理检查Modality"); - //var patientStudyService = _serviceProvider.GetService(); - //await patientStudyService.AutoBindingPatientStudyVisitAsync(_SCPStudyIdList); //处理检查Modality var _dictionaryRepository = _serviceProvider.GetService>(); @@ -262,7 +257,7 @@ namespace IRaCIS.Core.SCP.Service var _distributedLockProvider = _serviceProvider.GetService(); var storeRelativePath = string.Empty; - var ossFolderPath = $"Dicom/{studyInstanceUid}"; + var ossFolderPath = $"{_trialId}/Image/PACS/{_trialSiteId}{studyInstanceUid}"; long fileSize = 0; @@ -295,7 +290,7 @@ namespace IRaCIS.Core.SCP.Service { try { - var scpStudyId = await dicomArchiveService.ArchiveDicomFileAsync(request.Dataset, storeRelativePath, Association.CallingAE, Association.CalledAE); + var scpStudyId = await dicomArchiveService.ArchiveDicomFileAsync(request.Dataset,_trialId,_trialSiteId, storeRelativePath, Association.CallingAE, Association.CalledAE); if (!_SCPStudyIdList.Contains(scpStudyId)) { @@ -324,11 +319,6 @@ namespace IRaCIS.Core.SCP.Service series.ImageResizePath = seriesPath; - - - //await _seriesRepository.BatchUpdateNoTrackingAsync(t => t.Id == seriesId, u => new SCPSeries() { ImageResizePath = seriesPath }); - - } } @@ -347,7 +337,7 @@ namespace IRaCIS.Core.SCP.Service //监控信息设置 _upload.FileCount++; - _upload.FileSize= _upload.FileSize+ fileSize; + _upload.FileSize = _upload.FileSize + fileSize; return new DicomCStoreResponse(request, DicomStatus.Success); } diff --git a/IRC.Core.SCP/Service/DicomArchiveService.cs b/IRC.Core.SCP/Service/DicomArchiveService.cs index 439741952..6eb9a092a 100644 --- a/IRC.Core.SCP/Service/DicomArchiveService.cs +++ b/IRC.Core.SCP/Service/DicomArchiveService.cs @@ -50,7 +50,7 @@ namespace IRaCIS.Core.SCP.Service /// /// /// - public async Task ArchiveDicomFileAsync(DicomDataset dataset, string fileRelativePath, string callingAE, string calledAE) + public async Task ArchiveDicomFileAsync(DicomDataset dataset, Guid trialId, Guid trialSiteId, string fileRelativePath, string callingAE, string calledAE) { string studyInstanceUid = dataset.GetString(DicomTag.StudyInstanceUID); string seriesInstanceUid = dataset.GetString(DicomTag.SeriesInstanceUID); @@ -59,9 +59,9 @@ namespace IRaCIS.Core.SCP.Service string patientIdStr = dataset.GetString(DicomTag.PatientID); //Guid patientId= IdentifierHelper.CreateGuid(patientIdStr); - Guid studyId = IdentifierHelper.CreateGuid(studyInstanceUid); - Guid seriesId = IdentifierHelper.CreateGuid(studyInstanceUid, seriesInstanceUid); - Guid instanceId = IdentifierHelper.CreateGuid(studyInstanceUid, seriesInstanceUid, sopInstanceUid); + Guid studyId = IdentifierHelper.CreateGuid(studyInstanceUid,trialId.ToString()); + Guid seriesId = IdentifierHelper.CreateGuid(studyInstanceUid, seriesInstanceUid, trialId.ToString()); + Guid instanceId = IdentifierHelper.CreateGuid(studyInstanceUid, seriesInstanceUid, sopInstanceUid, trialId.ToString()); var isStudyNeedAdd = false; var isSeriesNeedAdd = false; @@ -88,6 +88,8 @@ namespace IRaCIS.Core.SCP.Service findPatient = new SCPPatient() { Id = NewId.NextSequentialGuid(), + TrialId=trialId, + TrialSiteId=trialSiteId, PatientIdStr = dataset.GetSingleValueOrDefault(DicomTag.PatientID, string.Empty), PatientName = dataset.GetSingleValueOrDefault(DicomTag.PatientName, string.Empty), PatientAge = dataset.GetSingleValueOrDefault(DicomTag.PatientAge, string.Empty), @@ -145,6 +147,8 @@ namespace IRaCIS.Core.SCP.Service PatientId = findPatient.Id, Id = studyId, + TrialId = trialId, + TrialSiteId = trialSiteId, StudyInstanceUid = studyInstanceUid, StudyTime = studyTime, Modalities = dataset.GetSingleValueOrDefault(DicomTag.Modality, string.Empty), diff --git a/IRC.Core.SCP/Service/Interface/IDicomArchiveService.cs b/IRC.Core.SCP/Service/Interface/IDicomArchiveService.cs index 970b3e146..1c107e94b 100644 --- a/IRC.Core.SCP/Service/Interface/IDicomArchiveService.cs +++ b/IRC.Core.SCP/Service/Interface/IDicomArchiveService.cs @@ -5,7 +5,7 @@ namespace IRaCIS.Core.SCP.Service { public interface IDicomArchiveService { - Task ArchiveDicomFileAsync(DicomDataset dicomDataset,string fileRelativePath,string callingAE,string calledAE); + Task ArchiveDicomFileAsync(DicomDataset dicomDataset,Guid trialId,Guid trialSiteId, string fileRelativePath,string callingAE,string calledAE); } } diff --git a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml index 8232128a0..ebd172a4c 100644 --- a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml +++ b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml @@ -9818,7 +9818,7 @@ DicomAEService - + 获取项目dicom AE 配置信息,otherinfo里面有IsPACSConnect IsTrialPACSConfirmed @@ -15048,6 +15048,41 @@ 9-拒绝入组,10-确认入组 + + + scp 影像推送记录表 + + + + + + + 影像检查列表-患者为维度组织 + + + + + + + 影像检查列表-> 获取患者的检查列表 + + + + + + + 影像访视上传 检查列表 + + + + + + + 提交 患者检查和访视的绑定 + + + + 添加或更新受试者信息[New] diff --git a/IRaCIS.Core.Application/Service/Visit/DTO/PatientViewModel.cs b/IRaCIS.Core.Application/Service/Visit/DTO/PatientViewModel.cs index 72b1ee836..0c3c515f8 100644 --- a/IRaCIS.Core.Application/Service/Visit/DTO/PatientViewModel.cs +++ b/IRaCIS.Core.Application/Service/Visit/DTO/PatientViewModel.cs @@ -224,31 +224,41 @@ namespace IRaCIS.Application.Contracts { public string? PatientIdStr { get; set; } public string? PatientName { get; set; } - public List CalledAEList { get; set; } = new List(); + //public List CalledAEList { get; set; } = new List(); public string? CallingAE { get; set; } - - public string? ExperimentName { get; set; } = string.Empty; + public string? CalledAE { get; set; } public DateTime? BeginPushTime { get; set; } public DateTime? EndPushTime { get; set; } + public string SubejctCode { get; set; } + + public string TrialSiteKeyInfo { get; set; } + } - public class PatientTrialView : PatientQueryView + public class PatientSubjectView : PatientQueryView { public int? StudyCount { get; set; } - public List TrialList { get; set; } + + + public Guid? SubejctId { get; set; } + + public Guid TrialId { get; set; } + + public string? SubjectCode { get; set; } + + public string? TrialSiteCode { get; set; } + + public string? TrialSiteName { get; set; } + + public string? TrialSiteAliasName { get; set; } } - public class PatientTrialStatInfo - { - public int? VisitCount { get; set; } - public string ExperimentName { get; set; } - } public class PatientQuery : PageInput { @@ -377,7 +387,10 @@ namespace IRaCIS.Application.Contracts [NotDefault] public Guid SubjectId { get; set; } - public List SubjectVisitIdList { get; set; } + [NotDefault] + public Guid SubjectVisitId { get; set; } + + public List SCPStudyIdList { get; set; } } public class SubjectVisitSelectQuery @@ -938,6 +951,8 @@ namespace IRaCIS.Application.Contracts public class SCPImageUploadQuery : PageInput { + public string TrialSiteKeyInfo { get; set; } + public string? CallingAE { get; set; } public string? CalledAE { get; set; } @@ -966,7 +981,18 @@ namespace IRaCIS.Application.Contracts public long FileSize { get; set; } public int StudyCount { get; set; } - + + + public Guid TrialId { get; set; } + public Guid TrialSiteId { get; set; } + + + public string TrialSiteCode { get; set; } + + public string TrialSiteName { get; set; } + + public string TrialSiteAliasName { get; set; } + } public class VisitPatientStudyView : PatientStudySelectDto { @@ -990,7 +1016,20 @@ namespace IRaCIS.Application.Contracts } - public class PatientStudySimpleView + public class VisitPatientStudyFilterQuery : PageInput + { + [NotDefault] + public Guid SubjectId { get; set; } + + [NotDefault] + public Guid SubjectVisitId { get; set; } + + public DateTime? EarliestStudyTime { get; set; } + + public DateTime? LatestStudyTime { get; set; } + public string? Modalities { get; set; } + } + public class VisitPatientStudyFilterView { public Guid SCPStudyId { get; set; } @@ -1006,9 +1045,32 @@ namespace IRaCIS.Application.Contracts public string CalledAE { get; set; } = string.Empty; public string CallingAE { get; set; } = string.Empty; + } + + public class PatientStudySimpleView: VisitPatientStudyFilterView + { + + + + public Guid? SubjectVisitId { get; set; } + public string? VisitName { get; set; } + + public string? BlindName { get; set; } = string.Empty; + + + //public SubjectVisitInfo SubejectVisit { get; set; } } + public class SubjectVisitInfo + { + public Guid Id { get; set; } + + public string VisitName { get; set; } + + public decimal VisitNum { get; set; } + public string BlindName { get; set; } = string.Empty; + } public class PatientSeriesDTO diff --git a/IRaCIS.Core.Application/Service/Visit/PatientService.cs b/IRaCIS.Core.Application/Service/Visit/PatientService.cs index c4bef2800..1f0468c0e 100644 --- a/IRaCIS.Core.Application/Service/Visit/PatientService.cs +++ b/IRaCIS.Core.Application/Service/Visit/PatientService.cs @@ -1,1323 +1,374 @@ -//using IRaCIS.Application.Interfaces; -//using IRaCIS.Application.Contracts; -//using IRaCIS.Core.Application.Filter; -//using IRaCIS.Core.Domain.Share; -//using Microsoft.AspNetCore.Mvc; -//using Microsoft.AspNetCore.Authorization; -//using IRaCIS.Core.Application.Auth; -//using MassTransit; -//using Panda.DynamicWebApi.Attributes; -//using DocumentFormat.OpenXml.Spreadsheet; -//using AutoMapper.EntityFrameworkCore; -//using IRaCIS.Core.Domain.Models; -//using IRaCIS.Core.Application.Service.Reading.Dto; -//using Microsoft.Extensions.Options; -//using Microsoft.Extensions.Configuration; -//using Microsoft.Extensions.Configuration.Json; -//using Newtonsoft.Json; -//using Newtonsoft.Json.Linq; -//using SharpCompress.Common; -//using System.Reactive.Subjects; -//using Subject = IRaCIS.Core.Domain.Models.Subject; -//using IRaCIS.Core.Application.ViewModel; -//using Medallion.Threading; -//using IRaCIS.Core.Infrastructure; -//using EasyCaching.Core; -//using Pipelines.Sockets.Unofficial.Arenas; -//using IRaCIS.Core.Application.Contracts; -//using MailKit.Search; -//using DocumentFormat.OpenXml.Office2010.Excel; -//using IRaCIS.Core.Application.Contracts.Dicom.DTO; -//using IRaCIS.Core.Application.Helper; -//using NPOI.SS.Formula.Functions; -//using System.Linq; -//using System.Linq.Dynamic.Core; -//using System.Text; -//using DocumentFormat.OpenXml.EMMA; -//using Azure; -//using System.IO.Compression; -//using static IRaCIS.Core.Domain.Share.StaticData; -//using FellowOakDicom; -//using DocumentFormat.OpenXml.Office2010.Drawing; -//using EasyCaching.Core.DistributedLock; -//using IDistributedLockProvider = Medallion.Threading.IDistributedLockProvider; -//using DocumentFormat.OpenXml.InkML; - -//namespace IRaCIS.Application.Services -//{ -// [ApiExplorerSettings(GroupName = "Trial")] -// public class PatientService : BaseService -// { - -// private readonly IRepository _trialRepository; -// private readonly IRepository _patientRepository; -// private readonly IRepository _studyRepository; -// private readonly IRepository _subjectRepository; -// private readonly IRepository _subjectVisitRepository; -// private readonly IDistributedLockProvider _distributedLockProvider; - -// public PatientService(IRepository studyRepository, IRepository trialRepository, IRepository patientRepository, IRepository subjectRepository, IRepository subjectVisitRepository, IDistributedLockProvider distributedLockProvider) -// { -// _studyRepository = studyRepository; -// _trialRepository = trialRepository; -// _patientRepository = patientRepository; -// _subjectRepository = subjectRepository; -// _subjectVisitRepository = subjectVisitRepository; -// _distributedLockProvider = distributedLockProvider; -// } - - - - - -// #region 患者检查管理 - -// /// -// ///检查管理-> 检查Tab 患者列表 (带加入的项目信息 以及检查统计) 原型标注错误,不是检查列表 -// /// -// /// -// /// -// [HttpPost] -// public async Task>> GetPatientList(PatientTrialQuery inQuery) -// { - -// var isAdminOrOA = _userInfo.UserTypeEnumInt == (int)UserTypeEnum.Admin || _userInfo.UserTypeEnumInt == (int)UserTypeEnum.OA || _userInfo.UserTypeEnumInt == (int)UserTypeEnum.SuperAdmin; - -// #region new ok -// var query = _patientRepository -// .WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientIdStr), t => t.PatientIdStr.Contains(inQuery.PatientIdStr)) -// .WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientName), t => t.PatientName.Contains(inQuery.PatientName)) -// //.WhereIf(!string.IsNullOrWhiteSpace(inQuery.ExperimentName), t => t.SubjectPatientList.Any(t => t.Subject.Trial.ExperimentName.Contains(inQuery.ExperimentName))) -// .WhereIf(!string.IsNullOrWhiteSpace(inQuery.CallingAE), t => t.SCPStudyList.Any(t => t.CallingAE == inQuery.CallingAE)) -// .WhereIf(inQuery.BeginPushTime != null, t => t.LatestPushTime >= inQuery.BeginPushTime) -// .WhereIf(inQuery.EndPushTime != null, t => t.LatestPushTime <= inQuery.EndPushTime); - -// foreach (var calledAE in inQuery.CalledAEList) -// { -// query = query.Where(t => t.SCPStudyList.Select(c => c.CalledAE).Contains(calledAE)); -// } - - -// var resultQuery = from patient in query - -// select new PatientTrialView() -// { -// PatientId = patient.Id, -// PatientBirthDate = patient.PatientBirthDate, -// CreateTime = patient.CreateTime, -// CalledAEList = patient.SCPStudyList.Select(t => t.CalledAE).Distinct().ToList(), -// CallingAEList = patient.SCPStudyList.Select(t => t.CallingAE).Distinct().ToList(), -// CreateUserId = patient.CreateUserId, -// UpdateTime = patient.UpdateTime, -// UpdateUserId = patient.UpdateUserId, - -// EarliestStudyTime = patient.EarliestStudyTime, -// LatestStudyTime = patient.LatestStudyTime, -// LatestPushTime = patient.LatestPushTime, -// PatientAge = patient.PatientAge, -// PatientName = patient.PatientName, -// PatientIdStr = patient.PatientIdStr, -// PatientSex = patient.PatientSex, - -// StudyCount = patient.SCPStudyList.Count(), - -// TrialList = patient.SubjectPatientList.Where(t => isAdminOrOA ? true : t.Subject.Trial.TrialUserList.Any(t => t.UserId == _userInfo.Id)).Select(c => new PatientTrialStatInfo() -// { -// ExperimentName = c.Subject.Trial.ExperimentName, -// VisitCount = c.Subject.SubjectVisitList.Count() -// }).ToList(), - -// }; +using IRaCIS.Application.Interfaces; +using IRaCIS.Application.Contracts; +using IRaCIS.Core.Application.Filter; +using IRaCIS.Core.Domain.Share; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Authorization; +using IRaCIS.Core.Application.Auth; +using MassTransit; +using Panda.DynamicWebApi.Attributes; +using DocumentFormat.OpenXml.Spreadsheet; +using AutoMapper.EntityFrameworkCore; +using IRaCIS.Core.Domain.Models; +using IRaCIS.Core.Application.Service.Reading.Dto; +using Microsoft.Extensions.Options; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Configuration.Json; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using SharpCompress.Common; +using System.Reactive.Subjects; +using Subject = IRaCIS.Core.Domain.Models.Subject; +using IRaCIS.Core.Application.ViewModel; +using Medallion.Threading; +using IRaCIS.Core.Infrastructure; +using EasyCaching.Core; +using Pipelines.Sockets.Unofficial.Arenas; +using IRaCIS.Core.Application.Contracts; +using MailKit.Search; +using DocumentFormat.OpenXml.Office2010.Excel; +using IRaCIS.Core.Application.Contracts.Dicom.DTO; +using IRaCIS.Core.Application.Helper; +using NPOI.SS.Formula.Functions; +using System.Linq; +using System.Linq.Dynamic.Core; +using System.Text; +using DocumentFormat.OpenXml.EMMA; +using Azure; +using System.IO.Compression; +using static IRaCIS.Core.Domain.Share.StaticData; +using FellowOakDicom; +using DocumentFormat.OpenXml.Office2010.Drawing; +using EasyCaching.Core.DistributedLock; +using IDistributedLockProvider = Medallion.Threading.IDistributedLockProvider; +using DocumentFormat.OpenXml.InkML; + +namespace IRaCIS.Application.Services +{ + [ApiExplorerSettings(GroupName = "Trial")] + public class PatientService : BaseService + { + + private readonly IRepository _trialRepository; + private readonly IRepository _patientRepository; + private readonly IRepository _scpStudyRepository; + private readonly IRepository _subjectRepository; + private readonly IRepository _subjectVisitRepository; + private readonly IDistributedLockProvider _distributedLockProvider; + + public PatientService(IRepository studyRepository, IRepository trialRepository, IRepository patientRepository, IRepository subjectRepository, IRepository subjectVisitRepository, IDistributedLockProvider distributedLockProvider) + { + _scpStudyRepository = studyRepository; + _trialRepository = trialRepository; + _patientRepository = patientRepository; + _subjectRepository = subjectRepository; + _subjectVisitRepository = subjectVisitRepository; + _distributedLockProvider = distributedLockProvider; + } + + + /// + /// scp 影像推送记录表 + /// + /// + /// + [HttpPost] + public async Task>> GetSCPImageUploadList(SCPImageUploadQuery inQuery) + { + var query = _repository.Where() + .WhereIf(!string.IsNullOrWhiteSpace(inQuery.CalledAE), t => t.CalledAE.Contains(inQuery.CalledAE)) + .WhereIf(!string.IsNullOrWhiteSpace(inQuery.CallingAEIP), t => t.CallingAEIP.Contains(inQuery.CallingAEIP)) + .WhereIf(!string.IsNullOrWhiteSpace(inQuery.CallingAE), t => t.CallingAE.Contains(inQuery.CallingAE)) + .WhereIf(inQuery.StartTime != null, t => t.StartTime >= inQuery.StartTime) + .WhereIf(inQuery.EndTime != null, t => t.EndTime <= inQuery.EndTime) + .WhereIf(!string.IsNullOrWhiteSpace(inQuery.TrialSiteKeyInfo), t => t.TrialSite.TrialSiteCode.Contains(inQuery.TrialSiteKeyInfo) + || t.TrialSite.TrialSiteAliasName.Contains(inQuery.TrialSiteKeyInfo) || t.TrialSite.TrialSiteName.Contains(inQuery.TrialSiteKeyInfo)) + .ProjectTo(_mapper.ConfigurationProvider); + + + var pageList = await query.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, inQuery.SortField == string.Empty ? nameof(SCPImageUploadView.CallingAE) : inQuery.SortField, inQuery.Asc); + + + return ResponseOutput.Ok(pageList); + } + + + #region 患者检查管理 + + /// + ///影像检查列表-患者为维度组织 + /// + /// + /// + [HttpPost] + public async Task>> GetPatientList(PatientTrialQuery inQuery) + { + + + #region new ok + var query = _patientRepository + .WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientIdStr), t => t.PatientIdStr.Contains(inQuery.PatientIdStr)) + .WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientName), t => t.PatientName.Contains(inQuery.PatientName)) + .WhereIf(!string.IsNullOrWhiteSpace(inQuery.SubejctCode), t => t.Subject.Code.Contains(inQuery.SubejctCode)) + .WhereIf(!string.IsNullOrWhiteSpace(inQuery.TrialSiteKeyInfo), t => t.TrialSite.TrialSiteCode.Contains(inQuery.TrialSiteKeyInfo) + || t.TrialSite.TrialSiteAliasName.Contains(inQuery.TrialSiteKeyInfo)|| t.TrialSite.TrialSiteName.Contains(inQuery.TrialSiteKeyInfo)) + .WhereIf(!string.IsNullOrWhiteSpace(inQuery.CallingAE), t => t.SCPStudyList.Any(t => t.CallingAE == inQuery.CallingAE)) + .WhereIf(!string.IsNullOrWhiteSpace(inQuery.CalledAE), t => t.SCPStudyList.Any(t => t.CalledAE == inQuery.CalledAE)) + .WhereIf(inQuery.BeginPushTime != null, t => t.LatestPushTime >= inQuery.BeginPushTime) + .WhereIf(inQuery.EndPushTime != null, t => t.LatestPushTime <= inQuery.EndPushTime); + + //foreach (var calledAE in inQuery.CalledAEList) + //{ + // query = query.Where(t => t.SCPStudyList.Select(c => c.CalledAE).Contains(calledAE)); + //} + + + var resultQuery = from patient in query + + select new PatientSubjectView() + { + PatientId = patient.Id, + PatientBirthDate = patient.PatientBirthDate, + CreateTime = patient.CreateTime, + CalledAEList = patient.SCPStudyList.Select(t => t.CalledAE).Distinct().ToList(), + CallingAEList = patient.SCPStudyList.Select(t => t.CallingAE).Distinct().ToList(), + CreateUserId = patient.CreateUserId, + UpdateTime = patient.UpdateTime, + UpdateUserId = patient.UpdateUserId, + + EarliestStudyTime = patient.EarliestStudyTime, + LatestStudyTime = patient.LatestStudyTime, + LatestPushTime = patient.LatestPushTime, + PatientAge = patient.PatientAge, + PatientName = patient.PatientName, + PatientIdStr = patient.PatientIdStr, + PatientSex = patient.PatientSex, + + StudyCount = patient.SCPStudyList.Count(), + + TrialId=patient.TrialId, + SubejctId=patient.SubjectId, + SubjectCode=patient.Subject.Code, + TrialSiteAliasName=patient.TrialSite.TrialSiteAliasName, + TrialSiteCode=patient.TrialSite.TrialSiteCode, + TrialSiteName=patient.TrialSite.TrialSiteName + + }; + + + + + var pageList = await resultQuery.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, inQuery.SortField == string.Empty ? nameof(PatientQueryView.PatientIdStr) : inQuery.SortField, inQuery.Asc); + #endregion + + + return ResponseOutput.Ok(pageList); + } + + + + + + /// + /// 影像检查列表-> 获取患者的检查列表 + /// + /// + /// + [HttpPost] + public async Task> GetPatientStudyList(PatientStudyInfoQuery inQuery) + { + var query = from scpStudy in _scpStudyRepository.Where(t => t.PatientId == inQuery.PatientId) + .WhereIf(inQuery.EarliestStudyTime != null, t => t.StudyTime >= inQuery.EarliestStudyTime) + .WhereIf(inQuery.LatestStudyTime != null, t => t.StudyTime <= inQuery.LatestStudyTime) + .WhereIf(!string.IsNullOrWhiteSpace(inQuery.Modalities), t => t.Modalities.Contains(inQuery.Modalities)) + select new PatientStudySimpleView() + { + Description = scpStudy.Description, + CalledAE = scpStudy.CalledAE, + CallingAE = scpStudy.CallingAE, + InstanceCount = scpStudy.InstanceCount, + Modalities = scpStudy.Modalities, + PatientId = scpStudy.PatientId, + SCPStudyId = scpStudy.Id, + SeriesCount = scpStudy.SeriesCount, + StudyTime = scpStudy.StudyTime, + + SubjectVisitId= scpStudy.SubjectVisitId, + VisitName=scpStudy.SubjectVisit.VisitName, + BlindName=scpStudy.SubjectVisit.BlindName + }; + + + //var sortField = string.IsNullOrWhiteSpace(inQuery.SortField) ? nameof(PatientStudySimpleView.StudyTime) : inQuery.SortField; + //var orderQuery = inQuery.Asc ? query.OrderBy(sortField) : query.OrderBy(sortField + " desc"); + //var list = await orderQuery.ToListAsync(); + var pageList = await query.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, inQuery.SortField == string.Empty ? nameof(PatientStudySimpleView.StudyTime) : inQuery.SortField, inQuery.Asc); + + return pageList; + } + + + public async Task> GetDicomCalledAEList() + { + var list = await _scpStudyRepository.Select(t => t.CalledAE).Distinct().ToListAsync(); + return list; + } -// var pageList = await resultQuery.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, inQuery.SortField == string.Empty ? nameof(PatientQueryView.PatientIdStr) : inQuery.SortField, inQuery.Asc); -// #endregion + public async Task> GetDicomCallingAEList() + { + var list = await _scpStudyRepository.Select(t => t.CallingAE).Distinct().ToListAsync(); + return list; + } -// return ResponseOutput.Ok(pageList); -// } + /// + /// 影像访视上传 检查列表 + /// + /// + /// + [HttpPost] + public async Task> GetVisitPatientStudyFilterList(VisitPatientStudyFilterQuery inQuery) + { + var trialSiteId=_subjectRepository.Where(t=>t.Id==inQuery.SubjectId).Select(t=>t.TrialSiteId).FirstOrDefault(); + var query = from scpStudy in _scpStudyRepository + //未绑定的患者,或者自己已绑定但是未绑定访视的 + .Where(t => t.Patient.SubjectId == null|| (t.Patient.SubjectId == inQuery.SubjectId && t.SubjectVisitId==null)) + //中心 + .Where(t=>t.TrialSiteId==trialSiteId) + .WhereIf(inQuery.EarliestStudyTime != null, t => t.StudyTime >= inQuery.EarliestStudyTime) + .WhereIf(inQuery.LatestStudyTime != null, t => t.StudyTime <= inQuery.LatestStudyTime) + .WhereIf(!string.IsNullOrWhiteSpace(inQuery.Modalities), t => t.Modalities.Contains(inQuery.Modalities)) + select new VisitPatientStudyFilterView() + { + Description = scpStudy.Description, + CalledAE = scpStudy.CalledAE, + CallingAE = scpStudy.CallingAE, + InstanceCount = scpStudy.InstanceCount, + Modalities = scpStudy.Modalities, + PatientId = scpStudy.PatientId, + SCPStudyId = scpStudy.Id, + SeriesCount = scpStudy.SeriesCount, + StudyTime = scpStudy.StudyTime, + }; + var pageList = await query.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, inQuery.SortField == string.Empty ? nameof(PatientStudySimpleView.StudyTime) : inQuery.SortField, inQuery.Asc); -// /// -// /// 检查管理-> 获取患者检查列表(同步影像数据之前的) -// /// -// /// -// /// -// [HttpPost] -// public async Task> GetPatientStudyList(PatientStudyInfoQuery inQuery) -// { -// var query = from scpStudy in _studyRepository.Where(t => t.PatientId == inQuery.PatientId) -// .WhereIf(inQuery.EarliestStudyTime != null, t => t.StudyTime >= inQuery.EarliestStudyTime) -// .WhereIf(inQuery.LatestStudyTime != null, t => t.StudyTime <= inQuery.LatestStudyTime) -// .WhereIf(!string.IsNullOrWhiteSpace(inQuery.Modalities), t => t.Modalities.Contains(inQuery.Modalities)) -// select new PatientStudySimpleView() -// { -// Description = scpStudy.Description, -// CalledAE = scpStudy.CalledAE, -// CallingAE = scpStudy.CallingAE, -// InstanceCount = scpStudy.InstanceCount, -// Modalities = scpStudy.Modalities, -// PatientId = scpStudy.PatientId, -// SCPStudyId = scpStudy.Id, -// SeriesCount = scpStudy.SeriesCount, -// StudyTime = scpStudy.StudyTime, -// }; + return pageList; + } -// var sortField = string.IsNullOrWhiteSpace(inQuery.SortField) ? nameof(PatientStudySimpleView.StudyTime) : inQuery.SortField; -// var orderQuery = inQuery.Asc ? query.OrderBy(sortField) : query.OrderBy(sortField + " desc"); - -// var list = await orderQuery.ToListAsync(); - -// return list; -// } - + /// + /// 提交 患者检查和访视的绑定 + /// + /// + /// + [HttpPost] + [UnitOfWork] + [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })] + public async Task SubmitVisitStudyBinding(SubmitVisitStudyBindingCommand inCommand) + { -// public async Task>> GetPatientSeriesList(Guid scpStudyId, -// [FromServices] IRepository _seriesRepository, -// [FromServices] IRepository _instanceRepository -// ) -// { + var subjectId = inCommand.SubjectId; + var subjectVisitId=inCommand.SubjectVisitId; + var trialId = inCommand.TrialId; + + -// var seriesList = await _seriesRepository.Where(s => s.StudyId == scpStudyId).OrderBy(s => s.SeriesNumber). -// ThenBy(s => s.SeriesTime).ThenBy(s => s.CreateTime) -// .ProjectTo(_mapper.ConfigurationProvider).ToListAsync(); + var @lock = _distributedLockProvider.CreateLock($"StudyCode"); -// var idList = await _instanceRepository.Where(s => s.StudyId == scpStudyId).OrderBy(t => t.SeriesId).ThenBy(t => t.InstanceNumber) -// .ThenBy(s => s.InstanceTime).ThenBy(s => s.CreateTime) -// .Select(t => new { t.SeriesId, t.Id, t.Path, t.NumberOfFrames, t.InstanceNumber }).ToListAsync();//.GroupBy(u => u.SeriesId); + using (await @lock.AcquireAsync()) + { + var dbStudyCodeIntMax = _repository.Where(s => s.TrialId == inCommand.TrialId).Select(t => t.Code).DefaultIfEmpty().Max(); -// foreach (var item in seriesList) -// { -// item.InstanceList = idList.Where(s => s.SeriesId == item.Id).Select(u => u.Id).ToList(); + int currentNextCodeInt = dbStudyCodeIntMax + 1; -// //处理多帧 -// item.InstancePathList = idList.Where(s => s.SeriesId == item.Id).OrderBy(t => t.InstanceNumber) -// .SelectMany(u => -// { + foreach (var scpStudyId in inCommand.SCPStudyIdList) + { -// if (u.NumberOfFrames > 1) -// { -// var pathList = new List(); + var find = _scpStudyRepository.Where(t => t.Id == scpStudyId).Include(t => t.SeriesList).Include(t => t.InstanceList).FirstOrDefault(); -// for (int i = 1; i <= u.NumberOfFrames; i++) -// { -// pathList.Add(u.Path + "?frame=" + (i - 1)); -// } -// return pathList; -// } -// else -// { -// return new List { u.Path }; + if (find != null) + { -// } -// }) -// .ToList(); -// } + var newStuty = _mapper.Map(find); + await _repository.AddAsync(newStuty); -// var study = await _studyRepository.FindAsync(scpStudyId); + newStuty.SeqId = Guid.Empty; + newStuty.Code = currentNextCodeInt; + newStuty.StudyCode = AppSettings.GetCodeStr(currentNextCodeInt, nameof(DicomStudy)); + newStuty.IsFromPACS = true; + newStuty.TrialId = trialId; + newStuty.SubjectId = subjectId; + newStuty.SubjectVisitId = subjectVisitId; -// return ResponseOutput.Ok(seriesList, study); -// } + var newSeriesList = _mapper.Map>(find.SeriesList); + foreach (var series in newSeriesList) + { + + series.SeqId = Guid.Empty; + series.TrialId = trialId; + series.SubjectId = subjectId; + series.SubjectVisitId = subjectVisitId; + } + await _repository.AddRangeAsync(newSeriesList); + var newInstanceList = _mapper.Map>(find.InstanceList); + foreach (var instance in newInstanceList) + { -// /// -// /// 清除该患者绑定的受试者的所有的数据、(subject subjectVisit visitTask dicom) -// /// -// /// -// /// -// [UnitOfWork] -// public async Task DeletePatientStudyAllData(Guid patientId, -// [FromServices] IRepository _visitTaskRepository, -// [FromServices] IRepository _SeriesRepository, -// [FromServices] IRepository _instanceRepository, -// [FromServices] IRepository _dicomStudyRepository, -// [FromServices] IRepository _dicomSeriesRepository, -// [FromServices] IRepository _dicomInstanceRepository, -// [FromServices] IOSSService oSSService) -// { -// //清理自己管理的项目的数据 -// var subjectPatientList = await _subjectPatientRepository.Where(t => t.PatientId == patientId && t.Subject.Trial.TrialUserList.Any(t => t.UserId == _userInfo.Id)) -// .Select(t => new { t.SubjectId, StudyInstanceUidList = t.Patient.SCPStudyList.Select(t => t.StudyInstanceUid).ToList() }).ToListAsync(); -// if (_studyRepository.Any(t => t.IsUploadFinished == false && t.PatientId == patientId)) -// { -// return ResponseOutput.NotOk("当前患者有检查正在上传,不允许清理数据"); -// } + instance.SeqId = Guid.Empty; + instance.TrialId = trialId; + instance.SubjectId = subjectId; + instance.SubjectVisitId = subjectVisitId; + + } + await _repository.AddRangeAsync(newInstanceList); + } -// foreach (var item in subjectPatientList) -// { -// var subjectId = item.SubjectId; + currentNextCodeInt++; -// await _subjectRepository.BatchDeleteNoTrackingAsync(t => t.Id == subjectId); -// await _subjectVisitRepository.BatchDeleteNoTrackingAsync(t => t.SubjectId == subjectId); -// await _visitTaskRepository.BatchDeleteNoTrackingAsync(t => t.SubjectId == subjectId); -// await _dicomStudyRepository.BatchDeleteNoTrackingAsync(t => t.SubjectId == subjectId); -// await _dicomSeriesRepository.BatchDeleteNoTrackingAsync(t => t.SubjectId == subjectId); -// await _dicomInstanceRepository.BatchDeleteNoTrackingAsync(t => t.SubjectId == subjectId); -// } + } -// var instanceUidList = subjectPatientList.SelectMany(t => t.StudyInstanceUidList).Distinct().ToList(); -// foreach (var studyInstanceUid in instanceUidList) -// { -// { -// var ossFolderPath = $"Dicom/{studyInstanceUid}"; -// await oSSService.DeleteFromPrefix(ossFolderPath); + } -// } -// } -// var sCPStudyIdList = _studyRepository.Where(t => t.PatientId == patientId).Select(t => t.Id).ToList(); + await _repository.SaveChangesAsync(); -// await _patientRepository.BatchDeleteNoTrackingAsync(t => t.Id == patientId); + return ResponseOutput.Ok(); + } -// foreach (var item in sCPStudyIdList) -// { -// await _studyRepository.BatchDeleteNoTrackingAsync(t => t.Id == item); -// await _SeriesRepository.BatchDeleteNoTrackingAsync(t => t.StudyId == item); -// await _instanceRepository.BatchDeleteNoTrackingAsync(t => t.StudyId == item); -// } + #endregion -// return ResponseOutput.Ok(); -// } -// #endregion -// #region 受试者管理 -// [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })] -// [HttpPost] -// public async Task> AddOrUpdateSubject([FromBody] AddOrUpdateSubjectCommand subjectCommand) -// { -// var svlist = new List(); -// var verifyExp1 = new EntityVerifyExp() -// { -// VerifyExp = u => u.Code == subjectCommand.Code && u.TrialId == subjectCommand.TrialId, -// //---已存在具有相关受试者编号的受试者。 -// VerifyMsg = _localizer["Subject_DuplicateSubjectNum"] -// }; -// Subject? mapedSubject = null; -// if (subjectCommand.Id == null) //insert -// { -// mapedSubject = await _subjectRepository.InsertFromDTOAsync(subjectCommand, false, verifyExp1); -// } -// else //update -// { + } -// mapedSubject = await _subjectRepository.UpdateFromDTOAsync(subjectCommand, false, false, verifyExp1/*, verifyExp2*/); -// } - - -// await _subjectRepository.SaveChangesAsync(); - -// return ResponseOutput.Ok(mapedSubject.Id.ToString()); - -// } - -// /// -// /// 受试者管理-> 受试者列表 (带患者信息,患者信息是数组) -// /// -// /// -// /// -// [HttpPost] -// public async Task>> GetPatientSubejctList(PatientSubjectQuery inQuery) -// { -// var subjectQuery = _subjectRepository.Where(u => u.TrialId == inQuery.TrialId) -// .WhereIf(!string.IsNullOrWhiteSpace(inQuery.Code), t => t.Code.Contains(inQuery.Code)) -// .WhereIf(!string.IsNullOrWhiteSpace(inQuery.ShortName), t => t.ShortName.Contains(inQuery.ShortName)) -// .WhereIf(!string.IsNullOrWhiteSpace(inQuery.Sex), t => t.Sex.Contains(inQuery.Sex)) - -// //.WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientIdStr), t => t.SubjectPatientList.Any(t => t.Patient.PatientIdStr.Contains(inQuery.PatientIdStr))) -// .WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientName), t => t.SubjectPatientList.Any(t => t.Patient.PatientName.Contains(inQuery.PatientName))) -// .WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientSex), t => t.SubjectPatientList.Any(t => t.Patient.PatientSex.Contains(inQuery.PatientSex))) - -// .WhereIf(inQuery.Status != null, t => t.Status == inQuery.Status) -// .ProjectTo(_mapper.ConfigurationProvider); - -// var pageList = await subjectQuery.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, inQuery.SortField == string.Empty ? nameof(PatienSubejctView.Code) : inQuery.SortField, inQuery.Asc); - - -// return ResponseOutput.Ok(pageList); -// } - -// /// -// /// 受试者管理-> 患者列表 (subject 列表进入,进行关系绑定初始化列表,排除已绑定的患者和已绑定给其他subject的患者) -// /// -// /// -// /// -// [HttpPost] -// public async Task>> GetPatientInitList(PatientQuery inQuery) -// { -// var query = _patientRepository -// .WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientIdStr), t => t.PatientIdStr.Contains(inQuery.PatientIdStr)) -// .WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientName), t => t.PatientName.Contains(inQuery.PatientName)) -// .WhereIf(!string.IsNullOrWhiteSpace(inQuery.CallingAE), t => t.SCPStudyList.Any(t => t.CallingAE == inQuery.CallingAE)) -// .WhereIf(inQuery.EarliestStudyTime != null, t => t.EarliestStudyTime >= inQuery.EarliestStudyTime) -// .WhereIf(inQuery.LatestStudyTime != null, t => t.LatestStudyTime <= inQuery.LatestStudyTime) - -// //排除该受试者已绑定的患者 -// //.WhereIf(inQuery.SubjectId != null, t => !t.SubjectPatientList.Any(u => u.SubjectId == inQuery.SubjectId)) - -// //排除该项目已绑定的其他患者 -// .Where(t => !t.SubjectPatientList.Any(c => c.Subject.TrialId == inQuery.TrialId)); - -// foreach (var calledAE in inQuery.CalledAEList) -// { -// query = query.Where(t => t.SCPStudyList.Select(c => c.CalledAE).Contains(calledAE)); -// } - - -// var patientQuery = query.ProjectTo(_mapper.ConfigurationProvider); - - -// var pageList = await patientQuery.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, inQuery.SortField == string.Empty ? nameof(PatientQueryView.PatientIdStr) : inQuery.SortField, inQuery.Asc); - - -// return ResponseOutput.Ok(pageList); -// } - -// /// -// /// 受试者管理->患者列表 Dicom AE 下拉框数据获取 -// /// -// /// -// public async Task> GetDicomCalledAEList() -// { -// var list = await _studyRepository.Select(t => t.CalledAE).Distinct().ToListAsync(); - -// return list; -// } - -// public async Task> GetDicomCallingAEList() -// { -// var list = await _studyRepository.Select(t => t.CallingAE).Distinct().ToListAsync(); - -// return list; -// } - -// /// -// ///受试者管理-> 患者列表 模糊搜索下拉 选择subject 排除已绑定并提交的 -// /// -// /// -// /// -// [HttpPost] -// public async Task> GetTrialSubejctSelectList(SubjectSelectQuery inQuery) -// { -// var list = await _subjectRepository.Where(t => t.TrialId == inQuery.TrialId && t.Status == SubjectStatus.OnVisit) -// .WhereIf(!string.IsNullOrWhiteSpace(inQuery.SubjectCode), u => u.Code.Contains(inQuery.SubjectCode)) -// .WhereIf(inQuery.SubjectId != null, t => t.Id == inQuery.SubjectId) -// //.Where(t => !t.SubjectVisitList.SelectMany(t => t.SCPStudySubjectVisitList).Any(c => c.StudyId != null)) -// .Select(t => new SubjectSelectDto() -// { -// SubejctId = t.Id, -// SubjectCode = t.Code, -// Status = t.Status, -// Sex = t.Sex, -// ShortName = t.ShortName, -// Age = t.Age, -// BirthDate = t.BirthDate, -// //PatientList = t.SubjectPatientList.Select(c => new PatienBasicInfo() { PatientId = c.PatientId, PatientIdStr = c.Patient.PatientIdStr }).ToList() -// }) -// .ToListAsync(); - -// return list; -// } - -// #endregion - - - -// #region 患者和受试者绑定,生成访视,预先绑定检查和访视 - - - - - - - -// /// -// /// 提交 患者检查和访视的绑定 -// /// -// /// -// /// -// [HttpPost] -// [UnitOfWork] -// [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })] -// public async Task SubmitVisitStudyBinding(SubmitVisitStudyBindingCommand inCommand, [FromServices] IOptionsMonitor _basicSystemConfigConfig) -// { - -// //防止访视重复 -// inCommand.SubjectVisitIdList = inCommand.SubjectVisitIdList.Distinct().ToList(); - -// //确认当前提交的最大的访视之前所有的访视都已提交,并且没有漏的 - -// var curentMaxNum = await _subjectVisitRepository.Where(t => inCommand.SubjectVisitIdList.Contains(t.Id)).Select(t => t.VisitNum).MaxAsync(); - -// var allVisitList = _subjectVisitRepository.Where(t => t.TrialId == inCommand.TrialId && t.SubjectId == inCommand.SubjectId && t.VisitNum <= curentMaxNum).Select(t => new { SubjectVisitId = t.Id, t.Subject.Status, t.VisitNum, t.SubmitState }).OrderBy(t => t.VisitNum).ToList(); - -// //批量提交 -// if (inCommand.SubjectVisitIdList.Count > 1) -// { -// if (allVisitList.Where(t => t.SubmitState != SubmitStateEnum.Submitted).Count() != inCommand.SubjectVisitIdList.Count()) -// { -// return ResponseOutput.NotOk(_localizer["当前批量提交的访视中间有遗漏的访视或者前序有访视未提交"]); -// } -// } - -// else -// { -// if (allVisitList.Any(t => t.VisitNum < curentMaxNum && t.SubmitState != SubmitStateEnum.Submitted)) -// { -// return ResponseOutput.NotOk(_localizer["前序有访视未提交,请先提交前序访视"]); -// } -// } - -// if (allVisitList.Any(t => t.Status == SubjectStatus.EndOfVisit)) -// { -// return ResponseOutput.NotOk(_localizer["受试者状态为访视结束,不允许提交访视生成任务"]); -// } - -// //var list = await _studySubjectVisitRepository.Where(t => inCommand.SubjectVisitIdList.Contains(t.SubjectVisitId)).Select(t => new { t.SCPStudyId, t.SCPStudy.PatientId, t.SubjectVisitId, t.SubjectVisit.VisitNum, t.SubjectVisit.SubjectId, SubjectCode = t.SubjectVisit.Subject.Code, t.SubjectVisit.TrialId, t.SCPStudy.StudyTime, t.StudyId, t.SCPStudy.IsUploadFinished }).OrderBy(t => t.StudyTime).ToListAsync(); - -// //if (list.Any(t => t.StudyId != null)) -// //{ -// // return ResponseOutput.NotOk(_localizer["有访视和检查处于已绑定关系,不允许再次提交绑定"]); -// //} - -// //if (list.Any(t => t.IsUploadFinished == false)) -// //{ -// // return ResponseOutput.NotOk(_localizer["有访视检查正在传输中,不允许提交"]); -// //} - - -// ////判断每个subject 批量提交的是否符合时间要求 -// //foreach (var g in list.GroupBy(t => new { t.SubjectId, t.SubjectCode })) -// //{ -// // var visitOrderStudyList = g.OrderBy(t => t.VisitNum).ThenBy(t => t.StudyTime).ToList(); - -// // var studyTimeOrderList = visitOrderStudyList.OrderBy(t => t.StudyTime).ToList(); - -// // bool arraysEqual = visitOrderStudyList.SequenceEqual(studyTimeOrderList); - -// // if (!arraysEqual) -// // { -// // return ResponseOutput.NotOk(_localizer[$"{g.Key.SubjectCode}所提交的访视中的检查时间,不符合后续访视的检查时间比前序检查的时间大的要求"]); -// // } - -// // if (DateTime.Now < studyTimeOrderList.Max(t => t.StudyTime)) -// // { -// // return ResponseOutput.NotOk(_localizer[$"您当前修改了服务器时间,试图绕过软件授权,请恢复服务器时间,并联系授权方授权才可进行操作"]); -// // } -// //} - -// var trialConfig = await _trialRepository.Where(t => t.Id == inCommand.TrialId).Select(t => new { t.IsEnrollementQualificationConfirm, t.IsPDProgressView, t.AuthorizationEncrypt }).FirstOrDefaultAsync(); - - - -// //var decodedText = Cryptography.DecryptString(trialConfig.AuthorizationEncrypt, _basicSystemConfigConfig.CurrentValue.AESKey, "Trial_AuthorizationEncrypt"); - -// //var authInfo = JsonConvert.DeserializeObject(decodedText); - - - - -// var @lock = _distributedLockProvider.CreateLock($"StudyCode"); - -// using (await @lock.AcquireAsync()) -// { -// var dbStudyCodeIntMax = _repository.Where(s => s.TrialId == inCommand.TrialId).Select(t => t.Code).DefaultIfEmpty().Max(); - -// int currentNextCodeInt = dbStudyCodeIntMax + 1; - -// foreach (var item in list) -// { - - -// var dbSubjectVisit = await _subjectVisitRepository.FirstOrDefaultAsync(t => t.Id == item.SubjectVisitId); - -// //处理脏数据,可能之前的绑定的数据状态是待上传,但是已经绑定了检查 -// if (dbSubjectVisit.SubmitState == SubmitStateEnum.ToSubmit || dbSubjectVisit.SubmitState == SubmitStateEnum.None) -// { -// dbSubjectVisit.SubmitState = SubmitStateEnum.Submitted; -// dbSubjectVisit.SubmitTime = DateTime.Now; -// dbSubjectVisit.SubmitUserId = _userInfo.Id; - -// //维护统一状态 -// //dbSubjectVisit.ReadingStatus = ReadingStatusEnum.TaskAllocate; - -// dbSubjectVisit.AuditState = AuditStateEnum.QCPassed; -// dbSubjectVisit.CheckState = CheckStateEnum.CVPassed; - -// dbSubjectVisit.IsEnrollmentConfirm = dbSubjectVisit.IsBaseLine ? trialConfig.IsEnrollementQualificationConfirm : false; - -// dbSubjectVisit.PDState = trialConfig.IsPDProgressView ? PDStateEnum.PDProgress : PDStateEnum.None; -// } - - - - -// var find = _studyRepository.Where(t => t.Id == item.SCPStudyId).Include(t => t.SeriesList).Include(t => t.InstanceList).FirstOrDefault(); - -// if (find != null) -// { -// //重新算Id -// Guid studyId = IdentifierHelper.CreateGuid(item.TrialId.ToString(), find.StudyInstanceUid); -// find.Id = studyId; -// var newStuty = _mapper.Map(find); - -// await _repository.AddAsync(newStuty); -// //newStuty.Id = NewId.NextSequentialGuid(); - -// newStuty.SeqId = Guid.Empty; -// newStuty.Code = currentNextCodeInt; -// newStuty.StudyCode = AppSettings.GetCodeStr(currentNextCodeInt, nameof(DicomStudy)); -// newStuty.TrialId = item.TrialId; -// newStuty.SubjectId = item.SubjectId; -// newStuty.SubjectVisitId = item.SubjectVisitId; - -// var newSeriesList = _mapper.Map>(find.SeriesList); - -// foreach (var series in newSeriesList) -// { -// Guid seriesId = IdentifierHelper.CreateGuid(item.TrialId.ToString(), find.StudyInstanceUid, series.SeriesInstanceUid); - -// //重新算Id -// series.Id = seriesId; -// series.StudyId = newStuty.Id; - -// series.SeqId = Guid.Empty; -// series.TrialId = item.TrialId; -// series.SubjectId = item.SubjectId; -// series.SubjectVisitId = item.SubjectVisitId; -// } - -// await _repository.AddRangeAsync(newSeriesList); - -// var newInstanceList = _mapper.Map>(find.InstanceList); - -// foreach (var instance in newInstanceList) -// { -// Guid seriesId = IdentifierHelper.CreateGuid(item.TrialId.ToString(), find.StudyInstanceUid, instance.SeriesInstanceUid); -// Guid instanceId = IdentifierHelper.CreateGuid(item.TrialId.ToString(), find.StudyInstanceUid, instance.SeriesInstanceUid, instance.SopInstanceUid); -// //重新算Id -// instance.Id = instanceId; -// instance.SeriesId = seriesId; -// instance.StudyId = newStuty.Id; - -// instance.SeqId = Guid.Empty; -// instance.TrialId = item.TrialId; -// instance.SubjectId = item.SubjectId; -// instance.SubjectVisitId = item.SubjectVisitId; -// } -// await _repository.AddRangeAsync(newInstanceList); -// } - -// currentNextCodeInt++; - -// //await _studySubjectVisitRepository.BatchUpdateNoTrackingAsync(t => t.SubjectVisitId == item.SubjectVisitId && t.SCPStudyId == item.SCPStudyId, u => new SCPStudySubjectVisit() { StudyId = find.Id }); - -// //await _subjectPatientRepository.BatchUpdateNoTrackingAsync(t => t.SubjectId == item.SubjectId && t.PatientId == item.PatientId, u => new SubjectPatient() { IsBinded = true }); - -// } - - -// } - - - -// //await _studySubjectVisitRepository.SaveChangesAsync(); - -// return ResponseOutput.Ok(); -// } - -// #endregion - -// #region 访视基本管理 - - -// /// -// /// 绑定访视 初始化患者检查列表 -// /// -// /// -// /// -// [HttpPost] -// public async Task> GetVisitPatientStudyList(PatientStudyQuery inQuery) -// { -// var patientQuery = from scpStudy in _studyRepository -// .Where(t => inQuery.PatientIdList.Contains(t.PatientId)) -// .WhereIf(inQuery.EarliestStudyTime != null, t => t.StudyTime >= inQuery.EarliestStudyTime) -// .WhereIf(inQuery.LatestStudyTime != null, t => t.StudyTime <= inQuery.LatestStudyTime) - -// join scpStudySubjectVisit in _studySubjectVisitRepository.Where(t => t.SubjectVisit.TrialId == inQuery.TrialId) on scpStudy.Id equals scpStudySubjectVisit.SCPStudyId into cc -// from scpStudySubjectVisit in cc.DefaultIfEmpty() -// select new PatientStudySelectDto() -// { -// Description = scpStudy.Description, -// CalledAE = scpStudy.CalledAE, -// InstanceCount = scpStudy.InstanceCount, -// Modalities = scpStudy.Modalities, -// PatientId = scpStudy.Patient.Id, - -// PatientIdStr = scpStudy.PatientIdStr, -// PatientAge = scpStudy.PatientAge, -// PatientBirthDate = scpStudy.PatientBirthDate, -// PatientSex = scpStudy.PatientSex, -// PatientName = scpStudy.PatientName, - -// SCPStudyId = scpStudy.Id, -// SeriesCount = scpStudy.SeriesCount, -// StudyTime = scpStudy.StudyTime, - -// CallingAE = scpStudy.CallingAE, - -// SubmitState = scpStudySubjectVisit.SubjectVisit.SubmitState, -// SubjectVisitId = scpStudySubjectVisit.SubjectVisitId -// } -// ; - -// var sortField = string.IsNullOrWhiteSpace(inQuery.SortField) ? nameof(VisitPatientStudyView.StudyTime) : inQuery.SortField; -// var orderQuery = inQuery.Asc ? patientQuery.OrderBy(sortField) : patientQuery.OrderBy(sortField + " desc"); - -// var list = await orderQuery.ToListAsync(); - - -// return list; -// } - - - -// /// -// /// 访视管理- 获取subject 已存在的访视列表 ,同时获取项目访视的配置 在otherData里 -// /// -// /// -// /// -// /// -// [HttpPost] -// public async Task GetSubjectVisitSelectList(SubjectVisitSelectQuery inQuery, [FromServices] IRepository _subjectVisitReposiotry) -// { - -// var scpStudyList = await _studySubjectVisitRepository.Where(t => t.TrialId == inQuery.TrialId && t.SubjectId == inQuery.SubjectId && t.SCPStudyId != inQuery.SCPStudyId) -// .Select(t => new { t.SubjectVisitId, StudyTime = t.SCPStudy.StudyTime }) -// .ToListAsync(); - -// var result = scpStudyList.GroupBy(t => t.SubjectVisitId) -// .Select(g => new -// { - -// SubejctVisitId = g.Key, -// VisitMaxStudyTime = g.Max(c => c.StudyTime), -// VisitMinStudyTime = g.Min(c => c.StudyTime) -// }).ToList(); - -// var list = _subjectVisitReposiotry.Where(t => t.SubjectId == inQuery.SubjectId).ProjectTo(_mapper.ConfigurationProvider).ToList(); - -// foreach (var item in list) -// { -// item.VisitMaxStudyTime = result.Where(t => t.SubejctVisitId == item.Id).FirstOrDefault()?.VisitMaxStudyTime; -// item.VisitMinStudyTime = result.Where(t => t.SubejctVisitId == item.Id).FirstOrDefault()?.VisitMinStudyTime; -// } - -// var trialconfig = _trialRepository.Where(t => t.Id == inQuery.TrialId).Select(t => new { t.BlindBaseLineName, t.BlindFollowUpPrefix }).FirstOrDefault(); - -// return ResponseOutput.Ok(list, trialconfig); -// } - - - - -// /// -// ///访视管理-> 访视列表 (带患者信息,患者信息是数组) -// /// -// /// -// /// -// [HttpPost] -// public async Task>> GetPatientSubejctVisitList(PatientSubejctVisitQuery inQuery) -// { -// var query = _subjectVisitRepository.Where(t => t.TrialId == inQuery.TrialId) -// .WhereIf(!string.IsNullOrWhiteSpace(inQuery.SubjectCode), u => u.Subject.Code.Contains(inQuery.SubjectCode)) -// .WhereIf(!string.IsNullOrWhiteSpace(inQuery.SubjectSex), u => u.Subject.Sex.Contains(inQuery.SubjectSex)) -// .WhereIf(!string.IsNullOrWhiteSpace(inQuery.SubjectShortName), u => u.Subject.ShortName.Contains(inQuery.SubjectShortName)) -// .WhereIf(!string.IsNullOrWhiteSpace(inQuery.VisitName), u => u.VisitName.Contains(inQuery.VisitName)) -// .WhereIf(inQuery.SubmitState != null, u => u.SubmitState == inQuery.SubmitState) -// .WhereIf(inQuery.BeginStudyTime != null, t => t.SCPStudySubjectVisitList.Min(t => t.SCPStudy.StudyTime) >= inQuery.BeginStudyTime) -// .WhereIf(inQuery.EndStudyTime != null, t => t.SCPStudySubjectVisitList.Max(t => t.SCPStudy.StudyTime) <= inQuery.EndStudyTime) - -// .WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientIdStr), t => t.Subject.SubjectPatientList.Any(t => t.Patient.PatientIdStr.Contains(inQuery.PatientIdStr))) -// .WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientName), t => t.Subject.SubjectPatientList.Any(t => t.Patient.PatientName.Contains(inQuery.PatientName))) -// .WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientSex), t => t.Subject.SubjectPatientList.Any(t => t.Patient.PatientSex.Contains(inQuery.PatientSex))) -// .Select(t => new PatientSubjectVisitView() -// { -// PatientList = t.Subject.SubjectPatientList.Select(c => new PatientBasicInfo() -// { -// PatientId = c.PatientId, -// PatientAge = c.Patient.PatientAge, -// PatientBirthDate = c.Patient.PatientBirthDate, -// PatientIdStr = c.Patient.PatientIdStr, -// PatientSex = c.Patient.PatientSex, -// PatientName = c.Patient.PatientName, -// }).ToList(), - -// TrialId = t.TrialId, -// SubjectId = t.SubjectId, -// SubjectVisitId = t.Id, -// SubjectAge = t.Subject.Age, -// SubjectSex = t.Subject.Sex, -// SubjectShortName = t.Subject.ShortName, -// SubjectCode = t.Subject.Code, -// SubmitState = t.SubmitState, -// SubmitTime = t.SubmitTime, -// VisitNum = t.VisitNum, -// VisitName = t.VisitName, -// VisitEarliestStudyTime = t.SCPStudySubjectVisitList.Min(t => t.SCPStudy.StudyTime), -// VisitLatestStudyTime = t.SCPStudySubjectVisitList.Max(t => t.SCPStudy.StudyTime), -// VisitImageZipPath = t.VisitImageZipPath, -// PackState = t.PackState, -// }); - -// var defalutSortArray = new string[] { nameof(PatientSubjectVisitView.SubjectId), nameof(PatientSubjectVisitView.VisitNum) }; -// var pageList = await query.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, inQuery.SortField, inQuery.Asc, string.IsNullOrWhiteSpace(inQuery.SortField), defalutSortArray); - - - -// return ResponseOutput.Ok(pageList); -// } - - -// /// -// ///访视管理-> 获取当前访视 已绑定的患者检查 (从访视列表 进入修改绑定) -// /// -// /// -// /// -// [HttpPost] -// public async Task> GetCurrentVisitPatientStudyList(SubjectVisitStudyQuery inQuery) -// { -// var patientQuery = _studySubjectVisitRepository.Where(t => t.SubjectVisitId == inQuery.SujectVisitId && t.SubjectVisit.SubmitState != SubmitStateEnum.Submitted) -// //.WhereIf(inQuery.SubmitState != null, u => u.SubjectVisit.SubmitState == inQuery.SubmitState) -// .ProjectTo(_mapper.ConfigurationProvider); - -// var sortField = string.IsNullOrWhiteSpace(inQuery.SortField) ? nameof(VisitPatientStudyView.StudyTime) : inQuery.SortField; -// var orderQuery = inQuery.Asc ? patientQuery.OrderBy(sortField) : patientQuery.OrderBy(sortField + " desc"); - -// var list = await orderQuery.ToListAsync(); - -// return list; -// } - - -// /// -// /// 访视管理-> 获取可选访视列表 (从访视列表 进入修改绑定) -// /// -// /// -// /// -// [HttpPost] -// public async Task> GetPatientOtherStudyList(PatientStudyOtherQuery inQuery) -// { -// var query = from scpStudy in _studyRepository.Where(t => inQuery.PatientIdList.Contains(t.PatientId) && !t.SCPStudySubjectVisitList.Any(t => (t.SubjectVisitId == inQuery.SujectVisitId || t.SubjectVisit.SubmitState == SubmitStateEnum.Submitted) && t.TrialId == inQuery.TrialId)) -// .WhereIf(inQuery.EarliestStudyTime != null, t => t.StudyTime >= inQuery.EarliestStudyTime) -// .WhereIf(inQuery.LatestStudyTime != null, t => t.StudyTime <= inQuery.LatestStudyTime) -// .WhereIf(!string.IsNullOrEmpty(inQuery.PatientIdStr), t => t.PatientIdStr.Contains(inQuery.PatientIdStr)) -// //不属于该访视的检查 或者未绑定的检查 -// join scpStudySubjectVisit in _studySubjectVisitRepository.Where(c => c.TrialId == inQuery.TrialId) on scpStudy.Id equals scpStudySubjectVisit.SCPStudyId -// into dd -// from scpStudySV in dd.DefaultIfEmpty() -// select new VisitPatientStudyView() -// { -// PatientIdStr = scpStudy.PatientIdStr, -// PatientBirthDate = scpStudy.PatientBirthDate, -// PatientAge = scpStudy.PatientAge, -// PatientName = scpStudy.PatientName, -// PatientSex = scpStudy.PatientSex, -// Description = scpStudy.Description, -// CalledAE = scpStudy.CalledAE, -// CallingAE = scpStudy.CallingAE, -// InstanceCount = scpStudy.InstanceCount, -// Modalities = scpStudy.Modalities, -// PatientId = scpStudy.PatientId, -// SCPStudyId = scpStudy.Id, -// SeriesCount = scpStudy.SeriesCount, -// StudyTime = scpStudy.StudyTime, - -// SubmitState = scpStudySV.SubjectVisit.SubmitState, -// SubjectVisitId = scpStudySV.SubjectVisitId, -// VisitName = scpStudySV.SubjectVisit.VisitName, -// }; - -// #region 废弃 -// //var notCurrentVisitQuey = _studySubjectVisitRepository.Where(t => t.SubjectVisitId != inQuery.SujectVisitId && t.SCPStudy.Patient.Id == inQuery.PatientId) -// // .Select(t => new VisitPatientStudyView() -// // { -// // Description = t.SCPStudy.Description, -// // CalledAE = t.SCPStudy.CalledAE, -// // InstanceCount = t.SCPStudy.InstanceCount, -// // Modalities = t.SCPStudy.Modalities, -// // PatientId = t.SCPStudy.PatientId, -// // SCPStudyId = t.SCPStudy.PatientId, -// // SeriesCount = t.SCPStudy.SeriesCount, -// // StudyTime = t.SCPStudy.StudyTime, -// // SubjectVisitId = t.SubjectVisitId, -// // VisitName = t.SubjectVisit.VisitName, -// // }); - -// //var notBindQuery= _studyRepository.Where(t => t.PatientId == inQuery.PatientId && t.pa) - -// //var patientQuery = query - -// // .ProjectTo(_mapper.ConfigurationProvider); -// #endregion -// var sortField = string.IsNullOrWhiteSpace(inQuery.SortField) ? nameof(VisitPatientStudyView.StudyTime) : inQuery.SortField; -// var orderQuery = inQuery.Asc ? query.OrderBy(sortField) : query.OrderBy(sortField + " desc"); - -// var list = await orderQuery.ToListAsync(); - -// return list; -// } - -// #endregion - -// #region 检查管理 - - - -// /// -// ///检查管理-> 检查列表 (同步影像数据之前的) -// /// -// /// -// /// -// [HttpPost] -// public async Task>> GetPatientStudyBeforeConfirmList(TrialPatientStudyQuery inQuery) -// { -// #region 只查询已绑定的 -// //var query = _studySubjectVisitRepository.Where(t => t.SubjectVisit.TrialId == inQuery.TrialId) -// // .WhereIf(inQuery.PatientId != null, t => t.SCPStudy.PatientId == inQuery.PatientId) -// // .WhereIf(!string.IsNullOrWhiteSpace(inQuery.SubjectCode), u => u.SubjectVisit.Subject.Code.Contains(inQuery.SubjectCode)) -// // .WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientIdStr), u => u.SCPStudy.Patient.PatientIdStr.Contains(inQuery.PatientIdStr)) -// // .WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientSex), t => t.SCPStudy.Patient.PatientSex.Contains(inQuery.PatientSex)) -// // .WhereIf(inQuery.SubjectAge != null, t => t.SubjectVisit.Subject.Age == inQuery.SubjectAge) -// // .WhereIf(!string.IsNullOrWhiteSpace(inQuery.SubjectCode), u => u.SubjectVisit.Subject.Code.Contains(inQuery.SubjectCode)) -// // .WhereIf(!string.IsNullOrWhiteSpace(inQuery.SubjectSex), u => u.SubjectVisit.Subject.Sex.Contains(inQuery.SubjectSex)) -// // .WhereIf(!string.IsNullOrWhiteSpace(inQuery.SubjectShortName), t => t.SubjectVisit.Subject.ShortName.Contains(inQuery.SubjectShortName)) -// // .WhereIf(inQuery.BeginStudyTime != null, t => t.SCPStudy.StudyTime >= inQuery.BeginStudyTime) -// // .WhereIf(inQuery.EndStudyTime != null, t => t.SCPStudy.StudyTime <= inQuery.EndStudyTime) -// // .Select(t => new PatientStudyBeforeConfirmView() -// // { -// // SubjectId = t.SubjectVisit.SubjectId, -// // SubjectAge = t.SubjectVisit.Subject.Age, -// // SubjectSex = t.SubjectVisit.Subject.Sex, -// // SubjectShortName = t.SubjectVisit.Subject.ShortName, - - -// // PatientId = t.SCPStudy.PatientId, -// // PatientAge = t.SCPStudy.PatientAge, -// // PatientBirthDate = t.SCPStudy.PatientBirthDate, -// // PatientIdStr = t.SCPStudy.PatientIdStr, -// // PatientSex = t.SCPStudy.PatientSex, - -// // //PatientList = t.SubjectVisit.Subject.SubjectPatientList.Select(t => new PatientBasicInfo() -// // //{ -// // // PatientId = t.PatientId, -// // // PatientAge = t.Patient.PatientAge, -// // // PatientBirthDate = t.Patient.PatientBirthDate, -// // // PatientIdStr = t.Patient.PatientIdStr, -// // // PatientSex = t.Patient.PatientSex, -// // //}).ToList(), - -// // SubjectCode = t.SubjectVisit.Subject.Code, -// // SubmitState = t.SubjectVisit.SubmitState, -// // SubmitTime = t.SubjectVisit.SubmitTime, -// // VisitName = t.SubjectVisit.VisitName, -// // SubjectVisitId = t.SubjectVisitId, -// // VisitEarliestStudyTime = t.SubjectVisit.SCPStudySubjectVisitList.Min(t => t.SCPStudy.StudyTime), -// // VisitLatestStudyTime = t.SubjectVisit.SCPStudySubjectVisitList.Max(t => t.SCPStudy.StudyTime), - -// // StudyId = t.SCPStudyId, -// // StudyTime = t.SCPStudy.StudyTime, -// // CallingAE = t.SCPStudy.CallingAE, -// // CalledAE = t.SCPStudy.CalledAE - -// // }); -// #endregion - -// var query = from scpStudy in _studyRepository.Where(t => !t.SCPStudySubjectVisitList.Any(t => t.SubjectVisit.SubmitState == SubmitStateEnum.Submitted && t.TrialId == inQuery.TrialId)) -// .WhereIf(inQuery.IsBindedVisit == false, t => !t.SCPStudySubjectVisitList.Any(t => t.TrialId == inQuery.TrialId)) -// .WhereIf(inQuery.IsBindedVisit == true, t => t.SCPStudySubjectVisitList.Any(t => t.TrialId == inQuery.TrialId)) -// .WhereIf(!string.IsNullOrWhiteSpace(inQuery.VisitName), t => t.SCPStudySubjectVisitList.Any(t => t.TrialId == inQuery.TrialId && t.SubjectVisit.VisitName.Contains(inQuery.VisitName))) -// .WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientSex), t => t.Patient.PatientSex.Contains(inQuery.PatientSex)) -// .WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientIdStr), u => u.Patient.PatientIdStr.Contains(inQuery.PatientIdStr)) -// .WhereIf(inQuery.BeginStudyTime != null, t => t.StudyTime >= inQuery.BeginStudyTime) -// .WhereIf(inQuery.EndStudyTime != null, t => t.StudyTime <= inQuery.EndStudyTime) -// join subjectPatient in _subjectPatientRepository.Where(t => t.Subject.TrialId == inQuery.TrialId) -// .WhereIf(!string.IsNullOrWhiteSpace(inQuery.SubjectCode), u => u.Subject.Code.Contains(inQuery.SubjectCode)) -// .WhereIf(!string.IsNullOrWhiteSpace(inQuery.SubjectSex), u => u.Subject.Sex.Contains(inQuery.SubjectSex)) -// .WhereIf(!string.IsNullOrWhiteSpace(inQuery.SubjectShortName), t => t.Subject.ShortName.Contains(inQuery.SubjectShortName)) -// on scpStudy.PatientId equals subjectPatient.PatientId -// join scpStudySubjectVisit in _studySubjectVisitRepository.Where(t => t.TrialId == inQuery.TrialId) -// on scpStudy.Id equals scpStudySubjectVisit.SCPStudyId into dd -// from scpStudySV in dd.DefaultIfEmpty() -// select new PatientStudyBeforeConfirmView() -// { -// SubjectId = subjectPatient.Subject.Id, -// SubjectAge = subjectPatient.Subject.Age, -// SubjectSex = subjectPatient.Subject.Sex, -// SubjectShortName = subjectPatient.Subject.ShortName, -// SubjectCode = subjectPatient.Subject.Code, - -// PatientId = scpStudy.PatientId, -// PatientName = scpStudy.PatientName, -// PatientAge = scpStudy.PatientAge, -// PatientBirthDate = scpStudy.PatientBirthDate, -// PatientIdStr = scpStudy.PatientIdStr, -// PatientSex = scpStudy.PatientSex, - -// //PatientList = t.SubjectVisit.Subject.SubjectPatientList.Select(t => new PatientBasicInfo() -// //{ -// // PatientId = t.PatientId, -// // PatientAge = t.Patient.PatientAge, -// // PatientBirthDate = t.Patient.PatientBirthDate, -// // PatientIdStr = t.Patient.PatientIdStr, -// // PatientSex = t.Patient.PatientSex, -// //}).ToList(), - - -// SubmitState = scpStudySV.SubjectVisit.SubmitState, -// SubmitTime = scpStudySV.SubjectVisit.SubmitTime, -// VisitName = scpStudySV.SubjectVisit.VisitName, -// VisitNum = scpStudySV.SubjectVisit.VisitNum, -// SubjectVisitId = scpStudySV.SubjectVisit.Id, -// VisitEarliestStudyTime = scpStudySV.SubjectVisit.SCPStudySubjectVisitList.Min(t => t.SCPStudy.StudyTime), -// VisitLatestStudyTime = scpStudySV.SubjectVisit.SCPStudySubjectVisitList.Max(t => t.SCPStudy.StudyTime), - -// StudyId = scpStudy.Id, -// StudyTime = scpStudy.StudyTime, -// CallingAE = scpStudy.CallingAE, -// CalledAE = scpStudy.CalledAE, -// Description = scpStudy.Description, -// InstanceCount = scpStudy.InstanceCount, -// Modalities = scpStudy.Modalities, -// ModalityForEdit = scpStudy.ModalityForEdit, -// SeriesCount = scpStudy.SeriesCount - -// }; - -// var defalutSortArray = new string[] { nameof(PatientStudyBeforeConfirmView.SubjectCode), nameof(PatientStudyBeforeConfirmView.VisitNum), nameof(PatientStudyBeforeConfirmView.StudyTime) }; -// var pageList = await query.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, inQuery.SortField, inQuery.Asc, string.IsNullOrWhiteSpace(inQuery.SortField), defalutSortArray); - - - -// return ResponseOutput.Ok(pageList); -// } - - -// /// -// ///检查管理-> 检查列表 (同步影像数据之后的 带患者信息 患者信息是数组) -// /// -// /// -// /// -// [HttpPost] -// public async Task>> GetTrialPatientStudyList(TrialPatientStudyQuery inQuery) -// { -// var query = _repository.Where(t => t.SubjectVisit.TrialId == inQuery.TrialId) -// .WhereIf(!string.IsNullOrWhiteSpace(inQuery.SubjectCode), u => u.SubjectVisit.Subject.Code.Contains(inQuery.SubjectCode)) -// .WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientIdStr), u => u.PatientIdStr.Contains(inQuery.PatientIdStr)) -// .WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientSex), t => t.PatientSex.Contains(inQuery.PatientSex)) -// .WhereIf(inQuery.SubjectAge != null, t => t.SubjectVisit.Subject.Age == inQuery.SubjectAge) -// .WhereIf(!string.IsNullOrWhiteSpace(inQuery.SubjectCode), u => u.SubjectVisit.Subject.Code.Contains(inQuery.SubjectCode)) -// .WhereIf(!string.IsNullOrWhiteSpace(inQuery.SubjectSex), u => u.SubjectVisit.Subject.Sex.Contains(inQuery.SubjectSex)) -// .WhereIf(!string.IsNullOrWhiteSpace(inQuery.SubjectShortName), t => t.SubjectVisit.Subject.ShortName.Contains(inQuery.SubjectShortName)) -// .WhereIf(inQuery.BeginStudyTime != null, t => t.StudyTime >= inQuery.BeginStudyTime) -// .WhereIf(inQuery.EndStudyTime != null, t => t.StudyTime <= inQuery.EndStudyTime) -// .Select(t => new PatientStudyView() -// { -// SubjectId = t.SubjectVisit.SubjectId, -// SubjectAge = t.Subject.Age, -// SubjectSex = t.Subject.Sex, -// SubjectShortName = t.Subject.ShortName, - - -// //PatientId = Guid.Empty, -// PatientAge = t.PatientAge, -// PatientName = t.PatientName, -// PatientBirthDate = t.PatientBirthDate, -// PatientIdStr = t.PatientIdStr, -// PatientSex = t.PatientSex, - -// //PatientList = t.Subject.SubjectPatientList.Select(t => new PatientBasicInfo() -// //{ -// // PatientId = t.PatientId, -// // PatientAge = t.Patient.PatientAge, -// // PatientBirthDate = t.Patient.PatientBirthDate, -// // PatientIdStr = t.Patient.PatientIdStr, -// // PatientSex = t.Patient.PatientSex, -// //}).ToList(), - -// Modalities = t.Modalities, -// ModalityForEdit = t.ModalityForEdit, -// SubjectCode = t.SubjectVisit.Subject.Code, -// SubmitState = t.SubjectVisit.SubmitState, -// SubmitTime = t.SubjectVisit.SubmitTime, -// VisitName = t.SubjectVisit.VisitName, -// VisitNum = t.SubjectVisit.VisitNum, -// SubjectVisitId = t.SubjectVisitId, -// VisitEarliestStudyTime = t.SubjectVisit.StudyList.Min(t => t.StudyTime), -// VisitLatestStudyTime = t.SubjectVisit.StudyList.Max(t => t.StudyTime), - -// StudyId = t.Id, -// StudyTime = t.StudyTime, -// Description = t.Description, -// SeriesCount = t.SeriesCount, -// InstanceCount = t.InstanceCount, -// }); - -// var defalutSortArray = new string[] { nameof(PatientStudyView.SubjectCode), nameof(PatientStudyView.VisitNum), nameof(PatientStudyView.StudyTime) }; - -// var pageList = await query.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, inQuery.SortField, inQuery.Asc, string.IsNullOrWhiteSpace(inQuery.SortField), defalutSortArray); - - -// return ResponseOutput.Ok(pageList); -// } - - - -// /// -// /// 获取该项目 患者已绑定subject ,新来了的检查 可能需要新建访视 但是新增的检查未绑定访视的检查列表 -// /// -// /// -// /// -// [HttpPost] -// public async Task>> GetTrialUnbindSubjectVisitStudyList(TrialPatientStudyQuery inQuery) -// { -// //属于该项目的已绑定患者的检查,同时没有绑定任何访视 -// var query = from scpStudy in _studyRepository.Where(t => !t.SCPStudySubjectVisitList.Any(t => t.TrialId == inQuery.TrialId)) -// .WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientSex), t => t.Patient.PatientSex.Contains(inQuery.PatientSex)) -// .WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientIdStr), u => u.Patient.PatientIdStr.Contains(inQuery.PatientIdStr)) -// .WhereIf(inQuery.BeginStudyTime != null, t => t.StudyTime >= inQuery.BeginStudyTime) -// .WhereIf(inQuery.EndStudyTime != null, t => t.StudyTime <= inQuery.EndStudyTime) -// join subjectPatient in _subjectPatientRepository.Where(t => t.Subject.TrialId == inQuery.TrialId) -// .WhereIf(!string.IsNullOrWhiteSpace(inQuery.SubjectCode), u => u.Subject.Code.Contains(inQuery.SubjectCode)) -// .WhereIf(!string.IsNullOrWhiteSpace(inQuery.SubjectSex), u => u.Subject.Sex.Contains(inQuery.SubjectSex)) -// .WhereIf(!string.IsNullOrWhiteSpace(inQuery.SubjectShortName), t => t.Subject.ShortName.Contains(inQuery.SubjectShortName)) -// on scpStudy.PatientId equals subjectPatient.PatientId -// join scpStudySubjectVisit in _studySubjectVisitRepository.AsQueryable() on scpStudy.Id equals scpStudySubjectVisit.SCPStudyId -// into dd -// from scpStudySV in dd.DefaultIfEmpty() -// select new UnbindStudyView() -// { -// PatientIdStr = scpStudy.PatientIdStr, -// PatientBirthDate = scpStudy.PatientBirthDate, -// PatientAge = scpStudy.PatientAge, -// PatientName = scpStudy.PatientName, -// PatientSex = scpStudy.PatientSex, -// Description = scpStudy.Description, -// CalledAE = scpStudy.CalledAE, -// InstanceCount = scpStudy.InstanceCount, -// Modalities = scpStudy.Modalities, -// PatientId = scpStudy.PatientId, -// SCPStudyId = scpStudy.Id, -// SeriesCount = scpStudy.SeriesCount, -// StudyTime = scpStudy.StudyTime, - -// SubjectVisitId = scpStudySV.SubjectVisitId, -// VisitName = scpStudySV.SubjectVisit.VisitName, - -// SubjectId = subjectPatient.SubjectId, -// SubjectCode = subjectPatient.Subject.Code, -// TrialId = subjectPatient.Subject.TrialId, -// SubjectAge = subjectPatient.Subject.Age, -// SubjectSex = subjectPatient.Subject.Sex, -// SubjectShortName = subjectPatient.Subject.ShortName, -// SubjectBirthDate = subjectPatient.Subject.BirthDate -// }; - -// #region 废弃 -// //var query = from subject in _subjectRepository.Where(t => t.TrialId == inQuery.TrialId) -// // .WhereIf(inQuery.SubjectAge != null, t => t.Age == inQuery.SubjectAge) -// // .WhereIf(!string.IsNullOrWhiteSpace(inQuery.SubjectCode), u => u.Code.Contains(inQuery.SubjectCode)) -// // .WhereIf(!string.IsNullOrWhiteSpace(inQuery.SubjectSex), u => u.Sex.Contains(inQuery.SubjectSex)) -// // .WhereIf(!string.IsNullOrWhiteSpace(inQuery.SubjectShortName), t => t.ShortName.Contains(inQuery.SubjectShortName)) -// // join subjectPatient in _subjectPatientRepository.AsQueryable() on subject.Id equals subjectPatient.PatientId -// // //没有绑定任何访视 -// // join scpStudy in _studyRepository.AsQueryable() -// // .WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientSex), t => t.Patient.PatientSex.Contains(inQuery.PatientSex)) -// // .WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientIdStr), u => u.Patient.PatientIdStr.Contains(inQuery.PatientIdStr)) -// // .WhereIf(inQuery.BeginStudyTime != null, t => t.StudyTime >= inQuery.BeginStudyTime) -// // .WhereIf(inQuery.EndStudyTime != null, t => t.StudyTime <= inQuery.EndStudyTime) -// // on subjectPatient.PatientId equals scpStudy.PatientId -// // select new SubjectPatientStudyView() -// // { -// // SubjectId = subject.Id, -// // SubjectAge = subject.Age, -// // SubjectSex = subject.Sex, -// // SubjectShortName = subject.ShortName, - -// // PatientList = subject.SubjectPatientList.Select(t => new PatientBasicInfo() -// // { -// // PatientId = t.PatientId, -// // PatientAge = t.Patient.PatientAge, -// // PatientBirthDate = t.Patient.PatientBirthDate, -// // PatientIdStr = t.Patient.PatientIdStr, -// // PatientSex = t.Patient.PatientSex, -// // }).ToList(), - -// // SubjectCode = subject.Code, - -// // SeriesCount = scpStudy.SeriesCount, -// // CalledAE = scpStudy.CalledAE, -// // InstanceCount = scpStudy.InstanceCount, -// // Description = scpStudy.Description, -// // Modalities = scpStudy.Modalities, -// // PatientId = scpStudy.PatientId, - -// // SCPStudyId = scpStudy.Id, -// // StudyTime = scpStudy.StudyTime - -// // }; -// #endregion - - - - - - -// var pageList = await query.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, inQuery.SortField == string.Empty ? nameof(UnbindStudyView.StudyTime) : inQuery.SortField, inQuery.Asc); - - -// return ResponseOutput.Ok(pageList); -// } - -// /// -// /// 删除某个项目 未提交的访视检查绑定, 清理数据,方便测试自动绑定 -// /// -// /// -// /// -// [HttpDelete] -// public async Task DeleteUnSubmittedStudyBind(Guid trialId, Guid? subjectId, -// [FromServices] IRepository _visitTaskRepository, -// [FromServices] IRepository _dicomStudyRepository, -// [FromServices] IRepository _dicomSeriesRepository, -// [FromServices] IRepository _dicomInstanceRepository) -// { -// if (subjectId != null) -// { -// await _studySubjectVisitRepository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId && t.SubjectId == subjectId); - -// await _subjectVisitRepository.BatchDeleteNoTrackingAsync(t => t.SubjectId == subjectId); - -// await _visitTaskRepository.BatchDeleteNoTrackingAsync(t => t.SubjectId == subjectId); - -// await _dicomStudyRepository.BatchDeleteNoTrackingAsync(t => t.SubjectId == subjectId); -// await _dicomSeriesRepository.BatchDeleteNoTrackingAsync(t => t.SubjectId == subjectId); -// await _dicomInstanceRepository.BatchDeleteNoTrackingAsync(t => t.SubjectId == subjectId); - -// } -// else -// { -// await _studySubjectVisitRepository.BatchDeleteNoTrackingAsync(t => t.TrialId == trialId && t.SubjectVisit.SubmitState != SubmitStateEnum.Submitted); - -// } - - -// return ResponseOutput.Ok(); -// } - - -// /// -// /// 阅片管理-> 任务列表 -// /// -// /// -// /// -// [HttpPost] -// public async Task>> GetPatientVisitTaskList([FromServices] IRepository _visitTaskRepository, PatientVisitTaskQuery inQuery) -// { -// var visitTaskQueryable = _visitTaskRepository.Where(t => t.TrialId == inQuery.TrialId && t.IsAnalysisCreate == false) -// .WhereIf(inQuery.ReadingCategory != null, t => t.ReadingCategory == inQuery.ReadingCategory) -// .WhereIf(inQuery.ReadingCategory == null, t => t.ReadingCategory != ReadingCategory.Judge) - -// .WhereIf(inQuery.ReadingTaskState != null, t => t.ReadingTaskState == inQuery.ReadingTaskState) -// .WhereIf(inQuery.TaskState != null, t => t.TaskState == inQuery.TaskState) -// .WhereIf(inQuery.SubjectId != null, t => t.SubjectId == inQuery.SubjectId) -// .WhereIf(inQuery.DoctorUserId != null, t => t.DoctorUserId == inQuery.DoctorUserId) -// .WhereIf(inQuery.TrialReadingCriterionId != null, t => t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId) - -// .WhereIf(!string.IsNullOrEmpty(inQuery.TaskName), t => t.TaskName.Contains(inQuery.TaskName) || t.TaskBlindName.Contains(inQuery.TaskName)) -// .WhereIf(inQuery.BeginSignTime != null, t => t.SignTime >= inQuery.BeginSignTime) -// .WhereIf(inQuery.EndSignTime != null, t => t.SignTime <= inQuery.EndSignTime) - -// .WhereIf(inQuery.BeginTaskCreateTime != null, t => t.CreateTime >= inQuery.BeginTaskCreateTime) -// .WhereIf(inQuery.EndTaskCreateTime != null, t => t.CreateTime <= inQuery.EndTaskCreateTime) - -// .WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientIdStr), t => t.Subject.SubjectPatientList.Any(t => t.Patient.PatientIdStr.Contains(inQuery.PatientIdStr))) -// .WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientName), t => t.Subject.SubjectPatientList.Any(t => t.Patient.PatientName.Contains(inQuery.PatientName))) -// .WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientSex), t => t.Subject.SubjectPatientList.Any(t => t.Patient.PatientSex.Contains(inQuery.PatientSex))) -// .WhereIf(!string.IsNullOrEmpty(inQuery.SubjectShortName), t => t.Subject.ShortName.Contains(inQuery.SubjectShortName)) -// .WhereIf(!string.IsNullOrEmpty(inQuery.SubjectCode), t => (t.Subject.Code.Contains(inQuery.SubjectCode) && t.IsAnalysisCreate == false) || (t.BlindSubjectCode.Contains(inQuery.SubjectCode) && t.IsAnalysisCreate)) -// .ProjectTo(_mapper.ConfigurationProvider); - -// var defalutSortArray = new string[] { nameof(PatientVisitTaskDTO.SubjectId), nameof(PatientVisitTaskDTO.VisitTaskNum) }; - -// var pageList = await visitTaskQueryable.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, inQuery.SortField, inQuery.Asc, string.IsNullOrWhiteSpace(inQuery.SortField), defalutSortArray); - -// return ResponseOutput.Ok(pageList); -// } - - -// #endregion - - - - - -// /// -// /// scp 影像推送记录表 -// /// -// /// -// /// -// [HttpPost] -// public async Task>> GetSCPImageUploadList(SCPImageUploadQuery inQuery) -// { -// var query = _repository.Where() -// .WhereIf(!string.IsNullOrWhiteSpace(inQuery.CalledAE), t => t.CalledAE.Contains(inQuery.CalledAE)) -// .WhereIf(!string.IsNullOrWhiteSpace(inQuery.CallingAEIP), t => t.CallingAEIP.Contains(inQuery.CallingAEIP)) -// .WhereIf(!string.IsNullOrWhiteSpace(inQuery.CallingAE), t => t.CallingAE.Contains(inQuery.CallingAE)) -// .WhereIf(inQuery.StartTime != null, t => t.StartTime >= inQuery.StartTime) -// .WhereIf(inQuery.EndTime != null, t => t.EndTime <= inQuery.EndTime) - -// .ProjectTo(_mapper.ConfigurationProvider); - - -// var pageList = await query.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, inQuery.SortField == string.Empty ? nameof(SCPImageUploadView.CallingAE) : inQuery.SortField, inQuery.Asc); - - -// return ResponseOutput.Ok(pageList); -// } - - - - -// } - - - -//} +} diff --git a/IRaCIS.Core.Application/Service/Visit/_MapConfig.cs b/IRaCIS.Core.Application/Service/Visit/_MapConfig.cs index 35a01056d..717c22d8e 100644 --- a/IRaCIS.Core.Application/Service/Visit/_MapConfig.cs +++ b/IRaCIS.Core.Application/Service/Visit/_MapConfig.cs @@ -112,6 +112,14 @@ namespace IRaCIS.Core.Application.Service .ForMember(d => d.InstanceInfoList, u => u.MapFrom(s => s.InstanceList)); CreateMap(); + + + CreateMap() + .ForMember(d => d.TrialSiteCode, u => u.MapFrom(s => s.TrialSite.TrialSiteCode)) + .ForMember(d => d.TrialSiteAliasName, u => u.MapFrom(s => s.TrialSite.TrialSiteAliasName)) + .ForMember(d => d.TrialSiteName, u => u.MapFrom(s => s.TrialSite.TrialSiteName)) +; + } } diff --git a/IRaCIS.Core.Domain/Image/DicomStudy.cs b/IRaCIS.Core.Domain/Image/DicomStudy.cs index e5193846b..b0d6526b5 100644 --- a/IRaCIS.Core.Domain/Image/DicomStudy.cs +++ b/IRaCIS.Core.Domain/Image/DicomStudy.cs @@ -99,5 +99,8 @@ namespace IRaCIS.Core.Domain.Models public Guid? DeleteUserId { get; set; } + public bool IsFromPACS { get; set; } + + } } diff --git a/IRaCIS.Core.Domain/Image/SCPImageUpload.cs b/IRaCIS.Core.Domain/Image/SCPImageUpload.cs index a2982fba0..10e6b4ef0 100644 --- a/IRaCIS.Core.Domain/Image/SCPImageUpload.cs +++ b/IRaCIS.Core.Domain/Image/SCPImageUpload.cs @@ -55,6 +55,19 @@ namespace IRaCIS.Core.Domain.Models public int StudyCount { get; set; } + + + + public Guid TrialId { get; set; } + public Guid TrialSiteId { get; set; } + + [JsonIgnore] + + public Trial Trial { get; set; } + + [JsonIgnore] + public TrialSite TrialSite { get; set; } + } diff --git a/IRaCIS.Core.Domain/Image/SCPPatient.cs b/IRaCIS.Core.Domain/Image/SCPPatient.cs index 21eda7f87..0c75de6d4 100644 --- a/IRaCIS.Core.Domain/Image/SCPPatient.cs +++ b/IRaCIS.Core.Domain/Image/SCPPatient.cs @@ -29,9 +29,17 @@ namespace IRaCIS.Core.Domain.Models public DateTime LatestPushTime { get; set; } + public Guid? SubjectId { get; set; } + public Guid TrialId { get; set; } + public Guid TrialSiteId { get; set; } + + [JsonIgnore] public Subject Subject { get; set; } - public Guid? SubjectId { get; set; } + [JsonIgnore] + public Trial Trial { get; set; } + [JsonIgnore] + public TrialSite TrialSite { get; set; } } } diff --git a/IRaCIS.Core.Domain/Image/SCPStudy.cs b/IRaCIS.Core.Domain/Image/SCPStudy.cs index c78222617..4af3686cd 100644 --- a/IRaCIS.Core.Domain/Image/SCPStudy.cs +++ b/IRaCIS.Core.Domain/Image/SCPStudy.cs @@ -84,12 +84,20 @@ namespace IRaCIS.Core.Domain.Models public bool IsUploadFinished { get; set; } - + public Guid TrialId { get; set; } + public Guid TrialSiteId { get; set; } public Guid? SubjectVisitId { get; set; } [JsonIgnore] public SubjectVisit SubjectVisit { get; set; } + [JsonIgnore] + + public Trial Trial { get; set; } + + [JsonIgnore] + public TrialSite TrialSite { get; set; } + } }