222 lines
		
	
	
		
			9.2 KiB
		
	
	
	
		
			C#
		
	
	
			
		
		
	
	
			222 lines
		
	
	
		
			9.2 KiB
		
	
	
	
		
			C#
		
	
	
using IRaCIS.Core.Infrastructure.ExpressionExtend;
 | 
						||
using IRaCIS.Core.Application.Filter;
 | 
						||
 | 
						||
using Microsoft.AspNetCore.Mvc;
 | 
						||
using IRaCIS.Core.Application.Contracts.Dicom.DTO;
 | 
						||
using Microsoft.AspNetCore.Authorization;
 | 
						||
using IRaCIS.Core.Domain.Share;
 | 
						||
using IRaCIS.Core.Application.Contracts;
 | 
						||
using IRaCIS.Core.Application.Interfaces;
 | 
						||
using IRaCIS.Core.Application.Service.Inspection.Interface;
 | 
						||
using Newtonsoft.Json;
 | 
						||
using IRaCIS.Core.Infrastructure;
 | 
						||
using IRaCIS.Core.Domain.Common;
 | 
						||
 | 
						||
namespace IRaCIS.Core.Application.Services
 | 
						||
{
 | 
						||
    [ApiExplorerSettings(GroupName = "Trial")]
 | 
						||
    public class SubjectVisitService : BaseService, ISubjectVisitService
 | 
						||
    {
 | 
						||
        private readonly IRepository<SubjectVisit> _subjectVisitRepository;
 | 
						||
        private readonly IInspectionService _inspectionService;
 | 
						||
        private readonly IRepository<Subject> _subjectRepository;
 | 
						||
 | 
						||
        public SubjectVisitService(IRepository<SubjectVisit> subjectVisitRepository, IInspectionService inspectionService,IRepository<Subject> subjectRepository)
 | 
						||
        {
 | 
						||
            _subjectVisitRepository = subjectVisitRepository;
 | 
						||
            this._inspectionService = inspectionService;
 | 
						||
            _subjectRepository = subjectRepository;
 | 
						||
        }
 | 
						||
 | 
						||
        [HttpPost]
 | 
						||
        [TypeFilter(typeof(TrialResourceFilter))]
 | 
						||
        [UnitOfWork]
 | 
						||
        public async Task<IResponseOutput<string>> AddOrUpdateSV(SubjectVisitCommand svCommand)
 | 
						||
        {
 | 
						||
  
 | 
						||
            var verifyExp1 = new EntityVerifyExp<SubjectVisit>()
 | 
						||
            {
 | 
						||
                VerifyExp = t => t.VisitNum == svCommand.VisitNum && t.SubjectId == svCommand.SubjectId,
 | 
						||
                VerifyMsg = "This subject's visit plan already contains a visit with the same visitnum."
 | 
						||
            };
 | 
						||
 | 
						||
            var verifyExp2 = new EntityVerifyExp<SubjectVisit>()
 | 
						||
            {
 | 
						||
                VerifyExp = t => t.SubjectId == svCommand.SubjectId && t.IsFinalVisit,
 | 
						||
                VerifyMsg = "该受试者已经有访视设置为末次访视,不允许将该访视设置为末次访视",
 | 
						||
                IsVerify=svCommand.IsFinalVisit              
 | 
						||
            };
 | 
						||
 | 
						||
 | 
						||
            svCommand.BlindName = "B" + ((int)(svCommand.VisitNum * 10)).ToString("D3");
 | 
						||
            svCommand.VisitExecuted = svCommand.IsLostVisit ? VisitExecutedEnum.Executed : svCommand.VisitExecuted;
 | 
						||
 | 
						||
 | 
						||
            SubjectVisit? dbBeforeEntity = null;
 | 
						||
            //Add
 | 
						||
            if (svCommand.Id == null)
 | 
						||
            {
 | 
						||
 | 
						||
                //设置末次评估后,不允许添加计划外访视
 | 
						||
                if (svCommand.InPlan == false)
 | 
						||
                {
 | 
						||
                    if (await _subjectVisitRepository.AnyAsync(t => t.SubjectId == svCommand.SubjectId && t.IsFinalVisit))
 | 
						||
                    {
 | 
						||
                          throw new BusinessValidationFailedException("设置末次评估后,不允许添加计划外访视");
 | 
						||
                    }
 | 
						||
                }
 | 
						||
 | 
						||
                 dbBeforeEntity = await _subjectVisitRepository.InsertFromDTOAsync(svCommand, false, verifyExp1, verifyExp2);
 | 
						||
            }
 | 
						||
 | 
						||
            else
 | 
						||
            {
 | 
						||
                 dbBeforeEntity = await _subjectVisitRepository.UpdateFromDTOAsync(svCommand, false,false, verifyExp1, verifyExp2);
 | 
						||
 | 
						||
                if (svCommand.PDState != dbBeforeEntity.PDState && dbBeforeEntity.SubmitState == SubmitStateEnum.Submitted)
 | 
						||
                {
 | 
						||
                    throw new BusinessValidationFailedException("CRC提交后,不允许修改PD确认状态");
 | 
						||
                }
 | 
						||
 | 
						||
                if (svCommand.PDState != dbBeforeEntity.PDState && dbBeforeEntity.RequestBackState == RequestBackStateEnum.PM_AgressBack)
 | 
						||
                {
 | 
						||
                    throw new BusinessValidationFailedException("回退的访视,不允许修改PD确认状态");
 | 
						||
                }
 | 
						||
 | 
						||
                if (svCommand.IsLostVisit )
 | 
						||
                {
 | 
						||
                    if (await _subjectVisitRepository.AnyAsync(t => t.Id == svCommand.Id && t.SubmitState == SubmitStateEnum.ToSubmit))
 | 
						||
                    {
 | 
						||
                        throw new BusinessValidationFailedException("该受试者此访视有影像上传,不允许设置为失访");
 | 
						||
                    }
 | 
						||
                }
 | 
						||
            }
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
            //更新受试者 首次给药日期 是否入组确认
 | 
						||
            if (svCommand.SubjectFirstGiveMedicineTime != null && svCommand.IsBaseLine)
 | 
						||
            {
 | 
						||
 | 
						||
                //await _subjectRepository.UpdatePartialSearchFirstAsync(svCommand.SubjectId,
 | 
						||
                //    u => new Subject() { FirstGiveMedicineTime = svCommand.SubjectFirstGiveMedicineTime });
 | 
						||
 | 
						||
 | 
						||
 | 
						||
                var subject = (await _subjectRepository.FirstOrDefaultAsync(t => t.Id == svCommand.SubjectId)).IfNullThrowException();
 | 
						||
 | 
						||
                //  更新受试者
 | 
						||
                subject.FirstGiveMedicineTime = svCommand.SubjectFirstGiveMedicineTime;
 | 
						||
              
 | 
						||
 | 
						||
            }
 | 
						||
 | 
						||
            
 | 
						||
            await _repository.SaveChangesAsync();
 | 
						||
 | 
						||
            return ResponseOutput.Ok(dbBeforeEntity.Id.ToString());
 | 
						||
 | 
						||
 | 
						||
        }
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
        [HttpPut("{trialId:guid}/{subjectVisitId:guid}/{isUrgent:bool}")]
 | 
						||
        public async Task<IResponseOutput> SetSubjectVisitUrgent(Guid subjectVisitId, bool isUrgent)
 | 
						||
        {
 | 
						||
            await _subjectVisitRepository.BatchUpdateNoTrackingAsync(t => t.Id == subjectVisitId, u => new SubjectVisit() { IsUrgent = isUrgent });
 | 
						||
 | 
						||
            return ResponseOutput.Ok();
 | 
						||
        }
 | 
						||
 | 
						||
 | 
						||
        [HttpDelete, Route("{id:guid}/{trialId:guid}")]
 | 
						||
        [TrialAudit(AuditType.SubjectAudit, AuditOptType.DeleteSubjectOutPlanVisit)]
 | 
						||
        [TypeFilter(typeof(TrialResourceFilter))]
 | 
						||
        public async Task<IResponseOutput> DeleteSV(Guid id)
 | 
						||
        {
 | 
						||
            if (await _repository.AnyAsync<DicomStudy>(t => t.SubjectVisitId == id))
 | 
						||
            {
 | 
						||
                return ResponseOutput.NotOk("This visit is associated with the uploaded study images and couldn't be deleted.");
 | 
						||
            }
 | 
						||
            if (await _subjectVisitRepository.AnyAsync(t => t.Id == id && t.InPlan))
 | 
						||
            {
 | 
						||
                return ResponseOutput.NotOk("This visit is InPlan and couldn't be deleted.");
 | 
						||
            }
 | 
						||
            if (await _subjectVisitRepository.AnyAsync(t => t.OutPlanPreviousVisitId == id ))
 | 
						||
            {
 | 
						||
                return ResponseOutput.NotOk("This visit is OutPlanPreviousVisitId and couldn't be deleted.");
 | 
						||
            }
 | 
						||
            return ResponseOutput.Result(await _repository.BatchDeleteAsync<SubjectVisit>(s => s.Id == id));
 | 
						||
        }
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 设置受试者访视已执行  也就是将studyUploaded状态置为true  为了那些没有影像 人工设置准备
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="subjectVisitId"></param>
 | 
						||
        /// <returns></returns>
 | 
						||
        [HttpPost("{subjectVisitId:guid}/{trialId:guid}")]
 | 
						||
        [TrialAudit(AuditType.SubjectAudit, AuditOptType.SetSVExecuted)]
 | 
						||
        [TypeFilter(typeof(TrialResourceFilter))]
 | 
						||
        public async Task<IResponseOutput> SetSVExecuted(Guid subjectVisitId)
 | 
						||
        {
 | 
						||
            return ResponseOutput.Result(await _subjectVisitRepository.BatchUpdateNoTrackingAsync(s => s.Id == subjectVisitId, u => new SubjectVisit() { VisitExecuted = VisitExecutedEnum.Executed }));
 | 
						||
        }
 | 
						||
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 获取访视下的Dicom 检查信息   分所有的, 阅片的 不阅片   isReading : 0 查询所有 1 查询仅仅阅片的
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="trialId"></param>
 | 
						||
        /// <param name="sujectVisitId"></param>
 | 
						||
        /// <param name="isReading"></param>
 | 
						||
        /// <returns></returns>
 | 
						||
        [HttpGet, Route("{trialId:guid}/{sujectVisitId:guid}/{isReading}")]
 | 
						||
        [AllowAnonymous]
 | 
						||
        public async Task<List<VisitStudyDTO>> GetVisitStudyList(Guid trialId, Guid sujectVisitId, int isReading)
 | 
						||
        {
 | 
						||
            var studyList = await _repository.Where<DicomStudy>(t => t.TrialId == trialId && t.SubjectVisitId == sujectVisitId).Select(k => new VisitStudyDTO()
 | 
						||
            {
 | 
						||
                InstanceCount = k.InstanceCount,
 | 
						||
                Modalities = k.Modalities,
 | 
						||
                SeriesCount = k.SeriesCount,
 | 
						||
                StudyCode = k.StudyCode,
 | 
						||
                StudyId = k.Id
 | 
						||
            }).ToListAsync();
 | 
						||
            var studyIds = studyList.Select(t => t.StudyId).ToList();
 | 
						||
 | 
						||
            var instanceList = await _repository.Where<DicomInstance>(t => studyIds.Contains(t.StudyId))
 | 
						||
                   .Select(t => new { t.SeriesId, t.Id, t.InstanceNumber }).ToListAsync();
 | 
						||
 | 
						||
            foreach (var t in studyList)
 | 
						||
            {
 | 
						||
                t.SeriesList = await _repository.Where<DicomSeries>(s => s.StudyId == t.StudyId)
 | 
						||
               .WhereIf(isReading == 1, s => s.IsReading).OrderBy(s => s.SeriesNumber).
 | 
						||
               ThenBy(s => s.SeriesTime)
 | 
						||
               .ProjectTo<DicomSeriesDTO>(_mapper.ConfigurationProvider).ToListAsync();
 | 
						||
 | 
						||
 | 
						||
                t.SeriesList.ForEach(series => series.InstanceList = instanceList.Where(t => t.SeriesId == series.Id).OrderBy(t => t.InstanceNumber).Select(k => k.Id).ToList());
 | 
						||
 | 
						||
                //设置为阅片与否 不更改数据库检查  的instance数量 和 SeriesCount  所以这里要实时统计
 | 
						||
                t.SeriesCount = t.SeriesList.Count();
 | 
						||
                t.InstanceCount = t.SeriesList.SelectMany(t => t.InstanceList).Count();
 | 
						||
            }
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
            return studyList;
 | 
						||
 | 
						||
            //return ResponseOutput.Ok(studyList.Where(t => t.SeriesList.Count > 0).ToList());
 | 
						||
 | 
						||
        }
 | 
						||
 | 
						||
 | 
						||
 | 
						||
      
 | 
						||
    }
 | 
						||
}
 |