Compare commits

...

44 Commits

Author SHA1 Message Date
hang a47ac76729 复核指派bug修改
continuous-integration/drone/push Build is passing
2025-07-22 15:29:09 +08:00
hang f86a88332c 复核稽查修改016
continuous-integration/drone/push Build is passing
2025-07-18 13:15:23 +08:00
hang f6be5e4355 复核稽查修改015
continuous-integration/drone/push Build is failing
2025-07-18 13:04:58 +08:00
hang 8deeb0290a 复核稽查修改014
continuous-integration/drone/push Build is failing
2025-07-18 12:17:55 +08:00
hang fb6231373b 复核稽查修改013
continuous-integration/drone/push Build is passing
2025-07-18 11:34:13 +08:00
hang a407313a95 复核稽查修改012
continuous-integration/drone/push Build is passing
2025-07-18 09:25:56 +08:00
hang b1806d2eff 复核稽查修改011
continuous-integration/drone/push Build is passing
2025-07-17 17:25:45 +08:00
hang 19351f34e1 复核稽查修改010
continuous-integration/drone/push Build is passing
2025-07-17 17:10:06 +08:00
hang e0f708082d 复核稽查修改009
continuous-integration/drone/push Build is passing
2025-07-17 16:49:20 +08:00
hang 44464a809d 复核稽查修改008
continuous-integration/drone/push Build is passing
2025-07-17 15:26:28 +08:00
hang c7c01b7ba3 复核稽查修改007
continuous-integration/drone/push Build is passing
2025-07-17 15:08:11 +08:00
hang 38b71d5267 复核稽查修改006
continuous-integration/drone/push Build is passing
2025-07-17 14:00:03 +08:00
hang 3950a3453a 复核稽查修改005
continuous-integration/drone/push Build is passing
2025-07-17 13:26:44 +08:00
hang 7aa59da586 复核稽查修改004
continuous-integration/drone/push Build is passing
2025-07-17 11:51:41 +08:00
hang 9b2fbdb13f 复核稽查修改003
continuous-integration/drone/push Build is passing
2025-07-17 11:28:47 +08:00
hang c98b9e1bd4 复核稽查修改002
continuous-integration/drone/push Build is passing
2025-07-17 11:08:02 +08:00
hang 9522461508 复核稽查修改
continuous-integration/drone/push Build is passing
2025-07-17 10:34:15 +08:00
hang 5bb99180b6 修改复核-退回-003
continuous-integration/drone/push Build is passing
2025-07-16 17:59:42 +08:00
hang 62ec1e4955 修改复核查询接口-002
continuous-integration/drone/push Build is passing
2025-07-16 17:34:09 +08:00
hang 58e1af24c9 修改复核查询接口-001
continuous-integration/drone/push Build is passing
2025-07-16 16:30:03 +08:00
hang a7394e7119 指派其他质控-uat-13
continuous-integration/drone/push Build is passing
2025-07-16 10:30:55 +08:00
hang a93d81de0d 指派其他质控-uat-12 2025-07-16 10:30:51 +08:00
hang 6aafe02c6c 指派其他质控-uat-11 2025-07-16 10:30:48 +08:00
hang 1511ef1608 修改QC复核 -二次提交-uat-10 2025-07-16 10:30:43 +08:00
hang 1141439c8e 修改QC复核 -二次提交-uat-9 2025-07-16 10:30:32 +08:00
hang 559663082b 修改QC复核 -二次提交-uat-8 2025-07-16 10:26:30 +08:00
hang 3a298518f9 修改QC复核 -二次提交-uat-7 2025-07-16 10:26:25 +08:00
hang 7f20232401 修改QC复核 -二次提交-uat-6 2025-07-16 10:26:21 +08:00
hang 20b0849b40 修改QC复核 -二次提交-uat-5 2025-07-16 10:26:16 +08:00
hang db951e9195 修改QC复核 -二次提交-uat-4 2025-07-16 10:26:13 +08:00
hang d5d78a99d2 QC复核 -二次提交-uat-3 2025-07-16 10:26:08 +08:00
hang 1609a7a88a QC复核 -二次提交-uat-3 2025-07-16 10:26:03 +08:00
hang 289831fce8 QC复核 -二次提交-uat-2 2025-07-16 10:25:59 +08:00
hang dde058be18 QC 审核提交--迁移uat 2025-07-16 10:25:26 +08:00
hang be8b730ee4 返回文件大小
continuous-integration/drone/push Build is passing
2025-07-14 15:00:36 +08:00
hang 28360861aa 修改subject 随机阅片下载影像重阅bug
continuous-integration/drone/push Build is passing
2025-07-14 13:36:27 +08:00
hang 3e097fa42b uat 序列获取Instance 增加文件大小 2025-07-14 13:32:21 +08:00
hang b8a7cd6ebc 修改非dicom 设置删除,检查上的数量不变更 2025-07-14 13:32:16 +08:00
hang a9aefaf240 修改预览看到阅片影像 修改后受试者随机bug修改 4 2025-07-14 13:32:10 +08:00
hang 266a0c5dd5 修改后受试者随机bug修改 3 2025-07-14 13:32:05 +08:00
hang 54822ae038 修改后受试者随机bug修改 2 2025-07-14 13:31:07 +08:00
hang 05203d6716 受试者随机bug修改 2025-07-14 13:31:00 +08:00
hang 2ce8edde80 uat升级excel 组件测试
continuous-integration/drone/push Build is passing
2025-07-05 13:34:09 +08:00
hang 3c30f5dc14 完全随机跟下载关联
continuous-integration/drone/push Build is passing
2025-07-03 14:54:23 +08:00
30 changed files with 502 additions and 150 deletions
@@ -52,7 +52,7 @@ namespace IRaCIS.Core.API.Controllers
/// <param name="opt"></param> /// <param name="opt"></param>
/// <returns></returns> /// <returns></returns>
[HttpPost, Route("Inspection/ReadingImageTask/SubmitOncologyReadingInfo")] [HttpPost, Route("Inspection/ReadingImageTask/SubmitOncologyReadingInfo")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )] [TrialGlobalLimit("AfterStopCannNotOpt")]
[UnitOfWork] [UnitOfWork]
public async Task<IResponseOutput> SetOncologyReadingInfo(DataInspectionDto<SubmitOncologyReadingInfoInDto> opt) public async Task<IResponseOutput> SetOncologyReadingInfo(DataInspectionDto<SubmitOncologyReadingInfoInDto> opt)
@@ -69,7 +69,7 @@ namespace IRaCIS.Core.API.Controllers
/// <param name="opt"></param> /// <param name="opt"></param>
/// <returns></returns> /// <returns></returns>
[HttpPost, Route("Inspection/ReadingImageTask/SubmitDicomVisitTask")] [HttpPost, Route("Inspection/ReadingImageTask/SubmitDicomVisitTask")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )] [TrialGlobalLimit("AfterStopCannNotOpt")]
[UnitOfWork] [UnitOfWork]
public async Task<IResponseOutput> SubmitDicomVisitTask(DataInspectionDto<SubmitDicomVisitTaskInDto> opt) public async Task<IResponseOutput> SubmitDicomVisitTask(DataInspectionDto<SubmitDicomVisitTaskInDto> opt)
@@ -88,7 +88,7 @@ namespace IRaCIS.Core.API.Controllers
/// <param name="opt"></param> /// <param name="opt"></param>
/// <returns></returns> /// <returns></returns>
[HttpPost, Route("Inspection/ReadingImageTask/SubmitGlobalReadingInfo")] [HttpPost, Route("Inspection/ReadingImageTask/SubmitGlobalReadingInfo")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )] [TrialGlobalLimit("AfterStopCannNotOpt")]
[UnitOfWork] [UnitOfWork]
public async Task<IResponseOutput> SubmitGlobalReadingInfo(DataInspectionDto<SubmitGlobalReadingInfoInDto> opt) public async Task<IResponseOutput> SubmitGlobalReadingInfo(DataInspectionDto<SubmitGlobalReadingInfoInDto> opt)
@@ -107,7 +107,7 @@ namespace IRaCIS.Core.API.Controllers
/// <param name="opt"></param> /// <param name="opt"></param>
/// <returns></returns> /// <returns></returns>
[HttpPost, Route("Inspection/configTrialBasicInfo/TrialReadingInfoSign")] [HttpPost, Route("Inspection/configTrialBasicInfo/TrialReadingInfoSign")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )] [TrialGlobalLimit("AfterStopCannNotOpt")]
[UnitOfWork] [UnitOfWork]
public async Task<IResponseOutput> TrialReadingInfoSign(DataInspectionDto<TrialReadingInfoSignInDto> opt) public async Task<IResponseOutput> TrialReadingInfoSign(DataInspectionDto<TrialReadingInfoSignInDto> opt)
@@ -126,7 +126,7 @@ namespace IRaCIS.Core.API.Controllers
/// <param name="opt"></param> /// <param name="opt"></param>
/// <returns></returns> /// <returns></returns>
[HttpPost, Route("Inspection/ReadingMedicalReview/FinishMedicalReview")] [HttpPost, Route("Inspection/ReadingMedicalReview/FinishMedicalReview")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )] [TrialGlobalLimit("AfterStopCannNotOpt")]
[UnitOfWork] [UnitOfWork]
public async Task<IResponseOutput> FinishMedicalReview(DataInspectionDto<FinishMedicalReviewInDto> opt) public async Task<IResponseOutput> FinishMedicalReview(DataInspectionDto<FinishMedicalReviewInDto> opt)
@@ -143,7 +143,7 @@ namespace IRaCIS.Core.API.Controllers
/// <param name="opt"></param> /// <param name="opt"></param>
/// <returns></returns> /// <returns></returns>
[HttpPost, Route("Inspection/ReadingMedicineQuestion/ConfirmReadingMedicineQuestion")] [HttpPost, Route("Inspection/ReadingMedicineQuestion/ConfirmReadingMedicineQuestion")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )] [TrialGlobalLimit("AfterStopCannNotOpt")]
[UnitOfWork] [UnitOfWork]
public async Task<IResponseOutput> ConfirmReadingMedicineQuestion(DataInspectionDto<ConfirmReadingMedicineQuestionInDto> opt) public async Task<IResponseOutput> ConfirmReadingMedicineQuestion(DataInspectionDto<ConfirmReadingMedicineQuestionInDto> opt)
@@ -161,7 +161,7 @@ namespace IRaCIS.Core.API.Controllers
/// <param name="opt"></param> /// <param name="opt"></param>
/// <returns></returns> /// <returns></returns>
[HttpPost, Route("Inspection/ReadingImageTask/SubmitVisitTaskQuestions")] [HttpPost, Route("Inspection/ReadingImageTask/SubmitVisitTaskQuestions")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )] [TrialGlobalLimit("AfterStopCannNotOpt")]
[UnitOfWork] [UnitOfWork]
public async Task<IResponseOutput> SubmitVisitTaskQuestions(DataInspectionDto<SubmitVisitTaskQuestionsInDto> opt) public async Task<IResponseOutput> SubmitVisitTaskQuestions(DataInspectionDto<SubmitVisitTaskQuestionsInDto> opt)
@@ -179,7 +179,7 @@ namespace IRaCIS.Core.API.Controllers
/// <param name="opt"></param> /// <param name="opt"></param>
/// <returns></returns> /// <returns></returns>
[HttpPost, Route("Inspection/ClinicalAnswer/CRCSignClinicalData")] [HttpPost, Route("Inspection/ClinicalAnswer/CRCSignClinicalData")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )] [TrialGlobalLimit("AfterStopCannNotOpt")]
[UnitOfWork] [UnitOfWork]
public async Task<IResponseOutput> CRCSignClinicalData(DataInspectionDto<CRCSignClinicalDataInDto> opt) public async Task<IResponseOutput> CRCSignClinicalData(DataInspectionDto<CRCSignClinicalDataInDto> opt)
@@ -197,7 +197,7 @@ namespace IRaCIS.Core.API.Controllers
/// <param name="opt"></param> /// <param name="opt"></param>
/// <returns></returns> /// <returns></returns>
[HttpPost, Route("Inspection/ClinicalAnswer/CRCConfirmClinical")] [HttpPost, Route("Inspection/ClinicalAnswer/CRCConfirmClinical")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )] [TrialGlobalLimit("AfterStopCannNotOpt")]
[UnitOfWork] [UnitOfWork]
public async Task<IResponseOutput> CRCConfirmClinical(DataInspectionDto<CRCConfirmClinicalInDto> opt) public async Task<IResponseOutput> CRCConfirmClinical(DataInspectionDto<CRCConfirmClinicalInDto> opt)
@@ -214,7 +214,7 @@ namespace IRaCIS.Core.API.Controllers
/// <param name="opt"></param> /// <param name="opt"></param>
/// <returns></returns> /// <returns></returns>
[HttpPost, Route("Inspection/ClinicalAnswer/CRCCancelConfirmClinical")] [HttpPost, Route("Inspection/ClinicalAnswer/CRCCancelConfirmClinical")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )] [TrialGlobalLimit("AfterStopCannNotOpt")]
[UnitOfWork] [UnitOfWork]
public async Task<IResponseOutput> CRCCancelConfirmClinical(DataInspectionDto<CRCCancelConfirmClinicalInDto> opt) public async Task<IResponseOutput> CRCCancelConfirmClinical(DataInspectionDto<CRCCancelConfirmClinicalInDto> opt)
@@ -232,7 +232,7 @@ namespace IRaCIS.Core.API.Controllers
/// <param name="opt"></param> /// <param name="opt"></param>
/// <returns></returns> /// <returns></returns>
[HttpPost, Route("Inspection/ClinicalAnswer/PMConfirmClinical")] [HttpPost, Route("Inspection/ClinicalAnswer/PMConfirmClinical")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )] [TrialGlobalLimit("AfterStopCannNotOpt")]
[UnitOfWork] [UnitOfWork]
public async Task<IResponseOutput> PMConfirmClinical(DataInspectionDto<CRCConfirmClinicalInDto> opt) public async Task<IResponseOutput> PMConfirmClinical(DataInspectionDto<CRCConfirmClinicalInDto> opt)
@@ -250,7 +250,7 @@ namespace IRaCIS.Core.API.Controllers
/// <param name="opt"></param> /// <param name="opt"></param>
/// <returns></returns> /// <returns></returns>
[HttpPost, Route("Inspection/ReadingClinicalData/SignConsistencyAnalysisReadingClinicalData")] [HttpPost, Route("Inspection/ReadingClinicalData/SignConsistencyAnalysisReadingClinicalData")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )] [TrialGlobalLimit("AfterStopCannNotOpt")]
[UnitOfWork] [UnitOfWork]
public async Task<IResponseOutput> SignConsistencyAnalysisReadingClinicalData(DataInspectionDto<SignConsistencyAnalysisReadingClinicalDataInDto> opt) public async Task<IResponseOutput> SignConsistencyAnalysisReadingClinicalData(DataInspectionDto<SignConsistencyAnalysisReadingClinicalDataInDto> opt)
@@ -267,7 +267,7 @@ namespace IRaCIS.Core.API.Controllers
/// <param name="opt"></param> /// <param name="opt"></param>
/// <returns></returns> /// <returns></returns>
[HttpPost, Route("Inspection/ClinicalAnswer/SubmitClinicalFormAndSign")] [HttpPost, Route("Inspection/ClinicalAnswer/SubmitClinicalFormAndSign")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )] [TrialGlobalLimit("AfterStopCannNotOpt")]
[UnitOfWork] [UnitOfWork]
public async Task<IResponseOutput> SubmitClinicalFormAndSign(DataInspectionDto<SubmitClinicalFormInDto> opt) public async Task<IResponseOutput> SubmitClinicalFormAndSign(DataInspectionDto<SubmitClinicalFormInDto> opt)
@@ -284,7 +284,7 @@ namespace IRaCIS.Core.API.Controllers
/// <param name="opt"></param> /// <param name="opt"></param>
/// <returns></returns> /// <returns></returns>
[HttpPost, Route("Inspection/ReadingImageTask/SubmitJudgeVisitTaskResult")] [HttpPost, Route("Inspection/ReadingImageTask/SubmitJudgeVisitTaskResult")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )] [TrialGlobalLimit("AfterStopCannNotOpt")]
[UnitOfWork] [UnitOfWork]
public async Task<IResponseOutput> SubmitJudgeVisitTaskResult(DataInspectionDto<SaveJudgeVisitTaskResult> opt) public async Task<IResponseOutput> SubmitJudgeVisitTaskResult(DataInspectionDto<SaveJudgeVisitTaskResult> opt)
@@ -303,7 +303,7 @@ namespace IRaCIS.Core.API.Controllers
/// <returns></returns> /// <returns></returns>
[HttpPost, Route("Inspection/configTrialBasicInfo/ConfigTrialBasicInfoConfirm")] [HttpPost, Route("Inspection/configTrialBasicInfo/ConfigTrialBasicInfoConfirm")]
[UnitOfWork] [UnitOfWork]
[TrialGlobalLimit( "BeforeOngoingCantOpt" )] [TrialGlobalLimit("BeforeOngoingCantOpt")]
public async Task<IResponseOutput> ConfigTrialBasicInfoConfirm(DataInspectionDto<BasicTrialConfig> opt) public async Task<IResponseOutput> ConfigTrialBasicInfoConfirm(DataInspectionDto<BasicTrialConfig> opt)
{ {
@@ -345,7 +345,7 @@ namespace IRaCIS.Core.API.Controllers
/// <returns></returns> /// <returns></returns>
[HttpPost, Route("Inspection/configTrialBasicInfo/ConfigTrialUrgentInfoConfirm")] [HttpPost, Route("Inspection/configTrialBasicInfo/ConfigTrialUrgentInfoConfirm")]
[UnitOfWork] [UnitOfWork]
[TrialGlobalLimit( "BeforeOngoingCantOpt" )] [TrialGlobalLimit("BeforeOngoingCantOpt")]
public async Task<IResponseOutput> ConfigTrialUrgentInfoConfirm(DataInspectionDto<TrialUrgentConfig> opt) public async Task<IResponseOutput> ConfigTrialUrgentInfoConfirm(DataInspectionDto<TrialUrgentConfig> opt)
{ {
opt.Data.IsTrialUrgentConfirmed = true; opt.Data.IsTrialUrgentConfirmed = true;
@@ -358,7 +358,7 @@ namespace IRaCIS.Core.API.Controllers
[HttpPost, Route("Inspection/configTrialBasicInfo/ConfigTrialPACSInfoConfirm")] [HttpPost, Route("Inspection/configTrialBasicInfo/ConfigTrialPACSInfoConfirm")]
[UnitOfWork] [UnitOfWork]
[TrialGlobalLimit( "BeforeOngoingCantOpt" )] [TrialGlobalLimit("BeforeOngoingCantOpt")]
public async Task<IResponseOutput> ConfigTrialPACSInfoConfirm(DataInspectionDto<TrialPACSConfig> opt) public async Task<IResponseOutput> ConfigTrialPACSInfoConfirm(DataInspectionDto<TrialPACSConfig> opt)
{ {
opt.Data.IsTrialPACSConfirmed = true; opt.Data.IsTrialPACSConfirmed = true;
@@ -374,7 +374,7 @@ namespace IRaCIS.Core.API.Controllers
/// <returns></returns> /// <returns></returns>
[HttpPost, Route("Inspection/configTrialBasicInfo/TrialConfigSignatureConfirm")] [HttpPost, Route("Inspection/configTrialBasicInfo/TrialConfigSignatureConfirm")]
[UnitOfWork] [UnitOfWork]
[TrialGlobalLimit( "AfterStopCannNotOpt" )] [TrialGlobalLimit("AfterStopCannNotOpt")]
public async Task<IResponseOutput> TrialConfigSignatureConfirm(DataInspectionDto<SignConfirmDTO> opt) public async Task<IResponseOutput> TrialConfigSignatureConfirm(DataInspectionDto<SignConfirmDTO> opt)
{ {
@@ -391,7 +391,7 @@ namespace IRaCIS.Core.API.Controllers
/// <returns></returns> /// <returns></returns>
[HttpPost, Route("Inspection/ReadingCriterion/ResetAndAsyncCriterion")] [HttpPost, Route("Inspection/ReadingCriterion/ResetAndAsyncCriterion")]
[UnitOfWork] [UnitOfWork]
[TrialGlobalLimit( "AfterStopCannNotOpt" )] [TrialGlobalLimit("AfterStopCannNotOpt")]
public async Task<IResponseOutput> ResetAndAsyncCriterion(DataInspectionDto<ResetAndAsyncCriterionInDto> opt) public async Task<IResponseOutput> ResetAndAsyncCriterion(DataInspectionDto<ResetAndAsyncCriterionInDto> opt)
{ {
@@ -409,7 +409,7 @@ namespace IRaCIS.Core.API.Controllers
/// <param name="opt"></param> /// <param name="opt"></param>
/// <returns></returns> /// <returns></returns>
[HttpPost, Route("Inspection/QCOperation/CRCRequestToQC")] [HttpPost, Route("Inspection/QCOperation/CRCRequestToQC")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )] [TrialGlobalLimit("AfterStopCannNotOpt")]
[UnitOfWork] [UnitOfWork]
public async Task<IResponseOutput> CRCRequestToQC(DataInspectionDto<CRCRequestToQCCommand> opt) public async Task<IResponseOutput> CRCRequestToQC(DataInspectionDto<CRCRequestToQCCommand> opt)
{ {
@@ -424,21 +424,31 @@ namespace IRaCIS.Core.API.Controllers
/// 设置QC 通过或者不通过 7:QC failed 8QC passed /// 设置QC 通过或者不通过 7:QC failed 8QC passed
/// </summary> /// </summary>
[HttpPost, Route("Inspection/QCOperation/QCPassedOrFailed")] [HttpPost, Route("Inspection/QCOperation/QCPassedOrFailed")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )] [TrialGlobalLimit("AfterStopCannNotOpt")]
[UnitOfWork] [UnitOfWork]
public async Task<IResponseOutput> QCPassedOrFailed(DataInspectionDto<QCPassedOrFailedDto> opt) public async Task<IResponseOutput> QCPassedOrFailed(DataInspectionDto<QCPassedOrFailedDto> opt)
{ {
var singid = await _inspectionService.RecordSing(opt.SignInfo); var singid = await _inspectionService.RecordSing(opt.SignInfo);
var result = await _qCOperationService.QCPassedOrFailed(opt.Data.trialId, opt.Data.subjectVisitId, opt.Data.auditState); if (opt.Data.IsSecondPass != null)
await _inspectionService.CompletedSign(singid, result); {
return result; var result = await _qCOperationService.QCSecondReviewPassedOrFailed(opt.Data.trialId, opt.Data.subjectVisitId, (bool)opt.Data.IsSecondPass);
await _inspectionService.CompletedSign(singid, result);
return result;
}
else
{
var result = await _qCOperationService.QCPassedOrFailed(opt.Data.trialId, opt.Data.subjectVisitId, opt.Data.auditState);
await _inspectionService.CompletedSign(singid, result);
return result;
}
} }
/// <summary> /// <summary>
/// 一致性核查 回退 对话记录不清除 只允许PM回退 /// 一致性核查 回退 对话记录不清除 只允许PM回退
/// </summary> /// </summary>
[HttpPost, Route("Inspection/QCOperation/CheckBack")] [HttpPost, Route("Inspection/QCOperation/CheckBack")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )] [TrialGlobalLimit("AfterStopCannNotOpt")]
[UnitOfWork] [UnitOfWork]
public async Task<IResponseOutput> CheckBack(DataInspectionDto<IDDto> opt) public async Task<IResponseOutput> CheckBack(DataInspectionDto<IDDto> opt)
{ {
@@ -455,7 +465,7 @@ namespace IRaCIS.Core.API.Controllers
/// <param name="opt"></param> /// <param name="opt"></param>
/// <returns></returns> /// <returns></returns>
[HttpPost, Route("Inspection/ReadClinicalData/ReadClinicalDataSign")] [HttpPost, Route("Inspection/ReadClinicalData/ReadClinicalDataSign")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )] [TrialGlobalLimit("AfterStopCannNotOpt")]
[UnitOfWork] [UnitOfWork]
public async Task<IResponseOutput> ReadClinicalDataSign(DataInspectionDto<ReadingClinicalDataSignIndto> opt) public async Task<IResponseOutput> ReadClinicalDataSign(DataInspectionDto<ReadingClinicalDataSignIndto> opt)
{ {
@@ -470,7 +480,7 @@ namespace IRaCIS.Core.API.Controllers
/// CRC 设置已经重传完成 /// CRC 设置已经重传完成
/// </summary> /// </summary>
[HttpPost, Route("Inspection/QCOperation/SetReuploadFinished")] [HttpPost, Route("Inspection/QCOperation/SetReuploadFinished")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )] [TrialGlobalLimit("AfterStopCannNotOpt")]
[UnitOfWork] [UnitOfWork]
public async Task<IResponseOutput> SetReuploadFinished(DataInspectionDto<CRCReuploadFinishedCommand> opt) public async Task<IResponseOutput> SetReuploadFinished(DataInspectionDto<CRCReuploadFinishedCommand> opt)
{ {
@@ -486,7 +496,7 @@ namespace IRaCIS.Core.API.Controllers
/// <param name="opt"></param> /// <param name="opt"></param>
/// <returns></returns> /// <returns></returns>
[HttpPost, Route("Inspection/TrialConfig/updateTrialState")] [HttpPost, Route("Inspection/TrialConfig/updateTrialState")]
[TrialGlobalLimit( "BeforeOngoingCantOpt")] [TrialGlobalLimit("BeforeOngoingCantOpt")]
[UnitOfWork] [UnitOfWork]
public async Task<IResponseOutput> UpdateTrialState(DataInspectionDto<UpdateTrialStateDto> opt) public async Task<IResponseOutput> UpdateTrialState(DataInspectionDto<UpdateTrialStateDto> opt)
{ {
@@ -502,7 +512,7 @@ namespace IRaCIS.Core.API.Controllers
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
[HttpPost, Route("Inspection/TrialDocument/userConfirm")] [HttpPost, Route("Inspection/TrialDocument/userConfirm")]
[TrialGlobalLimit( "BeforeOngoingCantOpt", "SignSystemDocNoTrialId", "AfterStopCannNotOpt" )] [TrialGlobalLimit("BeforeOngoingCantOpt", "SignSystemDocNoTrialId", "AfterStopCannNotOpt")]
[UnitOfWork] [UnitOfWork]
public async Task<IResponseOutput> UserConfirm(DataInspectionDto<UserConfirmCommand> opt) public async Task<IResponseOutput> UserConfirm(DataInspectionDto<UserConfirmCommand> opt)
{ {
@@ -519,10 +529,10 @@ namespace IRaCIS.Core.API.Controllers
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
[HttpPost, Route("Inspection/VisitTask/ConfirmReReading")] [HttpPost, Route("Inspection/VisitTask/ConfirmReReading")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )] [TrialGlobalLimit("AfterStopCannNotOpt")]
[UnitOfWork] [UnitOfWork]
public async Task<IResponseOutput> ConfirmReReading(DataInspectionDto<ConfirmReReadingCommand> opt, [FromServices] IVisitTaskService _visitTaskService) public async Task<IResponseOutput> ConfirmReReading(DataInspectionDto<ConfirmReReadingCommand> opt, [FromServices] IVisitTaskService _visitTaskService)
{ {
var singId = await _inspectionService.RecordSing(opt.SignInfo); var singId = await _inspectionService.RecordSing(opt.SignInfo);
var result = await _visitTaskService.ConfirmReReading(opt.Data); var result = await _visitTaskService.ConfirmReReading(opt.Data);
@@ -53,7 +53,7 @@
<PackageReference Include="MaxMind.GeoIP2" Version="5.2.0" /> <PackageReference Include="MaxMind.GeoIP2" Version="5.2.0" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.10" /> <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.10" />
<PackageReference Include="MimeKit" Version="4.11.0" /> <PackageReference Include="MimeKit" Version="4.11.0" />
<PackageReference Include="MiniExcel" Version="1.40.0" /> <PackageReference Include="MiniExcel" Version="1.41.3" />
<PackageReference Include="Minio" Version="6.0.4" /> <PackageReference Include="Minio" Version="6.0.4" />
<PackageReference Include="MiniWord" Version="0.9.2" /> <PackageReference Include="MiniWord" Version="0.9.2" />
<PackageReference Include="My.Extensions.Localization.Json" Version="3.3.0"> <PackageReference Include="My.Extensions.Localization.Json" Version="3.3.0">
@@ -2586,7 +2586,7 @@ public class VisitTaskService(IRepository<VisitTask> _visitTaskRepository,
sv.CurrentActionUserId = null; sv.CurrentActionUserId = null;
sv.PreliminaryAuditUserId = null; sv.PreliminaryAuditUserId = null;
sv.ReviewAuditUserId = null; sv.ReviewAuditUserId = null;
sv.SecondReviewState = SecondReviewState.None;
if (sv.IsBaseLine) if (sv.IsBaseLine)
{ {
@@ -81,7 +81,7 @@ namespace IRaCIS.Core.Application.Contracts.Dicom.DTO
public bool IsReading { get; set; } public bool IsReading { get; set; }
public bool IsDeleted { get; set; } public bool IsDeleted { get; set; }
public long? FileSize { get; set; }
public Guid? StudyId { get; set; } public Guid? StudyId { get; set; }
@@ -107,8 +107,13 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc.DTO
public string Modalities { get; set; } public string Modalities { get; set; }
public string Description { get; set; } public string Description { get; set; }
public int SeriesCount { get; set; } public int SeriesCount { get; set; }
public int InstanceCount { get; set; } public int InstanceCount { get; set; }
public int ReadingSeriesCount { get; set; }
public int ReadingInstanceCount { get; set; }
} }
public class NoneDicomStudyBasicInfo public class NoneDicomStudyBasicInfo
@@ -128,6 +133,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc.DTO
public string Description { get; set; } = string.Empty; public string Description { get; set; } = string.Empty;
public int ReadingFileCount { get; set; }
} }
} }
@@ -63,7 +63,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
//subject 随机阅片 或者无序 有上传 才处理任务编号 //subject 随机阅片 或者无序 有上传 才处理任务编号
if (_visitTaskRepository.Any(t => t.SubjectId == subjectId && t.TrialReadingCriterionId == trialReadingCriterionId && if (_visitTaskRepository.Any(t => t.SubjectId == subjectId && t.TrialReadingCriterionId == trialReadingCriterionId &&
(t.TrialReadingCriterion.IsReadingTaskViewInOrder == ReadingOrder.SubjectRandom || (t.TrialReadingCriterion.IsReadingTaskViewInOrder == ReadingOrder.SubjectRandom ||
(t.TrialReadingCriterion.IsReadingTaskViewInOrder == ReadingOrder.Random && t.TrialReadingCriterion.ImageUploadEnum != ReadingImageUpload.None)))) (t.TrialReadingCriterion.IsReadingTaskViewInOrder == ReadingOrder.Random && t.TrialReadingCriterion.ImageDownloadEnum != ReadingImageDownload.None))))
{ {
//找到 非一致性分析,未签名,状态正常的 并且任务名称是TimePoint的 任务 //找到 非一致性分析,未签名,状态正常的 并且任务名称是TimePoint的 任务
var needDealTaskList = await _visitTaskRepository.Where(t => t.SubjectId == subjectId && t.TrialReadingCriterionId == trialReadingCriterionId && t.IsAnalysisCreate == false && t.DoctorUserId == _userInfo.UserRoleId var needDealTaskList = await _visitTaskRepository.Where(t => t.SubjectId == subjectId && t.TrialReadingCriterionId == trialReadingCriterionId && t.IsAnalysisCreate == false && t.DoctorUserId == _userInfo.UserRoleId
@@ -882,6 +882,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
subjectCode = inQuery.SubjectCode; subjectCode = inQuery.SubjectCode;
} }
TaskState? taskState = null;
if (inQuery.VisitTaskId != null) if (inQuery.VisitTaskId != null)
{ {
//考虑到一致性分析,必须要这个编号进行过滤 //考虑到一致性分析,必须要这个编号进行过滤
@@ -892,20 +893,25 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
SubjectCode = t.IsAnalysisCreate ? t.BlindSubjectCode : t.Subject.Code, SubjectCode = t.IsAnalysisCreate ? t.BlindSubjectCode : t.Subject.Code,
SubjectId = t.SubjectId, SubjectId = t.SubjectId,
t.DoctorUserId, t.DoctorUserId,
t.IsAnalysisCreate t.IsAnalysisCreate,
t.TaskState
}).FirstNotNullAsync(); }).FirstNotNullAsync();
subjectId = taskInfo.SubjectId; subjectId = taskInfo.SubjectId;
subjectCode = taskInfo.SubjectCode; subjectCode = taskInfo.SubjectCode;
doctorUserId = (Guid)taskInfo.DoctorUserId!; doctorUserId = (Guid)taskInfo.DoctorUserId!;
isAnalysisCreate = taskInfo.IsAnalysisCreate; isAnalysisCreate = taskInfo.IsAnalysisCreate;
taskState = taskInfo.TaskState;
} }
var query = _visitTaskRepository.Where(t => t.SubjectId == subjectId && t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId var query = _visitTaskRepository.Where(t => t.SubjectId == subjectId && t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId
&& t.SourceSubjectVisitId != null && t.DoctorUserId == doctorUserId) && t.SourceSubjectVisitId != null && t.DoctorUserId == doctorUserId)
//满足 有序,或者随机只看到当前任务的dicom 非dicom检查 //满足 有序,或者随机只看到当前任务的dicom 非dicom检查
.WhereIf(inQuery.VisitTaskId == null, t => t.TaskState == TaskState.Effect)//从待阅列表进入,要筛选出有效的,任务可能重阅了,也要看到该任务的 .WhereIf(inQuery.VisitTaskId == null, t => t.TaskState == TaskState.Effect)//从待阅列表进入,要筛选出有效的,任务可能重阅了,也要看到该任务的
.WhereIf(criterionInfo.IsReadingTaskViewInOrder != ReadingOrder.SubjectRandom && inQuery.VisitTaskId != null, t => t.Id == inQuery.VisitTaskId) .WhereIf(criterionInfo.IsReadingTaskViewInOrder != ReadingOrder.SubjectRandom && inQuery.VisitTaskId != null, t => t.Id == inQuery.VisitTaskId)
.WhereIf(taskState == TaskState.Effect || taskState == TaskState.Freeze, t => t.TaskState == TaskState.Effect)//subject 随机可能当前阅片人有退回任务,此时传递了任务Id,但是要看整个subject得,要只留生效的
.WhereIf(taskState != null && taskState != TaskState.Effect && taskState != TaskState.Freeze, t => t.Id == inQuery.VisitTaskId) //非生效只查当前任务
.ProjectTo<SubjectCRCImageUploadedDto>(_mapper.ConfigurationProvider); .ProjectTo<SubjectCRCImageUploadedDto>(_mapper.ConfigurationProvider);
//这里过滤是否是一致性分析的 //这里过滤是否是一致性分析的
@@ -1006,11 +1012,11 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
u.StudyTime, u.StudyTime,
u.StudyCode, u.StudyCode,
SeriesList = u.SeriesList.Select(z => new SeriesList = u.SeriesList.Where(t => t.IsReading).Select(z => new
{ {
z.Modality, z.Modality,
InstancePathList = z.DicomInstanceList.Select(k => new InstancePathList = z.DicomInstanceList.Where(t => t.IsReading).Select(k => new
{ {
k.Path, k.Path,
k.FileSize k.FileSize
@@ -1021,13 +1027,14 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
NoneDicomStudyList = sv.NoneDicomStudyList.Where(t => isQueryNoneDicom ? inQuery.NoneDicomStudyIdList.Contains(t.Id) : false) NoneDicomStudyList = sv.NoneDicomStudyList.Where(t => isQueryNoneDicom ? inQuery.NoneDicomStudyIdList.Contains(t.Id) : false)
.Where(t => info.IsImageFilter ? ("|" + info.CriterionModalitys + "|").Contains("|" + t.Modality + "|") : true) .Where(t => info.IsImageFilter ? ("|" + info.CriterionModalitys + "|").Contains("|" + t.Modality + "|") : true)
.Where(t => t.IsReading)
.Select(nd => new .Select(nd => new
{ {
nd.Modality, nd.Modality,
nd.StudyCode, nd.StudyCode,
nd.ImageDate, nd.ImageDate,
FileList = nd.NoneDicomFileList.Select(file => new FileList = nd.NoneDicomFileList.Where(t => t.IsReading).Select(file => new
{ {
file.FileName, file.FileName,
file.Path, file.Path,
@@ -1109,7 +1116,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
HtmlPath = k.HtmlPath, HtmlPath = k.HtmlPath,
Path = k.Path, Path = k.Path,
InstanceNumber = k.InstanceNumber, InstanceNumber = k.InstanceNumber,
FileSize=k.FileSize,
}).ToList() }).ToList()
}) })
}); });
@@ -4,7 +4,7 @@ namespace IRaCIS.Core.Application.Contracts
{ {
public interface IStudyService public interface IStudyService
{ {
IResponseOutput<List<RelationStudyDTO>> GetAllRelationStudyList(Guid subjectVisitId); IResponseOutput<List<RelationStudyDTO>> GetAllRelationStudyList(Guid subjectVisitId,bool? isReading);
Task<PageOutput<UnionStudyViewModel>> GetDicomAndNoneDicomStudyList(StudyQuery studyQuery); Task<PageOutput<UnionStudyViewModel>> GetDicomAndNoneDicomStudyList(StudyQuery studyQuery);
Task<PageOutput<UnionStudyMonitorModel>> GetDicomAndNoneDicomStudyMonitorList(StudyQuery studyQuery); Task<PageOutput<UnionStudyMonitorModel>> GetDicomAndNoneDicomStudyMonitorList(StudyQuery studyQuery);
(List<string> SeriesInstanceUid, List<string> SopInstanceUid) GetHasUploadSeriesAndInstance(Guid studyId); (List<string> SeriesInstanceUid, List<string> SopInstanceUid) GetHasUploadSeriesAndInstance(Guid studyId);
@@ -1,5 +1,6 @@
using IRaCIS.Core.Application.Contracts.Dicom.DTO; using IRaCIS.Core.Application.Contracts.Dicom.DTO;
using IRaCIS.Core.Application.Helper; using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Infrastructure.Extention;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
@@ -19,8 +20,9 @@ namespace IRaCIS.Core.Application.Services
//医生读片那一块有耦合,关键序列 这里暂时留存 //医生读片那一块有耦合,关键序列 这里暂时留存
/// <summary> 指定资源Id,获取Dicom检查所属序列信息列表 </summary> /// <summary> 指定资源Id,获取Dicom检查所属序列信息列表 </summary>
/// <param name="studyId"> Dicom检查的Id </param> /// <param name="studyId"> Dicom检查的Id </param>
/// <param name="isReading"></param>
[HttpGet, Route("{studyId:guid}")] [HttpGet, Route("{studyId:guid}")]
public async Task<IResponseOutput<List<DicomSeriesDTO>>> List(Guid studyId) public async Task<IResponseOutput<List<DicomSeriesDTO>>> List(Guid studyId, bool? isReading)
{ {
//质控的时候,要标记序列,和instance 删除 ,所以要返回全部,但是 质控通过后,pm 进去看的时候要看过滤后的 //质控的时候,要标记序列,和instance 删除 ,所以要返回全部,但是 质控通过后,pm 进去看的时候要看过滤后的
@@ -32,14 +34,16 @@ namespace IRaCIS.Core.Application.Services
//断点 //断点
var seriesList = await _seriesRepository.Where(s => s.StudyId == studyId).IgnoreQueryFilters() var seriesList = await _seriesRepository.Where(s => s.StudyId == studyId).IgnoreQueryFilters()
.WhereIf(isQCFinished, t => t.IsDeleted == false) .WhereIf(isQCFinished, t => t.IsDeleted == false)
.WhereIf(isReading == true, t => t.IsReading == true)
.OrderBy(s => s.SeriesNumber).ThenBy(s => s.SeriesTime).ThenBy(s => s.CreateTime) .OrderBy(s => s.SeriesNumber).ThenBy(s => s.SeriesTime).ThenBy(s => s.CreateTime)
.ProjectTo<DicomSeriesDTO>(_mapper.ConfigurationProvider).ToListAsync(); .ProjectTo<DicomSeriesDTO>(_mapper.ConfigurationProvider).ToListAsync();
var instanceList = await _instanceRepository.Where(s => s.StudyId == studyId).IgnoreQueryFilters() var instanceList = await _instanceRepository.Where(s => s.StudyId == studyId).IgnoreQueryFilters()
.WhereIf(isQCFinished, t => t.IsDeleted == false) .WhereIf(isQCFinished, t => t.IsDeleted == false)
.WhereIf(isReading == true, t => t.IsReading == true)
.OrderBy(t => t.SeriesId).ThenBy(t => t.InstanceNumber) .OrderBy(t => t.SeriesId).ThenBy(t => t.InstanceNumber)
.ThenBy(s => s.InstanceTime).ThenBy(s => s.CreateTime) .ThenBy(s => s.InstanceTime).ThenBy(s => s.CreateTime)
.Select(t => new { t.SeriesId, t.Id, t.Path, t.NumberOfFrames, t.InstanceNumber, t.HtmlPath, t.IsReading, t.IsDeleted }).ToListAsync();//.GroupBy(u => u.SeriesId); .Select(t => new { t.SeriesId, t.Id, t.Path, t.NumberOfFrames, t.InstanceNumber, t.HtmlPath, t.IsReading, t.IsDeleted, t.FileSize }).ToListAsync();//.GroupBy(u => u.SeriesId);
foreach (var series in seriesList) foreach (var series in seriesList)
@@ -54,7 +58,8 @@ namespace IRaCIS.Core.Application.Services
Path = k.Path, Path = k.Path,
InstanceNumber = k.InstanceNumber, InstanceNumber = k.InstanceNumber,
IsReading = k.IsReading, IsReading = k.IsReading,
IsDeleted = k.IsDeleted IsDeleted = k.IsDeleted,
FileSize = k.FileSize
}).ToList(); }).ToList();
@@ -579,7 +579,7 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
/// <returns></returns> /// <returns></returns>
[HttpGet("{subjectVisitId:guid}")] [HttpGet("{subjectVisitId:guid}")]
[AllowAnonymous] [AllowAnonymous]
public IResponseOutput<List<RelationStudyDTO>> GetAllRelationStudyList(Guid subjectVisitId) public IResponseOutput<List<RelationStudyDTO>> GetAllRelationStudyList(Guid subjectVisitId,bool? isReading)
{ {
#region #region
//var studylist = _studyRepository.Where(u => u.SubjectVisitId == subjectVisitId && u.IsDeleted == false).Select(t => new { StudyId = t.Id, t.SubjectId, t.TrialId }).ToList(); //var studylist = _studyRepository.Where(u => u.SubjectVisitId == subjectVisitId && u.IsDeleted == false).Select(t => new { StudyId = t.Id, t.SubjectId, t.TrialId }).ToList();
@@ -607,10 +607,18 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
var studyInfo = _dicomStudyRepository.Where(u => u.SubjectVisitId == subjectVisitId).Select(t => new { t.SubjectId, t.TrialId }).FirstOrDefault().IfNullThrowException(); var studyInfo = _dicomStudyRepository.Where(u => u.SubjectVisitId == subjectVisitId).Select(t => new { t.SubjectId, t.TrialId }).FirstOrDefault().IfNullThrowException();
var query = _dicomStudyRepository.Where(t => t.SubjectVisitId != subjectVisitId && t.TrialId == studyInfo.TrialId && t.SubjectId == studyInfo.SubjectId) var list = _dicomStudyRepository.Where(t => t.SubjectVisitId != subjectVisitId && t.TrialId == studyInfo.TrialId && t.SubjectId == studyInfo.SubjectId)
.ProjectTo<RelationStudyDTO>(_mapper.ConfigurationProvider).ToList(); .Select(t=> new RelationStudyDTO()
{
StudyId = t.Id,
StudyCode = t.StudyCode,
VisitName = t.SubjectVisit.VisitName,
Modalities = t.Modalities,
Description = t.Description,
SeriesCount = t.SeriesList.Where(t=> isReading==true? t.IsReading==true:true).Count()
}) .ToList();
var list = query.OrderBy(u => u.VisitName).ThenBy(s => s.StudyCode).ToList(); list = list.Where(t=>t.SeriesCount>0).OrderBy(u => u.VisitName).ThenBy(s => s.StudyCode).ToList();
return ResponseOutput.Ok(list); return ResponseOutput.Ok(list);
} }
@@ -130,16 +130,20 @@ namespace IRaCIS.Core.Application.Service
.ForMember(d => d.CriterionModalitys, u => u.MapFrom(s => s.TrialReadingCriterion.CriterionModalitys)) .ForMember(d => d.CriterionModalitys, u => u.MapFrom(s => s.TrialReadingCriterion.CriterionModalitys))
.ForMember(d => d.SubjectCode, u => u.MapFrom(u => u.IsAnalysisCreate == true ? u.BlindSubjectCode : u.Subject.Code)); .ForMember(d => d.SubjectCode, u => u.MapFrom(u => u.IsAnalysisCreate == true ? u.BlindSubjectCode : u.Subject.Code));
CreateMap<DicomStudy, DicomStudyBasicInfo>(); CreateMap<DicomStudy, DicomStudyBasicInfo>()
CreateMap<NoneDicomStudy, NoneDicomStudyBasicInfo>(); .ForMember(d => d.ReadingSeriesCount, u => u.MapFrom(s => s.SeriesList.Where(t => t.IsReading).Count()))
.ForMember(d => d.ReadingInstanceCount, u => u.MapFrom(s => s.InstanceList.Where(t => t.IsReading && t.DicomSerie.IsReading).Count()));
CreateMap<NoneDicomStudy, NoneDicomStudyBasicInfo>()
.ForMember(d => d.ReadingFileCount, u => u.MapFrom(s => s.NoneDicomFileList.Where(t => t.IsReading).Count()));
CreateMap<VisitTask, SubjectCRCImageUploadedDto>() CreateMap<VisitTask, SubjectCRCImageUploadedDto>()
.ForMember(d => d.VisitTaskId, u => u.MapFrom(s => s.Id)) .ForMember(d => d.VisitTaskId, u => u.MapFrom(s => s.Id))
.ForMember(d => d.IsImageFilter, u => u.MapFrom(s => s.TrialReadingCriterion.IsImageFilter)) .ForMember(d => d.IsImageFilter, u => u.MapFrom(s => s.TrialReadingCriterion.IsImageFilter))
.ForMember(d => d.CriterionModalitys, u => u.MapFrom(s => s.TrialReadingCriterion.CriterionModalitys)) .ForMember(d => d.CriterionModalitys, u => u.MapFrom(s => s.TrialReadingCriterion.CriterionModalitys))
.ForMember(d => d.SubjectCode, u => u.MapFrom(u => u.IsAnalysisCreate == true ? u.BlindSubjectCode : u.Subject.Code)) .ForMember(d => d.SubjectCode, u => u.MapFrom(u => u.IsAnalysisCreate == true ? u.BlindSubjectCode : u.Subject.Code))
.ForMember(d => d.DicomStudyList, u => u.MapFrom(s => s.SourceSubjectVisit.StudyList)) .ForMember(d => d.DicomStudyList, u => u.MapFrom(s => s.SourceSubjectVisit.StudyList))
.ForMember(d => d.NoneDicomStudyList, u => u.MapFrom(s => s.SourceSubjectVisit.NoneDicomStudyList)) .ForMember(d => d.NoneDicomStudyList, u => u.MapFrom(s => s.SourceSubjectVisit.NoneDicomStudyList.Where(t => t.IsReading)));
;
CreateMap<TrialImageDownload, TrialImageDownloadView>() CreateMap<TrialImageDownload, TrialImageDownloadView>()
.ForMember(d => d.UserFullName, u => u.MapFrom(s => s.CreateUserRole.FullName)) .ForMember(d => d.UserFullName, u => u.MapFrom(s => s.CreateUserRole.FullName))
@@ -199,6 +199,8 @@ namespace IRaCIS.Core.Application.Service.Inspection.DTO
public Guid subjectVisitId { get; set; } public Guid subjectVisitId { get; set; }
public AuditStateEnum auditState { get; set; } public AuditStateEnum auditState { get; set; }
public bool? IsSecondPass { get; set; }
} }
public class SetSeriesStateDto public class SetSeriesStateDto
@@ -251,7 +251,13 @@ namespace IRaCIS.Core.Application.Contracts.DTO
} }
public class SecondReviewDto
{
public DateTime? SecondReviewTime { get; set; }
public string FullName { get; set; }
public string UserName { get; set; }
public DateTime? SignTime { get; set; }
}
public class TrialVisitQADTO public class TrialVisitQADTO
@@ -270,6 +276,7 @@ namespace IRaCIS.Core.Application.Contracts.DTO
public QARelationInfo RelationInfo { get; set; } = new QARelationInfo(); public QARelationInfo RelationInfo { get; set; } = new QARelationInfo();
public List<SecondReviewDto> SecondReviewList { get; set; }
} }
@@ -203,6 +203,8 @@ namespace IRaCIS.Core.Application.Contracts
public bool IsShowStudyName { get; set; } = false; public bool IsShowStudyName { get; set; } = false;
public bool IsQCQuestionConfirmed { get; set; }
} }
@@ -1949,6 +1951,7 @@ namespace IRaCIS.Core.Application.Contracts
public class QCQuestionAnswer public class QCQuestionAnswer
{ {
public Guid? AnswerId { get; set; }
public Guid Id { get; set; } public Guid Id { get; set; }
public string QuestionName { get; set; } = String.Empty; public string QuestionName { get; set; } = String.Empty;
public bool IsRequired { get; set; } public bool IsRequired { get; set; }
@@ -1977,6 +1980,8 @@ namespace IRaCIS.Core.Application.Contracts
// 1代表第一个人QC数据 2 代表第二个人QC数据 // 1代表第一个人QC数据 2 代表第二个人QC数据
public CurrentQC CurrentQCEnum { get; set; } public CurrentQC CurrentQCEnum { get; set; }
public DateTime? SecondReviewTime { get; set; }
} }
public class ForwardQuery : PageInput public class ForwardQuery : PageInput
@@ -2130,6 +2135,8 @@ namespace IRaCIS.Core.Application.Contracts
public class QCVisitBasicListViewModel public class QCVisitBasicListViewModel
{ {
public SecondReviewState SecondReviewState { get; set; }
public bool IsSubjectQuit { get; set; }
public ChallengeStateEnum ChallengeState { get; set; } public ChallengeStateEnum ChallengeState { get; set; }
public bool? IsConfirmedClinicalData { get; set; } public bool? IsConfirmedClinicalData { get; set; }
public bool IsQCConfirmedReupload { get; set; } public bool IsQCConfirmedReupload { get; set; }
@@ -35,6 +35,8 @@ namespace IRaCIS.Core.Application.Contracts
public DateTime UpdateTime { get; set; } public DateTime UpdateTime { get; set; }
public Guid UpdateUserId { get; set; } public Guid UpdateUserId { get; set; }
public bool IsQuestionQCAuditPassed { get; set; }
} }
public class QCQuestionFilterSelect public class QCQuestionFilterSelect
@@ -13,7 +13,7 @@ namespace IRaCIS.Core.Application.Image.QA
Task<IResponseOutput> QCPassedOrFailed(Guid trialId, Guid subjectVisitId, [FromRoute] AuditStateEnum auditState); Task<IResponseOutput> QCPassedOrFailed(Guid trialId, Guid subjectVisitId, [FromRoute] AuditStateEnum auditState);
Task<IResponseOutput> SetCheckPass(SetCheckPassDt data); Task<IResponseOutput> SetCheckPass(SetCheckPassDt data);
Task<IResponseOutput> QCSecondReviewPassedOrFailed(Guid trialId, Guid subjectVisitId, bool isSecondPass);
Task<IResponseOutput> AddCheckChallengeReply(CheckChallengeDialogCommand checkDialogCommand); Task<IResponseOutput> AddCheckChallengeReply(CheckChallengeDialogCommand checkDialogCommand);
@@ -7,6 +7,8 @@ using IRaCIS.Core.Infrastructure;
using IRaCIS.Core.Infrastructure.Extention; using IRaCIS.Core.Infrastructure.Extention;
using MassTransit.Initializers; using MassTransit.Initializers;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using NPOI.SS.Formula.Functions;
using System.Linq;
namespace IRaCIS.Core.Application.Image.QA namespace IRaCIS.Core.Application.Image.QA
{ {
@@ -24,6 +26,7 @@ namespace IRaCIS.Core.Application.Image.QA
IRepository<NoneDicomStudy> _noneDicomStudyRepository, IRepository<NoneDicomStudy> _noneDicomStudyRepository,
IRepository<QCChallenge> _qcChallengeRepository, IRepository<QCChallenge> _qcChallengeRepository,
IRepository<SubjectVisitImageBackRecord> _subjectVisitImageBackRecordReposiotry, IRepository<SubjectVisitImageBackRecord> _subjectVisitImageBackRecordReposiotry,
IRepository<UserRole> _userRoleReposiotry,
IReadingImageTaskService _IReadingImageTaskService, IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer) : BaseService, IQCListService IReadingImageTaskService _IReadingImageTaskService, IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer) : BaseService, IQCListService
{ {
@@ -409,10 +412,50 @@ namespace IRaCIS.Core.Application.Image.QA
var qacheckList = await GetQCQuestionAnswerList(subjectVisitId, sv.TrialId, trialQCProcess, currentQCType); var qacheckList = await GetQCQuestionAnswerList(subjectVisitId, sv.TrialId, trialQCProcess, currentQCType);
List<SecondReviewDto> secondReviewList = new List<SecondReviewDto>();
if (sv.SecondReviewState != SecondReviewState.None)
{
var trialConfirmTime = _trialRepository.Where(t => t.Id == sv.TrialId).Select(t => t.QCQuestionConfirmedTime).FirstOrDefault();
secondReviewList = (from answer in _trialQCQuestionAnswerRepository.Where(t => t.SubjectVisitId == subjectVisitId && t.CurrentQCEnum == CurrentQC.SecondReview).Where(t => t.SecondReviewTime != null)
join userRole in _userRoleReposiotry.Where() on answer.UpdateUserId equals userRole.Id
select new SecondReviewDto { SecondReviewTime = answer.SecondReviewTime, SignTime = answer.UpdateTime, FullName = userRole.FullName, UserName = userRole.UserName })
.Distinct().ToList();
var secondReviewTimeList = secondReviewList.Select(t => t.SecondReviewTime).Distinct().ToList();
//首次加入
if (!secondReviewTimeList.Contains(trialConfirmTime))
{
secondReviewList.Add(new SecondReviewDto() { SecondReviewTime = trialConfirmTime });
}
else
{
if (sv.SecondReviewState == SecondReviewState.WaitAudit)
{
foreach (var item in secondReviewList)
{
if (item.SecondReviewTime == trialConfirmTime)
{
item.SignTime = null;
item.FullName = "";
item.UserName = "";
}
}
}
}
secondReviewList = secondReviewList.OrderByDescending(t => t.SecondReviewTime).ToList();
}
return new TrialVisitQADTO return new TrialVisitQADTO
{ {
QCQuestionAnswerList = qacheckList, QCQuestionAnswerList = qacheckList,
SecondReviewList = secondReviewList,
IsHaveStudyClinicalData = await _clinicalDataTrialSetRepository.AnyAsync(x => x.IsConfirm && x.TrialId == sv.TrialId && x.ClinicalDataLevel == ClinicalLevel.Study), IsHaveStudyClinicalData = await _clinicalDataTrialSetRepository.AnyAsync(x => x.IsConfirm && x.TrialId == sv.TrialId && x.ClinicalDataLevel == ClinicalLevel.Study),
StudyList = temp.StudyList, StudyList = temp.StudyList,
ExistsManual = (await _IReadingImageTaskService.GetManualList(new GetManualListInDto() { TrialId = sv.TrialId })).Count() > 0, ExistsManual = (await _IReadingImageTaskService.GetManualList(new GetManualListInDto() { TrialId = sv.TrialId })).Count() > 0,
@@ -432,11 +475,53 @@ namespace IRaCIS.Core.Application.Image.QA
[HttpPost] [HttpPost]
public async Task<List<QCQuestionAnswer>> GetQCQuestionAnswer(GetQCQuestionAnswerInDto inDto) public async Task<List<QCQuestionAnswer>> GetQCQuestionAnswer(GetQCQuestionAnswerInDto inDto)
{ {
var questionAnswerlist = await (from data in _trialQCQuestionRepository.Where(x => x.TrialId == inDto.TrialId && x.IsEnable) var subjectVisitId = inDto.SubjectVisitId;
join answer in _trialQCQuestionAnswerRepository.Where(x => x.SubjectVisitId == inDto.SubjectVisitId && x.QCProcessEnum == inDto.QCProcessEnum && x.CurrentQCEnum == inDto.CurrentQCEnum).AsQueryable() on data.Id equals answer.TrialQCQuestionConfigureId into answertemp
List<QCQuestionAnswer> questionAnswerlist = new List<QCQuestionAnswer>();
//判断当前访视质控是否完成,再判断复审是完成查看,还是添加编辑
var sv = await _subjectVisitRepository.Where(t => t.Id == subjectVisitId).FirstNotNullAsync();
var trialConfirmTime = _trialRepository.Where(t => t.Id == sv.TrialId).Select(t => t.QCQuestionConfirmedTime).FirstOrDefault();
var secondReviewTime = inDto.SecondReviewTime != null ? (DateTime)inDto.SecondReviewTime : trialConfirmTime == null ? DateTime.Now : (DateTime)trialConfirmTime;
if ((sv.AuditState == AuditStateEnum.QCPassed && inDto.CurrentQCEnum != CurrentQC.SecondReview) || (inDto.CurrentQCEnum == CurrentQC.SecondReview && secondReviewTime.AddSeconds(1) < trialConfirmTime))
{
//之前质控完的,+二次复核完的,都要从答案表中取 二次复核完的还需要加时间
questionAnswerlist = await _trialQCQuestionAnswerRepository.Where(x => x.SubjectVisitId == inDto.SubjectVisitId && x.QCProcessEnum == inDto.QCProcessEnum && x.CurrentQCEnum == inDto.CurrentQCEnum)
.Where(t => inDto.CurrentQCEnum == CurrentQC.SecondReview ? t.SecondReviewTime >= secondReviewTime && t.SecondReviewTime <= secondReviewTime.AddSeconds(1) : true)
.Select(data => new QCQuestionAnswer()
{
AnswerId = data.Id,
Answer = data.Answer,
ShowOrder = data.TrialQCQuestionConfigure.ShowOrder,
QuestionName = data.TrialQCQuestionConfigure.QuestionName,
Id = data.TrialQCQuestionConfigure.Id,
IsRequired = data.TrialQCQuestionConfigure.IsRequired,
ParentId = data.TrialQCQuestionConfigure.ParentId,
ParentTriggerValue = data.TrialQCQuestionConfigure.ParentTriggerValue,
Type = data.TrialQCQuestionConfigure.Type,
TypeValue = data.TrialQCQuestionConfigure.TypeValue
}).OrderBy(t => t.ShowOrder).ToListAsync();
}
else
{
#region
questionAnswerlist = await (from data in _trialQCQuestionRepository.Where(x => x.TrialId == inDto.TrialId && x.IsEnable)
join answer in _trialQCQuestionAnswerRepository.Where(x => x.SubjectVisitId == inDto.SubjectVisitId && x.QCProcessEnum == inDto.QCProcessEnum && x.CurrentQCEnum == inDto.CurrentQCEnum)
.Where(t => inDto.CurrentQCEnum == CurrentQC.SecondReview ? t.SecondReviewTime >= secondReviewTime && t.SecondReviewTime <= secondReviewTime.AddSeconds(1) : true)
on data.Id equals answer.TrialQCQuestionConfigureId into answertemp
from leftanswer in answertemp.DefaultIfEmpty() from leftanswer in answertemp.DefaultIfEmpty()
select new QCQuestionAnswer() select new QCQuestionAnswer()
{ {
AnswerId = leftanswer.Id,
Answer = leftanswer.Answer, Answer = leftanswer.Answer,
ShowOrder = data.ShowOrder, ShowOrder = data.ShowOrder,
QuestionName = data.QuestionName, QuestionName = data.QuestionName,
@@ -447,6 +532,17 @@ namespace IRaCIS.Core.Application.Image.QA
Type = data.Type, Type = data.Type,
TypeValue = data.TypeValue TypeValue = data.TypeValue
}).OrderBy(t => t.ShowOrder).ToListAsync(); }).OrderBy(t => t.ShowOrder).ToListAsync();
#endregion
}
var result = questionAnswerlist.Where(x => x.ParentId == null).OrderBy(t => t.ShowOrder).ToList(); var result = questionAnswerlist.Where(x => x.ParentId == null).OrderBy(t => t.ShowOrder).ToList();
result.ForEach(x => result.ForEach(x =>
@@ -384,6 +384,7 @@ namespace IRaCIS.Core.Application.Image.QA
sv.CurrentActionUserId = null; sv.CurrentActionUserId = null;
sv.PreliminaryAuditUserId = null; sv.PreliminaryAuditUserId = null;
sv.ReviewAuditUserId = null; sv.ReviewAuditUserId = null;
sv.SecondReviewState = SecondReviewState.None;
if (sv.IsBaseLine) if (sv.IsBaseLine)
@@ -691,6 +692,7 @@ namespace IRaCIS.Core.Application.Image.QA
sv.CurrentActionUserId = null; sv.CurrentActionUserId = null;
sv.PreliminaryAuditUserId = null; sv.PreliminaryAuditUserId = null;
sv.ReviewAuditUserId = null; sv.ReviewAuditUserId = null;
sv.SecondReviewState = SecondReviewState.None;
//var success1 = _studyRepository.Delete(t => t.SubjectVisitId == subjectVisitId); //var success1 = _studyRepository.Delete(t => t.SubjectVisitId == subjectVisitId);
//var succeess2 = _instanceRepository.Delete(t => t.SubjectVisitId == subjectVisitId); //var succeess2 = _instanceRepository.Delete(t => t.SubjectVisitId == subjectVisitId);
@@ -727,9 +729,17 @@ namespace IRaCIS.Core.Application.Image.QA
//[Authorize(Policy = IRaCISPolicy.IQC)] //[Authorize(Policy = IRaCISPolicy.IQC)]
public async Task<IResponseOutput> AddOrUpdateQCQuestionAnswerList(QCQuestionAnswerCommand[] qcQuestionAnswerCommands, Guid trialId, Guid subjectVisitId, [FromRoute] TrialQCProcess trialQCProcess, [FromRoute] CurrentQC currentQCType) public async Task<IResponseOutput> AddOrUpdateQCQuestionAnswerList(QCQuestionAnswerCommand[] qcQuestionAnswerCommands, Guid trialId, Guid subjectVisitId, [FromRoute] TrialQCProcess trialQCProcess, [FromRoute] CurrentQC currentQCType)
{ {
if (currentQCType == CurrentQC.SecondReview)
{
//二次复核自动领取,如果有人先领取了,那么后续不能操作
await _subjectVisitRepository.UpdatePartialFromQueryAsync(t => t.Id == subjectVisitId && t.CurrentActionUserId == null, u => new SubjectVisit() { CurrentActionUserId = _userInfo.UserRoleId, IsTake = true }, true);
}
//验证是否能操作 //验证是否能操作
await VerifyIsCanQCAsync(null, subjectVisitId); await VerifyIsCanQCAsync(null, subjectVisitId);
var trialConfirmTime = _trialRepository.Where(t => t.Id == trialId).Select(t => t.QCQuestionConfirmedTime).FirstOrDefault();
//更新 //更新
if (qcQuestionAnswerCommands.Any(t => t.Id != null)) if (qcQuestionAnswerCommands.Any(t => t.Id != null))
{ {
@@ -774,11 +784,13 @@ namespace IRaCIS.Core.Application.Image.QA
{ {
var addlist = _mapper.Map<List<TrialQCQuestionAnswer>>(qcQuestionAnswerCommands); var addlist = _mapper.Map<List<TrialQCQuestionAnswer>>(qcQuestionAnswerCommands);
addlist.ForEach(t => { t.TrialId = trialId; t.SubjectVisitId = subjectVisitId; t.CurrentQCEnum = currentQCType; t.QCProcessEnum = trialQCProcess; });
addlist.ForEach(t => { t.TrialId = trialId; t.SubjectVisitId = subjectVisitId; t.CurrentQCEnum = currentQCType; t.QCProcessEnum = trialQCProcess; t.SecondReviewTime = currentQCType == CurrentQC.SecondReview ? trialConfirmTime : null; });
await _trialQCQuestionAnswerRepository.AddRangeAsync(addlist); await _trialQCQuestionAnswerRepository.AddRangeAsync(addlist);
return ResponseOutput.Result(await _trialQCQuestionAnswerRepository.SaveChangesAsync()); return ResponseOutput.Ok(await _trialQCQuestionAnswerRepository.SaveChangesAsync());
} }
@@ -961,6 +973,9 @@ namespace IRaCIS.Core.Application.Image.QA
var noneDicomStudyFile = (await _noneDicomStudyFileRepository.Where(t => t.Id == noneDicomStudyFileId, true).IgnoreQueryFilters().FirstOrDefaultAsync()).IfNullThrowException(); var noneDicomStudyFile = (await _noneDicomStudyFileRepository.Where(t => t.Id == noneDicomStudyFileId, true).IgnoreQueryFilters().FirstOrDefaultAsync()).IfNullThrowException();
var noneDicomStudy = (await _noneDicomStudyRepository.Where(t => t.Id == noneDicomStudyFile.NoneDicomStudyId, true).IgnoreQueryFilters().FirstOrDefaultAsync()).IfNullThrowException();
if (state == 1) if (state == 1)
{ {
noneDicomStudyFile.IsReading = false; noneDicomStudyFile.IsReading = false;
@@ -972,10 +987,15 @@ namespace IRaCIS.Core.Application.Image.QA
else if (state == 4) else if (state == 4)
{ {
noneDicomStudyFile.IsDeleted = true; noneDicomStudyFile.IsDeleted = true;
noneDicomStudy.FileCount = noneDicomStudy.FileCount - 1;
} }
else if (state == 5) else if (state == 5)
{ {
noneDicomStudyFile.IsDeleted = false; noneDicomStudyFile.IsDeleted = false;
noneDicomStudy.FileCount = noneDicomStudy.FileCount + 1;
} }
} }
@@ -1165,10 +1185,12 @@ namespace IRaCIS.Core.Application.Image.QA
[HttpPut("{trialId:guid}/{subjectVisitId:guid}")] [HttpPut("{trialId:guid}/{subjectVisitId:guid}")]
//[Authorize(Policy = IRaCISPolicy.IQC)] //[Authorize(Policy = IRaCISPolicy.IQC)]
[TrialGlobalLimit("AfterStopCannNotOpt")] [TrialGlobalLimit("AfterStopCannNotOpt")]
public async Task<IResponseOutput> ReplaceQCTaskActionUser(Guid trialId, Guid subjectVisitId) public async Task<IResponseOutput> ReplaceQCTaskActionUser(Guid trialId, Guid subjectVisitId, Guid? replaceUserRoleId)
{ {
var dbSubjectVisit = (await _subjectVisitRepository.FirstOrDefaultAsync(t => t.Id == subjectVisitId)).IfNullThrowException(); var dbSubjectVisit = (await _subjectVisitRepository.FirstOrDefaultAsync(t => t.Id == subjectVisitId)).IfNullThrowException();
//await VerifyIsCanQCAsync(dbSubjectVisit);
if (dbSubjectVisit.CurrentActionUserId == null && dbSubjectVisit.IsTake == false) if (dbSubjectVisit.CurrentActionUserId == null && dbSubjectVisit.IsTake == false)
{ {
@@ -1179,7 +1201,7 @@ namespace IRaCIS.Core.Application.Image.QA
dbSubjectVisit.IsTake = true; dbSubjectVisit.IsTake = true;
dbSubjectVisit.CurrentActionUserId = _userInfo.UserRoleId; dbSubjectVisit.CurrentActionUserId = replaceUserRoleId == null || replaceUserRoleId == Guid.Empty ? _userInfo.UserRoleId : replaceUserRoleId;
dbSubjectVisit.CurrentActionUserExpireTime = DateTime.Now.AddHours(1); dbSubjectVisit.CurrentActionUserExpireTime = DateTime.Now.AddHours(1);
@@ -1347,6 +1369,12 @@ namespace IRaCIS.Core.Application.Image.QA
if (obtaionOrCancel) if (obtaionOrCancel)
{ {
//复核的时候,指派后,另外一个人进来的时候如果是自己,那么不进行后续流程
if (dbSubjectVisit.CurrentActionUserId == _userInfo.UserRoleId)
{
return ResponseOutput.Ok();
}
if (dbSubjectVisit.CurrentActionUserId != null && dbSubjectVisit.IsTake) if (dbSubjectVisit.CurrentActionUserId != null && dbSubjectVisit.IsTake)
{ {
//throw new BusinessValidationFailedException("当前访视已被领取,不允许领取"); //throw new BusinessValidationFailedException("当前访视已被领取,不允许领取");
@@ -1378,65 +1406,69 @@ namespace IRaCIS.Core.Application.Image.QA
// return ResponseOutput.NotOk("您已经领取了其他受试者,完成后才允许领取新的受试者"); // return ResponseOutput.NotOk("您已经领取了其他受试者,完成后才允许领取新的受试者");
//} //}
#region if (dbSubjectVisit.SecondReviewState == SecondReviewState.None)
if (trialConfig.QCProcessEnum == TrialQCProcess.NotAudit)
{ {
//---项目配置为不审,没有领取QC Task #region
return ResponseOutput.NotOk(_localizer["QCOperation_NoQC"]);
} if (trialConfig.QCProcessEnum == TrialQCProcess.NotAudit)
else if (trialConfig.QCProcessEnum == TrialQCProcess.SingleAudit)
{
if (dbSubjectVisit.PreliminaryAuditUserId == _userInfo.UserRoleId)
{ {
//---初审已通过,不能继续领取 //---项目配置为不审,没有领取QC Task
return ResponseOutput.NotOk(_localizer["QCOperation_InitialAuditPassed"]); return ResponseOutput.NotOk(_localizer["QCOperation_NoQC"]);
}
else if (trialConfig.QCProcessEnum == TrialQCProcess.SingleAudit)
{
if (dbSubjectVisit.PreliminaryAuditUserId == _userInfo.UserRoleId)
{
//---初审已通过,不能继续领取
return ResponseOutput.NotOk(_localizer["QCOperation_InitialAuditPassed"]);
}
if (dbSubjectVisit.SubmitState == SubmitStateEnum.Submitted && dbSubjectVisit.AuditState == AuditStateEnum.ToAudit)
{
dbSubjectVisit.AuditState = AuditStateEnum.InPrimaryQC;
}
if (dbSubjectVisit.SubmitState == SubmitStateEnum.Submitted && dbSubjectVisit.AuditState == AuditStateEnum.InPrimaryQC)
{
//单审QC 释放后 也是可以领取的
}
else
{
// ---项目配置为单审,不满足Submmit State:已提交 或者 Audit State:待审核/审核中, 不允许领取,请刷新界面
return ResponseOutput.NotOk(_localizer["QCOperation_NoSingleAudit"]);
}
}
else if (trialConfig.QCProcessEnum == TrialQCProcess.DoubleAudit)
{
if (dbSubjectVisit.PreliminaryAuditUserId == _userInfo.UserRoleId)
{
//---复审不能和初审是同一个人
return ResponseOutput.NotOk(_localizer["QCOperation_NoSameReviewer"]);
}
//提交 并且初审通过 那么领取后进入 复审中
if (dbSubjectVisit.SubmitState == SubmitStateEnum.Submitted && dbSubjectVisit.AuditState == AuditStateEnum.PrimaryQCPassed)
{
dbSubjectVisit.AuditState = AuditStateEnum.InSecondaryQC;
}
else if (dbSubjectVisit.SubmitState == SubmitStateEnum.Submitted && dbSubjectVisit.AuditState == AuditStateEnum.ToAudit)
{
dbSubjectVisit.AuditState = AuditStateEnum.InPrimaryQC;
}
else if (dbSubjectVisit.SubmitState == SubmitStateEnum.Submitted && (dbSubjectVisit.AuditState == AuditStateEnum.InPrimaryQC || dbSubjectVisit.AuditState == AuditStateEnum.InSecondaryQC))
{
//初审中 复审中 领取也是ok的 其他人接着做
}
else
{
//---项目配置为复审,不满足提交状态:已提交 或者 审核状态:待审核/QC中, 不允许领取,请刷新界面
return ResponseOutput.NotOk(_localizer["QCOperation_NoSecondaryAudit"]);
}
} }
if (dbSubjectVisit.SubmitState == SubmitStateEnum.Submitted && dbSubjectVisit.AuditState == AuditStateEnum.ToAudit) #endregion
{
dbSubjectVisit.AuditState = AuditStateEnum.InPrimaryQC;
}
if (dbSubjectVisit.SubmitState == SubmitStateEnum.Submitted && dbSubjectVisit.AuditState == AuditStateEnum.InPrimaryQC)
{
//单审QC 释放后 也是可以领取的
}
else
{
// ---项目配置为单审,不满足Submmit State:已提交 或者 Audit State:待审核/审核中, 不允许领取,请刷新界面
return ResponseOutput.NotOk(_localizer["QCOperation_NoSingleAudit"]);
}
}
else if (trialConfig.QCProcessEnum == TrialQCProcess.DoubleAudit)
{
if (dbSubjectVisit.PreliminaryAuditUserId == _userInfo.UserRoleId)
{
//---复审不能和初审是同一个人
return ResponseOutput.NotOk(_localizer["QCOperation_NoSameReviewer"]);
}
//提交 并且初审通过 那么领取后进入 复审中
if (dbSubjectVisit.SubmitState == SubmitStateEnum.Submitted && dbSubjectVisit.AuditState == AuditStateEnum.PrimaryQCPassed)
{
dbSubjectVisit.AuditState = AuditStateEnum.InSecondaryQC;
}
else if (dbSubjectVisit.SubmitState == SubmitStateEnum.Submitted && dbSubjectVisit.AuditState == AuditStateEnum.ToAudit)
{
dbSubjectVisit.AuditState = AuditStateEnum.InPrimaryQC;
}
else if (dbSubjectVisit.SubmitState == SubmitStateEnum.Submitted && (dbSubjectVisit.AuditState == AuditStateEnum.InPrimaryQC || dbSubjectVisit.AuditState == AuditStateEnum.InSecondaryQC))
{
//初审中 复审中 领取也是ok的 其他人接着做
}
else
{
//---项目配置为复审,不满足提交状态:已提交 或者 审核状态:待审核/QC中, 不允许领取,请刷新界面
return ResponseOutput.NotOk(_localizer["QCOperation_NoSecondaryAudit"]);
}
} }
#endregion
dbSubjectVisit.IsTake = true; dbSubjectVisit.IsTake = true;
@@ -2069,8 +2101,46 @@ namespace IRaCIS.Core.Application.Image.QA
} }
public async Task<IResponseOutput> QCSecondReviewPassedOrFailed(Guid trialId, Guid subjectVisitId, bool isSecondPass)
{
if (!await _trialUserRoleRepository.AnyAsync(t => t.TrialId == trialId && t.UserId == _userInfo.UserRoleId))
{
//---您已经被移出项目,没有操作权限。
return ResponseOutput.NotOk(_localizer["QCOperation_RemoveItem"]);
}
var sv = await _subjectVisitRepository.FirstOrDefaultAsync(t => t.Id == subjectVisitId);
await VerifyIsCanQCAsync(sv);
var trialConfirmTime = _trialRepository.Where(t => t.Id == sv.TrialId).Select(t => t.QCQuestionConfirmedTime).FirstOrDefault();
if (sv.SecondReviewState == SecondReviewState.WaitAudit)
{
if (isSecondPass)
{
sv.SecondReviewState = SecondReviewState.AuditPassed;
sv.IsTake = false;
sv.CurrentActionUserId = null;
sv.CurrentActionUserExpireTime = null;
}
else
{
sv.SecondReviewState = SecondReviewState.AuditFailed;
}
await _trialQCQuestionAnswerRepository.BatchUpdateNoTrackingAsync(t => t.SubjectVisitId == sv.Id && t.CurrentQCEnum == CurrentQC.SecondReview && t.SecondReviewTime == trialConfirmTime, u => new TrialQCQuestionAnswer()
{
UpdateUserId = _userInfo.UserRoleId,
UpdateTime = DateTime.Now
});
}
await _subjectVisitRepository.SaveChangesAsync();
return ResponseOutput.Ok();
}
/// <summary> /// <summary>
/// 设置、取消 访视紧急 /// 设置、取消 访视紧急
@@ -472,6 +472,7 @@ namespace IRaCIS.Core.Application.Service
CreateMap<TrialQCQuestion, TrialQCQuestionAddOrEdit>(); CreateMap<TrialQCQuestion, TrialQCQuestionAddOrEdit>();
CreateMap<TrialQCQuestion, TrialQCQuestionConfigureView>() CreateMap<TrialQCQuestion, TrialQCQuestionConfigureView>()
.ForMember(d => d.IsQuestionQCAuditPassed, u => u.MapFrom(s => s.TrialQCQuestionAnswerList.Any(c => c.TrialQCQuestionConfigureId == s.Id && c.SubjectVisit.AuditState == AuditStateEnum.QCPassed)))
.ForMember(d => d.ParentShowOrder, u => u.MapFrom(s => s.ParentQCQuestion.ShowOrder)); .ForMember(d => d.ParentShowOrder, u => u.MapFrom(s => s.ParentQCQuestion.ShowOrder));
CreateMap<TrialQCQuestionSelect, TrialQCQuestionConfigureView>(); CreateMap<TrialQCQuestionSelect, TrialQCQuestionConfigureView>();
@@ -139,5 +139,16 @@ namespace IRaCIS.Core.Application.Contracts.DTO
} }
public class TrialSelectUserBasicInfo
{
public Guid UserRoleId { get; set; }
public string FullName { get; set; }
public string UserName { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
}
} }
@@ -6,6 +6,7 @@ using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Application.Interfaces; using IRaCIS.Core.Application.Interfaces;
using IRaCIS.Core.Application.Service.Reading.Dto; using IRaCIS.Core.Application.Service.Reading.Dto;
using IRaCIS.Core.Application.ViewModel; using IRaCIS.Core.Application.ViewModel;
using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infra.EFCore.Common; using IRaCIS.Core.Infra.EFCore.Common;
using IRaCIS.Core.Infrastructure; using IRaCIS.Core.Infrastructure;
@@ -41,6 +42,7 @@ namespace IRaCIS.Core.Application
IRepository<SystemBasicData> _systemBasicDataRepository, IRepository<SystemBasicData> _systemBasicDataRepository,
IRepository<SubjectVisit> _subjectVisitRepository, IRepository<SubjectVisit> _subjectVisitRepository,
IRepository<Enroll> _enrollRepository, IRepository<Enroll> _enrollRepository,
IRepository<TrialQCQuestionAnswer> _qcQuestionAnswerRepository,
IRepository<TrialStateChange> _trialStateChangeRepository, IRepository<TrialStateChange> _trialStateChangeRepository,
IRepository<ReadingTableQuestionTrial> _readingTableQuestionTrialRepository, IRepository<ReadingTableQuestionTrial> _readingTableQuestionTrialRepository,
IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer, IFusionCache _fusionCache) : BaseService, ITrialConfigService IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer, IFusionCache _fusionCache) : BaseService, ITrialConfigService
@@ -562,7 +564,7 @@ namespace IRaCIS.Core.Application
await _readingQuestionCriterionTrialRepository.UpdatePartialFromQueryAsync(inDto.TrialReadingCriterionId, x => new ReadingQuestionCriterionTrial() await _readingQuestionCriterionTrialRepository.UpdatePartialFromQueryAsync(inDto.TrialReadingCriterionId, x => new ReadingQuestionCriterionTrial()
{ {
ReadingToolList=inDto.ReadingToolList, ReadingToolList = inDto.ReadingToolList,
IsImageFilter = inDto.IsImageFilter, IsImageFilter = inDto.IsImageFilter,
ImageDownloadEnum = inDto.ImageDownloadEnum, ImageDownloadEnum = inDto.ImageDownloadEnum,
ImageUploadEnum = inDto.ImageUploadEnum, ImageUploadEnum = inDto.ImageUploadEnum,
@@ -837,9 +839,46 @@ namespace IRaCIS.Core.Application
{ {
await _trialRepository.UpdatePartialFromQueryAsync(t => t.Id == signConfirmDTO.TrialId, u => new Trial() { IsTrialUrgentConfirmed = true }); await _trialRepository.UpdatePartialFromQueryAsync(t => t.Id == signConfirmDTO.TrialId, u => new Trial() { IsTrialUrgentConfirmed = true });
} }
else else if (signConfirmDTO.SignCode == ((int)SignEnum.TrialQCQuestionConfirmUpdate).ToString())
{
var trialConfirmTime = _trialRepository.Where(t => t.Id == signConfirmDTO.TrialId).Select(t => t.QCQuestionConfirmedTime).FirstOrDefault();
if (signConfirmDTO.SignCode == ((int)SignEnum.TrialQCQuestionConfirm).ToString()) if (trialConfirmTime != null)
{
//删除复审中间临时数据
await _qcQuestionAnswerRepository.BatchDeleteNoTrackingAsync(t => t.SubjectVisit.TrialId == signConfirmDTO.TrialId && t.SubjectVisit.SecondReviewState == SecondReviewState.WaitAudit
&& t.CurrentQCEnum == CurrentQC.SecondReview && t.UpdateTime > trialConfirmTime);
}
await _trialRepository.UpdatePartialFromQueryAsync(t => t.Id == signConfirmDTO.TrialId, u => new Trial() { QCQuestionConfirmedTime = null, QCQuestionConfirmedUserId = null, IsQCQuestionConfirmed = false });
}
else if (signConfirmDTO.SignCode == ((int)SignEnum.SecondReviewConfirm).ToString())
{
var trialConfirmTime = _trialRepository.Where(t => t.Id == signConfirmDTO.TrialId).Select(t => t.QCQuestionConfirmedTime).FirstOrDefault();
if (trialConfirmTime != null)
{
//删除复审中间临时数据--没重置,一直点生成复核任务
await _qcQuestionAnswerRepository.BatchDeleteNoTrackingAsync(t => t.SubjectVisit.TrialId == signConfirmDTO.TrialId && t.SubjectVisit.SecondReviewState == SecondReviewState.WaitAudit
&& t.CurrentQCEnum == CurrentQC.SecondReview && t.UpdateTime > trialConfirmTime);
//删除质控中 临时保存的问题答案 (因为添加那里只会新增 和全部更新,如果不处理,那么有新增,也有更新,稽查那里也会有问题)
await _qcQuestionAnswerRepository.BatchDeleteNoTrackingAsync(t => t.SubjectVisit.TrialId == signConfirmDTO.TrialId && t.SubjectVisit.AuditState == AuditStateEnum.InPrimaryQC
&& t.CurrentQCEnum == CurrentQC.First);
await _qcQuestionAnswerRepository.BatchDeleteNoTrackingAsync(t => t.SubjectVisit.TrialId == signConfirmDTO.TrialId && t.SubjectVisit.AuditState == AuditStateEnum.InSecondaryQC
&& t.CurrentQCEnum == CurrentQC.Second);
//重复二次复核签名
await _subjectVisitRepository.UpdatePartialFromQueryAsync(t => t.TrialId == signConfirmDTO.TrialId && t.AuditState == AuditStateEnum.QCPassed
&& !t.TrialQCQuestionAnswerList.Any(t => t.SecondReviewTime == trialConfirmTime), u => new SubjectVisit() { SecondReviewState = SecondReviewState.WaitAudit });
}
}
else if (signConfirmDTO.SignCode == ((int)SignEnum.TrialQCQuestionConfirm).ToString())
{ {
var trialConfig = (await _trialRepository var trialConfig = (await _trialRepository
@@ -879,14 +918,14 @@ namespace IRaCIS.Core.Application
throw new BusinessValidationFailedException(_localizer["TrialConfig_AuditQuestionConfirmed"]); throw new BusinessValidationFailedException(_localizer["TrialConfig_AuditQuestionConfirmed"]);
} }
await _trialQCQuestionRepository.UpdatePartialFromQueryAsync(t => t.TrialId == signConfirmDTO.TrialId, x => new TrialQCQuestion await _trialQCQuestionRepository.BatchUpdateNoTrackingAsync(t => t.TrialId == signConfirmDTO.TrialId, x => new TrialQCQuestion
{ {
IsConfirm = true IsConfirm = true
}); });
await _trialRepository.UpdatePartialFromQueryAsync(t => t.Id == signConfirmDTO.TrialId, u => new Trial() { QCQuestionConfirmedTime = DateTime.Now, QCQuestionConfirmedUserId = _userInfo.UserRoleId, IsQCQuestionConfirmed = true }); await _trialRepository.UpdatePartialFromQueryAsync(t => t.Id == signConfirmDTO.TrialId, u => new Trial() { QCQuestionConfirmedTime = DateTime.Now, QCQuestionConfirmedUserId = _userInfo.UserRoleId, IsQCQuestionConfirmed = true });
await _trialRepository.SaveChangesAsync();
} }
await _trialRepository.SaveChangesAsync();
return ResponseOutput.Ok(); return ResponseOutput.Ok();
@@ -1311,7 +1350,7 @@ namespace IRaCIS.Core.Application
/// <returns></returns> /// <returns></returns>
public async Task<IResponseOutput<List<TrialBodyPartView>>> GetTrialBodyPartList(Guid trialId) public async Task<IResponseOutput<List<TrialBodyPartView>>> GetTrialBodyPartList(Guid trialId)
{ {
var list = await _trialRepository.Where(t => t.Id == trialId).SelectMany(t => t.TrialBodyPartList).Select(t => new TrialBodyPartView() { Code = t.Code, Name = _userInfo.IsEn_Us ? t.Name : t.NameCN, Id = t.Id, IsHandAdd = t.IsHandAdd }).OrderBy(t=>t.Name).ToListAsync(); var list = await _trialRepository.Where(t => t.Id == trialId).SelectMany(t => t.TrialBodyPartList).Select(t => new TrialBodyPartView() { Code = t.Code, Name = _userInfo.IsEn_Us ? t.Name : t.NameCN, Id = t.Id, IsHandAdd = t.IsHandAdd }).OrderBy(t => t.Name).ToListAsync();
return ResponseOutput.Ok(list); return ResponseOutput.Ok(list);
} }
@@ -1394,7 +1433,7 @@ namespace IRaCIS.Core.Application
[HttpPost] [HttpPost]
public async Task<IResponseOutput> UpdateTrialStudyNameList(UpdateTrialStudyNameListInDto inDto) public async Task<IResponseOutput> UpdateTrialStudyNameList(UpdateTrialStudyNameListInDto inDto)
{ {
var trial = await _trialRepository.FirstOrDefaultAsync(x => x.Id == inDto.TrialId); var trial = await _trialRepository.FirstOrDefaultAsync(x => x.Id == inDto.TrialId);
@@ -6,9 +6,11 @@ using IRaCIS.Core.Application.Contracts.DTO;
using IRaCIS.Core.Application.Filter; using IRaCIS.Core.Application.Filter;
using IRaCIS.Core.Domain.Models; using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infrastructure.Extention;
using MassTransit.Serialization; using MassTransit.Serialization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore.Storage.Json; using Microsoft.EntityFrameworkCore.Storage.Json;
using NPOI.SS.Formula.Functions;
using System; using System;
namespace IRaCIS.Core.Application.Service namespace IRaCIS.Core.Application.Service
@@ -56,8 +58,8 @@ namespace IRaCIS.Core.Application.Service
IsDeleted = t.IsDeleted, IsDeleted = t.IsDeleted,
UserTypeId = t.UserRole.UserTypeRole.Id, UserTypeId = t.UserRole.UserTypeRole.Id,
UserTypeShortName = t.UserRole.UserTypeRole.UserTypeShortName, UserTypeShortName = t.UserRole.UserTypeRole.UserTypeShortName,
CreateTime=t.CreateTime, CreateTime = t.CreateTime,
UpdateTime=t.UpdateTime, UpdateTime = t.UpdateTime,
}).ToList(), }).ToList(),
}).ToPagedListAsync(inQuery); }).ToPagedListAsync(inQuery);
@@ -315,7 +317,29 @@ namespace IRaCIS.Core.Application.Service
} }
public async Task<List<TrialSelectUserBasicInfo>> GetTrialUserRoleList(Guid trialId, Guid? subjectVisitId, UserTypeEnum? userTypeEnum)
{
var isSeconReview = await _subjectVisitRepository.Where(t => t.Id == subjectVisitId).AnyAsync(t => t.SecondReviewState == SecondReviewState.WaitAudit);
//复审指派需要过滤初审的人
var firstUserId = await _subjectVisitRepository.Where(t => t.Id == subjectVisitId).Select(t => t.PreliminaryAuditUserId).FirstOrDefaultAsync();
var list = await _trialIdentityUserRepository.Where(t => t.TrialId == trialId)
.SelectMany(t => t.TrialUserRoleList)
.WhereIf(userTypeEnum != null, t => t.UserRole.UserTypeEnum == userTypeEnum)
.Where(t => t.UserRole.Id != _userInfo.UserRoleId)//iQC 指派过滤自己
.WhereIf(firstUserId != null && isSeconReview == false, t => t.UserRole.Id != firstUserId)//iQC 过滤初审的人,复核不过滤
.Select(t => new TrialSelectUserBasicInfo()
{
FullName = t.TrialUser.IdentityUser.FullName,
UserRoleId = t.UserRole.Id,
UserName = t.TrialUser.IdentityUser.UserName,
Phone = t.TrialUser.IdentityUser.Phone,
Email = t.TrialUser.IdentityUser.EMail
})
.ToListAsync();
return list;
}
} }
} }
@@ -42,7 +42,7 @@ namespace IRaCIS.Core.Application.Service
var instanceList = await _instanceRepository.Where(s => s.StudyId == scpStudyId).OrderBy(t => t.SeriesId).ThenBy(t => t.InstanceNumber) var instanceList = await _instanceRepository.Where(s => s.StudyId == scpStudyId).OrderBy(t => t.SeriesId).ThenBy(t => t.InstanceNumber)
.ThenBy(s => s.InstanceTime).ThenBy(s => s.CreateTime) .ThenBy(s => s.InstanceTime).ThenBy(s => s.CreateTime)
.Select(t => new { t.SeriesId, t.Id, t.Path, t.NumberOfFrames, t.InstanceNumber }).ToListAsync();//.GroupBy(u => u.SeriesId); .Select(t => new { t.SeriesId, t.Id, t.Path, t.NumberOfFrames, t.InstanceNumber,t.FileSize }).ToListAsync();//.GroupBy(u => u.SeriesId);
foreach (var series in seriesList) foreach (var series in seriesList)
{ {
@@ -55,6 +55,7 @@ namespace IRaCIS.Core.Application.Service
//HtmlPath = string.Empty, //HtmlPath = string.Empty,
Path = k.Path, Path = k.Path,
InstanceNumber = k.InstanceNumber, InstanceNumber = k.InstanceNumber,
FileSize=k.FileSize,
}).ToList(); }).ToList();
} }
@@ -233,7 +233,7 @@ namespace IRaCIS.Core.Application.Services
var studyList = await _dicomStudyRepository.Where(t => t.TrialId == trialId && t.SubjectVisitId == sujectVisitId).IgnoreQueryFilters() var studyList = await _dicomStudyRepository.Where(t => t.TrialId == trialId && t.SubjectVisitId == sujectVisitId).IgnoreQueryFilters()
.Where(t => isImageFilter ? ("|" + criterionModalitys + "|").Contains("|" + t.ModalityForEdit + "|") : true) .Where(t => isImageFilter ? ("|" + criterionModalitys + "|").Contains("|" + t.ModalityForEdit + "|") : true)
.WhereIf(isReading == 1 || isQCFinished, s=> s.IsDeleted == false) .WhereIf(isReading == 1 || isQCFinished, s => s.IsDeleted == false)
.Select(k => new VisitStudyDTO() .Select(k => new VisitStudyDTO()
{ {
InstanceCount = k.InstanceCount, InstanceCount = k.InstanceCount,
@@ -248,7 +248,7 @@ namespace IRaCIS.Core.Application.Services
var instanceList = await _dicomInstanceRepository.Where(t => studyIds.Contains(t.StudyId)).IgnoreQueryFilters() var instanceList = await _dicomInstanceRepository.Where(t => studyIds.Contains(t.StudyId)).IgnoreQueryFilters()
.WhereIf(isReading == 1, s => s.IsReading && s.IsDeleted == false) .WhereIf(isReading == 1, s => s.IsReading && s.IsDeleted == false)
.WhereIf(isQCFinished, t => t.IsDeleted == false) .WhereIf(isQCFinished, t => t.IsDeleted == false)
.Select(t => new { t.SeriesId, t.Id, t.InstanceNumber, t.Path, t.NumberOfFrames, t.HtmlPath, t.IsReading, t.IsDeleted }).ToListAsync(); .Select(t => new { t.SeriesId, t.Id, t.InstanceNumber, t.Path, t.NumberOfFrames, t.HtmlPath, t.IsReading, t.IsDeleted, t.FileSize }).ToListAsync();
foreach (var t in studyList) foreach (var t in studyList)
{ {
@@ -272,6 +272,7 @@ namespace IRaCIS.Core.Application.Services
InstanceNumber = k.InstanceNumber, InstanceNumber = k.InstanceNumber,
IsReading = k.IsReading, IsReading = k.IsReading,
IsDeleted = k.IsDeleted, IsDeleted = k.IsDeleted,
FileSize = k.FileSize,
}).ToList(); }).ToList();
series.InstanceCount = series.InstanceInfoList.Count(); series.InstanceCount = series.InstanceInfoList.Count();
@@ -303,7 +304,7 @@ namespace IRaCIS.Core.Application.Services
DicomSeriesDTO series = await _dicomSeriesRepository.Where(s => s.Id == inDto.SeriesId).ProjectTo<DicomSeriesDTO>(_mapper.ConfigurationProvider).FirstNotNullAsync(); DicomSeriesDTO series = await _dicomSeriesRepository.Where(s => s.Id == inDto.SeriesId).ProjectTo<DicomSeriesDTO>(_mapper.ConfigurationProvider).FirstNotNullAsync();
var instanceList = await _dicomInstanceRepository.Where(t => t.SeriesId == inDto.SeriesId) var instanceList = await _dicomInstanceRepository.Where(t => t.SeriesId == inDto.SeriesId)
.Select(t => new { t.SeriesId, t.StudyId, t.Id, t.InstanceNumber, t.Path, t.NumberOfFrames, t.WindowCenter, t.WindowWidth, t.HtmlPath, t.SliceLocation }).ToListAsync(); .Select(t => new { t.SeriesId, t.StudyId, t.Id, t.InstanceNumber, t.Path, t.NumberOfFrames, t.WindowCenter, t.WindowWidth, t.HtmlPath, t.SliceLocation, t.FileSize }).ToListAsync();
@@ -315,6 +316,7 @@ namespace IRaCIS.Core.Application.Services
HtmlPath = k.HtmlPath, HtmlPath = k.HtmlPath,
Path = k.Path, Path = k.Path,
InstanceNumber = k.InstanceNumber, InstanceNumber = k.InstanceNumber,
FileSize = k.FileSize
}).ToList(); }).ToList();
@@ -391,7 +393,7 @@ namespace IRaCIS.Core.Application.Services
var seriesIds = ctseriesIds.Union(ptseriesIds).ToList(); //并集 var seriesIds = ctseriesIds.Union(ptseriesIds).ToList(); //并集
var instanceList = await _dicomInstanceRepository.Where(t => seriesIds.Contains(t.SeriesId)) var instanceList = await _dicomInstanceRepository.Where(t => seriesIds.Contains(t.SeriesId))
.Select(t => new { t.SeriesId, t.StudyId, t.Id, t.InstanceNumber, t.Path, t.NumberOfFrames, t.WindowCenter, t.WindowWidth, t.HtmlPath }).ToListAsync(); .Select(t => new { t.SeriesId, t.StudyId, t.Id, t.InstanceNumber, t.Path, t.NumberOfFrames, t.WindowCenter, t.WindowWidth, t.HtmlPath, t.FileSize }).ToListAsync();
var studyIds = instanceList.Select(x => x.StudyId).Distinct().ToList(); var studyIds = instanceList.Select(x => x.StudyId).Distinct().ToList();
@@ -422,7 +424,7 @@ namespace IRaCIS.Core.Application.Services
HtmlPath = k.HtmlPath, HtmlPath = k.HtmlPath,
Path = k.Path, Path = k.Path,
InstanceNumber = k.InstanceNumber, InstanceNumber = k.InstanceNumber,
FileSize = k.FileSize
}).ToList(); }).ToList();
@@ -506,7 +508,7 @@ namespace IRaCIS.Core.Application.Services
.Select(k => new VisitStudyDTO() .Select(k => new VisitStudyDTO()
{ {
InstanceCount = k.InstanceCount, InstanceCount = k.InstanceCount,
StudyName=k.StudyName, StudyName = k.StudyName,
Modalities = k.Modalities, Modalities = k.Modalities,
//SeriesCount = k.SeriesCount, //SeriesCount = k.SeriesCount,
StudyCode = k.StudyCode, StudyCode = k.StudyCode,
@@ -516,7 +518,7 @@ namespace IRaCIS.Core.Application.Services
var studyIds = dicomStudyList.Select(t => t.StudyId).ToList(); var studyIds = dicomStudyList.Select(t => t.StudyId).ToList();
var instanceList = await _dicomInstanceRepository.Where(t => studyIds.Contains(t.StudyId) && t.IsReading) var instanceList = await _dicomInstanceRepository.Where(t => studyIds.Contains(t.StudyId) && t.IsReading)
.Select(t => new { t.SeriesId, t.Id, t.InstanceNumber, t.Path, t.NumberOfFrames, t.WindowCenter, t.WindowWidth, t.HtmlPath, t.IsReading }).ToListAsync(); .Select(t => new { t.SeriesId, t.Id, t.InstanceNumber, t.Path, t.NumberOfFrames, t.WindowCenter, t.WindowWidth, t.HtmlPath, t.IsReading, t.FileSize }).ToListAsync();
List<DicomSeriesDTO> seriesLists = await _dicomSeriesRepository.Where(s => studyIds.Contains(s.StudyId)) List<DicomSeriesDTO> seriesLists = await _dicomSeriesRepository.Where(s => studyIds.Contains(s.StudyId))
.WhereIf(isManualGenerate == false, t => t.IsReading) .WhereIf(isManualGenerate == false, t => t.IsReading)
@@ -537,6 +539,7 @@ namespace IRaCIS.Core.Application.Services
HtmlPath = k.HtmlPath, HtmlPath = k.HtmlPath,
Path = k.Path, Path = k.Path,
InstanceNumber = k.InstanceNumber, InstanceNumber = k.InstanceNumber,
FileSize = k.FileSize
}).ToList(); }).ToList();
@@ -613,7 +616,7 @@ namespace IRaCIS.Core.Application.Services
var markInstanceIdList = rowInfoList.Where(y => y.InstanceId != null).OrderBy(x => x.ShowOrder).ThenBy(x => x.RowIndex).Select(y => y.InstanceId!.Value).Distinct().ToList(); var markInstanceIdList = rowInfoList.Where(y => y.InstanceId != null).OrderBy(x => x.ShowOrder).ThenBy(x => x.RowIndex).Select(y => y.InstanceId!.Value).Distinct().ToList();
item.InstanceInfoList = await _dicomInstanceRepository.Where(t => markInstanceIdList.Contains(t.Id)).OrderBy(s => s.DicomSerie.SeriesNumber).ThenBy(s => s.DicomSerie.SeriesTime).ThenBy(x=>x.InstanceTime).Select(k => item.InstanceInfoList = await _dicomInstanceRepository.Where(t => markInstanceIdList.Contains(t.Id)).OrderBy(s => s.DicomSerie.SeriesNumber).ThenBy(s => s.DicomSerie.SeriesTime).ThenBy(x => x.InstanceTime).Select(k =>
new InstanceBasicInfo() new InstanceBasicInfo()
{ {
Id = k.Id, Id = k.Id,
@@ -623,6 +626,7 @@ namespace IRaCIS.Core.Application.Services
InstanceNumber = k.InstanceNumber, InstanceNumber = k.InstanceNumber,
StudyId = k.StudyId, StudyId = k.StudyId,
SeriesId = k.SeriesId, SeriesId = k.SeriesId,
FileSize = k.FileSize
}).ToListAsync(); }).ToListAsync();
item.InstanceInfoList.ForEach(x => item.InstanceInfoList.ForEach(x =>
@@ -707,7 +711,7 @@ namespace IRaCIS.Core.Application.Services
{ {
var nodicom = noDicomList.Where(x => x.Id == item.StudyId).First(); var nodicom = noDicomList.Where(x => x.Id == item.StudyId).First();
var instanceCount = await _noneDicomStudyFileRepository.Where(t=>t.IsReading) var instanceCount = await _noneDicomStudyFileRepository.Where(t => t.IsReading)
.WhereIf(isExistTaskNoneDicomFile, x => x.OriginNoneDicomStudyId == item.StudyId) .WhereIf(isExistTaskNoneDicomFile, x => x.OriginNoneDicomStudyId == item.StudyId)
.WhereIf(isExistTaskNoneDicomFile == false, x => x.NoneDicomStudyId == item.StudyId).CountAsync(); .WhereIf(isExistTaskNoneDicomFile == false, x => x.NoneDicomStudyId == item.StudyId).CountAsync();
@@ -29,6 +29,13 @@ namespace IRaCIS.Core.Domain.Share
TrialQCQuestionConfirm=107, TrialQCQuestionConfirm=107,
//重置质控问题配置
TrialQCQuestionConfirmUpdate=112,
SecondReviewConfirm = 113,
} }
} }
@@ -19,4 +19,14 @@ namespace IRaCIS.Core.Domain.Share
} }
public enum SecondReviewState
{
None = 0,
WaitAudit=1,
AuditPassed=2,
AuditFailed=3,
}
} }
@@ -14,7 +14,11 @@
First = 1, First = 1,
Second = 2 Second = 2,
//二次复核,只会一个人
SecondReview=3,
} }
+1
View File
@@ -108,6 +108,7 @@ public abstract class BaseFullAuditEntity : Entity, IAuditUpdate, IAuditAdd
[ForeignKey("CreateUserId")] [ForeignKey("CreateUserId")]
[JsonIgnore] [JsonIgnore]
public UserRole CreateUserRole { get; set; } public UserRole CreateUserRole { get; set; }
} }
public abstract class BaseFullDeleteAuditEntity : Entity, IAuditUpdate, IAuditAdd, ISoftDelete public abstract class BaseFullDeleteAuditEntity : Entity, IAuditUpdate, IAuditAdd, ISoftDelete
{ {
@@ -8,6 +8,9 @@ public class TrialQCQuestionAnswer : BaseFullAuditEntity
#region #region
[JsonIgnore] [JsonIgnore]
public TrialQCQuestion TrialQCQuestionConfigure { get; set; } public TrialQCQuestion TrialQCQuestionConfigure { get; set; }
[JsonIgnore]
public SubjectVisit SubjectVisit { get; set; }
#endregion #endregion
public Guid TrialId { get; set; } public Guid TrialId { get; set; }
@@ -20,4 +23,7 @@ public class TrialQCQuestionAnswer : BaseFullAuditEntity
public Guid SubjectVisitId { get; set; } public Guid SubjectVisitId { get; set; }
public Guid TrialQCQuestionConfigureId { get; set; } public Guid TrialQCQuestionConfigureId { get; set; }
public DateTime? SecondReviewTime { get; set; }
} }
+4 -2
View File
@@ -6,6 +6,8 @@ namespace IRaCIS.Core.Domain.Models;
public class SubjectVisit : BaseFullDeleteAuditEntity public class SubjectVisit : BaseFullDeleteAuditEntity
{ {
#region #region
[JsonIgnore]
public List<TrialQCQuestionAnswer> TrialQCQuestionAnswerList { get; set; }
[JsonIgnore] [JsonIgnore]
public TrialSite TrialSite { get; set; } public TrialSite TrialSite { get; set; }
@@ -72,7 +74,7 @@ public class SubjectVisit : BaseFullDeleteAuditEntity
public List<SubjectCriteriaEvaluationVisitFilter> SubjectCriteriaEvaluationVisitFilterList { get; set; } public List<SubjectCriteriaEvaluationVisitFilter> SubjectCriteriaEvaluationVisitFilterList { get; set; }
[JsonIgnore] [JsonIgnore]
public List<SubjectVisitImageBackRecord> SubjectVisitImageBackRecordList { get; set; } public List<SubjectVisitImageBackRecord> SubjectVisitImageBackRecordList { get; set; }
#endregion #endregion
public Guid TrialSiteId { get; set; } public Guid TrialSiteId { get; set; }
@@ -185,7 +187,7 @@ public class SubjectVisit : BaseFullDeleteAuditEntity
public Guid? SubmitUserId { get; set; } public Guid? SubmitUserId { get; set; }
public ReadingStatusEnum ReadingStatus { get; set; } public ReadingStatusEnum ReadingStatus { get; set; }
public SecondReviewState SecondReviewState { get; set; }
} }
[Comment("受试者访视影像回退记录表")] [Comment("受试者访视影像回退记录表")]
+31 -13
View File
@@ -92,7 +92,7 @@ namespace IRaCIS.Core.Infra.EFCore.Common
/// <param name="unitDataList">单位字典</param> /// <param name="unitDataList">单位字典</param>
/// <param name="answer">答案</param> /// <param name="answer">答案</param>
/// <returns></returns> /// <returns></returns>
public string Translationunit(string answerType, ValueUnit? unit, string customUnit, List<UnitData> unitDataList,string? answer) public string Translationunit(string answerType, ValueUnit? unit, string customUnit, List<UnitData> unitDataList, string? answer)
{ {
if (answerType == "upload") if (answerType == "upload")
{ {
@@ -198,6 +198,13 @@ namespace IRaCIS.Core.Infra.EFCore.Common
extraIdentification = oldentity.IsConfigureEmail ? "/EmailUpdate" : "/EmailSave"; extraIdentification = oldentity.IsConfigureEmail ? "/EmailUpdate" : "/EmailSave";
break; break;
case "configTrialBasicInfo/TrialConfigSignatureConfirm":
if (entity.IsQCQuestionConfirmed == false)
{
extraIdentification = $"/ConfirmReset";
}
break;
} }
@@ -1971,7 +1978,15 @@ namespace IRaCIS.Core.Infra.EFCore.Common
//待处理? //待处理?
case "qcoperation/qcpassedorfailed": case "qcoperation/qcpassedorfailed":
extraIdentification = "/" + (40 % (int)entity.AuditState).ToString(); if (entity.AuditState == AuditStateEnum.QCPassed && (entity.SecondReviewState == SecondReviewState.AuditPassed || entity.SecondReviewState == SecondReviewState.AuditFailed))
{
extraIdentification = "/SecondReviewFinished";
}
else
{
extraIdentification = "/" + (40 % (int)entity.AuditState).ToString();
}
break; break;
@@ -2001,15 +2016,18 @@ namespace IRaCIS.Core.Infra.EFCore.Common
} }
break; break;
} }
if (entity.CheckChallengeState == CheckChanllengeTypeEnum.CRCWaitPMReply || entity.CheckChallengeState == CheckChanllengeTypeEnum.PMWaitCRCReply) if(_userInfo.RequestUrl== "QCOperation/addCheckChallengeReply" || _userInfo.RequestUrl == "QCOperation/UploadVisitCheckExcel")
{ {
//发送对话 修改质疑状态 不需要区分接口 if (entity.CheckChallengeState == CheckChanllengeTypeEnum.CRCWaitPMReply || entity.CheckChallengeState == CheckChanllengeTypeEnum.PMWaitCRCReply)
isDistinctionInterface = false; {
//发送对话 修改质疑状态 不需要区分接口
isDistinctionInterface = false;
extraIdentification = "/ModifyCheckChallengeState"; extraIdentification = "/ModifyCheckChallengeState";
}
} }
#endregion #endregion
@@ -3127,7 +3145,7 @@ namespace IRaCIS.Core.Infra.EFCore.Common
(t, u) => (t, u) =>
new new
{ {
Answer = Translationunit(u.AnswerType, u.Unit,u.CustomUnit, unitDataList, t.Answer), Answer = Translationunit(u.AnswerType, u.Unit, u.CustomUnit, unitDataList, t.Answer),
u.DictionaryCode, u.DictionaryCode,
u.QuestionName, u.QuestionName,
u.QuestionEnName, u.QuestionEnName,
@@ -3235,12 +3253,12 @@ namespace IRaCIS.Core.Infra.EFCore.Common
string extraIdentification = string.Empty; string extraIdentification = string.Empty;
var readingQuestion = await _dbContext.ReadingQuestionTrial.Where(t => t.Id == entity.QuestionId).Include(x=>x.ReadingQuestionCriterionTrial).FirstNotNullAsync(); var readingQuestion = await _dbContext.ReadingQuestionTrial.Where(t => t.Id == entity.QuestionId).Include(x => x.ReadingQuestionCriterionTrial).FirstNotNullAsync();
if (readingQuestion.ReadingQuestionCriterionTrial.CriterionGroup == CriterionGroup.Nontumorous) if (readingQuestion.ReadingQuestionCriterionTrial.CriterionGroup == CriterionGroup.Nontumorous)
{ {
extraIdentification = "/Nontumorous"; extraIdentification = "/Nontumorous";
} }
await InsertInspection<ReadingTableAnswerRowInfo>(entity, type, x => new InspectionConvertDTO() await InsertInspection<ReadingTableAnswerRowInfo>(entity, type, x => new InspectionConvertDTO()
@@ -3664,9 +3682,9 @@ namespace IRaCIS.Core.Infra.EFCore.Common
} }
} }
if(entity.TaskBlindName.Contains("Timepoint Ran")) if (entity.TaskBlindName.Contains("Timepoint Ran"))
{ {
if(_dbContext.VisitTask.Where(t => t.Id == entity.Id).Any(t => !t.TaskBlindName.Contains("Timepoint Ran"))) if (_dbContext.VisitTask.Where(t => t.Id == entity.Id).Any(t => !t.TaskBlindName.Contains("Timepoint Ran")))
{ {
isDistinctionInterface = false; isDistinctionInterface = false;
extraIdentification = "/TriggerSystemBlindingName"; extraIdentification = "/TriggerSystemBlindingName";