using IRaCIS.Core.Domain.Share;
using Microsoft.AspNetCore.Mvc;
using IRaCIS.Core.Application.Service.Reading.Dto;
using MassTransit;
using IRaCIS.Core.Infra.EFCore.Common;
using System.Linq.Dynamic.Core;
using IRaCIS.Core.Application.Service;
using IRaCIS.Core.Application.ViewModel;
using IRaCIS.Core.Infrastructure;
using IRaCIS.Core.Application.Filter;
using IRaCIS.Core.Domain.Models;
namespace IRaCIS.Application.Services
{
///
/// 生成的阅片模块(在大列表上展示的) 阅片期
///
[ApiExplorerSettings(GroupName = "Reading")]
public class ReadModuleService : BaseService
{
public IRepository _subjectVisitRepository;
private readonly IRepository _subjectRepository;
private readonly IRepository _visitstageRepository;
private readonly IRepository _userRepository;
private readonly IRepository _trialRepository;
private readonly IVisitTaskHelpeService _visitTaskHelpeService;
private readonly IRepository _visitTaskRepository;
private readonly IRepository _readModuleCriterionFromRepository;
private readonly IRepository _clinicalDataTrialSetRepository;
private readonly IRepository _readModuleViewRepository;
private readonly IRepository _readingQuestionCriterionTrialRepository;
private readonly IRepository _dicomInstanceRepository;
private readonly IRepository _noneDicomStudyFileRepository;
private readonly IRepository _readingPeriodSetRepository;
private readonly IRepository _readModuleRepository;
public ReadModuleService(IRepository subjectVisitRepository,
IRepository subjectRepository,
IRepository visitstageRepository,
IRepository UserRepository,
IRepository trialRepository,
IVisitTaskHelpeService visitTaskHelpeService,
IRepository visitTaskRepository,
IRepository readModuleCriterionFromRepository,
IRepository clinicalDataTrialSetRepository,
IRepository readModuleViewRepository,
IRepository readingQuestionCriterionTrialRepository,
IRepository dicomInstanceRepository,
IRepository noneDicomStudyFileRepository,
IRepository readingPeriodSetRepository,
IRepository readModuleRepository
)
{
this._subjectVisitRepository = subjectVisitRepository;
this._subjectRepository = subjectRepository;
this._visitstageRepository = visitstageRepository;
this._userRepository = UserRepository;
this._trialRepository = trialRepository;
this._visitTaskHelpeService = visitTaskHelpeService;
this._visitTaskRepository = visitTaskRepository;
this._readModuleCriterionFromRepository = readModuleCriterionFromRepository;
this._clinicalDataTrialSetRepository = clinicalDataTrialSetRepository;
this._readModuleViewRepository = readModuleViewRepository;
this._readingQuestionCriterionTrialRepository = readingQuestionCriterionTrialRepository;
this._dicomInstanceRepository = dicomInstanceRepository;
this._noneDicomStudyFileRepository = noneDicomStudyFileRepository;
this._readingPeriodSetRepository = readingPeriodSetRepository;
this._readModuleRepository = readModuleRepository;
}
#region 获取修改时可选择的阅片期截止访视
///
/// 获取修改截止访视下拉
///
///
///
[HttpPost]
public async Task> GetCanChangeReadVisitList(GetCanChangeReadVisitListInDto inDto)
{
//增加标准
var mixReadVisitNum = await _visitTaskRepository.Where(x =>
x.TrialReadingCriterionId == inDto.TrialReadingCriterionId
&& x.ReadingTaskState == ReadingTaskState.HaveSigned
&& x.ReadingCategory == ReadingCategory.Visit
&& x.SubjectId == inDto.SubjectId
&& x.TaskState == TaskState.Effect).OrderByDescending(x => x.VisitTaskNum).Select(x=> x.VisitTaskNum).FirstOrDefaultAsync();
var visitQuery = _subjectVisitRepository.Where(x => x.SubjectId == inDto.SubjectId && x.LatestScanDate != null && !x.IsLostVisit);
var finalVisitNum = await visitQuery.Where(x => x.IsFinalVisit).Select(x => x.VisitNum).FirstOrDefaultAsync();
//增加标准
var readModulequery = _readModuleRepository.AsQueryable().Where(x => x.TrialReadingCriterionId == inDto.TrialReadingCriterionId);
var resultlist = await visitQuery.WhereIf(finalVisitNum != null && finalVisitNum != 0, x => x.VisitNum <= finalVisitNum)
.Where(x => x.VisitNum > mixReadVisitNum)
.Where(x => !x.IsBaseLine) // 排除基线
.Where(x => readModulequery.Where(y => y.Id != inDto.Id && y.SubjectVisitId == x.Id && y.TrialReadingCriterionId == inDto.TrialReadingCriterionId && y.ReadingSetType == ReadingSetType.ImageReading).Count() == 0)
.Select(x => new GetSubjectReadVisitsOutDto()
{
SubjectVisitId = x.Id,
VisitName = x.VisitName,
VisitNum = x.VisitNum,
}).OrderBy(x => x.VisitNum).ToListAsync();
return resultlist;
}
#endregion
///
/// 修改全局阅片截止访视
///
///
///
[HttpPost]
public async Task ChangeCutOffVisit(ChangeCutOffVisitInDto inDto)
{
if (await _readModuleRepository.AnyAsync(x => x.Id == inDto.Id && x.IsCRCConfirm))
{
//---CRC已经确认临床数据 不允许编辑
throw new BusinessValidationFailedException(_localizer["ReadModule_CRCConfirmCanNtoEdit"]);
}
await _readModuleRepository.UpdatePartialFromQueryAsync(x => x.Id == inDto.Id, x => new ReadModule() {
SubjectVisitId=inDto.SubjectVisitIdId,
ModuleName=inDto.Name,
});
return await _readModuleRepository.SaveChangesAsync();
}
///
/// 获取读片模块 //加了标准参数
///
[HttpPost]
public async Task<(PageOutput,object)> GetReadModuleList(GetReadModuleDto dto)
{
#region MyRegion
if (dto.SortField.IsNullOrEmpty())
{
dto.SortField = nameof(ReadModuleView.SubjectCode);
dto.Asc = true;
}
dto.SortField = dto.Asc ? dto.SortField : dto.SortField + " desc";
var subjectQuery = _readModuleViewRepository.Where(x => x.TrialReadingCriterionId == dto.TrialReadingCriterionId)
.WhereIf(dto.TrialId != null, x => x.TrialId == dto.TrialId)
.WhereIf(dto.SubjectId != null, x => x.SubjectId == dto.SubjectId)
.WhereIf(dto.TrialSiteCode != null && dto.TrialSiteCode != string.Empty, x => x.TrialSiteCode.Contains(dto.TrialSiteCode))
.WhereIf(dto.SubjectCode != null && dto.SubjectCode != string.Empty, x => x.SubjectCode.Contains(dto.SubjectCode))
.WhereIf(dto.ModuleType != null, x => x.ModuleType == dto.ModuleType)
.WhereIf(dto.ReadingStatus != null, x => x.ReadingStatus == dto.ReadingStatus)
.WhereIf(dto.Name != null, x => x.Name.Contains(dto.Name!)).OrderBy(x => x.SiteCode);
var subjectIds = await subjectQuery.OrderBy(dto.SortField).Select(x => x.SubjectId).Distinct().Skip((dto.PageIndex - 1) * dto.PageSize).Take(dto.PageSize).ToListAsync();
List ReadModuleViewList = await subjectQuery.Where(x => subjectIds.Contains(x.SubjectId)).OrderBy(dto.SortField).ToListAsync();
List getReadList = ReadModuleViewList.GroupBy(x => new { x.SubjectId, x.SiteId, x.TrialSiteCode, x.SubjectCode })
.Select(x => new GetReadModuleDtoOut()
{
TrialSiteCode = x.Key.TrialSiteCode,
SiteId = x.Key.SiteId,
SubjectCode = x.Key.SubjectCode,
SubjectId = x.Key.SubjectId,
Data = x.OrderBy(x=>x.ModuleType).ThenBy(x=>x.VisitNum).ToList(),
}).ToList();
PageOutput pageOutput = new PageOutput()
{
PageSize = dto.PageSize,
CurrentPageData = getReadList,
PageIndex = dto.PageIndex,
TotalCount = await subjectQuery.Select(x => x.SubjectId).Distinct().CountAsync(),
};
var maxcount = 0;
pageOutput.CurrentPageData.ForEach(x =>
{
maxcount = maxcount < x.Data.Count ? x.Data.Count : maxcount;
});
var criterionInfo = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == dto.TrialReadingCriterionId).Select(x => new
{
x.IsReadingTaskViewInOrder,
x.IsOncologyReading,
x.IsGlobalReading,
x.IsReadingPeriod,
x.ReadingInfoSignTime,
}).FirstNotNullAsync();
return (pageOutput, new
{
MaxLength = maxcount,
IsReadingTaskViewInOrder= criterionInfo.IsReadingTaskViewInOrder,
IsClinicalReading = criterionInfo.IsOncologyReading,
// OnlyExistsMedicalHistory = !(await _clinicalDataTrialSetRepository.AnyAsync(x => x.TrialId == dto.TrialId && x.ClinicalDataSetName != "既往局部治疗史" && x.IsConfirm)),
IsExistsSubjectClinicalData= await _clinicalDataTrialSetRepository.AnyAsync(x => x.TrialId == dto.TrialId&&x.ClinicalDataLevel== ClinicalLevel.Subject && x.IsConfirm&&x.TrialClinicalDataSetCriteriaList.Any(y=>y.TrialReadingCriterionId== dto.TrialReadingCriterionId)),
IsExistsVisitClinicalData = await _clinicalDataTrialSetRepository.AnyAsync(x => x.TrialId == dto.TrialId && x.ClinicalDataLevel == ClinicalLevel.SubjectVisit && x.IsConfirm && x.TrialClinicalDataSetCriteriaList.Any(y => y.TrialReadingCriterionId == dto.TrialReadingCriterionId)),
IsExistsReadingClinicalData = await _clinicalDataTrialSetRepository.AnyAsync(x => x.TrialId == dto.TrialId && x.ClinicalDataLevel == ClinicalLevel.ImageRead && x.IsConfirm && x.TrialClinicalDataSetCriteriaList.Any(y => y.TrialReadingCriterionId == dto.TrialReadingCriterionId)),
IsExistsOncologyReadClinicalData = await _clinicalDataTrialSetRepository.AnyAsync(x => x.TrialId == dto.TrialId && x.ClinicalDataLevel == ClinicalLevel.OncologyRead && x.IsConfirm && x.TrialClinicalDataSetCriteriaList.Any(y => y.TrialReadingCriterionId == dto.TrialReadingCriterionId)),
IsGlobalReading = criterionInfo.IsGlobalReading,
IsReadingPeriod=criterionInfo.IsReadingPeriod,
ReadingInfoSignTime=criterionInfo.ReadingInfoSignTime,
ExistClinicalData=await _clinicalDataTrialSetRepository.AnyAsync(x => x.IsConfirm && x.TrialClinicalDataSetCriteriaList.Any(y => y.TrialReadingCriterionId == dto.TrialReadingCriterionId)),
}) ;
#endregion
}
///
/// 获取单条详情信息
///
///
///
[HttpPost]
public async Task GetReadModule(GetReadModuleSingleIndto dto)
{
var data = await GetReadModuleList(new GetReadModuleDto()
{
SubjectId = dto.SubjectId,
TrialId=dto.TrialId,
TrialReadingCriterionId=dto.TrialReadingCriterionId,
});
GetReadModuleSingleOutdto? readModule = data.Item1.CurrentPageData.FirstOrDefault().Data.Where(x => x.Id == dto.Id).Select(x => new GetReadModuleSingleOutdto()
{
Id = x.Id,
ModuleType = x.ModuleType,
SubjectVisitId = x.SubjectVisitId,
SubjectVisitName = x.SubjectVisitName,
Status = x.ReadingStatus,
}).FirstOrDefault();
var stakeholderIds = new List();
var subjectVisit =await _subjectVisitRepository.FirstOrDefaultAsync(x => x.Id == readModule.SubjectVisitId);
switch (readModule.Status)
{
case ReadingStatusEnum.ImageNotSubmit:
stakeholderIds.AddRange(await _dicomInstanceRepository.Where(x => x.SubjectVisitId == readModule.SubjectVisitId).Select(x => x.CreateUserId).Distinct().ToListAsync());
stakeholderIds.AddRange(await _noneDicomStudyFileRepository.Where(x => x.NoneDicomStudy.SubjectVisitId == readModule.SubjectVisitId).Select(x => x.CreateUserId).Distinct().ToListAsync());
break;
case ReadingStatusEnum.ImageQuality:
if (subjectVisit.PreliminaryAuditUserId != null)
{
stakeholderIds.Add(subjectVisit.PreliminaryAuditUserId.Value);
}
if (subjectVisit.ReviewAuditUserId != null)
{
stakeholderIds.Add(subjectVisit.ReviewAuditUserId.Value);
}
break;
case ReadingStatusEnum.TaskAllocate:
if (subjectVisit.CheckUserId != null)
{
stakeholderIds.Add(subjectVisit.CheckUserId.Value);
}
break;
case ReadingStatusEnum.ImageReading:
case ReadingStatusEnum.ReadCompleted:
var doctorUserId = await _visitTaskRepository.Where(x => (x.SouceReadModuleId == dto.Id || x.SourceSubjectVisitId == dto.Id)&&x.TaskState==TaskState.Effect)
.Where(x => x.DoctorUserId != null).Select(x => x.DoctorUserId.Value).ToListAsync();
stakeholderIds.AddRange(doctorUserId);
break;
};
readModule.StakeholderIds = stakeholderIds.Distinct().ToList();
readModule.StakeholderNames = await _userRepository.Where(x => readModule.StakeholderIds.Contains(x.Id)).Select(x => x.FirstName + "/" + x.LastName).ToListAsync();
return readModule;
}
///
/// 添加阅片的时候 获取访视 //标准参数必传
///
///
///
public async Task> GetSubjectReadVisitList(GetSubjectReadVisitsInDto inDto)
{
//增加标准
var maxReadVisit = await _readModuleRepository.Where(x => x.SubjectId == inDto.SubjectId && x.ReadingSetType==inDto.ReadingSetType && x.TrialReadingCriterionId==inDto.TrialReadingCriterionId).Include(x=>x.SubjectVisit).OrderByDescending(x=>x.SubjectVisit.VisitNum).FirstOrDefaultAsync();
var maxReadVisitNum= maxReadVisit==null?-1:maxReadVisit.SubjectVisit.VisitNum;
var visitQuery = _subjectVisitRepository.Where(x => x.SubjectId == inDto.SubjectId && x.LatestScanDate != null && !x.IsLostVisit);
var finalVisitNum = await visitQuery.Where(x => x.IsFinalVisit).Select(x => x.VisitNum).FirstOrDefaultAsync();
//增加标准
var readModulequery = _readModuleRepository.AsQueryable().Where(x=>x.TrialReadingCriterionId == inDto.TrialReadingCriterionId);
var resultlist= await visitQuery.WhereIf(finalVisitNum!=0, x => x.VisitNum <= finalVisitNum)
.WhereIf(inDto.ReadingSetType== ReadingSetType.TumorReading, x => readModulequery.Where(y => y.SubjectVisitId == x.Id&&y.TrialReadingCriterionId== inDto.TrialReadingCriterionId && y.ReadingSetType == ReadingSetType.ImageReading).Count() > 0)
.Where(x=>x.VisitNum> maxReadVisitNum)
.Where(x=>!x.IsBaseLine) // 排除基线
.Where(x => readModulequery.Where(y => y.SubjectVisitId == x.Id&& y.TrialReadingCriterionId == inDto.TrialReadingCriterionId && y.ReadingSetType == inDto.ReadingSetType).Count() == 0).OrderBy(x => finalVisitNum)
.Select(x => new GetSubjectReadVisitsOutDto()
{
SubjectVisitId = x.Id,
VisitName = x.VisitName,
VisitNum = x.VisitNum,
}).OrderBy(x=>x.VisitNum).ToListAsync();
return resultlist;
}
///
/// 添加阅片期
///
///
///
[HttpPost]
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
public async Task AddReadModule(ReadModuleAddDto dto)
{
var visitQuery = _subjectVisitRepository.Where(x => x.SubjectId == dto.SubjectId);
visitQuery = visitQuery
//.WhereIf(dto.ExpirationDate != null, x => x.LatestScanDate <= dto.ExpirationDate.Value)
.WhereIf(dto.ExpirationVisitNum != null, x => x.VisitNum == dto.ExpirationVisitNum!);
var visit = visitQuery.OrderByDescending(x => x.VisitNum).FirstOrDefault();
var moduleType = dto.ReadingSetType == ReadingSetType.ImageReading ? ModuleTypeEnum.Global : ModuleTypeEnum.Oncology;
if (visit != null)
{
if (await _readModuleRepository.AnyAsync(x => x.SubjectVisitId == visit.Id&&x.ModuleType== moduleType && x.TrialReadingCriterionId == dto.TrialReadingCriterionId))
{
//---当前访视已经添加过阅片期
throw new BusinessValidationFailedException(_localizer["ReadModule_AlreadyAdded"]);
}
var readModuleData = new ReadModule()
{
Id = NewId.NextGuid(),
SubjectId = dto.SubjectId,
ModuleType = moduleType,
IsUrgent = visit.IsUrgent,
ModuleName = dto.Name,
SubjectVisitId = visit.Id,
ReadingSetType = dto.ReadingSetType,
TrialId = dto.TrialId,
ReadingStatus = ReadingStatusEnum.TaskAllocate,
//增加标准
TrialReadingCriterionId = dto.TrialReadingCriterionId,
};
await _readModuleRepository.AddAsync(readModuleData);
// 判断是否要添加肿瘤学或者全局阅片任务
switch (readModuleData.ModuleType)
{
case ModuleTypeEnum.Global:
//增加标准
var taskListInfo = await _visitTaskRepository.Where(x => x.SourceSubjectVisitId == readModuleData.SubjectVisitId&&x.TaskState==TaskState.Effect && x.ReadingTaskState == ReadingTaskState.HaveSigned
&&!x.IsAnalysisCreate && x.TrialReadingCriterionId==dto.TrialReadingCriterionId
).ToListAsync();
foreach (var taskInfo in taskListInfo)
{
await _visitTaskHelpeService.AddTaskAsync(new GenerateTaskCommand()
{
OriginalVisitId = taskInfo.Id,
ReadingCategory = GenerateTaskCategory.Global,
TrialId = dto.TrialId,
ReadingGenerataTaskList = new List() {
new ReadingGenerataTaskDTO()
{
IsUrgent = readModuleData.IsUrgent ?? false,
SubjectId = readModuleData.SubjectId,
ReadingName = readModuleData.ModuleName,
ReadModuleId =readModuleData.Id,
ReadingCategory = ReadingCategory.Global,
}
}
});
}
break;
case ModuleTypeEnum.Oncology:
var criterionInfo = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == dto.TrialReadingCriterionId).Select(x => new
{
x.ReadingType,
}).FirstNotNullAsync();
//增加标准
var globalModule = await _readModuleRepository.Where(x => x.SubjectId == readModuleData.SubjectId && x.SubjectVisitId == readModuleData.SubjectVisitId&& x.ModuleType == ModuleTypeEnum.Global && x.TrialReadingCriterionId == dto.TrialReadingCriterionId).FirstOrDefaultAsync();
if (globalModule != null)
{
var globalTaskInfoList = await _visitTaskRepository.Where(x => x.SouceReadModuleId == globalModule.Id
&& x.TrialReadingCriterionId == dto.TrialReadingCriterionId
&& x.TaskState == TaskState.Effect && x.ReadingTaskState == ReadingTaskState.HaveSigned&&!x.IsAnalysisCreate).ToListAsync();
if (globalTaskInfoList.Count() > 0 && globalTaskInfoList.Count == (int)criterionInfo.ReadingType)
{
var isAdd = false;
if (globalTaskInfoList[0].JudgeVisitTaskId == null)
{
isAdd = true;
}
else
{
isAdd = await _visitTaskRepository.AnyAsync(x => x.Id == globalTaskInfoList[0].JudgeVisitTaskId && x.ReadingTaskState == ReadingTaskState.HaveSigned);
}
if (isAdd)
{
await _visitTaskHelpeService.AddTaskAsync(new GenerateTaskCommand()
{
OriginalVisitId = globalTaskInfoList[0].Id,
ReadingCategory = GenerateTaskCategory.Oncology,
TrialId = dto.TrialId,
ReadingGenerataTaskList = new List() {
new ReadingGenerataTaskDTO()
{
IsUrgent = readModuleData.IsUrgent ?? false,
SubjectId = readModuleData.SubjectId,
VisitNum=visit.VisitNum,
ReadingName = readModuleData.ModuleName,
ReadModuleId =readModuleData.Id,
ReadingCategory = ReadingCategory.Oncology,
}
}
});
}
}
}
else
{
//---请先添加全局阅片
return ResponseOutput.NotOk(_localizer["ReadModule_AddGlobalFirst"]);
}
break;
}
var res = await _readModuleRepository.SaveChangesAsync();
return ResponseOutput.Ok(res);
}
else
{
//---未找到符合要求的访视
return ResponseOutput.NotOk(_localizer["ReadModule_VisitNotFound"]);
}
}
///
/// 删除
///
///
///
[HttpDelete("{readModuleId:guid}")]
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
public async Task DeleteReadModule(Guid readModuleId)
{
var readModule = await _readModuleRepository.Where(x => x.Id == readModuleId).FirstNotNullAsync();
if(await _repository.Where(t => t.ReadingId == readModuleId).AnyAsync(t => t.ReadingClinicalDataState == ReadingClinicalDataStatus.HaveSigned))
{
//---临床资料已签名,不允许删除
return ResponseOutput.NotOk(_localizer["ReadModule_SignedDataCannotDelete"]);
}
if (await _readModuleRepository.AnyAsync(x => x.Id == readModuleId&&x.IsCRCConfirm))
{
//---CRC已经确认临床数据 不允许删除
return ResponseOutput.NotOk(_localizer["ReadModule_CRCConfirmClinicalData"]);
}
//增加标准
if (readModule.ModuleType==ModuleTypeEnum.Global&&(await _readModuleRepository.AnyAsync(x=>x.ModuleType==ModuleTypeEnum.Oncology&&x.SubjectVisitId== readModule.SubjectVisitId && x.TrialReadingCriterionId==readModule.TrialReadingCriterionId)))
{
//---当前访视存在肿瘤学阅片,请先删除肿瘤学阅片
throw new BusinessValidationFailedException(_localizer["ReadModule_TumorExists"]);
}
if (await _visitTaskRepository.AnyAsync(x => readModuleId==x.SouceReadModuleId))
{
//---当前阅片已生成任务,操作失败。
throw new BusinessValidationFailedException(_localizer["ReadModule_TaskGenerated"]);
}
await _visitTaskRepository.BatchUpdateNoTrackingAsync(x => readModuleId==x.SouceReadModuleId, x => new VisitTask()
{
TaskState = TaskState.Adbandon
});
await _readModuleRepository.UpdatePartialFromQueryAsync(t => t.Id == readModuleId, x => new ReadModule()
{
IsDeleted = true
});
await _readModuleRepository.SaveChangesAsync();
return ResponseOutput.Result(true);
}
}
}