修改统计

Test_IRC_Net8
hang 2025-04-09 15:09:53 +08:00
parent a7848727ee
commit 2ceddc1340
9 changed files with 265 additions and 87 deletions

View File

@ -11,6 +11,32 @@ using System.ComponentModel.DataAnnotations.Schema;
namespace IRaCIS.Core.Application.Contracts
{
public class ImageBackQueryDto : PageInput
{
[NotDefault]
public Guid TrialId { get; set; }
public Guid? TrialSiteId { get; set; }
public string SubjectCode { get; set; } = string.Empty;
public Guid? CreateUserId { get; set; }
public ImageBackApplyEnum? ApplyUserRole { get; set; }
public DateTime? ApplyBeginTime { get; set; }
public DateTime? ApplyEndTime { get; set; }
public ImageBackStateEnum? ImageBackState { get; set; }
public DateTime? AuditBeginTime { get; set; }
public DateTime? AuditEndTime { get; set; }
}
public class CRCVisitSearchDTO : PageInput
{
@ -1687,6 +1713,40 @@ namespace IRaCIS.Core.Application.Contracts
#endregion
public class ImageBackViewModel
{
public Guid Id { get; set; }
public DateTime CreateTime { get; set; }
public string CreateUserName { get; set; }
public string CreateUserFullName { get; set; }
public DateTime? AuditTime { get; set; }
public Guid SubjectVisitId { get; set; }
public ImageBackApplyEnum ApplyUserRole { get; set; }
public ImageBackStateEnum ImageBackState { get; set; }
public bool IsUrgent { get; set; }
public string VisitName { get; set; } = string.Empty;
public DateTime? EarliestScanDate { get; set; }
public DateTime? LatestScanDate { get; set; }
public decimal VisitNum { get; set; }
public string SubjectCode { get; set; } = String.Empty;
public String TrialSiteCode { get; set; } = String.Empty;
}
public class QCCRCVisitViewModel : QCVisitBasicListViewModel
@ -2108,7 +2168,6 @@ namespace IRaCIS.Core.Application.Contracts
public DateTime? ReviewAuditTime { get; set; }
public DateTime? PreliminaryAuditTime { get; set; }
public ImageBackStateEnum ImageBackState { get; set; }
public DateTime? AuditTime => QCProcessEnum == TrialQCProcess.SingleAudit ? PreliminaryAuditTime : (QCProcessEnum == TrialQCProcess.DoubleAudit ? ReviewAuditTime : null);
}

View File

@ -22,10 +22,37 @@ namespace IRaCIS.Core.Application.Image.QA
IRepository<DicomSeries> _dicomSeriesRepository,
IRepository<NoneDicomStudy> _noneDicomStudyRepository,
IRepository<QCChallenge> _qcChallengeRepository,
IRepository<SubjectVisitImageBackRecord> _subjectVisitImageBackRecordReposiotry,
IReadingImageTaskService _IReadingImageTaskService, IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer) : BaseService, IQCListService
{
#region CRC IQC 直接申请回退影像流程
[HttpPost]
public async Task<IResponseOutput<PageOutput<ImageBackViewModel>>> GetImageBackList(ImageBackQueryDto inQuery)
{
var query = _subjectVisitImageBackRecordReposiotry.Where(t => t.SubjectVisit.TrialId == inQuery.TrialId)
.WhereIf(inQuery.TrialSiteId != null, t => t.SubjectVisit.TrialSiteId == inQuery.TrialSiteId)
.WhereIf(!string.IsNullOrEmpty(inQuery.SubjectCode), t => t.SubjectVisit.Subject.Code.Contains(inQuery.SubjectCode))
.WhereIf(inQuery.CreateUserId != null, t => t.CreateUserId == inQuery.CreateUserId)
.WhereIf(inQuery.ApplyUserRole != null, t => t.ApplyUserRole == inQuery.ApplyUserRole)
.WhereIf(inQuery.ApplyBeginTime != null, t => t.CreateTime >= inQuery.ApplyBeginTime)
.WhereIf(inQuery.ApplyEndTime != null, t => t.CreateTime <= inQuery.ApplyEndTime)
.WhereIf(inQuery.ImageBackState != null, t => t.ImageBackState == inQuery.ImageBackState)
.WhereIf(inQuery.AuditBeginTime != null, t => t.AuditTime >= inQuery.AuditBeginTime)
.WhereIf(inQuery.AuditEndTime != null, t => t.AuditTime <= inQuery.AuditEndTime)
.ProjectTo<ImageBackViewModel>(_mapper.ConfigurationProvider);
var defalutSortArray = new string[] { nameof(ImageBackViewModel.IsUrgent) + " desc", nameof(ImageBackViewModel.SubjectCode), nameof(ImageBackViewModel.VisitNum) };
var pageList = await query.ToPagedListAsync(inQuery, defalutSortArray);
return ResponseOutput.Ok(pageList);
}
#endregion

View File

@ -40,6 +40,7 @@ namespace IRaCIS.Core.Application.Image.QA
IDistributedLockProvider _distributedLockProvider, IReadingClinicalDataService _readingClinicalDataService,
IOSSService _oSSService,
IRepository<ReadingClinicalData> _readingClinicalDataReposiotry,
IRepository<SubjectVisitImageBackRecord> _subjectVisitImageBackRecordReposiotry,
IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer, IWebHostEnvironment _hostEnvironment) : BaseService, IQCOperationService
{
@ -260,33 +261,42 @@ namespace IRaCIS.Core.Application.Image.QA
throw new BusinessValidationFailedException(_localizer["QCOperation_ShouldBeforeCheckPassed"]);
}
var newRecord = new SubjectVisitImageBackRecord() { SubjectVisitId = subjectVisitId };
if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.ClinicalResearchCoordinator)
{
await _subjectVisitRepository.UpdatePartialFromQueryAsync(t => t.Id == subjectVisitId, u => new SubjectVisit() { ImageBackState = ImageBackStateEnum.CRCRequestBack }, true);
newRecord.ApplyUserRole = ImageBackApplyEnum.CRCRequestBack;
}
if (_userInfo.UserTypeEnumInt == (int)UserTypeEnum.IQC)
{
await _subjectVisitRepository.UpdatePartialFromQueryAsync(t => t.Id == subjectVisitId, u => new SubjectVisit() { ImageBackState = ImageBackStateEnum.IQCRequestBack }, true);
newRecord.ApplyUserRole = ImageBackApplyEnum.IQCRequestBack;
}
await _subjectVisitImageBackRecordReposiotry.AddAsync(newRecord, true);
return ResponseOutput.Ok();
}
/// <summary>
/// PM 审核CRC IQC 申请影像回退
/// </summary>
/// <param name="subjectVisitId"></param>
/// <param name="iamgeBackRecordId"></param>
/// <param name="isAgree"></param>
/// <returns></returns>
/// <exception cref="BusinessValidationFailedException"></exception>
[HttpPut]
public async Task<IResponseOutput> AuditImageBack(Guid subjectVisitId, bool isAgree)
public async Task<IResponseOutput> AuditImageBack(Guid iamgeBackRecordId, bool isAgree)
{
var sv = (await _subjectVisitRepository.FirstOrDefaultAsync(t => t.Id == subjectVisitId)).IfNullThrowException();
var backRecord = (await _subjectVisitImageBackRecordReposiotry.FirstOrDefaultAsync(t => t.Id == iamgeBackRecordId)).IfNullThrowException();
if (sv.ImageBackState != ImageBackStateEnum.CRCRequestBack && sv.ImageBackState != ImageBackStateEnum.IQCRequestBack)
var sv = (await _subjectVisitRepository.FirstOrDefaultAsync(t => t.Id == backRecord.SubjectVisitId)).IfNullThrowException();
var subjectVisitId = backRecord.SubjectVisitId;
if (backRecord.ApplyUserRole != ImageBackApplyEnum.CRCRequestBack && backRecord.ApplyUserRole != ImageBackApplyEnum.IQCRequestBack)
{
//当前访视状态不在影像申请回退状态,不允许审核通过
throw new BusinessValidationFailedException(_localizer["QCOperation_NotInRequestImageBackState"]);
@ -294,9 +304,9 @@ namespace IRaCIS.Core.Application.Image.QA
if (isAgree)
{
if (sv.SubmitState == SubmitStateEnum.Submitted && _subjectVisitRepository.Any(t => t.Id == subjectVisitId && !t.VisitTaskList.Any()))
if (sv.SubmitState == SubmitStateEnum.Submitted && _subjectVisitRepository.Any(t => t.Id == backRecord.SubjectVisitId && !t.VisitTaskList.Any()))
{
sv.ImageBackState = ImageBackStateEnum.PMAgreeBack;
backRecord.ImageBackState = ImageBackStateEnum.PMAgreeBack;
}
@ -361,10 +371,12 @@ namespace IRaCIS.Core.Application.Image.QA
}
else
{
sv.ImageBackState = ImageBackStateEnum.PMNotAgreeBack;
backRecord.ImageBackState = ImageBackStateEnum.PMNotAgreeBack;
}
backRecord.AuditTime = DateTime.Now;
await _subjectVisitRepository.SaveChangesAsync();
return ResponseOutput.Ok();

View File

@ -737,6 +737,16 @@ namespace IRaCIS.Core.Application.Service
.OrderBy(t => t.CreateTime).ThenBy(t => t.FileName)))
.ForMember(d => d.CodeView, u => u.MapFrom(s => s.StudyCode));
CreateMap<SubjectVisitImageBackRecord, ImageBackViewModel>()
.ForMember(d => d.SubjectCode, u => u.MapFrom(s => s.SubjectVisit.Subject.Code))
.ForMember(d => d.VisitNum, u => u.MapFrom(t => t.SubjectVisit.VisitNum))
.ForMember(d => d.TrialSiteCode, u => u.MapFrom(s => s.SubjectVisit.TrialSite.TrialSiteCode))
.ForMember(d => d.VisitName, u => u.MapFrom(s => s.SubjectVisit.VisitName))
.ForMember(d => d.IsUrgent, u => u.MapFrom(s => s.SubjectVisit.IsUrgent))
.ForMember(d => d.EarliestScanDate, u => u.MapFrom(s => s.SubjectVisit.EarliestScanDate))
.ForMember(d => d.LatestScanDate, u => u.MapFrom(s => s.SubjectVisit.LatestScanDate));
}
}

View File

@ -114,6 +114,19 @@ namespace IRaCIS.Core.Application.Contracts
{
}
public class ImageBackToBeDoneQuery : PageInput
{
}
public class ImageBackToBeDoneDto: TrialBaseInfoDto
{
public int? ToBeApprovalCount { get; set; }
}
public class ReviewerSelectToBeDoneDto : TrialBaseInfoDto
{
public bool IsUrgent { get; set; }
@ -402,6 +415,8 @@ namespace IRaCIS.Core.Application.Contracts
public int? PM_ClinicalDataCount { get; set; }
public int? PM_ImageBackApprovalCount { get; set; }
#endregion
#region CRC

View File

@ -16,6 +16,7 @@ namespace IRaCIS.Core.Application
IRepository<SystemDocument> _systemDocumentRepository,
IClinicalAnswerService _clinicalAnswerService,
IRepository<SystemNotice> _systemNoticeRepository,
IRepository<SubjectVisitImageBackRecord> _subjectVisitImageBackRecordReposiotry,
IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer) : BaseService
{
@ -213,7 +214,7 @@ namespace IRaCIS.Core.Application
.Where(t => t.Trial.TrialIdentityUserList.Any(t => t.IdentityUserId == _userInfo.IdentityUserId && t.TrialUserRoleList.Any(t => t.UserRole.UserTypeId == _userInfo.UserTypeId)))
.Where(u => u.EnrollStatus == EnrollStatus.HasCommittedToCRO).CountAsync();
return ResponseOutput.Ok(result, new { ToBeApprovalCount = toBeApprovalCount }); ;
return ResponseOutput.Ok(result, new { ToBeApprovalCount = toBeApprovalCount });
}
@ -259,6 +260,32 @@ namespace IRaCIS.Core.Application
return ResponseOutput.Ok(result, new { ToBeApprovalCount = all.Sum(x => x.ToBeApprovalCount) }); ;
}
[HttpPost]
public async Task<IResponseOutput<PageOutput<ImageBackToBeDoneDto>>> GetPMImageBackToBeDoneList(ImageBackToBeDoneQuery inQuery)
{
var query = _trialRepository.Where(t => t.TrialStatusStr == StaticData.TrialState.TrialOngoing)
.Where(t => t.TrialIdentityUserList.Any(t => t.IdentityUserId == _userInfo.IdentityUserId && t.TrialUserRoleList.Any(t => t.UserRole.UserTypeId == _userInfo.UserTypeId)))
.Select(t => new ImageBackToBeDoneDto()
{
TrialId = t.Id,
ResearchProgramNo = t.ResearchProgramNo,
ExperimentName = t.ExperimentName,
TrialCode = t.TrialCode,
ToBeApprovalCount = t.SubjectVisitList.SelectMany(u => u.SubjectVisitImageBackRecordList).Count()
}).Where(x => x.ToBeApprovalCount > 0);
var defalutSortArray = new string[] { nameof(ImageBackToBeDoneDto.ToBeApprovalCount) + " desc" };
var result = await query.ToPagedListAsync(inQuery, defalutSortArray);
return ResponseOutput.Ok(result);
}
#endregion
@ -1223,6 +1250,9 @@ namespace IRaCIS.Core.Application
.Where(t => t.TrialIdentityUserList.Any(t => t.IdentityUserId == _userInfo.IdentityUserId && t.TrialUserRoleList.Any(t => t.UserRole.UserTypeId == _userInfo.UserTypeId)))
.Where(t => t.ReadModuleList.Where(u => u.IsCRCConfirm && !u.IsPMConfirm).Count() > 0).CountAsync() : 0,
PM_ImageBackApprovalCount = isPM ? await _subjectVisitImageBackRecordReposiotry.Where(t => t.SubjectVisit.Trial.TrialStatusStr == StaticData.TrialState.TrialOngoing)
.Where(t => t.SubjectVisit.Trial.TrialIdentityUserList.Any(t => t.IdentityUserId == _userInfo.IdentityUserId && t.TrialUserRoleList.Any(t => t.UserRole.UserTypeId == _userInfo.UserTypeId)))
.CountAsync() : 0,
#endregion
#region CRC

View File

@ -23,13 +23,16 @@ namespace IRaCIS.Core.Domain.Share
{
None = 0,
PMAgreeBack = 1,
PMNotAgreeBack = 2,
}
public enum ImageBackApplyEnum
{
CRCRequestBack = 1,
IQCRequestBack = 2,
PMAgreeBack=3,
PMNotAgreeBack = 4,
}
}

View File

@ -70,6 +70,9 @@ public class SubjectVisit : BaseFullDeleteAuditEntity
[JsonIgnore]
public List<SubjectCriteriaEvaluationVisitFilter> SubjectCriteriaEvaluationVisitFilterList { get; set; }
[JsonIgnore]
public List<SubjectVisitImageBackRecord> SubjectVisitImageBackRecordList { get; set; }
#endregion
public Guid TrialSiteId { get; set; }
@ -182,7 +185,24 @@ public class SubjectVisit : BaseFullDeleteAuditEntity
public Guid? SubmitUserId { get; set; }
public ReadingStatusEnum ReadingStatus { get; set; }
[Comment("影像上传 回退")]
public ImageBackStateEnum ImageBackState { get; set; }
}
[Comment("受试者访视影像回退记录表")]
[Table("SubjectVisitImageBackRecord")]
public class SubjectVisitImageBackRecord : BaseFullAuditEntity
{
[JsonIgnore]
public SubjectVisit SubjectVisit { get; set; }
public Guid SubjectVisitId { get; set; }
public ImageBackApplyEnum ApplyUserRole { get; set; }
[Comment("影像上传 回退")]
public ImageBackStateEnum ImageBackState { get; set; }
public DateTime? AuditTime { get; set; }
}

View File

@ -659,6 +659,8 @@ public class IRaCISDBContext : DbContext
#endregion
public virtual DbSet<SubjectVisitImageBackRecord> SubjectVisitImageBackRecord { get; set; }
}
public class TestLength : Entity