irc-netcore-api/IRaCIS.Core.Application/Service/TrialSiteUser/TrialConfigService.cs

423 lines
16 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.Core.Application.Contracts;
using Microsoft.AspNetCore.Mvc;
using IRaCIS.Core.Infra.EFCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using IRaCIS.Core.Domain.Share;
using EasyCaching.Core;
using IRaCIS.Core.Application.Filter;
using IRaCIS.Core.Infrastructure;
namespace IRaCIS.Core.Application
{
[ApiExplorerSettings(GroupName = "Trial")]
public class TrialConfigService : BaseService, ITrialConfigService
{
private readonly IRepository<Trial> _trialRepository;
private readonly IEasyCachingProvider _provider;
public TrialConfigService(IRepository<Trial> trialRepository,
IEasyCachingProvider provider
)
{
_trialRepository = trialRepository;
this._provider = provider;
}
/// <summary>
/// 获取签名文本
/// </summary>
/// <param name="signCode"></param>
/// <returns></returns>
[HttpGet("{signCode}")]
public async Task<IResponseOutput> GetSignText(string signCode)
{
var signRawText = await _repository.Where<SystemBasicData>(t => t.Code == signCode).Select(t => new { t.Code, t.Value, t.Id, ParentValue = t.Parent.Value, ParentValueCN = t.Parent.ValueCN }).FirstOrDefaultAsync();
if (signRawText == null)
{
return ResponseOutput.NotOk("未在系统中找到该签名场景的数据");
}
return ResponseOutput.Ok(new
{
SignCodeId = signRawText.Id,
SignCode = signRawText.Code,
SignText = signRawText.ParentValue.Replace("xxx", signRawText.Value),
SignTextCN = signRawText.ParentValueCN.Replace("xxx", signRawText.Value)
});
}
/// <summary>
/// 签名认证 +
/// </summary>
/// <returns></returns>
[HttpPost]
public async Task<IResponseOutput> VerifySignature(SignDTO signDTO)
{
var user = await _repository.FirstOrDefaultAsync<User>(u => u.UserName == signDTO.UserName && u.Password == signDTO.PassWord);
if (user == null)
{
return ResponseOutput.NotOk("password error");
}
else if (user.Status == UserStateEnum.Disable)
{
return ResponseOutput.NotOk("The user has been disabled!");
}
//if (signDTO.IsAddSignData)
//{
// 记录签名信息
var add = await _repository.AddAsync(_mapper.Map<TrialSign>(signDTO));
await _repository.SaveChangesAsync();
return ResponseOutput.Ok(add.Id);
//}
//return ResponseOutput.Ok();
}
/// <summary>
/// 业务接口操作成功后, 让签署数据生效
/// </summary>
/// <param name="signId"></param>
/// <returns></returns>
[HttpPut("{signId:guid}")]
[Obsolete]
public async Task<IResponseOutput> MakeSignEffective(Guid signId)
{
var success = await _repository.BatchUpdateAsync<TrialSign>(t => t.Id == signId, u => new TrialSign() { IsCompleted = true });
return ResponseOutput.Result(success);
}
/// <summary>
/// 签名确认 包括项目的三组配置 + QC问题确认 后修改状态 (适用于不会回退的,项目废除、状态修改, 存在回退 不在这里弄,提供单独接口修改状态)
/// </summary>
/// <returns></returns>
public async Task<IResponseOutput> TrialConfigSignatureConfirm(SignConfirmDTO signConfirmDTO)
{
//var currentEntry = _trialRepository._dbContext.ChangeTracker.Entries().Where(x => x.Entity.GetType() == typeof(Trial)).ToList();
//currentEntry.ForEach(x =>
//{
// x.State = EntityState.Detached;
//});
if (!await _trialRepository.AnyAsync(t => t.Id == signConfirmDTO.TrialId && (t.TrialStatusStr == StaticData.TrialInitializing|| t.TrialStatusStr == StaticData.TrialOngoing)))
{
throw new BusinessValidationFailedException("项目不在Initializing/Ongoing不允许确认配置");
}
if (signConfirmDTO.SignCode == ((int)SignEnum.TrialLogicConfim).ToString())
{
await _trialRepository.UpdatePartialFromQueryAsync(t => t.Id == signConfirmDTO.TrialId, u => new Trial() { IsTrialBasicLogicConfirmed = true });
}
else if (signConfirmDTO.SignCode == ((int)SignEnum.TrialProcessConfim).ToString())
{
await _trialRepository.UpdatePartialFromQueryAsync(t => t.Id == signConfirmDTO.TrialId, u => new Trial() { IsTrialProcessConfirmed = true });
}
else if (signConfirmDTO.SignCode == ((int)SignEnum.TrialUrgentConfim).ToString())
{
await _trialRepository.UpdatePartialFromQueryAsync(t => t.Id == signConfirmDTO.TrialId, u => new Trial() { IsTrialUrgentConfirmed = true });
}
else if (signConfirmDTO.SignCode == ((int)SignEnum.TrialQCQuestionConfirm).ToString())
{
var trialConfig = (await _trialRepository
.Select(t => new { TrialId = t.Id, t.QCProcessEnum, t.IsImageConsistencyVerification })
.FirstOrDefaultAsync(t => t.TrialId == signConfirmDTO.TrialId))
.IfNullThrowException();
var showOrderList = await _repository.Where<TrialQCQuestion>(t => t.TrialId == signConfirmDTO.TrialId).Select(t =>
new { t.ShowOrder , ParentShowOrder=(int?) t.ParentQCQuestion.ShowOrder} ).ToListAsync();
if (trialConfig.QCProcessEnum ==
TrialQCProcess.DoubleAudit || trialConfig.QCProcessEnum == TrialQCProcess.SingleAudit)
{
if (showOrderList.Count == 0)
{
throw new BusinessValidationFailedException("请先添加影像质控审核问题,再确认");
}
}
if (showOrderList.Count() != showOrderList.Select(t=>t.ShowOrder).Distinct().Count())
{
throw new BusinessValidationFailedException("QC问题显示序号不允许重复");
}
if (showOrderList.Where(t=>t.ParentShowOrder != null).Any(t => t.ParentShowOrder > t.ShowOrder))
{
throw new BusinessValidationFailedException("父问题的序号要比子问题序号小,请确认");
}
await _trialRepository.UpdatePartialFromQueryAsync(t => t.Id == signConfirmDTO.TrialId, u => new Trial() { QCQuestionConfirmedTime = DateTime.Now, QCQuestionConfirmedUserId = _userInfo.Id, IsQCQuestionConfirmed = true });
}
return ResponseOutput.Ok();
}
/// <summary>
/// 配置 基础逻辑信息
/// </summary>
/// <param name="trialConfig"></param>
/// <returns></returns>
[HttpPut]
public async Task<IResponseOutput> ConfigTrialBasicInfo(BasicTrialConfig trialConfig)
{
if (!await _trialRepository.Where(t => t.Id == trialConfig.TrialId).IgnoreQueryFilters().AnyAsync(t => t.TrialStatusStr == StaticData.TrialOngoing || t.TrialStatusStr == StaticData.TrialInitializing))
{
return ResponseOutput.NotOk(" only in Initializing or Ongoing State can operate ");
}
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialConfig.TrialId);
if (trialInfo == null) return Null404NotFound(trialInfo);
_mapper.Map(trialConfig, trialInfo);
trialInfo.UpdateTime = DateTime.Now;
return ResponseOutput.Ok(await _repository.SaveChangesAsync());
}
[HttpGet("{trialId:guid}")]
public async Task<IResponseOutput> IfTrialCanOngoing(Guid trialId)
{
var canOPt = await _trialRepository.AnyAsync(trial =>
trial.Id == trialId && trial.IsTrialBasicLogicConfirmed && trial.IsTrialProcessConfirmed &&
trial.IsTrialUrgentConfirmed && trial.VisitPlanConfirmed);
return ResponseOutput.Ok(canOPt, msg: canOPt?"": "项目 基础配置、流程配置、加急配置 、访视计划,有未确认项");
}
/// <summary>
/// 更新项目状态
/// </summary>
/// <param name="trialId"></param>
/// <param name="trialStatusStr"></param>
/// <param name="reason"></param>
/// <returns></returns>
[HttpPut("{trialId:guid}/{trialStatusStr}/{reason?}")]
[UnitOfWork]
public async Task<IResponseOutput> UpdateTrialState(Guid trialId, string trialStatusStr, string? reason)
{
var trial = (await _trialRepository.Where(t => t.Id == trialId, true).IgnoreQueryFilters().FirstOrDefaultAsync()).IfNullThrowException();
if (trialStatusStr == StaticData.TrialOngoing)
{
if (trial.IsTrialBasicLogicConfirmed && trial.IsTrialProcessConfirmed && trial.IsTrialUrgentConfirmed && trial.VisitPlanConfirmed)
{
}
else
{
return ResponseOutput.NotOk("项目 基础配置、流程配置、加急配置 、访视计划,有未确认项");
}
}
if (trialStatusStr != "Ongoing")
{
trial.TrialFinishTime = DateTime.Now;
}
trial.TrialStateChangeList.Add(new TrialStateChange() { OriginState = trial.TrialStatusStr, NowState = trialStatusStr, Reason = reason ?? String.Empty, TrialId = trialId });
trial.TrialStatusStr = trialStatusStr;
//Paused、 添加工总量 算医生读片中
if (trialStatusStr.Contains(StaticData.TrialCompleted))
{
await _repository.BatchUpdateAsync<Enroll>(u => u.TrialId == trialId, e => new Enroll
{
EnrollStatus = (int)EnrollStatus.Finished
});
await _trialRepository.BatchUpdateNoTrackingAsync(u => u.Id == trialId, s => new Trial { TrialFinishedTime = DateTime.UtcNow.AddHours(8) });
}
await _provider.SetAsync(trialId.ToString(), trialStatusStr, TimeSpan.FromDays(7));
await _repository.SaveChangesAsync();
//var success = await _repository.BatchUpdateAsync<TrialSign>(t => t.Id == signId, u => new TrialSign() { IsCompleted = true });
return ResponseOutput.Ok();
}
/// <summary>
/// 项目状态 变更历史
/// </summary>
/// <param name="trialId"></param>
/// <returns></returns>
[HttpGet("{trialId:guid}")]
public async Task<List<TrialStateChangeDTO>> GetTrialStateChangeList(Guid trialId)
{
return await _repository.Where<TrialStateChange>(t => t.TrialId == trialId).ProjectTo<TrialStateChangeDTO>(_mapper.ConfigurationProvider).ToListAsync();
}
/// <summary>
/// 废除项目
/// </summary>
/// <param name="trialId"></param>
/// <param name="isAbandon"></param>
/// <returns></returns>
[HttpPut("{trialId:guid}/{isAbandon:bool}")]
public async Task<IResponseOutput> AbandonTrial(Guid trialId, /*Guid? signId,*/ bool isAbandon)
{
await _trialRepository.UpdatePartialFromQueryAsync(trialId, u => new Trial() {
IsDeleted = isAbandon,
TrialFinishTime= isAbandon?DateTime.Now:null
},true);
return ResponseOutput.Ok();
}
/// <summary>
/// 获取 配置的所有信息 没有分多个接口
/// </summary>
/// <param name="trialId"></param>
/// <returns></returns>
[HttpGet("{trialId:guid}")]
public async Task<TrialConfigDTO> GetTrialConfigInfo(Guid trialId)
{
return await _trialRepository.Where(t => t.Id == trialId).ProjectTo<TrialConfigDTO>(_mapper.ConfigurationProvider)
.FirstOrDefaultAsync().IfNullThrowException();
}
/// <summary>
/// 配置流程
/// </summary>
/// <param name="trialConfig"></param>
/// <returns></returns>
[HttpPut]
public async Task<IResponseOutput> ConfigTrialProcessInfo(TrialProcessConfig trialConfig)
{
if (!await _trialRepository.Where(t => t.Id == trialConfig.TrialId).IgnoreQueryFilters().AnyAsync(t => t.TrialStatusStr == StaticData.TrialInitializing))
{
return ResponseOutput.NotOk(" only in Initializing State can operate ");
}
var trialInfo = await _trialRepository.Where(t => t.Id == trialConfig.TrialId, true).Include(t => t.TrialDicList.Where(u => u.KeyName == StaticData.Criterion)).FirstOrDefaultAsync();
if (trialInfo == null) return Null404NotFound(trialInfo);
_mapper.Map(trialConfig, trialInfo);
trialInfo.UpdateTime = DateTime.Now;
return ResponseOutput.Ok(await _repository.SaveChangesAsync());
}
/// <summary>
/// 配置加急信息
/// </summary>
/// <param name="trialConfig"></param>
/// <returns></returns>
[HttpPut]
public async Task<IResponseOutput> ConfigTrialUrgentInfo(TrialUrgentConfig trialConfig)
{
if (!await _repository.Where<Trial>(t => t.Id == trialConfig.TrialId).IgnoreQueryFilters().AnyAsync(t => t.TrialStatusStr == StaticData.TrialOngoing || t.TrialStatusStr == StaticData.TrialInitializing))
{
return ResponseOutput.NotOk(" only in Initializing or Ongoing State can operate ");
}
var trialInfo = await _trialRepository.FirstOrDefaultAsync(t => t.Id == trialConfig.TrialId);
if (trialInfo == null) return Null404NotFound(trialInfo);
//项目紧急 当前所有已提交,但未完成的访视,设置为加急。后续提交的访视也设置为加急 ,
if (trialConfig.IsUrgent)
{
await _repository.BatchUpdateAsync<SubjectVisit>(t => t.TrialId == trialInfo.Id && t.SubmitState == SubmitStateEnum.Submitted && t.ForwardState < ForwardStateEnum.Forwarded,
s => new SubjectVisit() { IsUrgent = trialConfig.IsUrgent });
}
else //之前设置为加急的访视状态不变。后续提交的访视,为不加急。
{
}
_mapper.Map(trialConfig, trialInfo);
trialInfo.UpdateTime = DateTime.Now;
return ResponseOutput.Ok(await _repository.SaveChangesAsync());
}
[Obsolete]
[HttpPost("{trialId:guid}/{type}")]
public async Task<IResponseOutput> UploadTrialFile(IFormFile file, string type, Guid trialId, [FromServices] IWebHostEnvironment _hostEnvironment)
{
var rootPath = Directory.GetParent(_hostEnvironment.ContentRootPath.TrimEnd('\\')).IfNullThrowException().FullName;
//上传根路径
var _fileStorePath = Path.Combine(rootPath, StaticData.TrialDataFolder);
//文件类型路径处理
var uploadFolderPath = Path.Combine(_fileStorePath, trialId.ToString(), type);
if (!Directory.Exists(uploadFolderPath)) Directory.CreateDirectory(uploadFolderPath);
var realName = file.FileName;
var fileNameEX = Path.GetExtension(realName);
var trustedFileNameForFileStorage = Guid.NewGuid().ToString() + fileNameEX;
var relativePath = $"/{StaticData.TrialDataFolder}/{trialId}/{type}/{trustedFileNameForFileStorage}";
var filePath = Path.Combine(uploadFolderPath, trustedFileNameForFileStorage);
using (FileStream fs = System.IO.File.Create(filePath))
{
await file.CopyToAsync(fs);
fs.Flush();
}
return ResponseOutput.Ok(new
{
FilePath = relativePath,
FullFilePath = relativePath + "?access_token=" + _userInfo.UserToken
});
}
}
}