292 lines
12 KiB
C#
292 lines
12 KiB
C#
using IRaCIS.Application.Interfaces;
|
||
using IRaCIS.Application.Contracts;
|
||
using IRaCIS.Core.Infra.EFCore;
|
||
using IRaCIS.Core.Application.Filter;
|
||
using IRaCIS.Core.Domain.Share;
|
||
using Microsoft.AspNetCore.Mvc;
|
||
using IRaCIS.Core.Application.Service.Inspection.Interface;
|
||
using IRaCIS.Core.Infrastructure;
|
||
using Newtonsoft.Json;
|
||
using IRaCIS.Core.Domain.Common;
|
||
|
||
namespace IRaCIS.Application.Services
|
||
{
|
||
[ApiExplorerSettings(GroupName = "Trial")]
|
||
public class SubjectService : BaseService, ISubjectService
|
||
{
|
||
private readonly IRepository<Subject> _subjectRepository;
|
||
private readonly IInspectionService _inspectionService;
|
||
private readonly IRepository<SubjectVisit> _subjectVisitRepository;
|
||
|
||
public SubjectService(IRepository<Subject> subjectRepository, IInspectionService inspectionService,IRepository<SubjectVisit> subjectVisitRepository)
|
||
{
|
||
_subjectRepository = subjectRepository;
|
||
_inspectionService = inspectionService;
|
||
_subjectVisitRepository = subjectVisitRepository;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 添加或更新受试者信息[New]
|
||
/// </summary>
|
||
/// <param name="subjectCommand">state:1-访视中,2-出组。0-全部</param>
|
||
/// <returns></returns>
|
||
|
||
[TrialAudit(AuditType.SubjectAudit, AuditOptType.AddOrUpdateSubject)]
|
||
[TypeFilter(typeof(TrialResourceFilter))]
|
||
public async Task<IResponseOutput<string>> AddOrUpdateSubject([FromBody] SubjectCommand subjectCommand)
|
||
{
|
||
var svlist = new List<SubjectVisit>();
|
||
if (await _repository.AnyAsync<Trial>(t => t.Id == subjectCommand.TrialId && !t.VisitPlanConfirmed))
|
||
{
|
||
return ResponseOutput.NotOk("The trial visit plan has not been confirmed yet.Please contact the project manager to confirm the visit plan before adding subject.");
|
||
}
|
||
|
||
var verifyExp1 = new EntityVerifyExp<Subject>()
|
||
{
|
||
VerifyExp = u => u.Code == subjectCommand.Code && u.TrialId == subjectCommand.TrialId,
|
||
VerifyMsg = "A subjects with the same subject ID already existed in this trial."
|
||
};
|
||
|
||
|
||
bool isadd = false;
|
||
|
||
Subject mapedSubject = null;
|
||
|
||
if (subjectCommand.Id == null) //insert
|
||
{
|
||
isadd = true;
|
||
|
||
mapedSubject= await _subjectRepository.InsertFromDTOAsync(subjectCommand, false, verifyExp1);
|
||
|
||
|
||
//添加受试者的时候,获取访视计划列表,添加到受试者访视表。
|
||
var visitPlan = await _repository.Where<VisitStage>(t => t.TrialId == subjectCommand.TrialId).ToListAsync();
|
||
|
||
svlist = _mapper.Map<List<SubjectVisit>>(visitPlan);
|
||
|
||
var IsEnrollementQualificationConfirm = await _repository.Where<Trial>(t => t.Id == mapedSubject.TrialId).Select(u => u.IsEnrollementQualificationConfirm).FirstOrDefaultAsync();
|
||
|
||
svlist.ForEach(t =>
|
||
{
|
||
t.SubjectId = mapedSubject.Id;
|
||
t.TrialId = subjectCommand.TrialId;
|
||
t.SiteId = subjectCommand.SiteId;
|
||
t.IsEnrollmentConfirm = t.IsBaseLine ? IsEnrollementQualificationConfirm : false;
|
||
});
|
||
|
||
|
||
await _subjectVisitRepository.AddRangeAsync(svlist);
|
||
}
|
||
else //update
|
||
{
|
||
|
||
mapedSubject = await _subjectRepository.UpdateFromDTOAsync(subjectCommand, false,false, verifyExp1/*, verifyExp2*/);
|
||
|
||
}
|
||
|
||
|
||
|
||
await _repository.SaveChangesAsync();
|
||
|
||
|
||
var createtime = DateTime.Now.AddSeconds(1);
|
||
// 添加稽查记录
|
||
if (isadd)
|
||
{
|
||
List<DataInspection> datas = new List<DataInspection>();
|
||
|
||
// 移到仓储了
|
||
|
||
//datas.Add(new DataInspection()
|
||
//{
|
||
// TrialId = subjectCommand.TrialId,
|
||
// SiteId = subjectCommand.SiteId,
|
||
// SubjectId = mapedSubject.Id,
|
||
// SubjectCode = subjectCommand.Code,
|
||
// IsSign=false,
|
||
// CreateTime = createtime,
|
||
// Identification = "Init|Subject|Status|Subject",
|
||
// JsonDetail= JsonConvert.SerializeObject(new {
|
||
// Status= "新增",
|
||
// })
|
||
//});
|
||
|
||
|
||
JsonSerializerSettings settings = new JsonSerializerSettings();
|
||
settings.PreserveReferencesHandling = PreserveReferencesHandling.Objects;
|
||
settings.ReferenceLoopHandling = ReferenceLoopHandling.Serialize;
|
||
//var jsonData = JsonConvert.SerializeObject(info, settings);
|
||
|
||
var visittime = createtime.AddSeconds(1);
|
||
foreach (var item in svlist)
|
||
{
|
||
// 添加访视
|
||
datas.Add(new DataInspection()
|
||
{
|
||
TrialId = subjectCommand.TrialId,
|
||
SiteId = subjectCommand.SiteId,
|
||
SubjectId = mapedSubject.Id,
|
||
SubjectCode = subjectCommand.Code,
|
||
SubjectVisitId = item.Id,
|
||
SubjectVisitName = item.VisitName,
|
||
BlindName = item.BlindName,
|
||
IsSign = false,
|
||
CreateTime = visittime,
|
||
Identification = "Add|Visit|Info|Visit-Image Upload",
|
||
JsonDetail = item.ToJcJson()
|
||
});
|
||
|
||
// 初始化访视
|
||
datas.Add(new DataInspection()
|
||
{
|
||
TrialId = subjectCommand.TrialId,
|
||
SiteId = subjectCommand.SiteId,
|
||
SubjectId = mapedSubject.Id,
|
||
SubjectCode = subjectCommand.Code,
|
||
SubjectVisitId = item.Id,
|
||
|
||
BlindName = item.BlindName,
|
||
SubjectVisitName = item.VisitName,
|
||
IsSign = false,
|
||
CreateTime = visittime.AddSeconds(1),
|
||
Identification = "Init|Visit|Status|Visit-Image Upload",
|
||
JsonDetail = item.ToJcJson()
|
||
});
|
||
}
|
||
|
||
|
||
await _inspectionService.AddListInspectionRecordAsync(datas);
|
||
}
|
||
|
||
return ResponseOutput.Ok(mapedSubject.Id.ToString());
|
||
|
||
}
|
||
|
||
[HttpPut("{trialId:guid}")]
|
||
[UnitOfWork]
|
||
public async Task<IResponseOutput> UpdateSubjectStatus(SubjectStatusChangeCommand subjectStatusChangeCommand)
|
||
{
|
||
|
||
await _subjectRepository.UpdateFromDTOAsync(subjectStatusChangeCommand, true);
|
||
|
||
return ResponseOutput.Ok();
|
||
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
[HttpDelete("{id:guid}/{trialId:guid}")]
|
||
|
||
[TrialAudit(AuditType.SubjectAudit, AuditOptType.DeleteSubject)]
|
||
[TypeFilter(typeof(TrialResourceFilter))]
|
||
public async Task<IResponseOutput> DeleteSubject(Guid id)
|
||
{
|
||
|
||
if (await _subjectVisitRepository.AnyAsync(u => u.SubjectId == id && u.VisitExecuted == VisitExecutedEnum.Executed))
|
||
{
|
||
return ResponseOutput.NotOk("This subject has executed a visit with uploading study images,and couldn't be deleted.");
|
||
}
|
||
|
||
var isSuccess = await _subjectRepository.BatchDeleteNoTrackingAsync(u => u.Id == id);
|
||
await _subjectVisitRepository.DeleteFromQueryAsync(u => u.SubjectId == id);
|
||
|
||
|
||
var subvisit = await _subjectVisitRepository.Where(x => x.SubjectId == id).ToListAsync();
|
||
|
||
List<DataInspection> datas = new List<DataInspection>();
|
||
|
||
foreach (var item in subvisit)
|
||
{
|
||
datas.Add(new DataInspection()
|
||
{
|
||
SiteId = item.SiteId,
|
||
SubjectId = item.SubjectId,
|
||
TrialId = item.TrialId,
|
||
SubjectVisitId = item.Id,
|
||
Identification = "Delete|Visit|Data|Visit-Image Upload",
|
||
JsonDetail = JsonConvert.SerializeObject(item)
|
||
});
|
||
};
|
||
|
||
|
||
|
||
await _inspectionService.AddListInspectionRecordAsync(datas);
|
||
return ResponseOutput.Result(isSuccess);
|
||
}
|
||
|
||
/// <summary> 分页获取受试者列表[New] </summary>
|
||
/// /// <param name="param">state:1-访视中,2-出组。0-全部</param>
|
||
[HttpPost]
|
||
public async Task<IResponseOutput<PageOutput<SubjectQueryView>, TrialSubjectConfig>> GetSubjectList(SubjectQueryParam param)
|
||
{
|
||
|
||
var subjectQuery = _subjectRepository.Where(u => u.TrialId == param.TrialId)
|
||
.WhereIf(!string.IsNullOrWhiteSpace(param.Code), t => t.Code.Contains(param.Code))
|
||
.WhereIf(!string.IsNullOrWhiteSpace(param.Name), t => t.ShortName.Contains(param.Name))
|
||
.WhereIf(!string.IsNullOrWhiteSpace(param.Sex), t => t.Sex.Contains(param.Sex))
|
||
.WhereIf(param.Status != null, t => t.Status == param.Status)
|
||
.WhereIf(param.SiteId != null, t => t.SiteId == param.SiteId)
|
||
// CRC 只负责他管理site的受试者
|
||
.WhereIf(_userInfo.UserTypeEnumInt == (int)UserTypeEnum.ClinicalResearchCoordinator, t => t.TrialSite.CRCUserList.Any(t => t.UserId == _userInfo.Id))
|
||
.ProjectTo<SubjectQueryView>(_mapper.ConfigurationProvider);
|
||
|
||
|
||
var pageList = await subjectQuery.ToPagedListAsync(param.PageIndex, param.PageSize, param.SortField == string.Empty ? "Code" : param.SortField, param.Asc);
|
||
|
||
var trialConfig = await _repository.Where<Trial>(t => t.Id == param.TrialId).ProjectTo<TrialSubjectConfig>(_mapper.ConfigurationProvider).FirstOrDefaultAsync().IfNullThrowException();
|
||
|
||
return ResponseOutput.Ok(pageList, trialConfig);
|
||
|
||
}
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// 计划外访视 获取受试者选择下拉框列表
|
||
/// </summary>
|
||
[HttpGet("{siteId:guid}/{trialId:guid}")]
|
||
public List<SubjectSelect> GetSubjectListBySiteId(Guid siteId, Guid trialId)
|
||
{
|
||
var query = _subjectRepository.Where(t => t.SiteId == siteId && 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();
|
||
}
|
||
|
||
[Obsolete]
|
||
[HttpGet("{trialId:guid}/{subjectId:guid}/{finalSubjectVisitId:guid}")]
|
||
public async Task<IResponseOutput> VerifySubjectFinalVisit(Guid subjectId, Guid finalSubjectVisitId)
|
||
{
|
||
|
||
if (await _repository.AnyAsync<SubjectVisit>(t => t.SubjectId == subjectId && t.IsFinalVisit))
|
||
{
|
||
return ResponseOutput.NotOk("该受试者已经有访视设置为末次访视,不允许将该访视设置为末次访视");
|
||
}
|
||
|
||
var sv = (await _repository.FirstOrDefaultAsync<SubjectVisit>(t => t.Id == finalSubjectVisitId)).IfNullThrowException();
|
||
|
||
if (await _repository.AnyAsync<SubjectVisit>(t => t.SubjectId == subjectId && t.VisitNum > sv.VisitNum && t.SubmitState == SubmitStateEnum.ToSubmit))
|
||
{
|
||
return ResponseOutput.NotOk("该受试者此访视后有影像上传,该访视不允许设置为末次访视");
|
||
}
|
||
|
||
return ResponseOutput.Ok();
|
||
}
|
||
|
||
}
|
||
}
|