653 lines
31 KiB
C#
653 lines
31 KiB
C#
using IRaCIS.Core.Infrastructure.ExpressionExtend;
|
||
using IRaCIS.Application.Interfaces;
|
||
using IRaCIS.Application.Contracts;
|
||
using IRaCIS.Core.Infra.EFCore;
|
||
using IRaCIS.Core.Application.Filter;
|
||
using Microsoft.AspNetCore.Mvc;
|
||
using IRaCIS.Core.Domain.Share;
|
||
using IRaCIS.Core.Application.MediatR.CommandAndQueries;
|
||
using Magicodes.ExporterAndImporter.Core;
|
||
using Magicodes.ExporterAndImporter.Excel;
|
||
using Magicodes.ExporterAndImporter.Excel.AspNetCore;
|
||
using IRaCIS.Core.Application.Service.Inspection.Interface;
|
||
using Newtonsoft.Json;
|
||
|
||
namespace IRaCIS.Application.Services
|
||
{
|
||
[ApiExplorerSettings(GroupName = "Trial")]
|
||
public class VisitPlanService : BaseService, IVisitPlanService
|
||
{
|
||
private readonly IRepository<VisitStage> _visitStageRepository;
|
||
private readonly IRepository<Trial> _trialRepository;
|
||
private readonly IRepository<SubjectVisit> _subjectVisitRepository;
|
||
private readonly IRepository<VisitPlanInfluenceStat> _influnceStatRepository;
|
||
private readonly IRepository<VisitPlanInfluenceStudy> _influnceRepository;
|
||
private readonly IInspectionService _inspectionService;
|
||
|
||
public VisitPlanService(IRepository<VisitStage> visitStageRepository,IRepository<Trial> trialRepository, IRepository<SubjectVisit> subjectVisitRepository,
|
||
IRepository<VisitPlanInfluenceStat> influnceStatRepository,
|
||
IRepository<VisitPlanInfluenceStudy> visitPlanInfluenceStudy,
|
||
|
||
IInspectionService inspectionService)
|
||
{
|
||
_visitStageRepository = visitStageRepository;
|
||
_trialRepository = trialRepository;
|
||
this._subjectVisitRepository = subjectVisitRepository;
|
||
this._influnceStatRepository = influnceStatRepository;
|
||
this._influnceRepository = visitPlanInfluenceStudy;
|
||
this._inspectionService = inspectionService;
|
||
}
|
||
|
||
|
||
///暂时不用
|
||
/// <summary> 获取项目访视计划</summary>
|
||
public async Task<PageOutput<VisitStageDTO>> GetTrialVisitStageList(VisitPlanQueryDTO param)
|
||
{
|
||
var visitStageQuery = _visitStageRepository.AsQueryable(true).Where(u => u.TrialId == param.TrialId)
|
||
.WhereIf(!string.IsNullOrWhiteSpace(param.Keyword), t => t.VisitName.Contains(param.Keyword))
|
||
.ProjectTo<VisitStageDTO>(_mapper.ConfigurationProvider);
|
||
|
||
return await visitStageQuery.ToPagedListAsync(param.PageIndex, param.PageSize, "CreateTime", param.Asc);
|
||
|
||
|
||
}
|
||
|
||
/// <summary> 根据项目Id,获取项目访视计划(不分页)[New]</summary>
|
||
[HttpGet("{trialId:guid}")]
|
||
public async Task<VisitPlanView> GetVisitStageList(Guid trialId)
|
||
{
|
||
var query = _visitStageRepository.AsQueryable(true).Where(u => u.TrialId == trialId)
|
||
.ProjectTo<VisitStageDTO>(_mapper.ConfigurationProvider).OrderBy(t => t.VisitNum);
|
||
var list = await query.ToListAsync();
|
||
var trial = await _repository.FirstOrDefaultAsync<Trial>(t => t.Id == trialId).IfNullThrowException();
|
||
|
||
return new VisitPlanView()
|
||
{
|
||
VisitPlanList = list,
|
||
TimePointsPerPatient = trial.TimePointsPerPatient,
|
||
VisitPlanConfirmed = trial.VisitPlanConfirmed,
|
||
IsHaveFirstGiveMedicineDate = trial.IsHaveFirstGiveMedicineDate,
|
||
//SubjectHasAdded = _subjectVisitRepository.Any(t => t.TrialId == trialId)
|
||
};
|
||
}
|
||
|
||
/// <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> 添加或更新访视计划某项[New]</summary>
|
||
[HttpPost]
|
||
[UnitOfWork]
|
||
public async Task<IResponseOutput<string>> AddOrUpdateVisitStage(VisitPlanCommand visitPlan)
|
||
{
|
||
DateTime createtime = DateTime.Now;
|
||
List<DataInspection> datas = new List<DataInspection>();
|
||
if (!await _trialRepository.Where(t => t.Id == visitPlan.TrialId).IgnoreQueryFilters().AnyAsync(t => t.TrialStatusStr == StaticData.TrialOngoing || t.TrialStatusStr == StaticData.TrialInitializing))
|
||
{
|
||
return ResponseOutput.NotOk(" only in Initializing or Ongoing State can operate ");
|
||
}
|
||
|
||
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())
|
||
{
|
||
return ResponseOutput.NotOk("For the visit plan, the VisitDay with a larger VisitNum should be larger than the VisitDay with a smaller VisitNum.");
|
||
}
|
||
}
|
||
|
||
if (visitPlanList.Any(t => t.VisitNum > visitPlan.VisitNum))
|
||
{
|
||
if (visitPlan.VisitDay >= visitPlanList.Where(t => t.VisitNum > visitPlan.VisitNum).Select(t => t.VisitDay).Min())
|
||
{
|
||
return ResponseOutput.NotOk("For the visit plan, the VisitDay with a larger VisitNum should be larger than the VisitDay with a smaller VisitNum.");
|
||
}
|
||
}
|
||
|
||
if (visitPlan.Id == Guid.Empty || visitPlan.Id == null)//add
|
||
{
|
||
|
||
if (await _visitStageRepository.AnyAsync(t => t.TrialId == visitPlan.TrialId && (t.VisitName == visitPlan.VisitName || t.VisitNum == visitPlan.VisitNum), true))
|
||
{
|
||
return ResponseOutput.NotOk("A visit with the same VisitName/VisitNum already existed in the current visit plan.");
|
||
}
|
||
|
||
if (await _visitStageRepository.AnyAsync(t => t.TrialId == visitPlan.TrialId && t.IsBaseLine, true) && visitPlan.IsBaseLine)
|
||
{
|
||
return ResponseOutput.NotOk("A visit already is baseline in the current visit plan.");
|
||
}
|
||
|
||
//已添加受试者 都不存在该新增的计划名称 那么该项目所有受试者都增加一个访视记录
|
||
if (!await _subjectVisitRepository.AnyAsync(t => t.VisitName == visitPlan.VisitName && t.TrialId == visitPlan.TrialId))
|
||
{
|
||
var subjectSVS = await _subjectVisitRepository.Where(t => t.TrialId == visitPlan.TrialId).Select(t => new { t.SubjectId, t.SiteId,t.IsFinalVisit }).Distinct().ToListAsync();
|
||
|
||
var subjects = subjectSVS.Select(t => new { t.SubjectId, t.SiteId }).Distinct().ToList();
|
||
|
||
foreach (var subject in subjects)
|
||
{
|
||
var svItem = _mapper.Map<SubjectVisit>(visitPlan);
|
||
|
||
svItem.SiteId = subject.SiteId;
|
||
|
||
svItem.SubjectId = subject.SubjectId;
|
||
svItem.Id = Guid.NewGuid();
|
||
|
||
//设置了末次访视,那么加访视计划的时候,设置为不可用
|
||
if (subjectSVS.Any(t => t.SubjectId == svItem.SubjectId && t.IsFinalVisit))
|
||
{
|
||
svItem.VisitExecuted = VisitExecutedEnum.Unavailable;
|
||
}
|
||
//datas.Add(new DataInspection()
|
||
//{
|
||
// SubjectVisitId = svItem.Id,
|
||
// SubjectVisitName = svItem.VisitName,
|
||
// BlindName = visitPlan.BlindName,
|
||
// Identification = "Add|Visit|Info|Visit-Image Upload",
|
||
// SiteId = svItem.SiteId,
|
||
// TrialId = svItem.TrialId,
|
||
// SubjectId = svItem.SubjectId,
|
||
// IsSign = false,
|
||
// CreateTime = createtime,
|
||
// JsonDetail = JsonConvert.SerializeObject(svItem)
|
||
//});
|
||
|
||
|
||
await _repository.AddAsync(svItem);
|
||
}
|
||
}
|
||
|
||
|
||
var visitPlanItem = _mapper.Map<VisitStage>(visitPlan);
|
||
|
||
visitPlanItem.BlindName = "B" + ((int)visitPlanItem.VisitNum * 10).ToString("D3");
|
||
|
||
var result = await _repository.AddAsync(visitPlanItem);
|
||
visitPlan.Id = result.Id;
|
||
//datas.Add(new DataInspection()
|
||
//{
|
||
// BlindName = visitPlan.BlindName,
|
||
// Identification = "Add|Visit|Info|Visit-Image Upload",
|
||
// TrialId = visitPlan.TrialId,
|
||
// IsSign = false,
|
||
// CreateTime = createtime.AddSeconds(1),
|
||
// VisitStageId = result.Id,
|
||
// JsonDetail = JsonConvert.SerializeObject(visitPlan)
|
||
//});
|
||
|
||
//更新项目访视计划状态为未确认
|
||
await _trialRepository.BatchUpdateAsync(u => u.Id == visitPlan.TrialId, t => new Trial() { VisitPlanConfirmed = false });
|
||
|
||
await _repository.SaveChangesAsync();
|
||
|
||
//return ResponseOutput.Ok(result.Id.ToString());
|
||
|
||
|
||
}
|
||
|
||
else//update
|
||
{
|
||
|
||
|
||
if (await _visitStageRepository.AnyAsync(t => t.TrialId == visitPlan.TrialId && (t.VisitName == visitPlan.VisitName || t.VisitNum == visitPlan.VisitNum) && t.Id != visitPlan.Id,true))
|
||
{
|
||
return ResponseOutput.NotOk("A visit with the same VisitName/VisitNum already existed in the current visit plan.");
|
||
}
|
||
|
||
if (await _visitStageRepository.AnyAsync(t => t.TrialId == visitPlan.TrialId && t.IsBaseLine && t.Id != visitPlan.Id,true) && visitPlan.IsBaseLine)
|
||
{
|
||
return ResponseOutput.NotOk("A visit already is baseline in the current visit plan.");
|
||
}
|
||
|
||
|
||
|
||
var stage = await _visitStageRepository.FirstOrDefaultAsync(t => t.Id == visitPlan.Id,true);
|
||
if (stage == null) return ResponseOutput.NotOk("None");
|
||
|
||
//修改是否是基线
|
||
if (stage.IsBaseLine && stage.IsBaseLine != visitPlan.IsBaseLine)
|
||
{
|
||
if (await _repository.Where<SubjectVisit>(t => t.TrialId == visitPlan.TrialId).AnyAsync(v => v.IsBaseLine && v.SubmitState >= SubmitStateEnum.ToSubmit))
|
||
{
|
||
return ResponseOutput.NotOk("有CRC已经为基线上传了影像数据,不允许修改基线");
|
||
}
|
||
}
|
||
|
||
_mapper.Map(visitPlan, stage);
|
||
|
||
stage.BlindName = "B" + ((int)visitPlan.VisitNum * 10).ToString("D3");
|
||
|
||
//更新项目访视计划状态为未确认
|
||
//await _trialRepository.UpdateFromQueryAsync(u => u.Id == visitPlan.TrialId, t => new Trial() { VisitPlanConfirmed = false });
|
||
|
||
await _repository.SaveChangesAsync();
|
||
|
||
//return ResponseOutput.Ok();
|
||
}
|
||
|
||
|
||
await _inspectionService.AddListInspectionRecordAsync(datas);
|
||
return ResponseOutput.Ok(visitPlan.Id.Value.ToString());
|
||
}
|
||
|
||
/// <summary> 删除项目计划某一项[New]</summary>
|
||
[HttpDelete("{id:guid}/{trialId:guid}")]
|
||
[TrialAudit(AuditType.TrialAudit, AuditOptType.DeleteTrialVisitPlanItem)]
|
||
|
||
[TypeFilter(typeof(TrialResourceFilter))]
|
||
public async Task<IResponseOutput> DeleteVisitStage(Guid id)
|
||
{
|
||
|
||
var visitPlan = await _visitStageRepository.FirstOrDefaultAsync(t => t.Id == id);
|
||
|
||
if (visitPlan == null) return Null404NotFound(visitPlan);
|
||
|
||
if (await _repository.AnyAsync<SubjectVisit>(t => t.VisitName == visitPlan.VisitName && t.TrialId == visitPlan.TrialId && t.VisitExecuted == VisitExecutedEnum.Executed))
|
||
{
|
||
return ResponseOutput.NotOk("The visit plan has been assigned to the subjects and executed.");
|
||
}
|
||
|
||
|
||
var list = await _subjectVisitRepository.Where(t => t.TrialId == visitPlan.TrialId && t.VisitName == visitPlan.VisitName).ToListAsync();
|
||
|
||
|
||
List<DataInspection> datas = new List<DataInspection>();
|
||
var createtime = DateTime.Now.AddSeconds(1);
|
||
list.ForEach(x =>
|
||
{
|
||
datas.Add(new DataInspection()
|
||
{
|
||
BlindName = x.BlindName,
|
||
IsSign = false,
|
||
SiteId = x.SiteId,
|
||
SubjectId = x.SubjectId,
|
||
SubjectVisitId = x.Id,
|
||
CreateTime = createtime,
|
||
SubjectVisitName = x.VisitName,
|
||
TrialId = x.TrialId,
|
||
JsonDetail = JsonConvert.SerializeObject(x),
|
||
Identification = "Delete|Visit|Data|Visit-Image Upload"
|
||
});
|
||
});
|
||
|
||
|
||
await _inspectionService.AddListInspectionRecordAsync(datas);
|
||
await _repository.BatchDeleteAsync<SubjectVisit>(t => t.TrialId == visitPlan.TrialId && t.VisitName == visitPlan.VisitName);
|
||
|
||
var result = await _visitStageRepository.BatchDeleteAsync(u => u.Id == id);
|
||
|
||
return ResponseOutput.Result(result);
|
||
}
|
||
|
||
|
||
[UnitOfWork]
|
||
[HttpPost("{trialId:guid}")]
|
||
[TrialAudit(AuditType.TrialAudit, AuditOptType.ConfirmTrialVisitPlan)]
|
||
|
||
public async Task<IResponseOutput> ConfirmTrialVisitPlan(Guid trialId)
|
||
{
|
||
if (!await _trialRepository.AnyAsync(t => t.Id == trialId &&( t.TrialStatusStr==StaticData.TrialInitializing || t.TrialStatusStr == StaticData.TrialOngoing)))
|
||
{
|
||
return ResponseOutput.NotOk("仅仅在项目初始化或者进行中时,才允许修改确认");
|
||
}
|
||
|
||
if (!await _visitStageRepository.AnyAsync(t => t.TrialId == trialId && t.IsBaseLine))
|
||
{
|
||
return ResponseOutput.NotOk("没有基线,不允许确认");
|
||
}
|
||
|
||
if (!await _trialRepository.AnyAsync(t => t.Id == trialId && t.IsTrialBasicLogicConfirmed && t.IsTrialProcessConfirmed && t.IsTrialUrgentConfirmed))
|
||
{
|
||
return ResponseOutput.NotOk("项目配置未确认,不允许确认访视计划");
|
||
}
|
||
|
||
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)
|
||
{
|
||
return ResponseOutput.NotOk("基线VisitDay 不是最小的, 不允许确认");
|
||
}
|
||
|
||
List<DataInspection> datas = new List<DataInspection>();
|
||
|
||
var addvisitStages = await _visitStageRepository.Where(x => !x.IsHaveFirstConfirmed&&x.TrialId== trialId).ToListAsync();
|
||
|
||
//更新项目访视计划状态为已确认
|
||
await _trialRepository.BatchUpdateAsync(u => u.Id == trialId, t => new Trial() { VisitPlanConfirmed = true });
|
||
|
||
//找到访视计划修改的Item
|
||
var changedList = await _visitStageRepository.Where(t => t.TrialId == trialId && 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 }).ToListAsync();
|
||
var createtime = DateTime.Now.AddSeconds(1);
|
||
|
||
|
||
changedList.ForEach(x =>
|
||
{
|
||
datas.Add(new DataInspection()
|
||
{
|
||
IsSign = false,
|
||
|
||
CreateTime = createtime,
|
||
//SubjectVisitName = x.VisitName,
|
||
VisitStageId = x.Id,
|
||
TrialId = x.TrialId,
|
||
JsonDetail = JsonConvert.SerializeObject(x),
|
||
Identification = "Confirm|Visit Plan Template|Data|Trial Setting-Visit Plan"
|
||
});
|
||
|
||
});
|
||
|
||
//访视计划 整体状态变更为 确认
|
||
await _visitStageRepository.BatchUpdateAsync(u => u.TrialId == trialId, t => new VisitStage() { IsConfirmed = true ,IsHaveFirstConfirmed = true});
|
||
|
||
var stat = new VisitPlanInfluenceStat() { TrialId = trialId };
|
||
|
||
foreach (var changedItem in changedList)
|
||
{
|
||
//找到该项目 访视已经执行,并且配置了有首次给药日期 并且更新后超窗的访视,要把超窗之前的值也要查询出来
|
||
var qcPassedVisitList = await _repository.Where<SubjectVisit>(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 =>
|
||
{
|
||
stat.InconsistentCount++;
|
||
stat.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 =>
|
||
{
|
||
stat.InconsistentCount++;
|
||
stat.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 =>
|
||
{
|
||
stat.InconsistentCount++;
|
||
stat.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 =>
|
||
{
|
||
stat.InconsistentCount++;
|
||
stat.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")
|
||
|
||
});
|
||
});
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
var list = await _subjectVisitRepository.Where(t => t.TrialId == trialId && t.VisitStageId == changedItem.Id).ToListAsync();
|
||
list.ForEach(x =>
|
||
{
|
||
datas.Add(new DataInspection()
|
||
{
|
||
BlindName = x.BlindName,
|
||
IsSign = false,
|
||
SiteId = x.SiteId,
|
||
SubjectId = x.SubjectId,
|
||
SubjectVisitId = x.Id,
|
||
CreateTime = createtime,
|
||
SubjectVisitName = x.VisitName,
|
||
TrialId = x.TrialId,
|
||
JsonDetail = JsonConvert.SerializeObject(new {
|
||
|
||
IsBaseLine = changedItem.IsBaseLine,
|
||
VisitName = changedItem.VisitName,
|
||
VisitNum = changedItem.VisitNum,
|
||
VisitDay = changedItem.VisitDay,
|
||
VisitWindowLeft = changedItem.VisitWindowLeft,
|
||
VisitWindowRight = changedItem.VisitWindowRight
|
||
}),
|
||
Identification = "Edit|Visit|Info|Visit-Image Upload"
|
||
});
|
||
});
|
||
|
||
|
||
|
||
|
||
|
||
|
||
//变更某一访视计划Item 受试者访视相关字段
|
||
await _repository.BatchUpdateAsync<SubjectVisit>(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
|
||
});
|
||
|
||
}
|
||
var subjectsids = _repository.GetQueryable<Subject>().Where(x => x.TrialId == trialId).Select(x => new
|
||
{
|
||
x.Code,
|
||
x.SiteId,
|
||
x.Id,
|
||
x.IsEnrollment,
|
||
x.IsUrgent
|
||
|
||
});
|
||
|
||
List<SubjectVisit> subjectVisits = new List<SubjectVisit>();
|
||
|
||
|
||
|
||
|
||
|
||
|
||
addvisitStages.ForEach(x =>
|
||
{
|
||
subjectsids.ForEach(y =>
|
||
{
|
||
var guid = new Guid();
|
||
// 新增受试者
|
||
datas.Add(new DataInspection()
|
||
{
|
||
BlindName = x.BlindName,
|
||
IsSign = false,
|
||
SiteId = y.SiteId,
|
||
SubjectId = y.Id,
|
||
SubjectVisitId = guid,
|
||
CreateTime = createtime.AddMilliseconds(200),
|
||
SubjectVisitName = x.VisitName,
|
||
TrialId = x.TrialId,
|
||
Identification = "Add|Visit|Info|Visit-Image Upload",
|
||
JsonDetail = JsonConvert.SerializeObject(new
|
||
{
|
||
IsBaseLine = x.IsBaseLine,
|
||
VisitName = x.VisitName,
|
||
VisitNum = x.VisitNum,
|
||
VisitDay = x.VisitDay,
|
||
VisitExecuted=false,
|
||
BlindName=x.BlindName,
|
||
VisitWindowLeft = x.VisitWindowLeft,
|
||
VisitWindowRight = x.VisitWindowRight,
|
||
IsEnrollment=y.IsEnrollment,
|
||
IsUrgent=y.IsUrgent,
|
||
}),
|
||
});
|
||
|
||
// 初始化受试者
|
||
datas.Add(new DataInspection()
|
||
{
|
||
SiteId = y.SiteId,
|
||
SubjectId = y.Id,
|
||
SubjectVisitId = guid,
|
||
TrialId = x.TrialId,
|
||
SubjectCode = y.Code,
|
||
BlindName = x.BlindName,
|
||
|
||
SubjectVisitName = x.VisitName,
|
||
IsSign = false,
|
||
CreateTime = createtime.AddMilliseconds(500),
|
||
Identification = "Init|Visit|Status|Visit-Image Upload",
|
||
JsonDetail = JsonConvert.SerializeObject(new
|
||
{
|
||
BlindName = x.BlindName,
|
||
VisitName = x.VisitName,
|
||
SubmitState = "",
|
||
AuditState = "",
|
||
IsBaseLine = x.IsBaseLine,
|
||
IsEnrollment = y.IsEnrollment,
|
||
IsUrgent = y.IsUrgent,
|
||
})
|
||
});
|
||
|
||
subjectVisits.Add(new SubjectVisit()
|
||
{
|
||
|
||
SiteId = y.SiteId,
|
||
SubjectId = y.Id,
|
||
Id = guid,
|
||
BlindName=x.BlindName,
|
||
IsBaseLine=x.IsBaseLine,
|
||
IsCheckBack=x.IsBaseLine,
|
||
IsUrgent=y.IsUrgent,
|
||
|
||
|
||
});
|
||
});
|
||
|
||
|
||
});
|
||
await _inspectionService.AddListInspectionRecordAsync(datas);
|
||
await _repository.AddAsync(stat);
|
||
await _repository.AddRangeAsync(subjectVisits);
|
||
await _repository.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();
|
||
|
||
|
||
IExporter exporter = new ExcelExporter();
|
||
|
||
var result = await exporter.ExportAsByteArray(list);
|
||
|
||
|
||
return new XlsxFileResult(bytes: result, fileDownloadName: $"检查导出_{DateTime.Now.ToString("yyyy-MM-dd:hh:mm:ss")}.xlsx");
|
||
|
||
|
||
}
|
||
|
||
|
||
}
|
||
} |