EI-Image-Viewer-Api/IRaCIS.Core.Application/Service/QC/QCListService.cs

757 lines
43 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using IRaCIS.Core.Application.Contracts;
using Microsoft.AspNetCore.Mvc;
using IRaCIS.Core.Infrastructure.ExpressionExtend;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Application.Contracts.DTO;
using IRaCIS.Core.Infra.EFCore;
namespace IRaCIS.Core.Application.Image.QA
{
[ApiExplorerSettings(GroupName = "Image")]
public class QCListService : BaseService, IQCListService
{
private readonly IRepository<SubjectVisit> _subjectVisitRepository;
public QCListService(IRepository<SubjectVisit> subjectVisitRepository)
{
_subjectVisitRepository = subjectVisitRepository;
}
#region CRC上传、质疑页面
/// <summary>
/// CRC 访视上传列表
/// </summary>
/// <param name="visitSearchDTO"></param>
/// <returns></returns>
[HttpPost]
public async Task<IResponseOutput<PageOutput<QCCRCVisitViewModel>, TrialSubjectAndSVConfig>> GetCRCVisitList(CRCVisitSearchDTO visitSearchDTO)
{
var query = _repository.Where<SubjectVisit>(x => x.TrialId == visitSearchDTO.TrialId)
.WhereIf(visitSearchDTO.SiteId != null, t => t.SiteId == visitSearchDTO.SiteId)
.WhereIf(visitSearchDTO.SubjectId != null, t => t.Subject.Id == visitSearchDTO.SubjectId)
.WhereIf(!string.IsNullOrEmpty(visitSearchDTO.SubjectInfo), t => t.Subject.Code.Contains(visitSearchDTO.SubjectInfo))
.WhereIf(!string.IsNullOrEmpty(visitSearchDTO.VisitPlanInfo), visitSearchDTO.VisitPlanInfo.Contains('.') ? t => t.InPlan == false : t => t.VisitNum == decimal.Parse(visitSearchDTO.VisitPlanInfo))
.WhereIf(visitSearchDTO.AuditStateArray != null && visitSearchDTO.AuditStateArray?.Length > 0, t => visitSearchDTO.AuditStateArray!.Contains(t.AuditState))
.WhereIf(visitSearchDTO.SubmitState != null, t => t.SubmitState == visitSearchDTO.SubmitState)
.WhereIf(visitSearchDTO.ChallengeState != null, t => t.ChallengeState == visitSearchDTO.ChallengeState)
.WhereIf(visitSearchDTO.IsUrgent != null, t => t.IsUrgent == visitSearchDTO.IsUrgent)
.WhereIf(_userInfo.UserTypeEnumInt == (int)UserTypeEnum.ClinicalResearchCoordinator, t => t.TrialSite.CRCUserList.Any(t => t.UserId == _userInfo.Id))
.ProjectTo<QCCRCVisitViewModel>(_mapper.ConfigurationProvider);
var pageList = await query.ToPagedListAsync(visitSearchDTO.PageIndex, visitSearchDTO.PageSize, visitSearchDTO.SortField, visitSearchDTO.Asc);
var config = await _repository.Where<Trial>(t => t.Id == visitSearchDTO.TrialId).ProjectTo<TrialSubjectAndSVConfig>(_mapper.ConfigurationProvider).FirstOrDefaultAsync().IfNullThrowException();
return ResponseOutput.Ok(pageList, config!);
}
/// <summary>
/// CRC 质疑列表
/// </summary>
/// <param name="challengeQuery"></param>
/// <returns></returns>
[HttpPost]
public async Task<IResponseOutput<PageOutput<QCCRCChallengeViewModel>, TrialSubjectAndSVConfig>> GetCRCChallengeList(ChallengeQuery challengeQuery)
{
#region CRC 质疑列表 join连表方式
//var query = from qcChanllenge in _qcChallengeRepository.Find(qcChallengeLambda)
// join subjectVisit in _subjectVisitRepository.Find() on qcChanllenge.SubjectVisitId equals subjectVisit.Id
// join trialSite in _trialSiteRepository.Find(t => t.TrialId == challengeQuery.TrialId) on subjectVisit.SiteId equals trialSite.SiteId
// join subject in _subjectRepository.Find() on subjectVisit.SubjectId equals subject.Id
// select new QCCRCChallengeViewModel()
// {
// Id = qcChanllenge.Id,
// SubjectVisitId = qcChanllenge.SubjectVisitId,
// ChallengeCode = qcChanllenge.ChallengeCode,
// ChallengeType = qcChanllenge.ChallengeType,
// Note = qcChanllenge.Note,
// Content = qcChanllenge.Content,
// UserTypeEnum = qcChanllenge.UserTypeEnum,
// CreateTime = qcChanllenge.CreateTime,
// CreateUser = qcChanllenge.CreateUser,
// CreateUserId = qcChanllenge.CreateUserId,
// DeadlineTime = qcChanllenge.DeadlineTime,
// IsClosed = qcChanllenge.IsClosed,
// ClosedTime = qcChanllenge.ClosedTime,
// ClosedUser = qcChanllenge.ClosedUser,
// NeedReUpload = qcChanllenge.NeedReUpload,
// VisitName = subjectVisit.VisitName,
// VisitNum = subjectVisit.VisitNum,
// SubjectCode = subject.Code,
// TrialSiteCode = trialSite.TrialSiteCode,
// LatestMsgTime = qcChanllenge.LatestMsgTime,
// LatestReplyUser = qcChanllenge.LatestReplyUser,
// };
#endregion
var query2 = _repository.Where<QCChallenge>(x => x.TrialId == challengeQuery.TrialId)
.WhereIf(challengeQuery.ReuploadEnum != null, t => t.ReuploadEnum == challengeQuery.ReuploadEnum)
.WhereIf(challengeQuery.IsClosed != null, t => t.IsClosed == challengeQuery.IsClosed)
.WhereIf(challengeQuery.SiteId != null, t => t.SubjectVisit.SiteId == challengeQuery.SiteId)
.WhereIf(challengeQuery.SubjectId != null, t => t.SubjectVisit.SubjectId == challengeQuery.SubjectId)
.WhereIf(challengeQuery.CreateUserId != null, t => t.CreateUserId == challengeQuery.CreateUserId)
.WhereIf(challengeQuery.SubjectCode != null, t => t.SubjectVisit.Subject.Code.Contains(challengeQuery.SubjectCode!))
.WhereIf(!string.IsNullOrEmpty(challengeQuery.VisitPlanInfo), challengeQuery.VisitPlanInfo.Contains('.') ? t => t.SubjectVisit.VisitNum.ToString().Contains(".") : t => t.SubjectVisit.VisitNum == decimal.Parse(challengeQuery.VisitPlanInfo))
.WhereIf(challengeQuery.IsOverTime != null, t => DateTime.Now > t.DeadlineTime)
.WhereIf(challengeQuery.IsUrgent != null, t => t.SubjectVisit.IsUrgent == challengeQuery.IsUrgent)
.WhereIf(_userInfo.UserTypeEnumInt == (int)UserTypeEnum.ClinicalResearchCoordinator, t => t.SubjectVisit.TrialSite.CRCUserList.Any(t => t.UserId == _userInfo.Id))
.ProjectTo<QCCRCChallengeViewModel>(_mapper.ConfigurationProvider);
var pageList = await query2.ToPagedListAsync(challengeQuery.PageIndex, challengeQuery.PageSize, challengeQuery.SortField, challengeQuery.Asc,string.IsNullOrWhiteSpace(challengeQuery.SortField), new string[] { "IsUrgent desc", "IsClosed asc" });
var config = await _repository.Where<Trial>(t => t.Id == challengeQuery.TrialId).ProjectTo<TrialSubjectAndSVConfig>(_mapper.ConfigurationProvider).FirstOrDefaultAsync().IfNullThrowException();
return ResponseOutput.Ok(pageList, config);
}
#endregion
#region QC 质疑 质控页面
/// <summary>
/// QC 质疑列表 分页
/// </summary>
/// <param name="challengeQuery"></param>
/// <returns></returns>
[HttpPost]
public async Task<IResponseOutput<PageOutput<QCCRCChallengeViewModel>, TrialSubjectAndSVConfig>> GetQCChallengeList(ChallengeQuery challengeQuery)
{
#region linq方式 + Expression 拼接
//Expression<Func<QCChallenge, bool>> qcChallengeLambda = x => x.TrialId == challengeQuery.TrialId;
//if (challengeQuery.ReuploadEnum != null)
//{
// qcChallengeLambda = qcChallengeLambda.And(t => t.ReuploadEnum == challengeQuery.ReuploadEnum);
//}
//if (challengeQuery.IsClosed != null)
//{
// qcChallengeLambda = qcChallengeLambda.And(t => t.IsClosed == challengeQuery.IsClosed);
//}
//if (challengeQuery.SiteId != null)
//{
// qcChallengeLambda = qcChallengeLambda.And(t => t.SubjectVisit.SiteId == challengeQuery.SiteId.Value);
//}
//if (challengeQuery.SubjectId != null)
//{
// qcChallengeLambda = qcChallengeLambda.And(t => t.SubjectVisit.Subject.Id == challengeQuery.SubjectId.Value);
//}
//var query = from qcChanllenge in _qcChallengeRepository.Find(qcChallengeLambda)
// join subjectVisit in _subjectVisitRepository.Find(subjectVisitLambda) on qcChanllenge.SubjectVisitId equals subjectVisit.Id
// join trialSite in _trialSiteRepository.Find(t => t.TrialId == challengeQuery.TrialId) on subjectVisit.SiteId equals trialSite.SiteId
// join subject in _subjectRepository.Find() on subjectVisit.SubjectId equals subject.Id
// select new QCChallengeViewModel()
// {
// Id = qcChanllenge.Id,
// SubjectVisitId = qcChanllenge.SubjectVisitId,
// ChallengeCode = qcChanllenge.ChallengeCode.ToString(),
// ChallengeType = qcChanllenge.ChallengeType,
// Note = qcChanllenge.Note,
// UserTypeEnum = qcChanllenge.UserTypeEnum,
// Content = qcChanllenge.Content,
// CreateTime = qcChanllenge.CreateTime,
// CreateUserId = qcChanllenge.CreateUserId,
// CreateUser = qcChanllenge.CreateUser,
// SubjectCode = subject.Code,
// TrialSiteCode = trialSite.TrialSiteCode,
// DeadlineTime = qcChanllenge.DeadlineTime,
// IsClosed = qcChanllenge.IsClosed,
// ClosedTime = qcChanllenge.ClosedTime,
// ClosedUser = qcChanllenge.ClosedUser,
// NeedReUpload = qcChanllenge.NeedReUpload,
// VisitName = subjectVisit.VisitName,
// VisitNum = subjectVisit.VisitNum,
// LatestMsgTime = qcChanllenge.LatestMsgTime,
// LatestReplyUser = qcChanllenge.LatestReplyUser,
// };
#endregion
var query = _repository.Where<QCChallenge>(x => x.TrialId == challengeQuery.TrialId)
.WhereIf(challengeQuery.ReuploadEnum != null, t => t.ReuploadEnum == challengeQuery.ReuploadEnum)
.WhereIf(challengeQuery.IsClosed != null, t => t.IsClosed == challengeQuery.IsClosed)
.WhereIf(challengeQuery.SiteId != null, t => t.SubjectVisit.SiteId == challengeQuery.SiteId)
.WhereIf(challengeQuery.SubjectId != null, t => t.SubjectVisit.SubjectId == challengeQuery.SubjectId)
.WhereIf(challengeQuery.CreateUserId != null, t => t.CreateUserId == challengeQuery.CreateUserId)
.WhereIf(!string.IsNullOrEmpty(challengeQuery.SubjectCode), t => t.SubjectVisit.Subject.Code.Contains(challengeQuery.SubjectCode))
.WhereIf(!string.IsNullOrEmpty(challengeQuery.VisitPlanInfo), challengeQuery.VisitPlanInfo.Contains('.') ? t => t.SubjectVisit.InPlan == false : t => t.SubjectVisit.VisitNum == decimal.Parse(challengeQuery.VisitPlanInfo))
.WhereIf(challengeQuery.IsUrgent != null, t => t.SubjectVisit.IsUrgent == challengeQuery.IsUrgent)
.WhereIf(challengeQuery.IsOverTime != null, t => DateTime.Now > t.DeadlineTime)
.ProjectTo<QCCRCChallengeViewModel>(_mapper.ConfigurationProvider);
var pageList = await query.ToPagedListAsync(challengeQuery.PageIndex, challengeQuery.PageSize, challengeQuery.SortField, challengeQuery.Asc, string.IsNullOrWhiteSpace(challengeQuery.SortField), new string[] { "IsUrgent desc", "IsClosed asc" });
var config = await _repository.Where<Trial>(t => t.Id == challengeQuery.TrialId).ProjectTo<TrialSubjectAndSVConfig>(_mapper.ConfigurationProvider).FirstOrDefaultAsync().IfNullThrowException();
return ResponseOutput.Ok(pageList, config);
}
/// <summary>
/// QC 访视列表
/// </summary>
/// <param name="visitSearchDTO"></param>
/// <returns></returns>
[HttpPost]
public async Task<IResponseOutput<PageOutput<QCVisitViewModel>, TrialSubjectAndSVConfig>> GetQCVisitList(QCVisitSearchDTO visitSearchDTO)
{
#region 经典 linq
//Expression<Func<Subject, bool>> subjectLambda = x => true;
//Expression<Func<SubjectVisit, bool>> subjectVisitLambda = x => x.TrialId == visitSearchDTO.TrialId;
//Expression<Func<DicomStudy, bool>> studyLambda = x => x.TrialId == visitSearchDTO.TrialId;
////Expression<Func<VisitStage, bool>> visitPlanLambda = x => x.TrialId == subjectVisitSearch.TrialId;
//if (visitSearchDTO.SiteId != null && visitSearchDTO.SiteId != Guid.Empty)
//{
// subjectVisitLambda = subjectVisitLambda.And(t => t.SiteId == visitSearchDTO.SiteId.Value);
// studyLambda = studyLambda.And(t => t.SiteId == visitSearchDTO.SiteId.Value);
//}
//if (visitSearchDTO.SubjectId != null && visitSearchDTO.SubjectId != Guid.Empty)
//{
// subjectLambda = subjectLambda.And(t => t.Id == visitSearchDTO.SubjectId.Value);
// studyLambda = studyLambda.And(t => t.SubjectId == visitSearchDTO.SubjectId.Value);
//}
//if (!string.IsNullOrEmpty(visitSearchDTO.SubjectInfo))
//{
// var search = visitSearchDTO.SubjectInfo.Trim();
// subjectLambda = subjectLambda.And(t => t.FirstName.Contains(search) || t.LastName.Contains(search) || t.Code.Contains(search));
//}
//if (!string.IsNullOrWhiteSpace(visitSearchDTO.VisitPlanInfo))
//{
// var visitInfo = visitSearchDTO.VisitPlanInfo.Trim();
// if (visitInfo.Contains('.')) // 包含小数点的是计划外访视
// {
// subjectVisitLambda = subjectVisitLambda.And(t => t.VisitNum.ToString().Contains("."));
// }
// else
// {
// if (int.TryParse(visitInfo, out var visitNum))
// {
// subjectVisitLambda = subjectVisitLambda.And(t => t.VisitNum == visitNum);
// }
// }
//}
//var query = from subjectVisit in _subjectVisitRepository.Where(subjectVisitLambda)
// join subject in _subjectRepository.Where(subjectLambda) on subjectVisit.SubjectId equals subject.Id
// join trialSite in _trialSiteRepository.Where(t => t.TrialId == visitSearchDTO.TrialId) on subjectVisit.SiteId equals trialSite.SiteId
// join study in _studyRepository.Where(studyLambda).GroupBy(t => t.SubjectVisitId).Select(g => new { SubjectVisitId = g.Key, StudyCount = g.Count() }) on subjectVisit.Id equals study.SubjectVisitId into d
// from study in d.DefaultIfEmpty()
// join trial in _trialRepository.AsQueryable() on subjectVisit.TrialId equals trial.Id
// select new QCVisitViewModel()
// {
// Id = subjectVisit.Id,
// //VisitPlanId = visitStage.Id,
// SubjectId = subjectVisit.SubjectId,
// TrialId = subjectVisit.TrialId,
// SiteId = subjectVisit.SiteId,
// VisitDay = subjectVisit.VisitDay,
// VisitNum = subjectVisit.VisitNum,
// VisitName = subjectVisit.VisitName,
// SVENDTC = subjectVisit.SVENDTC,
// SVSTDTC = subjectVisit.SVSTDTC,
// SVUPDES = subjectVisit.SVUPDES,
// InPlan = subjectVisit.InPlan,
// VisitExecuted = subjectVisit.VisitExecuted,
// StudyCount = study.StudyCount,
// SubjectStatus = subject.Status,
// SubjectCode = subject.Code,
// IsUrgent = subjectVisit.IsUrgent,
// TrialSiteCode = trialSite.TrialSiteCode,
// EarliestScanDate = subjectVisit.EarliestScanDate,
// LatestScanDate = subjectVisit.LatestScanDate,
// QCProcessEnum = trial.QCProcessEnum,
// CurrentActionUserId = subjectVisit.CurrentActionUserId,
// CurrentActionUser = subjectVisit.CurrentActionUser,
// CurrentActionUserExpireTime = subjectVisit.CurrentActionUserExpireTime,
// PreliminaryAuditTime = subjectVisit.PreliminaryAuditTime,
// PreliminaryAuitUser = subjectVisit.PreliminaryAuitUser,
// ReviewAuitTime = subjectVisit.ReviewAuitTime,
// ReviewAuitUser = subjectVisit.ReviewAuitUser,
// AuditState = subjectVisit.AuditState,
// SubmitTime = subjectVisit.SubmitTime,
// IsTake = subjectVisit.IsTake,
// };
#endregion
#region WhereIf + ling 统计
//var query = from subjectVisit in _subjectVisitRepository.Where(x => x.TrialId == visitSearchDTO.TrialId)
// .WhereIf(visitSearchDTO.SiteId != null, t => t.SiteId == visitSearchDTO.SiteId)
// .WhereIf(visitSearchDTO.SubjectId != null, t => t.Subject.Id == visitSearchDTO.SubjectId)
// .WhereIf(!string.IsNullOrEmpty(subjectInfo), t => /*t.Subject.FirstName.Contains(subjectInfo) || t.Subject.LastName.Contains(subjectInfo) ||*/ t.Subject.Code.Contains(subjectInfo))
// .WhereIf(!string.IsNullOrEmpty(visitInfo), visitInfo.Contains('.') ? t => t.VisitNum.ToString().Contains(".") : t => t.VisitNum.ToString() == visitInfo)
// .WhereIf(visitSearchDTO.AuditState != null, t => t.AuditState == visitSearchDTO.AuditState)
// .WhereIf(visitSearchDTO.HandleUser != null, t => t.PreliminaryAuitUser.Contains(visitSearchDTO.HandleUser) || t.ReviewAuitUser.Contains(visitSearchDTO.HandleUser))
// .WhereIf(visitSearchDTO.IsUrgent != null, t => t.IsUrgent == visitSearchDTO.IsUrgent)
// //.WhereIf(visitSearchDTO.SubmitState != null, t => t.SubmitState == visitSearchDTO.SubmitState)
// //.WhereIf(visitSearchDTO.ChallengeState != null, t => t.ChallengeState == visitSearchDTO.ChallengeState)
// join subject in _subjectRepository.AsQueryable() on subjectVisit.SubjectId equals subject.Id
// join trialSite in _trialSiteRepository.Where(t => t.TrialId == visitSearchDTO.TrialId) on subjectVisit.SiteId equals trialSite.SiteId
// join study in _studyRepository.AsQueryable().GroupBy(t => t.SubjectVisitId).Select(g => new { SubjectVisitId = g.Key, StudyCount = g.Count() }) on subjectVisit.Id equals study.SubjectVisitId into d
// from study in d.DefaultIfEmpty()
// join trial in _trialRepository.AsQueryable() on subjectVisit.TrialId equals trial.Id
// select new QCVisitViewModel()
// {
// Id = subjectVisit.Id,
// //VisitPlanId = visitStage.Id,
// SubjectId = subjectVisit.SubjectId,
// TrialId = subjectVisit.TrialId,
// SiteId = subjectVisit.SiteId,
// VisitDay = subjectVisit.VisitDay,
// VisitNum = subjectVisit.VisitNum,
// VisitName = subjectVisit.VisitName,
// SVENDTC = subjectVisit.SVENDTC,
// SVSTDTC = subjectVisit.SVSTDTC,
// SVUPDES = subjectVisit.SVUPDES,
// InPlan = subjectVisit.InPlan,
// VisitExecuted = subjectVisit.VisitExecuted,
// IsUrgent = subjectVisit.IsUrgent,
// EarliestScanDate = subjectVisit.EarliestScanDate,
// LatestScanDate = subjectVisit.LatestScanDate,
// CurrentActionUserId = subjectVisit.CurrentActionUserId,
// CurrentActionUser = subjectVisit.CurrentActionUser,
// CurrentActionUserExpireTime = subjectVisit.CurrentActionUserExpireTime,
// PreliminaryAuditTime = subjectVisit.PreliminaryAuditTime,
// PreliminaryAuitUser = subjectVisit.PreliminaryAuitUser,
// ReviewAuitTime = subjectVisit.ReviewAuitTime,
// ReviewAuitUser = subjectVisit.ReviewAuitUser,
// AuditState = subjectVisit.AuditState,
// SubmitTime = subjectVisit.SubmitTime,
// IsTake = subjectVisit.IsTake,
// QCProcessEnum = trial.QCProcessEnum,
// TrialSiteCode = trialSite.TrialSiteCode,
// SubjectStatus = subject.Status,
// SubjectCode = subject.Code,
// StudyCount = study.StudyCount,
// };
#endregion
var query = _subjectVisitRepository.Where(x => x.TrialId == visitSearchDTO.TrialId)
.WhereIf(visitSearchDTO.SiteId != null, t => t.SiteId == visitSearchDTO.SiteId)
.WhereIf(visitSearchDTO.SubjectId != null, t => t.Subject.Id == visitSearchDTO.SubjectId)
.WhereIf(!string.IsNullOrEmpty(visitSearchDTO.SubjectInfo), t => /*t.Subject.FirstName.Contains(subjectInfo) || t.Subject.LastName.Contains(subjectInfo) ||*/ t.Subject.Code.Contains(visitSearchDTO.SubjectInfo))
.WhereIf(!string.IsNullOrEmpty(visitSearchDTO.VisitPlanInfo), visitSearchDTO.VisitPlanInfo.Contains('.') ? t => t.VisitNum.ToString().Contains(".") : t => t.VisitNum == decimal.Parse(visitSearchDTO.VisitPlanInfo))
//.WhereIf(visitSearchDTO.AuditState != null, t => t.AuditState == visitSearchDTO.AuditState)
.WhereIf(visitSearchDTO.AuditStateArray != null&& visitSearchDTO.AuditStateArray?.Length>0, t => visitSearchDTO.AuditStateArray!.Contains(t.AuditState))
.WhereIf(visitSearchDTO.HandleUserId != null, t => t.PreliminaryAuditUserId == visitSearchDTO.HandleUserId
|| t.ReviewAuditUserId == visitSearchDTO.HandleUserId
|| t.QCChallengeList.Any(t => t.CreateUserId == visitSearchDTO.HandleUserId)
|| t.QCChallengeDialogList.Any(t => t.CreateUserId == visitSearchDTO.HandleUserId))
.WhereIf(visitSearchDTO.IsUrgent != null, t => t.IsUrgent == visitSearchDTO.IsUrgent)
//.WhereIf(visitSearchDTO.SubmitState != null, t => t.SubmitState == visitSearchDTO.SubmitState)
//.WhereIf(visitSearchDTO.ChallengeState != null, t => t.ChallengeState == visitSearchDTO.ChallengeState)
.ProjectTo<QCVisitViewModel>(_mapper.ConfigurationProvider);
var pageList = query.ToPagedList(visitSearchDTO.PageIndex, visitSearchDTO.PageSize, visitSearchDTO.SortField, visitSearchDTO.Asc);
var config = await _repository.Where<Trial>(t => t.Id == visitSearchDTO.TrialId).ProjectTo<TrialSubjectAndSVConfig>(_mapper.ConfigurationProvider).FirstOrDefaultAsync().IfNullThrowException();
return ResponseOutput.Ok(pageList, config);
}
#endregion
#region 一致性核查 转发页面
/// <summary>
/// 获取一致性核查列表 CRC/PM 公用
/// </summary>
/// <param name="checkQuery"></param>
/// <returns></returns>
[HttpPost]
public async Task<IResponseOutput<PageOutput<QCCheckViewModel>, TrialSubjectAndSVConfig>> GetConsistencyVerificationList(CheckQuery checkQuery)
{
#region linq 废弃 byzhouhang 2021 11 30
//Expression<Func<Subject, bool>> subjectLambda = x => true;
//Expression<Func<SubjectVisit, bool>> subjectVisitLambda = x => x.TrialId == checkQuery.TrialId && x.AuditState == AuditStateEnum.QCPassed;
//Expression<Func<DicomStudy, bool>> studyLambda = x => x.TrialId == checkQuery.TrialId;
//if (checkQuery.SiteId != null && checkQuery.SiteId != Guid.Empty)
//{
// subjectVisitLambda = subjectVisitLambda.And(t => t.SiteId == checkQuery.SiteId.Value);
//}
//if (checkQuery.SubjectId != null && checkQuery.SubjectId != Guid.Empty)
//{
// subjectLambda = subjectLambda.And(t => t.Id == checkQuery.SubjectId.Value);
//}
//if (_userInfo.UserTypeEnumInt == (int)UserType.ClinicalResearchCoordinator)
//{
// var siteQuery = _userTrialSiteRepository.Where(t => t.UserId == _userInfo.Id && t.TrialId == checkQuery.TrialId).Select(t => t.SiteId);
// subjectVisitLambda = subjectVisitLambda.And(t => siteQuery.Contains(t.SiteId));
//}
//var query =
// from subjectVisit in _subjectVisitRepository.Where(subjectVisitLambda)
// join trialSite in _trialSiteRepository.Where(t => t.TrialId == checkQuery.TrialId) on subjectVisit.SiteId equals trialSite.SiteId
// join subject in _subjectRepository.Where() on subjectVisit.SubjectId equals subject.Id
// select new QCCheckViewModel()
// {
// Id = subjectVisit.Id,
// AuditState = subjectVisit.AuditState,
// CheckTime = subjectVisit.CheckTime,
// CheckState = subjectVisit.CheckState,
// CheckChallengeState = subjectVisit.CheckChallengeState,
// CheckResult = subjectVisit.CheckResult,
// VisitName = subjectVisit.VisitName,
// VisitNum = subjectVisit.VisitNum,
// SubjectCode = subject.Code,
// //Modality=study.Modalities,
// //StudyTime = subjectVisit.sv,
// TrialSiteCode = trialSite.TrialSiteCode,
// };
#endregion
var query = _subjectVisitRepository.Where(x => x.TrialId == checkQuery.TrialId)
.Where(x => x.AuditState == AuditStateEnum.QCPassed) //一致性核查中的,或者还没一致性核查的
.WhereIf(checkQuery.CheckState != null, t => t.CheckState == checkQuery.CheckState)
.WhereIf(checkQuery.SiteId != null, t => t.SiteId == checkQuery.SiteId)
.WhereIf(!string.IsNullOrEmpty(checkQuery.SubjectInfo), t => t.Subject.Code.Contains(checkQuery.SubjectInfo))
.WhereIf(!string.IsNullOrEmpty(checkQuery.VisitPlanInfo), checkQuery.VisitPlanInfo.Contains('.') ? t => t.InPlan == false : t => t.VisitNum == decimal.Parse(checkQuery.VisitPlanInfo))
.WhereIf(_userInfo.UserTypeEnumInt == (int)UserTypeEnum.ClinicalResearchCoordinator, t => t.TrialSite.CRCUserList.Any(t => t.UserId == _userInfo.Id))//CRC 过滤负责的site
.ProjectTo<QCCheckViewModel>(_mapper.ConfigurationProvider);
var pageList = await query.ToPagedListAsync(checkQuery.PageIndex, checkQuery.PageSize, checkQuery.SortField, checkQuery.Asc);
var config = await _repository.Where<Trial>(t => t.Id == checkQuery.TrialId).ProjectTo<TrialSubjectAndSVConfig>(_mapper.ConfigurationProvider).FirstOrDefaultAsync().IfNullThrowException();
return ResponseOutput.Ok(pageList, config);
}
/// <summary>
/// 一致性核查 聊天记录列表
/// </summary>
/// <param name="subjectVisitId"></param>
/// <returns></returns>
///
[HttpGet("{subjectVisitId:guid}")]
public async Task<List<CheckChanllengeDialogDTO>> GetCheckChallengeDialogList(Guid subjectVisitId)
{
var list = await _repository.Where<CheckChallengeDialog>(t => t.SubjectVisitId == subjectVisitId).OrderBy(t => t.CreateTime)
.ProjectTo<CheckChanllengeDialogDTO>(_mapper.ConfigurationProvider).ToListAsync();
list.ForEach(t => t.IsCurrentUser = _userInfo.Id == t.CreateUserId);
return list;
}
/// <summary>
/// 转发列表 查询一致性核查通过的,针对不一致性核查的 要维护CV状态
/// </summary>
/// <param name="forwardQuery"></param>
/// <returns></returns>
[HttpPost]
public async Task<IResponseOutput<PageOutput<ForWardViewModel>>> GetForwardList(ForwardQuery forwardQuery)
{
//var trialConfig = _trialReposioty.Select(t => new { TrialId = t.Id, t.QCProcessEnum, t.IsImageConsistencyVerification }).FirstOrDefault(t => t.TrialId == forwardQuery.TrialId);
var query = _subjectVisitRepository.Where(x => x.TrialId == forwardQuery.TrialId)
.Where(t => t.CheckState == CheckStateEnum.CVPassed)
.WhereIf(forwardQuery.ForwardState != null, t => t.ForwardState == forwardQuery.ForwardState)
.WhereIf(forwardQuery.SiteId != null, t => t.SiteId == forwardQuery.SiteId)
.WhereIf(!string.IsNullOrEmpty(forwardQuery.SubjectInfo), t => t.Subject.Code.Contains(forwardQuery.SubjectInfo))
.WhereIf(!string.IsNullOrEmpty(forwardQuery.VisitPlanInfo), forwardQuery.VisitPlanInfo.Contains('.') ? t => t.InPlan == false : t => t.VisitNum == decimal.Parse(forwardQuery.VisitPlanInfo))
//.WhereIf(_userInfo.UserTypeEnumInt == (int)UserType.ClinicalResearchCoordinator, t => t.TrialSite.CRCUserList.Any(t => t.UserId == _userInfo.Id))//CRC 过滤负责的site
.ProjectTo<ForWardViewModel>(_mapper.ConfigurationProvider);
var pageList = await query.ToPagedListAsync(forwardQuery.PageIndex, forwardQuery.PageSize, forwardQuery.SortField, forwardQuery.Asc);
return ResponseOutput.Ok(pageList);
}
#endregion
#region QC 具体质控页面 各种列表
/// <summary>
/// 获取某次访视 QA界面所有信息 单独每一项都有接口(往下看),这里是一个大接口,方便第一次获取完整的所有的数据
/// </summary>
/// <param name="subjectVisitId"></param>
/// <param name="trialQCProcess">项目配置的针对访视检查是那种审核0 不审1 单审2双审</param>
/// <param name="currentQCType">当前 QC进入的是那种审核 1 单审2复审</param>
[HttpGet("{subjectVisitId:guid}/{trialQCProcess:int}/{currentQCType:int}")]
public async Task<TrialVisitQADTO> GetVisitQCInfo(Guid subjectVisitId, [FromRoute] TrialQCProcess trialQCProcess, [FromRoute] CurrentQC currentQCType)
{
var sv = (await _subjectVisitRepository.FirstOrDefaultAsync(t => t.Id == subjectVisitId)).IfNullThrowException();
if (currentQCType == CurrentQC.First)
{
if (_userInfo.Id != sv.CurrentActionUserId)
{
throw new Exception("当前用户不是初审用户,不允许操作!");
}
}
else
{
if (_userInfo.Id != sv.CurrentActionUserId)
{
throw new Exception("当前用户不是复审用户,不允许操作!");
}
}
var temp = await GetVisitQCStudyAndSeriesList(subjectVisitId);
var qacheckList = await GetQCQuestionAnswerList(subjectVisitId, sv.TrialId, trialQCProcess, currentQCType);
return new TrialVisitQADTO
{
QCQuestionAnswerList = qacheckList,
StudyList = temp.StudyList,
SeriesList = temp.SeriesList,
RelationInfo = await GetVisitQCSubjectInfo(subjectVisitId),
NoneDicomStudyList = await _repository.Where<NoneDicomStudy>(t => t.SubjectVisitId == subjectVisitId).ProjectTo<NoneDicomStudyView>(_mapper.ConfigurationProvider, new { token = _userInfo.UserToken }).ToListAsync(),
SubjectClinicalData = await _subjectVisitRepository.Where(t => t.Id == subjectVisitId)
.ProjectTo<SubjectClinicalDataDto>(_mapper.ConfigurationProvider, new { subjectVisitId = subjectVisitId, token = _userInfo.UserToken }).FirstOrDefaultAsync()
};
}
/// <summary>
/// 获取某次访视 QC 问题核对答案 列表 初始化进去的时候是模板项QC填写了就是对应的内容
/// </summary>
/// <param name="subjectVisitId"></param>
/// <param name="trialId"></param>
/// <param name="trialQCProcess">项目配置的针对访视检查是那种审核0 不审1 单审2双审</param>
/// <param name="currentQCType">当前 QC进入的是那种审核 1 单审2复审</param>
[HttpGet("{trialId:guid}/{subjectVisitId:guid}/{trialQCProcess:int}/{currentQCType:int}")]
public async Task<List<QCQuestionAnswerItemDto>> GetQCQuestionAnswerList(Guid subjectVisitId, Guid trialId, [FromRoute] TrialQCProcess trialQCProcess, [FromRoute] CurrentQC currentQCType)
{
//https://github.com/dotnet/efcore/issues/26833 ef core 导航属性不支持右连接
// 直接用ProjectTo的方式 多做一次查询 代码简洁很多 特别是连表多,字段多的情况
if (await _repository.AnyAsync<TrialQCQuestionAnswer>(t => t.SubjectVisitId == subjectVisitId && t.QCProcessEnum == trialQCProcess && t.CurrentQCEnum == currentQCType))
{
var list = await _repository.Where<TrialQCQuestionAnswer>(t => t.SubjectVisitId == subjectVisitId && t.QCProcessEnum == trialQCProcess && t.CurrentQCEnum == currentQCType).OrderBy(t => t.TrialQCQuestionConfigure.ShowOrder)
.ProjectTo<QCQuestionAnswerItemDto>(_mapper.ConfigurationProvider).ToListAsync();
return list;
}
else
{
return await _repository.Where<TrialQCQuestion>(t => t.IsEnable == true && t.TrialId == trialId).OrderBy(t => t.ShowOrder).ProjectTo<QCQuestionAnswerItemDto>(_mapper.ConfigurationProvider).ToListAsync();
}
}
/// <summary>
/// 获次QC 历史质疑列表 不分页
/// </summary>
/// <param name="subjectVisitId"></param>
/// <param name="trialQCProcess">项目配置的针对访视检查是那种审核0 不审1 单审2双审</param>
/// <param name="currentQCType">当前 QC进入的是那种审核 1 单审2复审</param>
[HttpGet("{subjectVisitId:guid}/{trialQCProcess:int}/{currentQCType:int}")]
public async Task<List<QCChallengeWithUser>> GetHistoryChallengeList(Guid subjectVisitId, [FromRoute] TrialQCProcess trialQCProcess, [FromRoute] CurrentQC currentQCType)
{
var qaChallengeQuery = _repository.Where<QCChallenge>(t => t.SubjectVisitId == subjectVisitId && t.QCProcessEnum == trialQCProcess)
.WhereIf(currentQCType == CurrentQC.First, t => t.CurrentQCEnum == currentQCType)//复审的时候可以看到初审的质疑
.ProjectTo<QCChallengeWithUser>(_mapper.ConfigurationProvider);
var qaChallenges = await qaChallengeQuery.ToListAsync();
return qaChallenges;
}
/// <summary>
/// 获取访视下的受试者访视、受试者、site信息
/// </summary>
/// <param name="subjectVisitId"></param>
/// <returns></returns>
public async Task<QARelationInfo> GetVisitQCSubjectInfo(Guid subjectVisitId)
{
// automapper Explicit expansion ProjectTo
return await _subjectVisitRepository.Where(t => t.Id == subjectVisitId).ProjectTo<QARelationInfo>(_mapper.ConfigurationProvider).FirstOrDefaultAsync().IfNullThrowException();
}
/// <summary>
/// 访视下的Study 和Series列表
/// </summary>
/// <param name="subjectVisitId"></param>
/// <returns></returns>
[HttpGet("{subjectVisitId:guid}")]
public async Task<QAStudySeriesInfo> GetVisitQCStudyAndSeriesList(Guid subjectVisitId)
{
var studyList = await _repository.Where<DicomStudy>(s => s.SubjectVisitId == subjectVisitId).IgnoreQueryFilters().ProjectTo<QAStudyInfoDTO>(_mapper.ConfigurationProvider).ToListAsync();
var studyIds = studyList.Select(t => t.StudyId).ToList();
var seriesList = await _repository.Where<DicomSeries>(t => studyIds.Contains(t.StudyId)).IgnoreQueryFilters().ProjectTo<QASeriesInfoDto>(_mapper.ConfigurationProvider).ToListAsync();
return new QAStudySeriesInfo { StudyList = studyList, SeriesList = seriesList };
}
/// <summary>
/// 访视下的检查列表
/// </summary>
/// <param name="subjectVisitId"></param>
/// <returns></returns>
[HttpGet("{subjectVisitId:guid}")]
public async Task<List<QAStudyInfoDTO>> GetSubjectVisitUploadedStudyList(Guid subjectVisitId)
{
return await _repository.Where<DicomStudy>(s => s.SubjectVisitId == subjectVisitId).IgnoreQueryFilters().ProjectTo<QAStudyInfoDTO>(_mapper.ConfigurationProvider).ToListAsync();
}
/// <summary>
/// 展开 某一QC质疑 下得 聊天记录
/// </summary>
/// <param name="qaChallengeId"></param>
/// <returns></returns>
[HttpGet("{qaChallengeId:guid}")]
public async Task<List<QCChanllengeDialogDTO>> GetQCChallengeDialogList(Guid qaChallengeId)
{
var list = await _repository.Where<QCChallengeDialog>(t => t.QCChallengeId == qaChallengeId).OrderBy(t => t.CreateTime)
.ProjectTo<QCChanllengeDialogDTO>(_mapper.ConfigurationProvider, new { currentUserId = _userInfo.Id }).ToListAsync();
//利用automapper 运行时映射
//list.ForEach(t => t.IsCurrentUser = _userInfo.Id == t.CreateUserId);
return list;
}
#endregion
/// <summary>
/// CRC/PM 看到某次访视下的所有质疑和聊天内容 包括初审和复审的 。
/// </summary>
/// <param name="subjectVisitId"></param>
/// <param name="trialQCProcess"></param>
/// <returns></returns>
[HttpGet("{subjectVisitId:guid}/{trialQCProcess:int}")]
public async Task<List<QCChallengeWithUser>> GetCRCVisitChallengeAndDialog(Guid subjectVisitId, [FromRoute] TrialQCProcess trialQCProcess)
{
var qaChallengeQuery = _repository.Where<QCChallenge>(t => t.SubjectVisitId == subjectVisitId && t.QCProcessEnum == trialQCProcess)
.ProjectTo<QCChallengeWithUser>(_mapper.ConfigurationProvider, new { currentUserId = _userInfo.Id });
var list = await qaChallengeQuery.ToListAsync();
//list.ForEach(t => t.DialogList.ToList().ForEach(u => u.IsCurrentUser = _userInfo.Id == u.CreateUserId));
return list;
}
/// <summary>
/// 质询发起人
/// </summary>
/// <param name="trialId"></param>
/// <returns></returns>
[HttpGet("{trialId:guid}")]
public async Task<List<QCChanllengeCreatorDto>> GetQCChallengeCreatorList(Guid trialId)
{
return await _repository.Where<TrialUser>(t => t.TrialId == trialId && t.User.UserTypeEnum == UserTypeEnum.IQC).Select(t => new QCChanllengeCreatorDto()
{
CreatorRealName = t.User.LastName + " / " + t.User.FirstName,
Creator = t.User.UserName,
CreateUserId = t.UserId
}).ToListAsync();
}
/// <summary>
/// QC 质疑页面 处理用户 下拉框
/// </summary>
/// <param name="trialId"></param>
/// <returns></returns>
[HttpGet("{trialId:guid}")]
public async Task<List<ParticipantDTO>> GetQCParticipantList(Guid trialId)
{
return await _repository.Where<TrialUser>(t => t.TrialId == trialId && (t.User.UserTypeEnum == UserTypeEnum.IQC || t.User.UserTypeEnum == UserTypeEnum.ClinicalResearchCoordinator)).Select(t => new ParticipantDTO()
{
HandleUserRealName = t.User.LastName + " / " + t.User.FirstName,
HandleUser = t.User.UserName,
HandleUserId = t.UserId
}).ToListAsync();
}
/// <summary>
/// 添加计划外访视 下拉框 选择上一次访视
/// </summary>
/// <param name="subjectId"></param>
/// <returns></returns>
[HttpGet("{subjectId:guid}")]
public async Task<List<SubjectVisitSelectItem>> GetSubjectVisitSelectList(Guid subjectId)
{
return await _subjectVisitRepository.Where(t => t.SubjectId == subjectId).OrderBy(T => T.VisitNum).ProjectTo<SubjectVisitSelectItem>(_mapper.ConfigurationProvider).ToListAsync();
}
/// <summary>
/// 上传界面 受试者 访视、site 基本信息
/// </summary>
/// <param name="subjectVisitId"></param>
/// <returns></returns>
[HttpGet("{subjectVisitId:guid}/{trialQCProcess:int}")]
[Obsolete]
public async Task<UploadViewInitDto> GetUploadInitInfo(Guid subjectVisitId)
{
return await _subjectVisitRepository.Where(t => t.Id == subjectVisitId).ProjectTo<UploadViewInitDto>(_mapper.ConfigurationProvider).FirstOrDefaultAsync().IfNullThrowException();
}
}
}