Files
irc-netcore-api/IRaCIS.Core.Application/Service/Visit/SubjectService.cs
T
hang 70160cb937
continuous-integration/drone/push Build is running
更新状态,不忽略null值
2026-06-17 17:17:01 +08:00

167 lines
6.8 KiB
C#

using IRaCIS.Application.Contracts;
using IRaCIS.Application.Interfaces;
using IRaCIS.Core.Application.Filter;
using IRaCIS.Core.Domain.Share;
using Microsoft.AspNetCore.Mvc;
namespace IRaCIS.Core.Application.Service
{
[ApiExplorerSettings(GroupName = "Trial")]
public class SubjectService(IRepository<Subject> _subjectRepository,
IRepository<Trial> _trialRepository,
IRepository<VisitStage> _visitStageRepository,
IRepository<SubjectVisit> _subjectVisitRepository, IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer) : BaseService, ISubjectService
{
/// <summary>
/// 添加或更新受试者信息[New]
/// </summary>
/// <param name="subjectCommand">state:1-访视中,2-出组。0-全部</param>
/// <returns></returns>
[TrialGlobalLimit( "AfterStopCannNotOpt" )]
//[Authorize(Policy = IRaCISPolicy.PM_APM_CRC_QC)]
public async Task<IResponseOutput<string>> AddOrUpdateSubject([FromBody] SubjectCommand subjectCommand)
{
var svlist = new List<SubjectVisit>();
if (await _trialRepository.AnyAsync(t => t.Id == subjectCommand.TrialId && !t.VisitPlanConfirmed))
{
//---项目访视计划没有确认。请联系项目经理确认项目访视计划后,再添加受试者。
return ResponseOutput.NotOk(_localizer["Subject_NoConfirmedPlan"]);
}
if ( !(await _visitStageRepository.AnyAsync(x => x.IsBaseLine && x.TrialId == subjectCommand.TrialId&&x.IsConfirmed)))
{
return ResponseOutput.NotOk(_localizer["Subject_NoBaseLinePlan"]);
}
var verifyExp1 = new EntityVerifyExp<Subject>()
{
VerifyExp = u => u.Code == subjectCommand.Code && u.TrialId == subjectCommand.TrialId,
//---已存在具有相关受试者编号的受试者。
VerifyMsg = _localizer["Subject_DuplicateSubjectNum"]
};
Subject? mapedSubject = null;
if (subjectCommand.Id == null) //insert
{
mapedSubject = await _subjectRepository.InsertFromDTOAsync(subjectCommand, false, verifyExp1);
}
else //update
{
mapedSubject = await _subjectRepository.UpdateFromDTOAsync(subjectCommand, false, false, verifyExp1/*, verifyExp2*/);
}
await _subjectRepository.SaveChangesAsync();
return ResponseOutput.Ok(mapedSubject.Id.ToString());
}
[HttpPut]
[UnitOfWork]
//[Authorize(Policy = IRaCISPolicy.PM_APM_CRC_QC)]
[TrialGlobalLimit( "AfterStopCannNotOpt" )]
public async Task<IResponseOutput> UpdateSubjectStatus(SubjectStatusChangeCommand subjectStatusChangeCommand)
{
subjectStatusChangeCommand.IsSubjectQuit = subjectStatusChangeCommand.Status == SubjectStatus.EndOfVisit;
await _subjectRepository.UpdateFromDTOAsync(subjectStatusChangeCommand,true, false);
return ResponseOutput.Ok();
}
[HttpDelete("{trialId:guid}/{id:guid}")]
[TrialGlobalLimit( "AfterStopCannNotOpt" )]
[UnitOfWork]
//[Authorize(Policy = IRaCISPolicy.PM_APM_CRC)]
public async Task<IResponseOutput> DeleteSubject(Guid id)
{
if (await _subjectVisitRepository.AnyAsync(u => u.SubjectId == id && u.VisitExecuted == VisitExecutedEnum.Executed))
{
//---该受试者已经有访视已经上传影像,不允许删除。
return ResponseOutput.NotOk(_localizer["Subject_UploadedVisitNoDelete"]);
}
await _subjectRepository.UpdatePartialFromQueryAsync(id, x => new Subject
{
IsDeleted = true,
});
await _subjectVisitRepository.UpdatePartialFromQueryAsync(u => u.SubjectId == id, x => new SubjectVisit()
{
IsDeleted = true,
});
var isSuccess = await _subjectRepository.SaveChangesAsync();
return ResponseOutput.Result(isSuccess);
}
/// <summary> 分页获取受试者列表[New] </summary>
/// /// <param name="inQuery">state:1-访视中,2-出组。0-全部</param>
[HttpPost]
public async Task<IResponseOutput<PageOutput<SubjectQueryView>>> GetSubjectList(SubjectQueryParam inQuery)
{
var subjectQuery = _subjectRepository.Where(u => u.TrialId == inQuery.TrialId)
.WhereIf(!string.IsNullOrWhiteSpace(inQuery.Code), t => t.Code.Contains(inQuery.Code))
.WhereIf(!string.IsNullOrWhiteSpace(inQuery.Name), t => t.ShortName.Contains(inQuery.Name))
.WhereIf(!string.IsNullOrWhiteSpace(inQuery.Sex), t => t.Sex.Contains(inQuery.Sex))
.WhereIf(inQuery.Status != null, t => t.Status == inQuery.Status)
.WhereIf(inQuery.IsSubjectQuit != null, t => t.IsSubjectQuit == inQuery.IsSubjectQuit)
.WhereIf(inQuery.TrialSiteId != null, t => t.TrialSiteId == inQuery.TrialSiteId)
// CRC 只负责他管理site的受试者
.WhereIf(_userInfo.UserTypeEnumInt == (int)UserTypeEnum.ClinicalResearchCoordinator || _userInfo.UserTypeEnumInt == (int)UserTypeEnum.CRA, t => t.TrialSite.CRCUserList.Any(t => t.UserId == _userInfo.UserRoleId))
.ProjectTo<SubjectQueryView>(_mapper.ConfigurationProvider)
.WhereIf(inQuery.IsMissingImages != null, t => t.IsMissingImages == inQuery.IsMissingImages);
var pageList = await subjectQuery.ToPagedListAsync(inQuery, nameof(SubjectQueryView.Code));
var trialConfig = await _trialRepository.Where(t => t.Id == inQuery.TrialId).ProjectTo<TrialSubjectConfig>(_mapper.ConfigurationProvider).FirstOrDefaultAsync().IfNullThrowException();
return ResponseOutput.Ok(pageList, trialConfig);
}
/// <summary>
/// 计划外访视 获取受试者选择下拉框列表
/// </summary>
[HttpGet("{trialSiteId:guid}/{trialId:guid}")]
public List<SubjectSelect> GetSubjectListBySiteId(Guid trialSiteId, Guid trialId)
{
var query = _subjectRepository.Where(t => t.TrialSiteId == trialSiteId && t.TrialId == trialId && t.Status == SubjectStatus.OnVisit).Select(u => new SubjectSelect()
{
Code = u.Code,
FirstName = u.FirstName,
LastName = u.LastName,
Sex = u.Sex,
SubjectId = u.Id,
Age = u.Age,
MRN = u.MedicalNo,
Status = u.Status,
FirstGiveMedicineTime = u.FirstGiveMedicineTime
});
return query.ToList();
}
}
}