521 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			C#
		
	
	
			
		
		
	
	
			521 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			C#
		
	
	
using IRaCIS.Application.Contracts;
 | 
						||
using IRaCIS.Application.Interfaces;
 | 
						||
using IRaCIS.Core.Application.Filter;
 | 
						||
using IRaCIS.Core.Domain.Share;
 | 
						||
using IRaCIS.Core.Infrastructure;
 | 
						||
using Microsoft.AspNetCore.Mvc;
 | 
						||
using MiniExcelLibs;
 | 
						||
 | 
						||
namespace IRaCIS.Core.Application.Service
 | 
						||
{
 | 
						||
    [ApiExplorerSettings(GroupName = "Trial")]
 | 
						||
    public class VisitPlanService(IRepository<VisitStage> _visitStageRepository,
 | 
						||
        IRepository<Trial> _trialRepository,
 | 
						||
        IRepository<SubjectVisit> _subjectVisitRepository,
 | 
						||
        IRepository<VisitPlanInfluenceStudy> _influnceRepository,
 | 
						||
        IRepository<VisitTask> _visitTaskRepository,
 | 
						||
        IRepository<Subject> _subjectRepository,
 | 
						||
        IRepository<VisitPlanInfluenceStat> _visitPlanInfluenceStatRepository, IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer) : BaseService, IVisitPlanService
 | 
						||
    {
 | 
						||
 | 
						||
 | 
						||
 | 
						||
        ///暂时不用
 | 
						||
        /// <summary> 获取项目访视计划</summary>
 | 
						||
        [HttpPost]
 | 
						||
        public async Task<PageOutput<VisitStageDTO>> GetTrialVisitStageList(VisitPlanQueryDTO inQuery)
 | 
						||
        {
 | 
						||
            var visitStageQuery = _visitStageRepository.AsQueryable(true).Where(u => u.TrialId == inQuery.TrialId)
 | 
						||
                  .WhereIf(!string.IsNullOrWhiteSpace(inQuery.Keyword), t => t.VisitName.Contains(inQuery.Keyword))
 | 
						||
                  .ProjectTo<VisitStageDTO>(_mapper.ConfigurationProvider);
 | 
						||
 | 
						||
            return await visitStageQuery.ToPagedListAsync(inQuery, nameof(VisitStageDTO.CreateTime));
 | 
						||
 | 
						||
 | 
						||
        }
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 根据项目Id,获取项目访视计划
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="inDto"></param>
 | 
						||
        /// <returns></returns>
 | 
						||
        [HttpPost]
 | 
						||
        public async Task<VisitPlanView> GetVisitStageList(GetVisitStageListInDto inDto)
 | 
						||
        {
 | 
						||
            var query = _visitStageRepository.AsQueryable(true).Where(u => u.TrialId == inDto.TrialId)
 | 
						||
                .ProjectTo<VisitStageDTO>(_mapper.ConfigurationProvider).OrderBy(t => t.VisitNum);
 | 
						||
            var list = await query.ToPagedListAsync(inDto);
 | 
						||
            var trial = (await _trialRepository.FirstOrDefaultAsync(t => t.Id == inDto.TrialId)).IfNullThrowException();
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
            var isHaveGeneratedTask = (await _visitTaskRepository.AnyAsync(t => t.TrialId == inDto.TrialId));
 | 
						||
            return new VisitPlanView()
 | 
						||
            {
 | 
						||
                VisitPlanList = list,
 | 
						||
                TimePointsPerPatient = trial.TimePointsPerPatient,
 | 
						||
                VisitPlanConfirmed = trial.VisitPlanConfirmed,
 | 
						||
                IsHaveFirstGiveMedicineDate = trial.IsHaveFirstGiveMedicineDate,
 | 
						||
                BlindBaseLineName = trial.BlindBaseLineName,
 | 
						||
                BlindFollowUpPrefix = trial.BlindFollowUpPrefix,
 | 
						||
                IsHaveGeneratedTask = isHaveGeneratedTask,
 | 
						||
                //SubjectHasAdded = _subjectVisitRepository.Any(t => t.TrialId == trialId)
 | 
						||
            };
 | 
						||
        }
 | 
						||
 | 
						||
        [TrialGlobalLimit( "BeforeOngoingCantOpt", "AfterStopCannNotOpt" )]
 | 
						||
        public async Task<IResponseOutput> UpdateVisitBlindName(VisitBlindNameCommand command)
 | 
						||
        {
 | 
						||
 | 
						||
            await _trialRepository.UpdatePartialFromQueryAsync(command.TrialId, t => new Trial() { BlindBaseLineName = command.BlindBaseLineName, BlindFollowUpPrefix = command.BlindFollowUpPrefix });
 | 
						||
 | 
						||
            await _trialRepository.SaveChangesAsync();
 | 
						||
 | 
						||
            return ResponseOutput.Ok();
 | 
						||
        }
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 获取访视计划下拉框列表
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="trialId"></param>
 | 
						||
        /// <returns></returns>
 | 
						||
        [HttpGet("{trialId:guid}")]
 | 
						||
        public async Task<IEnumerable<VisitStageSelectDTO>> GetTrialVisitStageSelect(Guid trialId)
 | 
						||
        {
 | 
						||
            var query = _visitStageRepository.Where(u => u.TrialId == trialId)
 | 
						||
                .ProjectTo<VisitStageSelectDTO>(_mapper.ConfigurationProvider).OrderBy(t => t.VisitNum);
 | 
						||
            var list = await query.ToListAsync();
 | 
						||
            return list;
 | 
						||
        }
 | 
						||
 | 
						||
 | 
						||
        /// <summary> 添加或更新访视计划某项</summary>
 | 
						||
        [UnitOfWork]
 | 
						||
        [HttpPost]
 | 
						||
        //[Authorize(Policy = IRaCISPolicy.PM_APM)]
 | 
						||
        [TrialGlobalLimit( "BeforeOngoingCantOpt", "AfterStopCannNotOpt" )]
 | 
						||
        //[TrialGlobalLimit( "AfterStopCannNotOpt" )]
 | 
						||
        public async Task<IResponseOutput> AddOrUpdateVisitStage(VisitPlanCommand visitPlan)
 | 
						||
        {
 | 
						||
 | 
						||
            if (!await _trialRepository.Where(t => t.Id == visitPlan.TrialId).IgnoreQueryFilters().AnyAsync(t => t.TrialStatusStr == StaticData.TrialState.TrialOngoing || t.TrialStatusStr == StaticData.TrialState.TrialInitializing))
 | 
						||
            {
 | 
						||
                //---只有当项目状态为:初始化或进行中时,可以操作。
 | 
						||
                throw new BusinessValidationFailedException(_localizer["VisitPlan_OnlyInitOrOngoing"]);
 | 
						||
            }
 | 
						||
 | 
						||
            var visitPlanList = await _visitStageRepository.Where(t => t.TrialId == visitPlan.TrialId, ignoreQueryFilters: true)
 | 
						||
                .Select(t => new { t.Id, t.VisitNum, t.VisitDay }).OrderBy(t => t.VisitNum).ToListAsync();
 | 
						||
 | 
						||
            //更新的时候,需要排除自己
 | 
						||
            if (visitPlan.Id != null)
 | 
						||
            {
 | 
						||
                visitPlanList = visitPlanList.Where(t => t.Id != visitPlan.Id).ToList();
 | 
						||
            }
 | 
						||
 | 
						||
            if (visitPlanList.Any(t => t.VisitNum < visitPlan.VisitNum))
 | 
						||
            {
 | 
						||
                //比当前 visitNum小的 visitDay的最大值    还小 不允许添加
 | 
						||
                if (visitPlan.VisitDay <= visitPlanList.Where(t => t.VisitNum < visitPlan.VisitNum).Select(t => t.VisitDay).Max())
 | 
						||
                {
 | 
						||
                    //---访视计划中,访视号大的访视,其访视间隔也应该比访视号小的访视大。
 | 
						||
                    throw new BusinessValidationFailedException(_localizer["VisitPlan_LargerVisitNumLargerInterval"]);
 | 
						||
 | 
						||
                }
 | 
						||
            }
 | 
						||
 | 
						||
            if (visitPlanList.Any(t => t.VisitNum > visitPlan.VisitNum))
 | 
						||
            {
 | 
						||
                if (visitPlan.VisitDay >= visitPlanList.Where(t => t.VisitNum > visitPlan.VisitNum).Select(t => t.VisitDay).Min())
 | 
						||
                {
 | 
						||
                    //---访视计划中,访视号大的计划访视,其访视间隔也应该比访视号小的计划访视大。
 | 
						||
                    throw new BusinessValidationFailedException(_localizer["VisitPlan_LargerPlanNumLargerInterval"]);
 | 
						||
                }
 | 
						||
            }
 | 
						||
 | 
						||
            if (visitPlan.Id == Guid.Empty || visitPlan.Id == null)//add
 | 
						||
            {
 | 
						||
                var trial = (await _trialRepository.FirstOrDefaultAsync(t => t.Id == visitPlan.TrialId)).IfNullThrowException();
 | 
						||
 | 
						||
 | 
						||
                if (await _visitStageRepository.AnyAsync(t => t.TrialId == visitPlan.TrialId && (t.VisitName == visitPlan.VisitName || t.VisitNum == visitPlan.VisitNum), true))
 | 
						||
                {
 | 
						||
                    //---访视计划中已经存在具有项目访视名称或者访视号的计划访视模板。
 | 
						||
                    throw new BusinessValidationFailedException(_localizer["VisitPlan_ExistNameOrNumTemplate"]);
 | 
						||
                }
 | 
						||
 | 
						||
                if (await _visitStageRepository.AnyAsync(t => t.TrialId == visitPlan.TrialId && t.IsBaseLine, true) && visitPlan.IsBaseLine)
 | 
						||
                {
 | 
						||
                    //---访视计划中已经存在基线。
 | 
						||
                    throw new BusinessValidationFailedException(_localizer["VisitPlan_ExistBaseline"]);
 | 
						||
                }
 | 
						||
 | 
						||
                //不用前端传递的值
 | 
						||
                visitPlan.BlindName = "B" + ((int)visitPlan.VisitNum * 10).ToString("D3");
 | 
						||
 | 
						||
                var visitPlanItem = await _visitStageRepository.InsertFromDTOAsync(visitPlan, true);
 | 
						||
 | 
						||
 | 
						||
                return ResponseOutput.Ok(visitPlanItem.Id);
 | 
						||
            }
 | 
						||
 | 
						||
            else//update
 | 
						||
            {
 | 
						||
 | 
						||
 | 
						||
                if (await _visitStageRepository.AnyAsync(t => t.TrialId == visitPlan.TrialId && (t.VisitName == visitPlan.VisitName || t.VisitNum == visitPlan.VisitNum) && t.Id != visitPlan.Id, true))
 | 
						||
                {
 | 
						||
                    //---访视计划中已经存在具有项目访视名称或者访视号的计划访视模板。
 | 
						||
                    throw new BusinessValidationFailedException(_localizer["VisitPlan_ExistNameOrNumTemplate"]);
 | 
						||
                }
 | 
						||
 | 
						||
                if (await _visitStageRepository.AnyAsync(t => t.TrialId == visitPlan.TrialId && t.IsBaseLine && t.Id != visitPlan.Id, true) && visitPlan.IsBaseLine)
 | 
						||
                {
 | 
						||
                    //---访视计划中已经存在基线。
 | 
						||
                    throw new BusinessValidationFailedException(_localizer["VisitPlan_ExistBaseline"]);
 | 
						||
                }
 | 
						||
 | 
						||
                visitPlan.IsConfirmed = false;
 | 
						||
                //不用前端传递的值
 | 
						||
                visitPlan.BlindName = "B" + ((int)visitPlan.VisitNum * 10).ToString("D3");
 | 
						||
                //返回的是数据库查询的数据
 | 
						||
                var stage = await _visitStageRepository.UpdateFromDTOAsync(visitPlan, true);
 | 
						||
 | 
						||
                if (stage.IsBaseLine && stage.IsBaseLine != visitPlan.IsBaseLine)
 | 
						||
                {
 | 
						||
                    if (await _subjectVisitRepository.Where(t => t.TrialId == visitPlan.TrialId).AnyAsync(v => v.IsBaseLine && v.SubmitState >= SubmitStateEnum.ToSubmit))
 | 
						||
                    {
 | 
						||
                        //---有受试者的基线已经上传了影像数据,不允许修改基线访视。
 | 
						||
                        throw new BusinessValidationFailedException(_localizer["VisitPlan_ExistBaselineImgNoModify"]);
 | 
						||
                    }
 | 
						||
                }
 | 
						||
 | 
						||
 | 
						||
                return ResponseOutput.Ok();
 | 
						||
            }
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
        }
 | 
						||
 | 
						||
 | 
						||
 | 
						||
        [UnitOfWork]
 | 
						||
        [HttpPost("{trialId:guid}")]
 | 
						||
        //[Authorize(Policy = IRaCISPolicy.PM_APM)]
 | 
						||
        [TrialGlobalLimit( "BeforeOngoingCantOpt", "AfterStopCannNotOpt" )]
 | 
						||
        //[TrialGlobalLimit( "AfterStopCannNotOpt" )]
 | 
						||
        public async Task<IResponseOutput> ConfirmTrialVisitPlan(Guid trialId)
 | 
						||
        {
 | 
						||
            if (!await _trialRepository.AnyAsync(t => t.Id == trialId && (t.TrialStatusStr == StaticData.TrialState.TrialInitializing || t.TrialStatusStr == StaticData.TrialState.TrialOngoing)))
 | 
						||
            {
 | 
						||
                //---仅仅在项目初始化或者进行中时,才允许修改确认
 | 
						||
                return ResponseOutput.NotOk(_localizer["VisitPlan_OnlyInitOrOngoingModifyConfirm"]);
 | 
						||
            }
 | 
						||
 | 
						||
            if (!await _visitStageRepository.AnyAsync(t => t.TrialId == trialId && t.IsBaseLine))
 | 
						||
            {
 | 
						||
                //---没有基线,不允许确认
 | 
						||
                return ResponseOutput.NotOk(_localizer["VisitPlan_NoBaselineNotConfirm"]);
 | 
						||
            }
 | 
						||
 | 
						||
            if (!await _trialRepository.AnyAsync(t => t.Id == trialId && t.IsTrialBasicLogicConfirmed && t.IsTrialProcessConfirmed && t.IsTrialUrgentConfirmed))
 | 
						||
            {
 | 
						||
                //---项目配置未确认,不允许确认访视计划
 | 
						||
                return ResponseOutput.NotOk(_localizer["VisitPlan_ConfigNotConfirmNotConfirm"]);
 | 
						||
            }
 | 
						||
 | 
						||
            var svList = await _visitStageRepository.Where(t => t.TrialId == trialId).Select(u => new { u.VisitDay, u.IsBaseLine }).ToListAsync();
 | 
						||
 | 
						||
            if (svList.Min(t => t.VisitDay) != svList.Where(t => t.IsBaseLine).FirstOrDefault()?.VisitDay)
 | 
						||
            {
 | 
						||
                //---基线VisitDay 不是最小的, 不允许确认
 | 
						||
                return ResponseOutput.NotOk(_localizer["VisitPlan_BaselineNotMinDayNotConfirm"]);
 | 
						||
            }
 | 
						||
 | 
						||
 | 
						||
            //更新项目访视计划状态为已确认  必定生成更新的sql  通过状态改变 触发操作
 | 
						||
            //await _trialRepository.UpdatePartialNowNoQueryAsync(trialId, t => new Trial() { VisitPlanConfirmed = true });
 | 
						||
 | 
						||
 | 
						||
            var trial = (await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialId)).IfNullThrowException();
 | 
						||
 | 
						||
            //确认是否是首次确认
 | 
						||
            var initTrialVisitPlanConfirmed = trial.VisitPlanConfirmed;
 | 
						||
 | 
						||
            trial.VisitPlanConfirmed = true;
 | 
						||
 | 
						||
 | 
						||
            #region 统一给Subject  增加访视任务
 | 
						||
 | 
						||
            //首次确认时 IsHaveFirstConfirmed都为false  不需要给Subject 加访视
 | 
						||
            if (initTrialVisitPlanConfirmed)
 | 
						||
            {
 | 
						||
                List<SubjectVisit> subjectVisits = new List<SubjectVisit>();
 | 
						||
 | 
						||
                var addvisitStages = await _visitStageRepository.Where(x => !x.IsHaveFirstConfirmed && x.TrialId == trialId).ToListAsync();
 | 
						||
 | 
						||
                foreach (var visitPlan in addvisitStages)
 | 
						||
                {
 | 
						||
 | 
						||
                    var subjectSVS = await _subjectVisitRepository.Where(t => t.TrialId == visitPlan.TrialId).Select(t => new { t.SubjectId, t.TrialSiteId, t.IsFinalVisit }).Distinct().ToListAsync();
 | 
						||
 | 
						||
                    var subjectList = subjectSVS.Select(t => new { t.SubjectId, t.TrialSiteId }).Distinct().ToList();
 | 
						||
 | 
						||
                    foreach (var subject in subjectList)
 | 
						||
                    {
 | 
						||
 | 
						||
                        var svItem = _mapper.Map<SubjectVisit>(visitPlan);
 | 
						||
                        svItem.TrialSiteId = subject.TrialSiteId;
 | 
						||
                        svItem.SubjectId = subject.SubjectId;
 | 
						||
 | 
						||
                        //设置了末次访视,那么加访视计划的时候,设置为不可用
 | 
						||
                        if (subjectSVS.Any(t => t.SubjectId == svItem.SubjectId && t.IsFinalVisit))
 | 
						||
                        {
 | 
						||
                            svItem.VisitExecuted = VisitExecutedEnum.Unavailable;
 | 
						||
                        }
 | 
						||
 | 
						||
                        //再加一层保险,防止重复
 | 
						||
                        if (!await _subjectVisitRepository.AnyAsync(t => t.VisitStageId == visitPlan.Id && t.SubjectId == subject.SubjectId))
 | 
						||
                        {
 | 
						||
                            await _subjectVisitRepository.AddAsync(svItem);
 | 
						||
 | 
						||
                        }
 | 
						||
                    }
 | 
						||
 | 
						||
 | 
						||
                }
 | 
						||
 | 
						||
                await _subjectVisitRepository.AddRangeAsync(subjectVisits);
 | 
						||
            }
 | 
						||
 | 
						||
 | 
						||
            #endregion
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
            #region 访视计划修改 影响检查
 | 
						||
 | 
						||
            //找到访视计划修改的Item
 | 
						||
            var changedList = await _visitStageRepository.Where(t => t.TrialId == trial.Id && t.IsConfirmed == false)
 | 
						||
                .Select(t => new
 | 
						||
                {
 | 
						||
                    t.Trial.IsHaveFirstGiveMedicineDate,
 | 
						||
                    t.Id,
 | 
						||
                    t.VisitName,
 | 
						||
                    t.TrialId,
 | 
						||
                    t.VisitWindowLeft,
 | 
						||
                    t.VisitWindowRight,
 | 
						||
                    t.VisitDay,
 | 
						||
                    t.VisitNum,
 | 
						||
                    t.IsBaseLine,
 | 
						||
                    t.BlindName,
 | 
						||
 | 
						||
                    t.Description,
 | 
						||
                    IsConfirmed = true,
 | 
						||
                }).ToListAsync();
 | 
						||
 | 
						||
            var visitPlanInfluenceStat = new VisitPlanInfluenceStat() { TrialId = trial.Id };
 | 
						||
 | 
						||
            foreach (var changedItem in changedList)
 | 
						||
            {
 | 
						||
                //找到该项目 访视已经执行,并且配置了有首次给药日期 并且更新后超窗的访视,要把超窗之前的值也要查询出来
 | 
						||
                var qcPassedVisitList = await _subjectVisitRepository.Where(t => t.TrialId == trialId
 | 
						||
                                                && t.VisitExecuted == VisitExecutedEnum.Executed
 | 
						||
                                                && t.AuditState == AuditStateEnum.QCPassed
 | 
						||
                                                && t.Trial.IsHaveFirstGiveMedicineDate == true
 | 
						||
                                                && t.VisitStageId == changedItem.Id
 | 
						||
                                                && t.Subject.FirstGiveMedicineTime != null
 | 
						||
                                                 ).Select(k => new
 | 
						||
                                                 {
 | 
						||
                                                     SubjectVisitId = k.Id,
 | 
						||
                                                     SelfWindowLeft = k.Subject.FirstGiveMedicineTime!.Value.AddDays(k.VisitDay + k.VisitWindowLeft),
 | 
						||
                                                     SelfWindowRight = k.Subject.FirstGiveMedicineTime!.Value.AddDays(k.VisitDay + k.VisitWindowRight + 1).AddSeconds(-1),
 | 
						||
 | 
						||
                                                     NowWindowLeft = k.Subject.FirstGiveMedicineTime!.Value.AddDays(changedItem.VisitDay + changedItem.VisitWindowLeft),
 | 
						||
                                                     NowWindowRight = k.Subject.FirstGiveMedicineTime!.Value.AddDays(changedItem.VisitDay + changedItem.VisitWindowRight + 1).AddSeconds(-1),
 | 
						||
 | 
						||
                                                     NoneDicomStudyList =
 | 
						||
                                                     k.NoneDicomStudyList  //之前是查询调整之后超窗的  现在调整前超窗  调整后 没超窗的也要记录
 | 
						||
                                                                           //.Where(study => study.ImageDate <k.Subject.FirstGiveMedicineTime.Value.AddDays(changedItem.VisitDay + changedItem.VisitWindowLeft??0)
 | 
						||
                                                                           //|| study.ImageDate >k.Subject.FirstGiveMedicineTime.Value.AddDays(changedItem.VisitDay + changedItem.VisitWindowRight??0 + 1).AddSeconds(-1))
 | 
						||
                                                     .Select(t => new { NoneDicomStudyId = t.Id, t.Modality, StudyTime = t.ImageDate }),
 | 
						||
 | 
						||
 | 
						||
                                                     DicomStudyList = k.StudyList
 | 
						||
                                                     //.Where(study => study.StudyTime <k.Subject.FirstGiveMedicineTime.Value.AddDays(changedItem.VisitDay + changedItem.VisitWindowLeft??0)
 | 
						||
                                                     // || study.StudyTime >k.Subject.FirstGiveMedicineTime.Value.AddDays(changedItem.VisitDay + changedItem.VisitWindowRight??0 + 1).AddSeconds(-1))
 | 
						||
                                                     .Select(t => new { StudyId = t.Id, Modality = t.Modalities, t.StudyTime })
 | 
						||
 | 
						||
                                                 }).ToListAsync();
 | 
						||
 | 
						||
 | 
						||
                foreach (var visit in qcPassedVisitList)
 | 
						||
                {
 | 
						||
                    //找到本身没有超窗的数据 修改后超窗的
 | 
						||
                    visit.DicomStudyList.Where(t => (t.StudyTime > visit.SelfWindowLeft && t.StudyTime < visit.SelfWindowRight) && (t.StudyTime < visit.NowWindowLeft || t.StudyTime > visit.NowWindowRight)).ForEach(t =>
 | 
						||
                    {
 | 
						||
                        visitPlanInfluenceStat.InconsistentCount++;
 | 
						||
                        visitPlanInfluenceStat.InfluenceStudyList.Add(new VisitPlanInfluenceStudy()
 | 
						||
                        {
 | 
						||
                            IsOverWindowNowNotOverWindow = false,
 | 
						||
                            Modality = t.Modality,
 | 
						||
                            SubjectVisitId = visit.SubjectVisitId,
 | 
						||
                            StudyId = t.StudyId,
 | 
						||
                            IsDicomStudy = true,
 | 
						||
                            StudyTime = t.StudyTime,
 | 
						||
                            TrialId = trialId,
 | 
						||
                            HistoryWindow = visit.SelfWindowLeft.ToString("yyyy-MM-dd") + " ~ " + visit.SelfWindowRight.ToString("yyyy-MM-dd"),
 | 
						||
                            NowWindow = visit.NowWindowLeft.ToString("yyyy-MM-dd") + " ~ " + visit.NowWindowRight.ToString("yyyy-MM-dd")
 | 
						||
 | 
						||
                        });
 | 
						||
 | 
						||
                    });
 | 
						||
 | 
						||
                    visit.NoneDicomStudyList.Where(t => (t.StudyTime > visit.SelfWindowLeft && t.StudyTime < visit.SelfWindowRight) && (t.StudyTime < visit.NowWindowLeft || t.StudyTime > visit.NowWindowRight)).ForEach(t =>
 | 
						||
                    {
 | 
						||
                        visitPlanInfluenceStat.InconsistentCount++;
 | 
						||
                        visitPlanInfluenceStat.InfluenceStudyList.Add(new VisitPlanInfluenceStudy()
 | 
						||
                        {
 | 
						||
                            IsOverWindowNowNotOverWindow = false,
 | 
						||
                            Modality = t.Modality,
 | 
						||
                            SubjectVisitId = visit.SubjectVisitId,
 | 
						||
                            StudyId = t.NoneDicomStudyId,
 | 
						||
                            IsDicomStudy = false,
 | 
						||
                            StudyTime = t.StudyTime,
 | 
						||
                            TrialId = trialId,
 | 
						||
                            HistoryWindow = visit.SelfWindowLeft.ToString("yyyy-MM-dd") + " ~ " + visit.SelfWindowRight.ToString("yyyy-MM-dd"),
 | 
						||
                            NowWindow = visit.NowWindowLeft.ToString("yyyy-MM-dd") + " ~ " + visit.NowWindowRight.ToString("yyyy-MM-dd")
 | 
						||
 | 
						||
                        });
 | 
						||
                    });
 | 
						||
 | 
						||
                    //本身超窗  修改后没超窗的
 | 
						||
                    visit.DicomStudyList.Where(t => (t.StudyTime < visit.SelfWindowLeft || t.StudyTime > visit.SelfWindowRight) && (t.StudyTime > visit.NowWindowLeft && t.StudyTime < visit.NowWindowRight)).ForEach(t =>
 | 
						||
                    {
 | 
						||
                        visitPlanInfluenceStat.InconsistentCount++;
 | 
						||
                        visitPlanInfluenceStat.InfluenceStudyList.Add(new VisitPlanInfluenceStudy()
 | 
						||
                        {
 | 
						||
                            IsOverWindowNowNotOverWindow = true,
 | 
						||
                            Modality = t.Modality,
 | 
						||
                            SubjectVisitId = visit.SubjectVisitId,
 | 
						||
                            StudyId = t.StudyId,
 | 
						||
                            IsDicomStudy = true,
 | 
						||
                            StudyTime = t.StudyTime,
 | 
						||
                            TrialId = trialId,
 | 
						||
                            HistoryWindow = visit.SelfWindowLeft.ToString("yyyy-MM-dd") + " ~ " + visit.SelfWindowRight.ToString("yyyy-MM-dd"),
 | 
						||
                            NowWindow = visit.NowWindowLeft.ToString("yyyy-MM-dd") + " ~ " + visit.NowWindowRight.ToString("yyyy-MM-dd")
 | 
						||
 | 
						||
                        });
 | 
						||
                    });
 | 
						||
 | 
						||
                    visit.NoneDicomStudyList.Where(t => (t.StudyTime < visit.SelfWindowLeft || t.StudyTime > visit.SelfWindowRight) && (t.StudyTime > visit.NowWindowLeft && t.StudyTime < visit.NowWindowRight)).ForEach(t =>
 | 
						||
                    {
 | 
						||
                        visitPlanInfluenceStat.InconsistentCount++;
 | 
						||
                        visitPlanInfluenceStat.InfluenceStudyList.Add(new VisitPlanInfluenceStudy()
 | 
						||
                        {
 | 
						||
                            IsOverWindowNowNotOverWindow = true,
 | 
						||
                            Modality = t.Modality,
 | 
						||
                            SubjectVisitId = visit.SubjectVisitId,
 | 
						||
                            StudyId = t.NoneDicomStudyId,
 | 
						||
                            IsDicomStudy = false,
 | 
						||
                            StudyTime = t.StudyTime,
 | 
						||
                            TrialId = trialId,
 | 
						||
                            HistoryWindow = visit.SelfWindowLeft.ToString("yyyy-MM-dd") + " ~ " + visit.SelfWindowRight.ToString("yyyy-MM-dd"),
 | 
						||
                            NowWindow = visit.NowWindowLeft.ToString("yyyy-MM-dd") + " ~ " + visit.NowWindowRight.ToString("yyyy-MM-dd")
 | 
						||
 | 
						||
                        });
 | 
						||
                    });
 | 
						||
 | 
						||
                }
 | 
						||
 | 
						||
 | 
						||
 | 
						||
                //变更某一访视计划Item  受试者访视相关字段
 | 
						||
                await _subjectVisitRepository.BatchUpdateNoTrackingAsync(t => t.TrialId == trialId && t.VisitStageId == changedItem.Id, k => new SubjectVisit()
 | 
						||
                {
 | 
						||
                    IsBaseLine = changedItem.IsBaseLine,
 | 
						||
                    VisitName = changedItem.VisitName,
 | 
						||
                    VisitNum = changedItem.VisitNum,
 | 
						||
                    VisitDay = changedItem.VisitDay,
 | 
						||
                    VisitWindowLeft = changedItem.VisitWindowLeft,
 | 
						||
                    VisitWindowRight = changedItem.VisitWindowRight
 | 
						||
                });
 | 
						||
            }
 | 
						||
 | 
						||
 | 
						||
            await _visitPlanInfluenceStatRepository.AddAsync(visitPlanInfluenceStat, true);
 | 
						||
 | 
						||
            #endregion
 | 
						||
 | 
						||
 | 
						||
 | 
						||
            //访视计划 整体状态变更为 确认
 | 
						||
            await _visitStageRepository.UpdatePartialFromQueryAsync(u => u.TrialId == trialId && u.IsConfirmed == false, t => new VisitStage() { IsConfirmed = true, IsHaveFirstConfirmed = true });
 | 
						||
 | 
						||
            await _visitStageRepository.SaveChangesAsync();
 | 
						||
            return ResponseOutput.Ok();
 | 
						||
 | 
						||
        }
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
        [HttpGet("{trialId:guid}")]
 | 
						||
        public async Task<List<VisitPlanInfluenceSubjectVisitStatDTO>> GetInfluenceHistoryList(Guid trialId, [FromServices] IRepository<VisitPlanInfluenceStat> _influnceStatRepository)
 | 
						||
        {
 | 
						||
            var list = await _influnceStatRepository.Where(t => t.TrialId == trialId).ProjectTo<VisitPlanInfluenceSubjectVisitStatDTO>(_mapper.ConfigurationProvider).OrderByDescending(t => t.CreateTime).ToListAsync();
 | 
						||
 | 
						||
            return list;
 | 
						||
        }
 | 
						||
 | 
						||
        [HttpGet("{visitPlanInfluenceStatId:guid}")]
 | 
						||
        public async Task<IActionResult> DownloadInflunceStudyList(Guid visitPlanInfluenceStatId)
 | 
						||
        {
 | 
						||
            var list = _influnceRepository.Where(t => t.VisitPlanInfluenceStatId == visitPlanInfluenceStatId)
 | 
						||
                .ProjectTo<VisitPlanInfluenceSubjectVisitDTO>(_mapper.ConfigurationProvider).ToList();
 | 
						||
 | 
						||
            var memoryStream = new MemoryStream();
 | 
						||
            memoryStream.SaveAs(list);
 | 
						||
            memoryStream.Seek(0, SeekOrigin.Begin);
 | 
						||
            return new FileStreamResult(memoryStream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
 | 
						||
            {
 | 
						||
                FileDownloadName = _localizer["VisitPlan_CheckExport", DateTime.Now.ToString("yyyy-MM-dd:hh:mm:ss")]
 | 
						||
            };
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
        }
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
        /// <summary> 删除项目计划某一项 废弃  </summary>
 | 
						||
        [HttpDelete("{id:guid}/{trialId:guid}")]
 | 
						||
        [Obsolete]
 | 
						||
        public async Task<IResponseOutput> DeleteVisitStage(Guid id)
 | 
						||
        {
 | 
						||
 | 
						||
            var visitPlan = await _visitStageRepository.FirstOrDefaultAsync(t => t.Id == id);
 | 
						||
            if (visitPlan == null) return Null404NotFound(visitPlan);
 | 
						||
            if (await _subjectVisitRepository.AnyAsync(t => t.VisitName == visitPlan.VisitName && t.TrialId == visitPlan.TrialId && t.VisitExecuted == VisitExecutedEnum.Executed))
 | 
						||
            {
 | 
						||
                //---The visit plan has been assigned to the subjects and executed.
 | 
						||
                return ResponseOutput.NotOk(_localizer["VisitPlan_Assigned"]);
 | 
						||
            }
 | 
						||
 | 
						||
            await _subjectVisitRepository.BatchDeleteNoTrackingAsync(t => t.TrialId == visitPlan.TrialId && t.VisitName == visitPlan.VisitName);
 | 
						||
 | 
						||
            var result = await _visitStageRepository.BatchDeleteNoTrackingAsync(u => u.Id == id);
 | 
						||
 | 
						||
            return ResponseOutput.Result(result);
 | 
						||
        }
 | 
						||
 | 
						||
 | 
						||
    }
 | 
						||
}
 |