663 lines
29 KiB
C#
663 lines
29 KiB
C#
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<Trial> _trialRepository;
|
|
private readonly IRepository<SCPPatient> _patientRepository;
|
|
private readonly IRepository<SCPStudy> _scpStudyRepository;
|
|
private readonly IRepository<Subject> _subjectRepository;
|
|
private readonly IRepository<SubjectVisit> _subjectVisitRepository;
|
|
private readonly IRepository<Dictionary> _dictionaryRepository;
|
|
private readonly IDistributedLockProvider _distributedLockProvider;
|
|
|
|
public PatientService(IRepository<SCPStudy> studyRepository, IRepository<Dictionary> dictionaryRepository, IRepository<Trial> trialRepository, IRepository<SCPPatient> patientRepository, IRepository<Subject> subjectRepository, IRepository<SubjectVisit> subjectVisitRepository, IDistributedLockProvider distributedLockProvider)
|
|
{
|
|
_dictionaryRepository = dictionaryRepository;
|
|
_scpStudyRepository = studyRepository;
|
|
_trialRepository = trialRepository;
|
|
_patientRepository = patientRepository;
|
|
_subjectRepository = subjectRepository;
|
|
_subjectVisitRepository = subjectVisitRepository;
|
|
_distributedLockProvider = distributedLockProvider;
|
|
}
|
|
|
|
|
|
[HttpGet]
|
|
public async Task<IResponseOutput<List<DicomSeriesDTO>>> GetPatientSeriesList(Guid scpStudyId,
|
|
[FromServices] IRepository<SCPSeries> _seriesRepository,
|
|
[FromServices] IRepository<SCPInstance> _instanceRepository
|
|
)
|
|
{
|
|
|
|
var seriesList = await _seriesRepository.Where(s => s.StudyId == scpStudyId).OrderBy(s => s.SeriesNumber).
|
|
ThenBy(s => s.SeriesTime).ThenBy(s => s.CreateTime)
|
|
.ProjectTo<DicomSeriesDTO>(_mapper.ConfigurationProvider).ToListAsync();
|
|
|
|
var instanceList = 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);
|
|
|
|
foreach (var series in seriesList)
|
|
{
|
|
|
|
series.InstanceInfoList = instanceList.Where(t => t.SeriesId == series.Id).OrderBy(t => t.InstanceNumber).Select(k =>
|
|
new InstanceBasicInfo()
|
|
{
|
|
Id = k.Id,
|
|
NumberOfFrames = k.NumberOfFrames,
|
|
//HtmlPath = string.Empty,
|
|
Path = k.Path,
|
|
InstanceNumber = k.InstanceNumber,
|
|
|
|
}).ToList();
|
|
}
|
|
|
|
var study = await _scpStudyRepository.FindAsync(scpStudyId);
|
|
|
|
return ResponseOutput.Ok(seriesList, study);
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// scp 影像推送记录表
|
|
/// </summary>
|
|
/// <param name="inQuery"></param>
|
|
/// <returns></returns>
|
|
[HttpPost]
|
|
public async Task<IResponseOutput<PageOutput<SCPImageUploadView>>> GetSCPImageUploadList(SCPImageUploadQuery inQuery)
|
|
{
|
|
var query = _repository.Where<SCPImageUpload>(t => t.TrialId == inQuery.TrialId)
|
|
.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<SCPImageUploadView>(_mapper.ConfigurationProvider);
|
|
|
|
|
|
var pageList = await query.ToPagedListAsync(inQuery);
|
|
|
|
|
|
return ResponseOutput.Ok(pageList);
|
|
}
|
|
|
|
|
|
#region 患者检查管理
|
|
|
|
/// <summary>
|
|
///影像检查列表-患者为维度组织
|
|
/// </summary>
|
|
/// <param name="inQuery"></param>
|
|
/// <returns></returns>
|
|
[HttpPost]
|
|
public async Task<IResponseOutput<PageOutput<PatientSubjectView>>> GetPatientList(PatientTrialQuery inQuery)
|
|
{
|
|
|
|
|
|
#region new ok
|
|
var query = _patientRepository.Where(t => t.TrialId == inQuery.TrialId)
|
|
.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);
|
|
#endregion
|
|
|
|
|
|
return ResponseOutput.Ok(pageList);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// 影像检查列表-> 获取患者的检查列表
|
|
/// </summary>
|
|
/// <param name="inQuery"></param>
|
|
/// <returns></returns>
|
|
[HttpPost]
|
|
public async Task<PageOutput<PatientStudySimpleView>> 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);
|
|
|
|
return pageList;
|
|
}
|
|
|
|
|
|
public async Task<List<string>> GetDicomCalledAEList(Guid trialId)
|
|
{
|
|
var list = await _scpStudyRepository.Where(t => t.TrialId == trialId).Select(t => t.CalledAE).Distinct().ToListAsync();
|
|
|
|
return list;
|
|
}
|
|
|
|
public async Task<List<string>> GetDicomCallingAEList(Guid trialId)
|
|
{
|
|
var list = await _scpStudyRepository.Where(t => t.TrialId == trialId).Select(t => t.CallingAE).Distinct().ToListAsync();
|
|
|
|
return list;
|
|
}
|
|
|
|
public async Task<List<string>> GetDicomModalityList(Guid trialId)
|
|
{
|
|
var list = await _scpStudyRepository.Where(t => t.TrialId == trialId).SelectMany(t => t.SeriesList).Select(t => t.Modality).Distinct().ToListAsync();
|
|
|
|
return list;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 影像访视上传 检查列表
|
|
/// </summary>
|
|
/// <param name="inQuery"></param>
|
|
/// <returns></returns>
|
|
[HttpPost]
|
|
public async Task<PageOutput<VisitPatientStudyFilterView>> 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))
|
|
.WhereIf(!string.IsNullOrWhiteSpace(inQuery.PatientInfo), t => t.PatientIdStr.Contains(inQuery.PatientInfo) || t.PatientName.Contains(inQuery.PatientInfo) || t.PatientSex.Contains(inQuery.PatientInfo))
|
|
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,
|
|
BodyPartExamined = scpStudy.BodyPartExamined,
|
|
AccessionNumber = scpStudy.AccessionNumber,
|
|
|
|
PatientBirthDate = scpStudy.PatientBirthDate,
|
|
PatientAge = scpStudy.PatientAge,
|
|
PatientIdStr = scpStudy.PatientIdStr,
|
|
PatientName = scpStudy.PatientName,
|
|
PatientSex = scpStudy.PatientSex,
|
|
};
|
|
|
|
|
|
var pageList = await query.ToPagedListAsync(inQuery);
|
|
|
|
return pageList;
|
|
}
|
|
|
|
|
|
|
|
public async Task<List<VerifySCPStudyUploadResult>> VerifyPacsImage(VerifyPacsImageCommand inCommand)
|
|
{
|
|
var trialId = inCommand.TrialId;
|
|
|
|
var subjectId = inCommand.SubjectId;
|
|
|
|
var isVerifyVisitImageDate = await _repository.Where<Trial>(t => t.Id == inCommand.TrialId).Select(t => t.IsVerifyVisitImageDate).FirstNotNullAsync();
|
|
|
|
var result = new List<VerifySCPStudyUploadResult>();
|
|
|
|
var visitList = _repository.Where<SubjectVisit>(t => t.SubjectId == inCommand.SubjectId).Select(t => new { t.VisitNum, t.EarliestScanDate, t.LatestScanDate, t.Id }).ToList();
|
|
|
|
var currentVisitNum = visitList.First(t => t.Id == inCommand.SubjectVisitId).VisitNum;
|
|
|
|
var scpStudyList = _scpStudyRepository.Where(t => inCommand.SCPStudyIdList.Contains(t.Id)).Select(t => new { StudyDate = t.StudyTime, t.Id }).ToList();
|
|
|
|
foreach (var waitUploadItem in scpStudyList)
|
|
{
|
|
|
|
if (isVerifyVisitImageDate)
|
|
{
|
|
//小于当前访视 最近的最晚拍片
|
|
var before = visitList.Where(u => u.VisitNum < currentVisitNum).Max(k => k.LatestScanDate);
|
|
|
|
if (before != null && waitUploadItem.StudyDate != null && before > waitUploadItem.StudyDate)
|
|
{
|
|
|
|
// $"当前访视检查时间{waitUploadItem.StudyDate?.ToString("yyyy-MM-dd")}不能早于前序访视检查时间{before?.ToString("yyyy-MM-dd")},请核对检查数据是否有误",
|
|
result.Add(new VerifySCPStudyUploadResult() { SCPStudyId = waitUploadItem.Id, ErrorMesseage = _localizer["Study_VisitBeforePrevError", waitUploadItem.StudyDate?.ToString("yyyy-MM-dd")!, before?.ToString("yyyy-MM-dd")!] });
|
|
continue; // 跳过当前迭代
|
|
}
|
|
|
|
//大于当前访视 最近的最早拍片日期
|
|
var after = visitList.Where(u => u.VisitNum > currentVisitNum).Min(k => k.EarliestScanDate);
|
|
|
|
if (after != null && waitUploadItem.StudyDate != null && after < waitUploadItem.StudyDate)
|
|
{
|
|
// $"当前访视检查时间{waitUploadItem.StudyDate?.ToString("yyyy-MM-dd")}不能晚于该访视之后的检查时间{after?.ToString("yyyy-MM-dd")},请核对检查数据是否有误"
|
|
result.Add(new VerifySCPStudyUploadResult() { SCPStudyId = waitUploadItem.Id, ErrorMesseage = _localizer["Study_VisitAfterSubseqError", waitUploadItem.StudyDate?.ToString("yyyy-MM-dd")!, after?.ToString("yyyy-MM-dd")!] });
|
|
continue; // 跳过当前迭代
|
|
}
|
|
}
|
|
|
|
var verifyStudyInfo = _repository.Where<DicomStudy>(t => t.TrialId == trialId && t.Id == waitUploadItem.Id).ProjectTo<VerifyStudyDto>(_mapper.ConfigurationProvider).FirstOrDefault();
|
|
|
|
var currentStudyResult = new VerifySCPStudyUploadResult() { SCPStudyId = waitUploadItem.Id };
|
|
|
|
|
|
//数据库不存在该检查 允许上传
|
|
if (verifyStudyInfo == null)
|
|
{
|
|
currentStudyResult.AllowUpload = true;
|
|
}
|
|
//数据库该项目有该检查 看是否支持重传
|
|
else
|
|
{
|
|
//是同一个受试者 支持重传
|
|
if (verifyStudyInfo.SubjectId == subjectId && verifyStudyInfo.SubjectVisitId == inCommand.SubjectVisitId)
|
|
{
|
|
currentStudyResult.AllowReUpload = true;
|
|
}
|
|
//不是同一个受试者
|
|
else
|
|
{
|
|
//有默认值,其实不用写,这里为了好理解
|
|
currentStudyResult.AllowUpload = false;
|
|
|
|
currentStudyResult.AllowReUpload = false;
|
|
|
|
//$"此处不可以上传。当前影像检查已经上传给受试者{verifyStudyInfo.SubjectCode}的{verifyStudyInfo.VisitName}"
|
|
currentStudyResult.ErrorMesseage = _localizer["Study_ImgAlreadyUploaded", verifyStudyInfo.SubjectCode, verifyStudyInfo.VisitName];
|
|
}
|
|
}
|
|
|
|
result.Add(currentStudyResult);
|
|
}
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// 提交 患者检查和访视的绑定
|
|
/// </summary>
|
|
/// <param name="inCommand"></param>
|
|
/// <param name="_dicomstudyRepository"></param>
|
|
/// <param name="_dicomSeriesRepository"></param>
|
|
/// <param name="_dicomInstanceRepository"></param>
|
|
/// <returns></returns>
|
|
[HttpPost]
|
|
[UnitOfWork]
|
|
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
|
public async Task<IResponseOutput> SubmitVisitStudyBinding(SubmitVisitStudyBindingCommand inCommand,
|
|
[FromServices] IRepository<DicomStudy> _dicomstudyRepository,
|
|
[FromServices] IRepository<DicomSeries> _dicomSeriesRepository,
|
|
[FromServices] IRepository<DicomInstance> _dicomInstanceRepository)
|
|
{
|
|
|
|
//这里要做校验 + 同时验证本地系统里面的影像是否存在pacs推过来的
|
|
|
|
var copyCommand = inCommand.Clone();
|
|
copyCommand.SCPStudyIdList = inCommand.SCPStudyIdList.Union(inCommand.ReUploadSCPStudyIdList).ToList();
|
|
var verifyResult = await VerifyPacsImage(copyCommand);
|
|
|
|
var allowUploadList = verifyResult.Where(u => u.AllowUpload == true).Select(t => t.SCPStudyId).ToList();
|
|
var allowReUploadList = verifyResult.Where(u => u.AllowReUpload == true).Select(t => t.SCPStudyId).ToList();
|
|
|
|
if (!(inCommand.SCPStudyIdList.All(t => allowUploadList.Contains(t)) && inCommand.ReUploadSCPStudyIdList.All(t => allowReUploadList.Contains(t))))
|
|
{
|
|
throw new BusinessValidationFailedException("对接提示: 前端提交的检查有不能上传的,请刷新页面调用验证接口重试!");
|
|
}
|
|
|
|
var subjectId = inCommand.SubjectId;
|
|
var subjectVisitId = inCommand.SubjectVisitId;
|
|
var trialId = inCommand.TrialId;
|
|
|
|
var @lock = _distributedLockProvider.CreateLock($"StudyCode");
|
|
|
|
using (await @lock.AcquireAsync())
|
|
{
|
|
var dbStudyCodeIntMax = _repository.Where<DicomStudy>(s => s.TrialId == inCommand.TrialId).Select(t => t.Code).DefaultIfEmpty().Max();
|
|
|
|
int currentNextCodeInt = dbStudyCodeIntMax + 1;
|
|
|
|
//新增的,上传的
|
|
foreach (var scpStudyId in inCommand.SCPStudyIdList)
|
|
{
|
|
|
|
var find = _scpStudyRepository.Where(t => t.Id == scpStudyId).Select(t => new { SCPStudy = t, t.SeriesList, t.InstanceList }).FirstOrDefault();
|
|
|
|
if (find != null)
|
|
{
|
|
var newStuty = _mapper.Map<DicomStudy>(find.SCPStudy);
|
|
|
|
await _repository.AddAsync(newStuty);
|
|
|
|
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;
|
|
|
|
var newSeriesList = _mapper.Map<List<DicomSeries>>(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<List<DicomInstance>>(find.InstanceList);
|
|
|
|
foreach (var instance in newInstanceList)
|
|
{
|
|
instance.SeqId = Guid.Empty;
|
|
instance.TrialId = trialId;
|
|
instance.SubjectId = subjectId;
|
|
instance.SubjectVisitId = subjectVisitId;
|
|
|
|
}
|
|
await _repository.AddRangeAsync(newInstanceList);
|
|
}
|
|
|
|
currentNextCodeInt++;
|
|
|
|
await _repository.BatchUpdateAsync<SCPPatient>(t => t.Id == find.SCPStudy.PatientId, u => new SCPPatient() { SubjectId = subjectId });
|
|
await _repository.BatchUpdateAsync<SCPStudy>(t => t.Id == scpStudyId, u => new SCPStudy() { SubjectVisitId = subjectVisitId });
|
|
|
|
|
|
}
|
|
|
|
foreach (var scpStudyId in inCommand.ReUploadSCPStudyIdList)
|
|
{
|
|
|
|
var study = await _dicomstudyRepository.FirstOrDefaultAsync(t => t.Id == scpStudyId);
|
|
|
|
var instanceIdList = _dicomInstanceRepository.Where(t => t.Id == scpStudyId).Select(t => t.Id).ToList();
|
|
|
|
var scpStudy = _scpStudyRepository.Where(t => t.Id == scpStudyId).Include(t => t.SeriesList).ThenInclude(t => t.SCPInstanceList).FirstOrDefault();
|
|
|
|
//以最后一次为准
|
|
study.IsFromPACS = true;
|
|
//特殊处理逻辑
|
|
study.Modalities = string.Join("、", scpStudy.SeriesList.Select(t => t.Modality).Union(study.Modalities.Split("、", StringSplitOptions.RemoveEmptyEntries)).Distinct());
|
|
|
|
SpecialArchiveStudyDeal(study);
|
|
|
|
|
|
// 少了整个序列
|
|
|
|
//某个序列下少了instance
|
|
foreach (var seriesItem in scpStudy.SeriesList)
|
|
{
|
|
var seriesId = IdentifierHelper.CreateGuid(seriesItem.StudyInstanceUid, seriesItem.SeriesInstanceUid, trialId.ToString());
|
|
|
|
DicomSeries dicomSeries = await _dicomSeriesRepository.FirstOrDefaultAsync(t => t.Id == seriesId);
|
|
|
|
//判断重复
|
|
if (dicomSeries == null)
|
|
{
|
|
var series = _mapper.Map<DicomSeries>(seriesItem);
|
|
|
|
series.SeqId = Guid.Empty;
|
|
series.TrialId = trialId;
|
|
series.SubjectId = subjectId;
|
|
series.SubjectVisitId = subjectVisitId;
|
|
|
|
|
|
dicomSeries = await _dicomSeriesRepository.AddAsync(series);
|
|
|
|
|
|
|
|
foreach (var instanceItem in seriesItem.SCPInstanceList)
|
|
{
|
|
var instance = _mapper.Map<DicomInstance>(instanceItem);
|
|
|
|
instance.SeqId = Guid.Empty;
|
|
instance.TrialId = trialId;
|
|
instance.SubjectId = subjectId;
|
|
instance.SubjectVisitId = subjectVisitId;
|
|
|
|
await _dicomInstanceRepository.AddAsync(instance);
|
|
}
|
|
|
|
//新的序列 那么 检查的序列数量+1
|
|
study.SeriesCount += 1;
|
|
|
|
study.InstanceCount += seriesItem.SCPInstanceList.Count;
|
|
}
|
|
else
|
|
{
|
|
//该序列掉了instance
|
|
dicomSeries.InstanceCount += seriesItem.SCPInstanceList.Count;
|
|
|
|
var newInstanceList = seriesItem.SCPInstanceList.Where(t => !instanceIdList.Contains(t.Id));
|
|
|
|
foreach (var instanceItem in newInstanceList)
|
|
{
|
|
var instance = _mapper.Map<DicomInstance>(instanceItem);
|
|
|
|
instance.SeqId = Guid.Empty;
|
|
instance.TrialId = trialId;
|
|
instance.SubjectId = subjectId;
|
|
instance.SubjectVisitId = subjectVisitId;
|
|
|
|
await _dicomInstanceRepository.AddAsync(instance);
|
|
}
|
|
|
|
study.InstanceCount += newInstanceList.Count();
|
|
|
|
}
|
|
}
|
|
|
|
await _repository.SaveChangesAsync();
|
|
await _repository.BatchUpdateAsync<SCPPatient>(t => t.Id == scpStudy.PatientId, u => new SCPPatient() { SubjectId = subjectId });
|
|
await _repository.BatchUpdateAsync<SCPStudy>(t => t.Id == scpStudyId, u => new SCPStudy() { SubjectVisitId = subjectVisitId });
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
await _repository.SaveChangesAsync();
|
|
|
|
|
|
return ResponseOutput.Ok();
|
|
}
|
|
|
|
|
|
private void SpecialArchiveStudyDeal(DicomStudy study)
|
|
{
|
|
#region 特殊逻辑
|
|
|
|
|
|
if (study.PatientBirthDate.Length == 8)
|
|
{
|
|
study.PatientBirthDate = $"{study.PatientBirthDate[0]}{study.PatientBirthDate[1]}{study.PatientBirthDate[2]}{study.PatientBirthDate[3]}-{study.PatientBirthDate[4]}{study.PatientBirthDate[5]}-{study.PatientBirthDate[6]}{study.PatientBirthDate[7]}";
|
|
}
|
|
|
|
var dicModalityList = _dictionaryRepository.Where(t => t.Code == "Modality").SelectMany(t => t.ChildList.Select(c => c.Value)).ToList();
|
|
|
|
|
|
var modality = study.Modalities;
|
|
|
|
var modalityForEdit = dicModalityList.Contains(modality) ? modality : String.Empty;
|
|
|
|
if (modality == "MR")
|
|
{
|
|
modalityForEdit = "MRI";
|
|
}
|
|
|
|
if (modality == "PT")
|
|
{
|
|
modalityForEdit = "PET";
|
|
}
|
|
if (modality == "PT、CT")
|
|
{
|
|
modalityForEdit = "PET-CT";
|
|
}
|
|
|
|
study.ModalityForEdit = modalityForEdit;
|
|
#endregion
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|