1069 lines
45 KiB
C#
1069 lines
45 KiB
C#
using AutoMapper;
|
||
using AutoMapper.QueryableExtensions;
|
||
using Dicom;
|
||
using IRaCIS.Application.ExpressionExtend;
|
||
using IRaCIS.Application.Interfaces;
|
||
using IRaCIS.Application.ViewModels;
|
||
using IRaCIS.Core.Application.Contracts.Dicom.DTO;
|
||
using IRaCIS.Core.Application.Contracts.RequestAndResponse;
|
||
using IRaCIS.Core.Application.Dicom;
|
||
using IRaCIS.Core.Domain.Interfaces;
|
||
using IRaCIS.Core.Domain.Models;
|
||
using IRaCIS.Core.Domain.Share;
|
||
using IRaCIS.Core.Domain.Share.AuthUser;
|
||
using IRaCIS.Infra.Data.ExpressionExtend;
|
||
using Microsoft.Extensions.Configuration;
|
||
using Microsoft.Extensions.Hosting;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.IO;
|
||
using System.Linq;
|
||
using System.Linq.Expressions;
|
||
using System.Text;
|
||
using System.Threading.Tasks;
|
||
using IConfiguration = Microsoft.Extensions.Configuration.IConfiguration;
|
||
|
||
namespace IRaCIS.Application.Services
|
||
{
|
||
public class StudyService : IStudyService
|
||
{
|
||
private readonly IDicomStudyRepository _studyRepository;
|
||
private readonly IVisitStageRepository _visitStageRepository;
|
||
private readonly ISubjectRepository _subjectRepository;
|
||
private readonly ISiteRepository _siteRepository;
|
||
private readonly ITrialRepository _trialRepository;
|
||
private readonly ISubjectVisitRepository _subjectVisitRepository;
|
||
private readonly IDicomInstanceRepository _dicomInstanceRepository;
|
||
private readonly IDicomSeriesRepository _dicomSeriesRepository;
|
||
|
||
private readonly IStudyReviewerRepository _studyReviewerRepository;
|
||
private readonly IDoctorRepository _doctorRepository;
|
||
private readonly IEnrollRepository _enrollRepository;
|
||
|
||
//private readonly IDicomStudyRepository _dicomStudyRepository;
|
||
private readonly IStudyStatusDetailRepository _studyStatusDetailRepository;
|
||
private readonly IUserInfo _userInfo;
|
||
private readonly IUserRepository _userRepository;
|
||
private readonly IUserTrialRepository _userTrialRepository;
|
||
private readonly IDictionaryRepository _dictionaryRepository;
|
||
private readonly IWorkloadTPRepository _workloadTPRepository;
|
||
|
||
private readonly IMapper _mapper;
|
||
|
||
private readonly IHostEnvironment _hostEnvironment;
|
||
private readonly ISponsorRepository _sponsorRepository;
|
||
private static string _fileStorePath = string.Empty;
|
||
public StudyService(IDicomStudyRepository visitPointRepository,
|
||
IVisitStageRepository visitPlanRepository,
|
||
ISubjectRepository subjectRepository,
|
||
ISiteRepository siteRepository,
|
||
ITrialRepository trialRepository,
|
||
ISubjectVisitRepository subjectVisitRepository,
|
||
IDicomInstanceRepository dicomInstanceRepository,
|
||
IDicomSeriesRepository dicomSeriesRepository,
|
||
IHostEnvironment hostEnvironment,
|
||
ISponsorRepository sponsorRepository,
|
||
IStudyReviewerRepository studyReviewerRepository,
|
||
IDoctorRepository doctorRepository,
|
||
IEnrollRepository enrollRepository,
|
||
//IDicomStudyRepository dicomStudyRepository,
|
||
IStudyStatusDetailRepository studyStatusDetailRepository,
|
||
IUserInfo userInfo,
|
||
IUserRepository userRepository,
|
||
IUserTrialRepository userTrialRepository,
|
||
IDictionaryRepository dictionaryRepository,
|
||
IWorkloadTPRepository workloadTPRepository,
|
||
IConfiguration config,
|
||
IMapper mapper)
|
||
{
|
||
_enrollRepository = enrollRepository;
|
||
//_dicomStudyRepository = dicomStudyRepository;
|
||
_studyReviewerRepository = studyReviewerRepository;
|
||
_studyStatusDetailRepository = studyStatusDetailRepository;
|
||
_userInfo = userInfo;
|
||
_userRepository = userRepository;
|
||
_userTrialRepository = userTrialRepository;
|
||
_dictionaryRepository = dictionaryRepository;
|
||
_doctorRepository = doctorRepository;
|
||
_studyRepository = visitPointRepository;
|
||
_visitStageRepository = visitPlanRepository;
|
||
_subjectRepository = subjectRepository;
|
||
_siteRepository = siteRepository;
|
||
_trialRepository = trialRepository;
|
||
_subjectVisitRepository = subjectVisitRepository;
|
||
_dicomInstanceRepository = dicomInstanceRepository;
|
||
_dicomSeriesRepository = dicomSeriesRepository;
|
||
_mapper = mapper;
|
||
_hostEnvironment = hostEnvironment;
|
||
_sponsorRepository = sponsorRepository;
|
||
_workloadTPRepository = workloadTPRepository;
|
||
_fileStorePath = config.GetValue<string>("DicomFileArchivedPath");
|
||
//_fileStorePath = Directory.GetParent(_hostEnvironment.ContentRootPath).FullName;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取受试者访视
|
||
/// </summary>
|
||
/// <param name="trialId"></param>
|
||
/// <param name="subjectId"></param>
|
||
/// <param name="siteId"></param>
|
||
/// <returns></returns>
|
||
public IEnumerable<StudyStatDTO> GetStudyStatList(Guid trialId, Guid subjectId, Guid siteId)
|
||
{
|
||
|
||
var query = from visitStage in _visitStageRepository.Find(u => u.TrialId == trialId)
|
||
join visit in (_studyRepository.GetAll()
|
||
.Where(t => t.TrialId == trialId && t.SubjectId == subjectId && t.SiteId == siteId)
|
||
.GroupBy(t => t.SubjectVisitId).Select(g => new
|
||
{
|
||
SubjectVisitId = g.Key,
|
||
VisitCount = g.Count()
|
||
}))
|
||
|
||
on visitStage.Id equals visit.SubjectVisitId into t
|
||
from visit in t.DefaultIfEmpty()
|
||
|
||
select new StudyStatDTO
|
||
{
|
||
|
||
StudyCount = visit.VisitCount,
|
||
TrialId = visitStage.TrialId,
|
||
VisitNum = visitStage.VisitNum,
|
||
VisitName = visitStage.VisitName,
|
||
VisitDay = visitStage.VisitDay,
|
||
Description = visitStage.Description,
|
||
SubjectVisitId = visitStage.Id
|
||
};
|
||
query = query.OrderBy(t => t.VisitNum);
|
||
var list = query.ToList();
|
||
|
||
return list;
|
||
|
||
}
|
||
|
||
public bool UpdateReUploadNewStudyCode(Guid studyId, Guid newStudyId)
|
||
{
|
||
var code = _studyRepository.GetAll().First(t => t.Id == studyId).StudyCode;
|
||
|
||
return _studyRepository.Update(t => t.Id == newStudyId, u => new DicomStudy()
|
||
{
|
||
//StudyCode = u.StudyCode+"("+code+")"
|
||
StudyCode = code
|
||
});
|
||
}
|
||
|
||
public VerifyStudyUploadResult VerifyStudyAllowUpload(string studyInstanceUid, Guid trialId, Guid? abandonStudyId)
|
||
{
|
||
Guid expectStudyId = IdentifierHelper.CreateGuid(studyInstanceUid.Trim(), trialId.ToString());
|
||
|
||
var result = new VerifyStudyUploadResult();
|
||
|
||
var query =
|
||
from study in _studyRepository.GetAll().Where(t => t.TrialId == trialId && t.Id == expectStudyId)
|
||
join subject in _subjectRepository.GetAll()
|
||
on study.SubjectId equals subject.Id
|
||
join trial in _trialRepository.GetAll() on study.TrialId equals trial.Id
|
||
join subjectVisit in _subjectVisitRepository.GetAll()
|
||
on study.SubjectVisitId equals subjectVisit.Id
|
||
join site in _siteRepository.GetAll() on study.SiteId equals site.Id
|
||
|
||
select new StudyDTO()
|
||
{
|
||
PatientAge = study.PatientAge,
|
||
PatientSex = study.PatientSex,
|
||
PatientName = study.PatientName,
|
||
SubjectAge = subject.Age,
|
||
SubjectCode = subject.Code,
|
||
SubjectId = subject.Id,
|
||
SubjectName = subject.Name,
|
||
SubjectSex = subject.Sex,
|
||
|
||
Id = study.Id,
|
||
TrialId = study.TrialId,
|
||
|
||
Modalities = study.Modalities,
|
||
StudyCode = study.StudyCode,
|
||
SeriesCount = study.SeriesCount,
|
||
InstanceCount = study.InstanceCount,
|
||
StudyStatus = study.Status,
|
||
StudyDate = study.StudyTime,
|
||
IsDoubleReview = study.IsDoubleReview,
|
||
StudyDescription = study.Description,
|
||
BodyPartExamined = study.BodyPartExamined,
|
||
Comment = study.Comment,
|
||
|
||
SiteId = study.SiteId,
|
||
SiteName = site.SiteName,
|
||
|
||
SubjectVisitId = study.SubjectVisitId,
|
||
VisitName = subjectVisit.VisitName,
|
||
VisitNum = subjectVisit.VisitNum,
|
||
VisitDay = subjectVisit.VisitDay,
|
||
SVUPDES = subjectVisit.SVUPDES,
|
||
SVENDTC = subjectVisit.SVENDTC,
|
||
SVSTDTC = subjectVisit.SVSTDTC
|
||
};
|
||
|
||
|
||
result.StudyInfo = query.FirstOrDefault();
|
||
|
||
|
||
//如果是上传 看当前项目有没有已经上传过该检查 存在就不允许上传
|
||
if (abandonStudyId == null || abandonStudyId == Guid.Empty)
|
||
{
|
||
result.AllowUpload = result.StudyInfo is null;
|
||
}
|
||
else
|
||
{
|
||
//如果是重传 已经上传的 在此传可以的,
|
||
if ( abandonStudyId.GetValueOrDefault()== expectStudyId)
|
||
{
|
||
result.AllowUpload = true;
|
||
}
|
||
//重传的时候换了新的影像 在数据库不存在该影像 也允许上传
|
||
else if(result.StudyInfo == null )
|
||
{
|
||
result.AllowUpload = true;
|
||
}
|
||
else
|
||
{
|
||
result.AllowUpload = false;
|
||
}
|
||
|
||
}
|
||
|
||
return result;
|
||
|
||
}
|
||
|
||
public PageOutput<StudyDTO> GetStudyList(StudyQueryDTO queryDto)
|
||
{
|
||
|
||
Expression<Func<DicomStudy, bool>> studyLambda = x => x.TrialId == queryDto.TrialId;
|
||
|
||
Expression<Func<SubjectVisit, bool>> subjectVisitLambda = x => x.TrialId == queryDto.TrialId;
|
||
|
||
if (queryDto.SubjectId != null)
|
||
{
|
||
studyLambda = studyLambda.And(t => t.SubjectId == queryDto.SubjectId);
|
||
}
|
||
if (queryDto.Status != null)
|
||
{
|
||
studyLambda = studyLambda.And(t => t.Status == queryDto.Status);
|
||
}
|
||
|
||
if (queryDto.SubjectVisitId != null)
|
||
{
|
||
studyLambda = studyLambda.And(t => t.SubjectVisitId == queryDto.SubjectVisitId);
|
||
}
|
||
|
||
if (!string.IsNullOrWhiteSpace(queryDto.VisitPlanInfo))
|
||
{
|
||
var visitInfo = queryDto.VisitPlanInfo.Trim();
|
||
|
||
if (visitInfo.Contains('.'))
|
||
|
||
{
|
||
|
||
subjectVisitLambda = subjectVisitLambda.And(t => t.VisitNum.ToString().Contains("."));
|
||
|
||
|
||
}
|
||
else
|
||
{
|
||
if (int.TryParse(visitInfo, out var visitNum))
|
||
{
|
||
subjectVisitLambda = subjectVisitLambda.And(t => t.VisitNum == visitNum);
|
||
}
|
||
}
|
||
|
||
//if (int.TryParse(visitInfo, out var visitNum))
|
||
//{
|
||
// subjectVisitLambda = subjectVisitLambda.And(t => t.VisitNum==visitNum);
|
||
//}
|
||
//else
|
||
//{
|
||
// subjectVisitLambda = subjectVisitLambda.And(t => t.VisitName.Contains(visitInfo));
|
||
//}
|
||
|
||
}
|
||
|
||
if (queryDto.StudyTimeBegin != null)
|
||
{
|
||
studyLambda = studyLambda.And(t => t.StudyTime >= queryDto.StudyTimeBegin);
|
||
}
|
||
if (queryDto.StudyTimeEnd != null)
|
||
{
|
||
studyLambda = studyLambda.And(t => t.StudyTime <= queryDto.StudyTimeEnd);
|
||
}
|
||
|
||
if (queryDto.UpdateTimeBegin != null)
|
||
{
|
||
studyLambda = studyLambda.And(t => t.UpdateTime >= queryDto.UpdateTimeBegin);
|
||
}
|
||
if (queryDto.UpdateTimeEnd != null)
|
||
{
|
||
studyLambda = studyLambda.And(t => t.UpdateTime <= queryDto.UpdateTimeEnd);
|
||
}
|
||
|
||
if (queryDto.SiteId != null)
|
||
{
|
||
studyLambda = studyLambda.And(t => t.SiteId == queryDto.SiteId);
|
||
}
|
||
else
|
||
{
|
||
//是CRC 需要过滤
|
||
var userId = _userInfo.Id;
|
||
var exist = _userRepository.GetAll()
|
||
.Any(t => t.Id == userId && t.UserType.Contains(StaticData.CRC));
|
||
|
||
if (exist)
|
||
{
|
||
//找到CRC负责的site
|
||
var siteIds = _userTrialRepository.GetAll().Where(t => t.SiteId != Guid.Empty && t.UserId == userId && t.TrialId == queryDto.TrialId)
|
||
.Select(u => u.SiteId);
|
||
|
||
studyLambda = studyLambda.And(t => siteIds.Contains(t.SiteId));
|
||
}
|
||
}
|
||
Expression<Func<Subject, bool>> subjectLambda = x => true;
|
||
if (!string.IsNullOrWhiteSpace(queryDto.SubjectInfo))
|
||
{
|
||
var subjectInfo = queryDto.SubjectInfo.Trim();
|
||
subjectLambda = subjectLambda.And(t => t.Code.Contains(subjectInfo) || t.Name.Contains(subjectInfo));
|
||
}
|
||
|
||
var query =
|
||
from study in _studyRepository.GetAll().Where(studyLambda)
|
||
join subject in _subjectRepository.Find(subjectLambda)
|
||
on study.SubjectId equals subject.Id
|
||
join trial in _trialRepository.GetAll() on study.TrialId equals trial.Id
|
||
join subjectVisit in _subjectVisitRepository.GetAll().Where(subjectVisitLambda)
|
||
on study.SubjectVisitId equals subjectVisit.Id
|
||
join site in _siteRepository.GetAll() on study.SiteId equals site.Id
|
||
|
||
select new StudyDTO()
|
||
{
|
||
PatientId = study.PatientId,
|
||
PatientAge = study.PatientAge,
|
||
PatientSex = study.PatientSex,
|
||
PatientName = study.PatientName,
|
||
AccessionNumber = study.AccessionNumber,
|
||
PatientBirthDate = study.PatientBirthDate,
|
||
StudyId = study.StudyId,
|
||
SubjectAge = subject.Age,
|
||
SubjectCode = subject.Code,
|
||
SubjectId = subject.Id,
|
||
SubjectName = subject.Name,
|
||
SubjectSex = subject.Sex,
|
||
|
||
Id = study.Id,
|
||
TrialId = study.TrialId,
|
||
|
||
Modalities = study.Modalities,
|
||
StudyCode = study.StudyCode,
|
||
SeriesCount = study.SeriesCount,
|
||
InstanceCount = study.InstanceCount,
|
||
StudyStatus = study.Status,
|
||
StudyDate = study.StudyTime,
|
||
IsDoubleReview = study.IsDoubleReview,
|
||
StudyDescription = study.Description,
|
||
BodyPartExamined = study.BodyPartExamined,
|
||
Comment = study.Comment,
|
||
UpdateTime = study.UpdateTime,
|
||
|
||
SiteId = study.SiteId,
|
||
SiteName = site.SiteName,
|
||
|
||
SubjectVisitId = study.SubjectVisitId,
|
||
VisitName = subjectVisit.VisitName,
|
||
VisitNum = subjectVisit.VisitNum,
|
||
VisitDay = subjectVisit.VisitDay,
|
||
SVUPDES = subjectVisit.SVUPDES,
|
||
SVENDTC = subjectVisit.SVENDTC,
|
||
SVSTDTC = subjectVisit.SVSTDTC
|
||
};
|
||
var count = query.Count();
|
||
|
||
// 默认按照 StudyCode 降序
|
||
var propName = queryDto.SortField == string.Empty ? "StudyCode" : queryDto.SortField;
|
||
if (string.IsNullOrWhiteSpace(queryDto.SortField))
|
||
{
|
||
queryDto.Asc = false;
|
||
}
|
||
query = queryDto.Asc
|
||
? query.OrderBy(propName).ThenBy(t => t.StudyCode).ThenBy(t => t.SiteName).ThenBy(u => u.SubjectCode).ThenBy(u => u.VisitNum)
|
||
: query.OrderByDescending(propName).ThenBy(t => t.StudyCode).ThenBy(t => t.SiteName).ThenBy(u => u.SubjectCode).ThenBy(u => u.VisitNum);
|
||
|
||
|
||
|
||
query = query.Skip((queryDto.PageIndex - 1) * queryDto.PageSize).Take(queryDto.PageSize);
|
||
|
||
var list = query.ToList();
|
||
|
||
|
||
// 可以看到分配的医生
|
||
//var studyIds = list.Select(t => t.Id).ToList();
|
||
|
||
//var studyReviewerQuery =
|
||
// from studyReviewer in _studyReviewerRepository.GetAll().Where(t => studyIds.Contains(t.StudyId))
|
||
// join doctor in _doctorRepository.GetAll() on studyReviewer.ReviewerId equals doctor.Id
|
||
// select new DistributeReviewer()
|
||
// {
|
||
// ReviewerId = doctor.Id,
|
||
// StudyId = studyReviewer.StudyId,
|
||
// NameCN = doctor.ChineseName,
|
||
// Name = doctor.LastName + " / " + doctor.FirstName,
|
||
// Status = studyReviewer.WorkloadType
|
||
// };
|
||
//var studyReviewerList = studyReviewerQuery.ToList();
|
||
|
||
//list.ForEach(t =>
|
||
//{
|
||
// t.DistributeReviewers = studyReviewerList.Where(u => u.StudyId == t.Id).OrderBy(c => c.NameCN).ToList();
|
||
//});
|
||
|
||
|
||
|
||
return new PageOutput<StudyDTO>(queryDto.PageIndex,
|
||
queryDto.PageSize, count, list);
|
||
|
||
}
|
||
|
||
/// <summary> 更新访视点和受试者 研究中心 项目的绑定关系</summary>
|
||
public async Task<IResponseOutput> UpdateStudyBinding(StudyEditCommand model)
|
||
{
|
||
var dicomStudy = _studyRepository.FindSingleOrDefault(s => s.Id == model.Id);
|
||
|
||
//var reviewModel = (from trial in _trialRepository.GetAll().Where(t => t.Id == model.TrialId)
|
||
// join dic in _dictionaryRepository.GetAll() on trial.ReviewModeId equals dic.Id
|
||
// select dic.Value).ToList();
|
||
|
||
var saveInfo = GetSaveToDicomInfo(new StudyCommand()
|
||
{
|
||
SiteId = model.SiteId,
|
||
SubjectVisitId = model.SubjectVisitId,
|
||
SubjectId = model.SubjectId,
|
||
TrialId = model.TrialId
|
||
});
|
||
if (SystemConfig.AddClinicalInfo)
|
||
{
|
||
UpdateDicomFile(dicomStudy, saveInfo);
|
||
}
|
||
|
||
|
||
var isSuccess = _studyRepository.Update(t => t.Id == model.Id, u => new DicomStudy()
|
||
{
|
||
SiteId = model.SiteId,
|
||
SubjectId = model.SubjectId,
|
||
SubjectVisitId = model.SubjectVisitId,
|
||
Comment = model.Comment
|
||
});
|
||
|
||
var isSuccess2 = _dicomSeriesRepository.Update(t => t.StudyId == model.Id, u => new DicomSeries()
|
||
{
|
||
SiteId = model.SiteId,
|
||
SubjectId = model.SubjectId,
|
||
SubjectVisitId = model.SubjectVisitId,
|
||
});
|
||
|
||
var isSuccess3 = _dicomInstanceRepository.Update(t => t.StudyId == model.Id, u => new DicomInstance()
|
||
{
|
||
SiteId = model.SiteId,
|
||
SubjectId = model.SubjectId,
|
||
SubjectVisitId = model.SubjectVisitId
|
||
});
|
||
|
||
return ResponseOutput.Result(isSuccess || isSuccess2 || isSuccess3);
|
||
}
|
||
|
||
|
||
/// <summary> 删除项目访视点</summary>
|
||
public IResponseOutput DeleteStudy(Guid id)
|
||
{
|
||
var success1 = _studyRepository.Delete(t => t.Id == id);
|
||
var succeess2 = _dicomInstanceRepository.Delete(t => t.StudyId == id);
|
||
var success3 = _dicomSeriesRepository.Delete(t => t.StudyId == id);
|
||
|
||
return ResponseOutput.Result(success1 || succeess2 || success3);
|
||
|
||
}
|
||
|
||
public DicomTrialSiteSubjectInfo GetSaveToDicomInfo(StudyCommand addtionalCommand)
|
||
{
|
||
var query = from subject in _subjectRepository.GetAll()
|
||
.Where(t => t.TrialId == addtionalCommand.TrialId && t.SiteId == addtionalCommand.SiteId &&
|
||
t.Id == addtionalCommand.SubjectId)
|
||
join trial in _trialRepository.GetAll().Where(t => t.Id == addtionalCommand.TrialId) on subject.TrialId
|
||
equals trial.Id
|
||
//join subjectVisit in _subjectVisitRepository.GetAll()
|
||
// .Where(t => t.Id == addtionalCommand.SubjectVisitId) on subject.SubjectVisitId equals subjectVisit
|
||
// .Id
|
||
join site in _siteRepository.GetAll().Where(t => t.Id == addtionalCommand.SiteId) on subject.SiteId
|
||
equals site.Id
|
||
join sponsor in _sponsorRepository.GetAll() on trial.SponsorId equals sponsor.Id into tt
|
||
from sponsor in tt.DefaultIfEmpty()
|
||
join dictionary in _dictionaryRepository.GetAll() on trial.ReviewModeId equals dictionary.Id into cc
|
||
from dictionary in cc.DefaultIfEmpty()
|
||
select new DicomTrialSiteSubjectInfo
|
||
{
|
||
SiteName = site.SiteName,
|
||
SiteCode = site.SiteCode,
|
||
SubjectName = subject.Name,
|
||
SubjectCode = subject.Code,
|
||
SubjectSex = subject.Sex,
|
||
SubjectAge = subject.Age,
|
||
|
||
//SubjectVisitNum = subjectVisit.VisitNum,
|
||
|
||
//SubjectVisitSVUPDES = subjectVisit.SVUPDES,
|
||
//SubjectVisitVisitName = subjectVisit.VisitName,
|
||
|
||
TrialCode = trial.Code,
|
||
TrialIndication = trial.Indication,
|
||
|
||
ReviewMode = dictionary.Value,
|
||
|
||
Sponsor = sponsor.SponsorName,
|
||
|
||
TrialId = addtionalCommand.TrialId,
|
||
SiteId = addtionalCommand.SiteId,
|
||
SubjectId = addtionalCommand.SubjectId,
|
||
SubjectVisitId = addtionalCommand.SubjectVisitId
|
||
};
|
||
|
||
|
||
var result = query.First();
|
||
if (result.ReviewMode.Contains("Double"))
|
||
{
|
||
result.IsDoubleReview = true;
|
||
}
|
||
|
||
var subjectVisitInfo = _subjectVisitRepository.GetAll()
|
||
.First(t => t.Id == addtionalCommand.SubjectVisitId);
|
||
|
||
result.SubjectVisitNum = subjectVisitInfo.VisitNum;
|
||
result.SubjectVisitSVUPDES = subjectVisitInfo.SVUPDES;
|
||
result.SubjectVisitVisitName = subjectVisitInfo.VisitName;
|
||
|
||
|
||
|
||
|
||
return result;
|
||
}
|
||
|
||
|
||
public Guid AddSubjectVisit(Guid subjectId, Guid siteId, Guid visitStageId, DateTime? SVSTDTC, DateTime? SVENDTC)
|
||
{
|
||
var visitPlanItem = _visitStageRepository.GetAll().First(t => t.Id == visitStageId);
|
||
var subjectVisit = new SubjectVisit()
|
||
{
|
||
TrialId = visitPlanItem.TrialId,
|
||
SiteId = siteId,
|
||
SubjectId = subjectId,
|
||
VisitName = visitPlanItem.VisitName,
|
||
VisitDay = visitPlanItem.VisitDay,
|
||
VisitNum = visitPlanItem.VisitNum,
|
||
SVSTDTC = SVSTDTC,
|
||
SVENDTC = SVENDTC
|
||
};
|
||
|
||
_subjectVisitRepository.Add(subjectVisit);
|
||
|
||
_subjectVisitRepository.SaveChanges();
|
||
|
||
|
||
|
||
return subjectVisit.Id;
|
||
|
||
}
|
||
|
||
public void UpdateSubjectLatestInfo( Guid subjectId,Guid trialId )
|
||
{
|
||
//更新最新得受试者访视
|
||
var latest = _subjectVisitRepository.GetAll()
|
||
.Where(t => t.SubjectId == subjectId && t.TrialId == trialId)
|
||
.OrderByDescending(t => t.SVSTDTC).FirstOrDefault();
|
||
|
||
if (latest != null)
|
||
{
|
||
_subjectRepository.Update(t => t.Id == subjectId, u => new Subject()
|
||
{
|
||
SubjectVisitId = latest.Id
|
||
});
|
||
}
|
||
|
||
}
|
||
|
||
public bool UpdateSubjectVisit(Guid subjectVisitId, DateTime? SVSTDTC, DateTime? SVENDTC)
|
||
{
|
||
return _subjectVisitRepository.Update(t => t.Id == subjectVisitId, u => new SubjectVisit()
|
||
{
|
||
SVENDTC = SVENDTC,
|
||
SVSTDTC = SVSTDTC,
|
||
StudyUploaded = true
|
||
});
|
||
}
|
||
|
||
|
||
private async Task UpdateDicomFile(DicomStudy dicomStudy, DicomTrialSiteSubjectInfo addtionalInfo)
|
||
{
|
||
//string studyPath = string.Empty;
|
||
//if (SystemConfig.Share)
|
||
//{
|
||
// WNetAddConnectionHelper.Connect();
|
||
// studyPath = Path.Combine("W:\\IRC_DICOM_ARCHIVED", dicomStudy.CreateTime.Year.ToString(), dicomStudy.TrialId.ToString(),
|
||
// dicomStudy.SiteId.ToString(), dicomStudy.SubjectId.ToString(), dicomStudy.Id.ToString());
|
||
//}
|
||
//else studyPath = Path.Combine(_fileStorePath, dicomStudy.CreateTime.Year.ToString(), dicomStudy.TrialId.ToString(),
|
||
// dicomStudy.SiteId.ToString(), dicomStudy.SubjectId.ToString(), dicomStudy.Id.ToString());
|
||
|
||
var studyPath = Path.Combine(_fileStorePath, dicomStudy.CreateTime.Year.ToString(), dicomStudy.TrialId.ToString(),
|
||
dicomStudy.SiteId.ToString(), dicomStudy.SubjectId.ToString(), dicomStudy.Id.ToString());
|
||
DirectoryInfo root = new DirectoryInfo(studyPath);
|
||
FileInfo[] files = root.GetFiles();
|
||
foreach (var file in files)
|
||
{
|
||
DicomFile dicomFile = await DicomFile.OpenAsync(file.FullName, Encoding.Default);
|
||
DicomDataset dataset = dicomFile.Dataset;
|
||
|
||
dataset.AddOrUpdate(DicomTag.ClinicalTrialProtocolID, addtionalInfo.TrialCode); //Trial
|
||
dataset.AddOrUpdate(DicomTag.ClinicalTrialProtocolName, addtionalInfo.TrialIndication); //indication
|
||
dataset.AddOrUpdate(DicomTag.ClinicalTrialSponsorName, addtionalInfo.Sponsor);//sponsor
|
||
dataset.AddOrUpdate(DicomTag.ClinicalTrialSiteID, addtionalInfo.SiteCode); //SiteId
|
||
dataset.AddOrUpdate(DicomTag.ClinicalTrialSiteName, addtionalInfo.SiteName);//SiteName
|
||
dataset.AddOrUpdate(DicomTag.ClinicalTrialSubjectID, addtionalInfo.SubjectCode + " " + addtionalInfo.SubjectName + " " + addtionalInfo.SubjectSex);//SubjectId
|
||
dataset.AddOrUpdate(DicomTag.ClinicalTrialTimePointID, addtionalInfo.SubjectVisitNum.ToString()); // TimePoint
|
||
dataset.AddOrUpdate(DicomTag.ClinicalTrialTimePointDescription, addtionalInfo.SubjectVisitVisitName + " " + addtionalInfo.SubjectVisitSVUPDES);
|
||
|
||
|
||
await dicomFile.SaveAsync(file.FullName);
|
||
}
|
||
}
|
||
|
||
#region Study 分配给 Reviewer
|
||
public bool DistributeStudy(StudyReviewerCommand studyReviewer)
|
||
{
|
||
//更新Study表中,总的状态
|
||
// 插入中间表
|
||
|
||
studyReviewer.StudyList.ForEach(study =>
|
||
{
|
||
var workloadType = 1;
|
||
StudyStatus studyStatus = StudyStatus.Distributed;
|
||
|
||
if (study.Status >= (int)StudyStatus.NeedAd)
|
||
{
|
||
workloadType = 2;
|
||
studyStatus = StudyStatus.AdDistributed;
|
||
}
|
||
var tempStudy = _studyRepository.FindSingleOrDefault(s => s.Id == study.StudyId);
|
||
tempStudy.Status = (int)studyStatus;
|
||
_studyRepository.Update(tempStudy);
|
||
|
||
_studyReviewerRepository.Add(new StudyReviewer()
|
||
{
|
||
ReviewerId = studyReviewer.ReviewerId,
|
||
StudyId = study.StudyId,
|
||
WorkloadType = workloadType,
|
||
TrialId = studyReviewer.TrialId,
|
||
Status = (int)studyStatus
|
||
});
|
||
});
|
||
|
||
return _studyReviewerRepository.SaveChanges();
|
||
}
|
||
|
||
|
||
public IResponseOutput EditStudyReviewer(StudyReviewerEditCommand studyReviewerEditCommand)
|
||
{
|
||
_studyReviewerRepository.Delete(t => studyReviewerEditCommand.StudyId == t.StudyId);
|
||
|
||
if (studyReviewerEditCommand.IsDoubleReview)
|
||
{
|
||
if (studyReviewerEditCommand.ReviewerId1 != null)
|
||
{
|
||
_studyReviewerRepository.Add(
|
||
new StudyReviewer()
|
||
{
|
||
StudyId = studyReviewerEditCommand.StudyId,
|
||
TrialId = studyReviewerEditCommand.TrialId,
|
||
ReviewerId = studyReviewerEditCommand.ReviewerId1.Value,
|
||
WorkloadType = 1
|
||
});
|
||
}
|
||
if (studyReviewerEditCommand.ReviewerId2 != null)
|
||
{
|
||
_studyReviewerRepository.Add(
|
||
new StudyReviewer()
|
||
{
|
||
StudyId = studyReviewerEditCommand.StudyId,
|
||
TrialId = studyReviewerEditCommand.TrialId,
|
||
ReviewerId = studyReviewerEditCommand.ReviewerId2.Value,
|
||
WorkloadType = 1
|
||
});
|
||
}
|
||
if (studyReviewerEditCommand.ReviewerIdForAD != null)
|
||
{
|
||
_studyReviewerRepository.Add(
|
||
new StudyReviewer()
|
||
{
|
||
StudyId = studyReviewerEditCommand.StudyId,
|
||
TrialId = studyReviewerEditCommand.TrialId,
|
||
ReviewerId = studyReviewerEditCommand.ReviewerIdForAD.Value,
|
||
WorkloadType = 2
|
||
});
|
||
}
|
||
|
||
if (studyReviewerEditCommand.ReviewerId2 == null || studyReviewerEditCommand.ReviewerId1 == null)
|
||
{
|
||
_studyRepository.Update(t => t.Id == studyReviewerEditCommand.StudyId,
|
||
u => new DicomStudy()
|
||
{
|
||
Status = (int)StudyStatus.QAFinish
|
||
});
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (studyReviewerEditCommand.ReviewerId1 != null)
|
||
{
|
||
_studyReviewerRepository.Add(
|
||
new StudyReviewer()
|
||
{
|
||
StudyId = studyReviewerEditCommand.StudyId,
|
||
TrialId = studyReviewerEditCommand.TrialId,
|
||
ReviewerId = studyReviewerEditCommand.ReviewerId1.Value,
|
||
WorkloadType = 1
|
||
});
|
||
}
|
||
else
|
||
{
|
||
_studyRepository.Update(t => t.Id == studyReviewerEditCommand.StudyId,
|
||
u => new DicomStudy()
|
||
{
|
||
Status = (int)StudyStatus.QAFinish
|
||
});
|
||
}
|
||
}
|
||
|
||
var success = _studyReviewerRepository.SaveChanges();
|
||
|
||
return ResponseOutput.Result(success);
|
||
|
||
}
|
||
public List<ReviewerDistributionDTO> GetReviewerListByTrialId(Guid trialId)
|
||
{
|
||
var query = from enrollItem in _enrollRepository
|
||
.Find(t => t.TrialId == trialId && t.EnrollStatus >= 10)
|
||
join doctorItem in _doctorRepository.GetAll()
|
||
on enrollItem.DoctorId equals doctorItem.Id into g
|
||
from doctor in g.DefaultIfEmpty()
|
||
select new
|
||
{
|
||
Code = doctor.Code,
|
||
FirstName = doctor.FirstName,
|
||
LastName = doctor.LastName,
|
||
ReviewerId = enrollItem.DoctorId,
|
||
ActivelyReading = doctor.ActivelyReading,
|
||
};
|
||
|
||
return query.Where(s => s.ActivelyReading).Select(s => new ReviewerDistributionDTO
|
||
{
|
||
Code = s.Code,
|
||
FirstName = s.FirstName,
|
||
LastName = s.LastName,
|
||
ReviewerId = s.ReviewerId,
|
||
|
||
}).ToList();
|
||
}
|
||
#endregion
|
||
|
||
public bool UpdateStudyModaliyAndComment(Guid studyId, string modaliy,string comment)
|
||
{
|
||
return _studyRepository.Update(s => s.Id == studyId, u => new DicomStudy
|
||
{
|
||
Modalities = modaliy,
|
||
Comment = comment
|
||
});
|
||
}
|
||
|
||
#region 更新检查状态,并记录操作记录
|
||
public bool UpdateStudyStatus(StudyStatusDetailCommand studyStatus, string optUserName)
|
||
{
|
||
var study = _studyRepository.FindSingleOrDefault(u => u.Id == studyStatus.StudyId);
|
||
study.Status = studyStatus.Status;
|
||
if (studyStatus.Status == (int)StudyStatus.QAFInishNotPass)
|
||
{
|
||
study.QAComment = studyStatus.QAComment;
|
||
}
|
||
_studyRepository.Update(study);
|
||
//如果状态QA完成就要添加一条TP工作量,待分配 QAFinish,
|
||
//QA 完成后,需要对Dicom文件进行匿名化
|
||
//if (studyStatus.Status == (int)StudyStatus.QAFinish)
|
||
//{
|
||
// _workloadTPRepository.Add(new WorkloadTP
|
||
// {
|
||
// SiteId = study.SiteId,
|
||
// StudyId = study.Id,
|
||
// SubjectId = study.SubjectId,
|
||
// SubjectVisitId = study.SubjectVisitId,
|
||
// Status = 0,
|
||
// ReviewerId = Guid.Empty,
|
||
// TrialId = study.TrialId,
|
||
// UpdateTime = DateTime.Now,
|
||
// TimepointCode = study.StudyCode + "T01"
|
||
// });
|
||
// if (study.IsDoubleReview)//双重阅片,则再添加一条,编号变为T02
|
||
// {
|
||
// _workloadTPRepository.Add(new WorkloadTP
|
||
// {
|
||
// SiteId = study.SiteId,
|
||
// StudyId = study.Id,
|
||
// SubjectId = study.SubjectId,
|
||
// SubjectVisitId = study.SubjectVisitId,
|
||
// Status = 0,
|
||
// ReviewerId = Guid.Empty,
|
||
// TrialId = study.TrialId,
|
||
// UpdateTime = DateTime.Now,
|
||
// TimepointCode = study.StudyCode + "T02"
|
||
// });
|
||
// }
|
||
|
||
//}
|
||
|
||
_studyStatusDetailRepository.Add(new StudyStatusDetail
|
||
{
|
||
Status = studyStatus.Status,
|
||
StudyId = studyStatus.StudyId,
|
||
Note = studyStatus.Note,
|
||
OptUserName = optUserName,
|
||
OptTime = DateTime.Now
|
||
});
|
||
return _studyStatusDetailRepository.SaveChanges();
|
||
}
|
||
public async Task<bool> DicomAnonymize(Guid studyId, string optUserName)
|
||
{
|
||
var study = _studyRepository.FindSingleOrDefault(u => u.Id == studyId);
|
||
|
||
study.Status = (int)StudyStatus.Anonymize;
|
||
_studyRepository.Update(study);
|
||
_studyStatusDetailRepository.Add(new StudyStatusDetail
|
||
{
|
||
Status = (int)StudyStatus.Anonymize,
|
||
StudyId = studyId,
|
||
Note = string.Empty,
|
||
OptUserName = optUserName,
|
||
OptTime = DateTime.Now
|
||
});
|
||
_workloadTPRepository.Add(new WorkloadTP
|
||
{
|
||
SiteId = study.SiteId,
|
||
StudyId = study.Id,
|
||
SubjectId = study.SubjectId,
|
||
SubjectVisitId = study.SubjectVisitId,
|
||
Status = 0,
|
||
ReviewerId = Guid.Empty,
|
||
TrialId = study.TrialId,
|
||
UpdateTime = DateTime.Now,
|
||
TimepointCode = study.StudyCode + "T01"
|
||
});
|
||
if (study.IsDoubleReview)//双重阅片,则再添加一条,编号变为T02
|
||
{
|
||
_workloadTPRepository.Add(new WorkloadTP
|
||
{
|
||
SiteId = study.SiteId,
|
||
StudyId = study.Id,
|
||
SubjectId = study.SubjectId,
|
||
SubjectVisitId = study.SubjectVisitId,
|
||
Status = 0,
|
||
ReviewerId = Guid.Empty,
|
||
TrialId = study.TrialId,
|
||
UpdateTime = DateTime.Now,
|
||
TimepointCode = study.StudyCode + "T02"
|
||
});
|
||
}
|
||
//读取Dicom 文件,匿名化
|
||
|
||
//按照配置文件 匿名化
|
||
var dicomSeries = _dicomSeriesRepository.Find(s => s.StudyId == studyId).ToList();
|
||
foreach (var seriesItem in dicomSeries)
|
||
{
|
||
var dicomInstances = _dicomInstanceRepository.Find(s => s.SeriesId == seriesItem.Id);
|
||
foreach (var instanceItem in dicomInstances)
|
||
{
|
||
try
|
||
{
|
||
string filePath = CreateInstanceFilePath(study, seriesItem.Id, instanceItem.Id);
|
||
DicomFile dicomFile = await DicomFile.OpenAsync(filePath, Encoding.Default);
|
||
//DicomDataset dataset = dicomFile.Dataset;
|
||
foreach (var anonymizeItem in SystemConfig.AnonymizeTagList)
|
||
{
|
||
if (anonymizeItem.Enable)
|
||
{
|
||
ushort group = Convert.ToUInt16(anonymizeItem.Group, 16);
|
||
ushort element = Convert.ToUInt16(anonymizeItem.Element, 16);
|
||
dicomFile.Dataset.AddOrUpdate(new DicomTag(group, element), anonymizeItem.ReplaceValue);
|
||
}
|
||
}
|
||
|
||
//string path = string.Empty;
|
||
//if (SystemConfig.Share)
|
||
//{
|
||
// WNetAddConnectionHelper.Connect();
|
||
// path = Path.Combine("W:\\IRC_DICOM_ARCHIVED", study.CreateTime.Year.ToString(), study.TrialId.ToString(),
|
||
// study.SiteId.ToString(), study.SubjectId.ToString(), study.Id.ToString());
|
||
//}
|
||
//else
|
||
//{
|
||
// path = Path.Combine(_fileStorePath, study.CreateTime.Year.ToString(), study.TrialId.ToString(),
|
||
// study.SiteId.ToString(), study.SubjectId.ToString(), study.Id.ToString(), study.ToString() + ".dcm");
|
||
//}
|
||
string path = Path.Combine(_fileStorePath, study.CreateTime.Year.ToString(), study.TrialId.ToString(),
|
||
study.SiteId.ToString(), study.SubjectId.ToString(), study.Id.ToString());
|
||
await dicomFile.SaveAsync(Path.Combine(path, instanceItem.Id.ToString() + ".Anonymize" + ".dcm"));
|
||
instanceItem.Anonymize = true;
|
||
_dicomInstanceRepository.Update(instanceItem);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
|
||
}
|
||
}
|
||
|
||
}
|
||
return _dicomInstanceRepository.SaveChanges();
|
||
}
|
||
|
||
private string CreateInstanceFilePath(DicomStudy dicomStudy, Guid seriesId, Guid instanceId)
|
||
{
|
||
//string path = string.Empty;
|
||
//if (SystemConfig.Share)
|
||
//{
|
||
// WNetAddConnectionHelper.Connect();
|
||
// path = Path.Combine("W:\\IRC_DICOM_ARCHIVED", dicomStudy.CreateTime.Year.ToString(), dicomStudy.TrialId.ToString(),
|
||
// dicomStudy.SiteId.ToString(), dicomStudy.SubjectId.ToString(), dicomStudy.Id.ToString());
|
||
//}
|
||
//else
|
||
//{
|
||
// path = Path.Combine(_fileStorePath, dicomStudy.CreateTime.Year.ToString(), dicomStudy.TrialId.ToString(),
|
||
// dicomStudy.SiteId.ToString(), dicomStudy.SubjectId.ToString(), dicomStudy.Id.ToString(), instanceId.ToString() + ".dcm");
|
||
//}
|
||
|
||
string path = Path.Combine(_fileStorePath, dicomStudy.CreateTime.Year.ToString(), dicomStudy.TrialId.ToString(),
|
||
dicomStudy.SiteId.ToString(), dicomStudy.SubjectId.ToString(), dicomStudy.Id.ToString());
|
||
if (!Directory.Exists(path)) Directory.CreateDirectory(path);
|
||
|
||
return Path.Combine(path, instanceId.ToString() + ".dcm");
|
||
}
|
||
|
||
public bool UpdateStudyStatus(List<StudyStatusDetailCommand> studyStatus, string optUserName)
|
||
{
|
||
foreach (var studyItem in studyStatus)
|
||
{
|
||
var study = _studyRepository.FindSingleOrDefault(u => u.Id == studyItem.StudyId);
|
||
study.Status = studyItem.Status;
|
||
_studyRepository.Update(study);
|
||
_studyStatusDetailRepository.Add(new StudyStatusDetail
|
||
{
|
||
Status = studyItem.Status,
|
||
StudyId = studyItem.StudyId,
|
||
OptUserName = optUserName,
|
||
OptTime = DateTime.Now,
|
||
Note = studyItem.Note
|
||
});
|
||
}
|
||
|
||
return _studyStatusDetailRepository.SaveChanges();
|
||
}
|
||
|
||
public List<StudyStatusDetailDTO> GetStudyStatusDetailList(Guid studyId)
|
||
{
|
||
return _studyStatusDetailRepository.Find(s => s.StudyId == studyId).OrderByDescending(s => s.OptTime)
|
||
.ProjectTo<StudyStatusDetailDTO>(_mapper.ConfigurationProvider).ToList();
|
||
}
|
||
|
||
public PageOutput<DistributeReviewerStudyStatusDTO> GetDistributeStudyList(StudyStatusQueryDTO studyStatusQueryDto)
|
||
{
|
||
|
||
Expression<Func<StudyReviewer, bool>> studyReviewerLambda = x => x.TrialId == studyStatusQueryDto.TrialId;
|
||
|
||
if (studyStatusQueryDto.ReviewerId != null)
|
||
{
|
||
studyReviewerLambda = studyReviewerLambda.And(t => t.ReviewerId == studyStatusQueryDto.ReviewerId);
|
||
}
|
||
|
||
if (studyStatusQueryDto.StudyStatus != null)
|
||
{
|
||
studyReviewerLambda = studyReviewerLambda.And(t => t.Status == studyStatusQueryDto.StudyStatus);
|
||
}
|
||
|
||
var query = from studyReviewer in _studyReviewerRepository.GetAll().Where(studyReviewerLambda)
|
||
join doctor in _doctorRepository.GetAll() on studyReviewer.ReviewerId equals doctor.Id
|
||
join study in _studyRepository.GetAll() on studyReviewer.StudyId equals study.Id
|
||
select new DistributeReviewerStudyStatusDTO()
|
||
{
|
||
Name = doctor.LastName + " / " + doctor.FirstName,
|
||
NameCN = doctor.ChineseName,
|
||
ReviewerCode = doctor.Code,
|
||
Status = studyReviewer.Status,
|
||
StudyCode = study.StudyCode
|
||
};
|
||
|
||
var count = query.Count();
|
||
|
||
var propName = studyStatusQueryDto.SortField == string.Empty ? "ReviewerCode" : studyStatusQueryDto.SortField;
|
||
|
||
query = studyStatusQueryDto.Asc
|
||
? query.OrderBy(propName)
|
||
: query.OrderByDescending(propName);
|
||
|
||
|
||
|
||
query = query.Skip((studyStatusQueryDto.PageIndex - 1) * studyStatusQueryDto.PageSize).Take(studyStatusQueryDto.PageSize);
|
||
|
||
var list = query.ToList();
|
||
|
||
return new PageOutput<DistributeReviewerStudyStatusDTO>(studyStatusQueryDto.PageIndex,
|
||
studyStatusQueryDto.PageSize, count, list);
|
||
}
|
||
|
||
public IEnumerable<RelationVisitDTO> GetRelationVisitList(decimal visitNum, string tpCode)
|
||
{
|
||
string tpGroup = tpCode.Substring(tpCode.Length - 3, 3);
|
||
var tp = _workloadTPRepository.FindSingleOrDefault(u => u.TimepointCode == tpCode);
|
||
var query = from workloadTp in _workloadTPRepository.GetAll().Where(u => u.SubjectId == tp.SubjectId
|
||
&& u.TrialId == tp.TrialId && u.TimepointCode.Contains(tpGroup))
|
||
join subjectVisit in _subjectVisitRepository.GetAll().Where(u => u.VisitNum <= visitNum)
|
||
on workloadTp.SubjectVisitId equals subjectVisit.Id
|
||
select new RelationVisitDTO
|
||
{
|
||
StudyId = workloadTp.StudyId,
|
||
TpCode = workloadTp.TimepointCode,
|
||
VisitName = subjectVisit.VisitName
|
||
};
|
||
return query.ToList();
|
||
}
|
||
|
||
public List<SubjectVisitStudyDTO> GetSubjectVisitStudyList(Guid trialId, Guid siteId, Guid subjectId, Guid subjectVisitId)
|
||
{
|
||
var query = _studyRepository.GetAll().Where(t =>
|
||
t.TrialId == trialId && t.SiteId == siteId && t.SubjectId == t.SubjectId &&
|
||
t.SubjectVisitId == subjectVisitId)
|
||
.Select(u => new SubjectVisitStudyDTO()
|
||
{
|
||
Modalities = u.Modalities,
|
||
StudyCode = u.StudyCode,
|
||
StudyId = u.Id,
|
||
Status = u.Status
|
||
});
|
||
|
||
return query.ToList();
|
||
|
||
}
|
||
|
||
|
||
#endregion
|
||
}
|
||
}
|