|
|
|
@@ -3,6 +3,7 @@ using IRaCIS.Core.Application.Contracts.DTO;
|
|
|
|
|
using IRaCIS.Core.Application.Filter;
|
|
|
|
|
using IRaCIS.Core.Application.Helper;
|
|
|
|
|
using IRaCIS.Core.Application.Service.Inspection.DTO;
|
|
|
|
|
using IRaCIS.Core.Domain.Models;
|
|
|
|
|
using IRaCIS.Core.Domain.Share;
|
|
|
|
|
using IRaCIS.Core.Infrastructure;
|
|
|
|
|
using Medallion.Threading;
|
|
|
|
@@ -38,6 +39,7 @@ namespace IRaCIS.Core.Application.Image.QA
|
|
|
|
|
IRepository<ReadingQuestionCriterionTrial> _readingQuestionCriterionTrialRepository,
|
|
|
|
|
IDistributedLockProvider _distributedLockProvider, IReadingClinicalDataService _readingClinicalDataService,
|
|
|
|
|
IOSSService _oSSService,
|
|
|
|
|
IRepository<ReadingClinicalData> _readingClinicalDataReposiotry,
|
|
|
|
|
IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer, IWebHostEnvironment _hostEnvironment) : BaseService, IQCOperationService
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
@@ -239,6 +241,132 @@ namespace IRaCIS.Core.Application.Image.QA
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#region CRC IQC 申请退回
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// CRC IQC 申请影像回退
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="subjectVisitId"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
/// <exception cref="BusinessValidationFailedException"></exception>
|
|
|
|
|
[HttpPut]
|
|
|
|
|
public async Task<IResponseOutput> RequestImageBack(Guid subjectVisitId)
|
|
|
|
|
{
|
|
|
|
|
if (!_subjectVisitRepository.Any(t => t.Id == subjectVisitId && t.CheckState < CheckStateEnum.CVPassed && t.SubmitState == SubmitStateEnum.Submitted))
|
|
|
|
|
{
|
|
|
|
|
//一致性核查通过前已提交的影像才允许进行回退
|
|
|
|
|
throw new BusinessValidationFailedException(_localizer["QCOperation_ShouldBeforeCheckPassed"]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.ClinicalResearchCoordinator)
|
|
|
|
|
{
|
|
|
|
|
await _subjectVisitRepository.UpdatePartialFromQueryAsync(t => t.Id == subjectVisitId, u => new SubjectVisit() { ImageBackState = ImageBackStateEnum.CRCRequestBack }, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.IQC)
|
|
|
|
|
{
|
|
|
|
|
await _subjectVisitRepository.UpdatePartialFromQueryAsync(t => t.Id == subjectVisitId, u => new SubjectVisit() { ImageBackState = ImageBackStateEnum.IQCRequestBack }, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ResponseOutput.Ok();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// PM 审核CRC IQC 申请影像回退
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="subjectVisitId"></param>
|
|
|
|
|
/// <param name="isAgree"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
/// <exception cref="BusinessValidationFailedException"></exception>
|
|
|
|
|
[HttpPut]
|
|
|
|
|
public async Task<IResponseOutput> AuditImageBack(Guid subjectVisitId, bool isAgree)
|
|
|
|
|
{
|
|
|
|
|
var sv = (await _subjectVisitRepository.FirstOrDefaultAsync(t => t.Id == subjectVisitId)).IfNullThrowException();
|
|
|
|
|
|
|
|
|
|
if (sv.ImageBackState != ImageBackStateEnum.CRCRequestBack && sv.ImageBackState != ImageBackStateEnum.IQCRequestBack)
|
|
|
|
|
{
|
|
|
|
|
//当前访视状态不在影像回退状态,不允许审核通过
|
|
|
|
|
throw new BusinessValidationFailedException(_localizer["QCOperation_NotInRequestImageBackState"]);
|
|
|
|
|
}
|
|
|
|
|
if (isAgree)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
if (sv.CheckState < CheckStateEnum.CVPassed)
|
|
|
|
|
{
|
|
|
|
|
//一致性核查通过前才允许进行回退
|
|
|
|
|
throw new BusinessValidationFailedException(_localizer["QCOperation_ShouldBeforeCheckPassed"]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sv.ImageBackState = ImageBackStateEnum.PMAgreeBack;
|
|
|
|
|
|
|
|
|
|
#region 回退处理
|
|
|
|
|
//需要重新产生任务
|
|
|
|
|
sv.IsVisitTaskGenerated = false;
|
|
|
|
|
sv.IsPMBackOrReReading = true;
|
|
|
|
|
|
|
|
|
|
sv.AuditState = AuditStateEnum.None;
|
|
|
|
|
sv.SubmitState = SubmitStateEnum.ToSubmit;
|
|
|
|
|
sv.ReadingStatus = ReadingStatusEnum.ImageNotSubmit;
|
|
|
|
|
|
|
|
|
|
//回退后,回退状态恢复
|
|
|
|
|
sv.RequestBackState = RequestBackStateEnum.NotRequest;
|
|
|
|
|
sv.IsCheckBack = false;
|
|
|
|
|
sv.CheckBackTime = null;
|
|
|
|
|
sv.CheckState = CheckStateEnum.None;
|
|
|
|
|
sv.CheckChallengeState = CheckChanllengeTypeEnum.None;
|
|
|
|
|
|
|
|
|
|
sv.SVENDTC = null;
|
|
|
|
|
sv.SVSTDTC = null;
|
|
|
|
|
|
|
|
|
|
sv.PreliminaryAuditTime = null;
|
|
|
|
|
sv.SubmitTime = null;
|
|
|
|
|
sv.ReviewAuditTime = null;
|
|
|
|
|
sv.CurrentActionUserExpireTime = null;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sv.IsTake = false;
|
|
|
|
|
sv.CurrentActionUserId = null;
|
|
|
|
|
sv.PreliminaryAuditUserId = null;
|
|
|
|
|
sv.ReviewAuditUserId = null;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (sv.IsBaseLine)
|
|
|
|
|
{
|
|
|
|
|
await _readingClinicalDataReposiotry.UpdatePartialFromQueryAsync(t => t.ReadingId == sv.Id && (t.ClinicalDataTrialSet.ClinicalDataLevel == ClinicalLevel.Subject || t.ClinicalDataTrialSet.ClinicalDataLevel == ClinicalLevel.SubjectVisit), c => new ReadingClinicalData() { IsSign = false, ReadingClinicalDataState = ReadingClinicalDataStatus.HaveUploaded });
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
await _readingClinicalDataReposiotry.UpdatePartialFromQueryAsync(t => t.ReadingId == sv.Id && t.ClinicalDataTrialSet.ClinicalDataLevel == ClinicalLevel.SubjectVisit, c => new ReadingClinicalData()
|
|
|
|
|
{
|
|
|
|
|
IsSign = false,
|
|
|
|
|
ReadingClinicalDataState = ReadingClinicalDataStatus.HaveUploaded,
|
|
|
|
|
IsBlind = null,
|
|
|
|
|
IsComplete = null
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
await _trialQCQuestionAnswerRepository.BatchDeleteNoTrackingAsync(t => t.SubjectVisitId == subjectVisitId);
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
sv.ImageBackState = ImageBackStateEnum.PMNotAgreeBack;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
await _subjectVisitRepository.SaveChangesAsync();
|
|
|
|
|
|
|
|
|
|
return ResponseOutput.Ok();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region 一致性核查
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
@@ -731,7 +859,7 @@ namespace IRaCIS.Core.Application.Image.QA
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
[HttpPut]
|
|
|
|
|
[TrialGlobalLimit("AfterStopCannNotOpt")]
|
|
|
|
|
public async Task<IResponseOutput> SetNodicomStudyState(Guid subjectVisitId, Guid noneDicomStudyId, Guid? noneDicomStudyFileId, int state)
|
|
|
|
|
public async Task<IResponseOutput> SetNodicomStudyState(Guid subjectVisitId, Guid noneDicomStudyId, Guid? noneDicomStudyFileId, int state)
|
|
|
|
|
{
|
|
|
|
|
await VerifyIsCanQCAsync(null, subjectVisitId);
|
|
|
|
|
|
|
|
|
@@ -757,7 +885,7 @@ namespace IRaCIS.Core.Application.Image.QA
|
|
|
|
|
else if (state == 5)
|
|
|
|
|
{
|
|
|
|
|
noneDicomStudy.IsDeleted = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//设置检查下面的文件
|
|
|
|
@@ -1697,8 +1825,8 @@ namespace IRaCIS.Core.Application.Image.QA
|
|
|
|
|
|
|
|
|
|
//删除 软删除的物理文件
|
|
|
|
|
var instancePathList = await _dicomInstanceRepository.Where(t => (t.DicomSerie.IsDeleted || t.IsDeleted) && t.SubjectVisitId == subjectVisitId, false, true)
|
|
|
|
|
.Select(t => t.Path).ToListAsync();
|
|
|
|
|
var noneDicomFileList = await _noneDicomStudyFileRepository.Where(t => (t.NoneDicomStudy.IsDeleted ||t.IsDeleted) && t.NoneDicomStudy.SubjectVisitId == subjectVisitId, false, true)
|
|
|
|
|
.Select(t => t.Path).ToListAsync();
|
|
|
|
|
var noneDicomFileList = await _noneDicomStudyFileRepository.Where(t => (t.NoneDicomStudy.IsDeleted || t.IsDeleted) && t.NoneDicomStudy.SubjectVisitId == subjectVisitId, false, true)
|
|
|
|
|
.Select(t => t.Path).ToListAsync();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -1739,13 +1867,13 @@ namespace IRaCIS.Core.Application.Image.QA
|
|
|
|
|
|
|
|
|
|
//删除影像
|
|
|
|
|
await _dicomStudyRepository.BatchDeleteNoTrackingAsync(t => t.IsDeleted && t.SubjectVisitId == subjectVisitId);
|
|
|
|
|
await _dicomSeriesRepository.BatchDeleteNoTrackingAsync(t => t.IsDeleted && t.SubjectVisitId == subjectVisitId);
|
|
|
|
|
await _dicomSeriesRepository.BatchDeleteNoTrackingAsync(t => t.IsDeleted && t.SubjectVisitId == subjectVisitId);
|
|
|
|
|
await _dicomInstanceRepository.BatchDeleteNoTrackingAsync(t => (t.DicomSerie.IsDeleted || t.IsDeleted) && t.SubjectVisitId == subjectVisitId);
|
|
|
|
|
await _noneDicomStudyFileRepository.BatchDeleteNoTrackingAsync(t => (t.NoneDicomStudy.IsDeleted || t.IsDeleted) && t.NoneDicomStudy.SubjectVisitId == subjectVisitId);
|
|
|
|
|
await _noneDicomStudyRepository.BatchDeleteNoTrackingAsync(t => t.IsDeleted && t.SubjectVisitId == subjectVisitId);
|
|
|
|
|
await _noneDicomStudyRepository.BatchDeleteNoTrackingAsync(t => t.IsDeleted && t.SubjectVisitId == subjectVisitId);
|
|
|
|
|
await _oSSService.DeleteObjects(instancePathList.Select(t => t.TrimStart('/')).ToList());
|
|
|
|
|
await _oSSService.DeleteObjects(noneDicomFileList.Select(t => t.TrimStart('/')).ToList());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|