irc-netcore-api/IRaCIS.Core.Application/Service/Visit/SubjectService.cs

344 lines
15 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.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 Newtonsoft.Json;
namespace IRaCIS.Application.Services
{
[ApiExplorerSettings(GroupName = "Trial")]
public class SubjectService : BaseService, ISubjectService
{
private readonly IRepository<Subject> _subjectRepository;
private readonly IInspectionService _inspectionService;
public SubjectService(IRepository<Subject> subjectRepository, IInspectionService inspectionService)
{
_subjectRepository = subjectRepository;
this._inspectionService = inspectionService;
}
/// <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)
{
bool isadd = false;
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."
};
var mapedSubject = await _subjectRepository.InsertOrUpdateAsync(subjectCommand, false, verifyExp1/*, verifyExp2*/);
if (subjectCommand.Id == null) //insert
{
isadd = true;
var IsEnrollementQualificationConfirm = await _repository.Where<Trial>(t => t.Id == mapedSubject.TrialId).Select(u => u.IsEnrollementQualificationConfirm).FirstOrDefaultAsync();
//添加受试者的时候,获取访视计划列表,添加到受试者访视表。
var visitPlan = await _repository.Where<VisitStage>(t => t.TrialId == subjectCommand.TrialId).ToListAsync();
var svlist = _mapper.Map<List<SubjectVisit>>(visitPlan);
svlist.ForEach(t =>
{
t.TrialId = subjectCommand.TrialId;
t.SiteId = subjectCommand.SiteId;
t.IsEnrollmentConfirm = t.IsBaseLine ? IsEnrollementQualificationConfirm : false;
});
mapedSubject.SubjectVisitList = svlist;
}
else //update
{
//变更site
if (mapedSubject.SiteId != subjectCommand.SiteId)
{
await _repository.UpdateFromQueryAsync<SubjectVisit>(t => t.SubjectId == mapedSubject.Id,
u => new SubjectVisit() { SiteId = mapedSubject.SiteId });
await _repository.UpdateFromQueryAsync<DicomStudy>(t => t.SubjectId == mapedSubject.Id,
u => new DicomStudy() { SiteId = mapedSubject.SiteId });
};
////如果访视结束了 需要删除计划外未执行的访视
//if (mapedSubject.Status == SubjectStatus.EndOfVisit)
//{
// await _repository.DeleteFromQueryAsync<SubjectVisit>(t => t.VisitExecuted == VisitExecutedEnum.UnExecuted && t.SubjectId == mapedSubject.Id && t.InPlan == false);
//}
////如果是出组了 将受试者未执行的 设置为不可用
//if (mapedSubject.Status == SubjectStatus.OutOfEnrollment)
//{
// await _repository.UpdateFromQueryAsync<SubjectVisit>(t => t.SubjectId == mapedSubject.Id && t.VisitExecuted == VisitExecutedEnum.UnExecuted, u => new SubjectVisit() { VisitExecuted = VisitExecutedEnum.Unavailable });
//}
}
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= "OnVisit",
})
});
var visittime = createtime.AddSeconds(1);
foreach (var item in mapedSubject.SubjectVisitList)
{
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 = JsonConvert.SerializeObject(new
{
VisitName = item.VisitName,
VisitNum = item.VisitNum,
IsBaseLine=item.IsBaseLine,
VisitExecuted= "否",
IsFinalVisit=item.IsFinalVisit,
PDState="",
IsLostVisit=item.IsLostVisit,
})
});
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 = JsonConvert.SerializeObject(new
{
VisitName = item.VisitName,
SubmitState = "",
AuditState = "",
})
});
}
await _inspectionService.AddListInspectionRecordAsync(datas);
}
return ResponseOutput.Ok(mapedSubject.Id.ToString());
}
[HttpPut("{trialId:guid}")]
public async Task<IResponseOutput> UpdateSubjectStatus(SubjectStatusChangeCommand subjectStatusChangeCommand)
{
var subject = await _subjectRepository.FirstOrDefaultAsync(t => t.Id == subjectStatusChangeCommand.SubjectId);
if (subject == null) return Null404NotFound(subject);
_mapper.Map(subjectStatusChangeCommand, subject);
////如果访视结束了 需要删除计划外未执行的访视
//if (subjectStatusChangeCommand.Status == SubjectStatus.EndOfVisit)
//{
// await _repository.DeleteFromQueryAsync<SubjectVisit>(t => t.VisitExecuted == VisitExecutedEnum.UnExecuted && t.SubjectId == subject.Id && t.InPlan == false);
//}
//如果是出组了
if (subjectStatusChangeCommand.Status == SubjectStatus.OutOfVisit)
{
if (subjectStatusChangeCommand.FinalSubjectVisitId != null)
{
if (await _repository.AnyAsync<SubjectVisit>(t => t.SubjectId == subjectStatusChangeCommand.SubjectId && t.IsFinalVisit && t.Id != subjectStatusChangeCommand.FinalSubjectVisitId))
{
return ResponseOutput.NotOk("该受试者已经有访视设置为末次访视,不允许将该访视设置为末次访视");
}
var sv = await _repository.FirstOrDefaultAsync<SubjectVisit>(t => t.Id == subjectStatusChangeCommand.FinalSubjectVisitId).IfNullThrowException();
if (await _repository.AnyAsync<SubjectVisit>(t => t.SubjectId == subjectStatusChangeCommand.SubjectId && t.VisitNum > sv.VisitNum && t.SubmitState == SubmitStateEnum.ToSubmit))
{
return ResponseOutput.NotOk("该受试者此访视后有影像上传,该访视不允许设置为末次访视");
}
sv.IsFinalVisit = true;
//末次访视后的 访视设置为不可用
await _repository.UpdateFromQueryAsync<SubjectVisit>(t => t.SubjectId == subjectStatusChangeCommand.SubjectId && t.VisitNum > sv.VisitNum, u => new SubjectVisit() { VisitExecuted = VisitExecutedEnum.Unavailable });
}
//将受试者未执行的 设置为不可用
await _repository.UpdateFromQueryAsync<SubjectVisit>(t => t.SubjectId == subject.Id && t.VisitExecuted == VisitExecutedEnum.UnExecuted, u => new SubjectVisit() { VisitExecuted = VisitExecutedEnum.Unavailable });
}
else
{
}
await _repository.SaveChangesAsync();
return ResponseOutput.Ok();
}
[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();
}
[HttpDelete("{id:guid}/{trialId:guid}")]
[TrialAudit(AuditType.SubjectAudit, AuditOptType.DeleteSubject)]
[TypeFilter(typeof(TrialResourceFilter))]
public async Task<IResponseOutput> DeleteSubject(Guid id)
{
if (await _repository.AnyAsync<SubjectVisit>(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.DeleteFromQueryAsync(u => u.Id == id);
await _repository.DeleteFromQueryAsync<SubjectVisit>(u => u.SubjectId == id);
var subvisit = await _repository.GetQueryable<SubjectVisit>().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();
}
}
}