2856 lines
132 KiB
C#
2856 lines
132 KiB
C#
using IRaCIS.Core.Domain.Share;
|
||
using Microsoft.AspNetCore.Mvc;
|
||
using IRaCIS.Core.Application.Service.Reading.Dto;
|
||
using MassTransit;
|
||
using IRaCIS.Core.Infra.EFCore.Common;
|
||
using Panda.DynamicWebApi.Attributes;
|
||
using AutoMapper;
|
||
using IRaCIS.Core.Application.Contracts;
|
||
using IRaCIS.Core.Infrastructure;
|
||
using IRaCIS.Core.Application.Service;
|
||
using IRaCIS.Core.Application.ViewModel;
|
||
using IRaCIS.Core.Application.Interfaces;
|
||
using Newtonsoft.Json;
|
||
using Newtonsoft.Json.Linq;
|
||
using Microsoft.Extensions.Caching.Memory;
|
||
using IRaCIS.Core.Application.Filter;
|
||
using DocumentFormat.OpenXml.Drawing;
|
||
using Quartz;
|
||
using IRaCIS.Application.Services.BackGroundJob;
|
||
|
||
namespace IRaCIS.Application.Services
|
||
{
|
||
/// <summary>
|
||
/// IR影像阅片
|
||
/// </summary>
|
||
[ApiExplorerSettings(GroupName = "Reading")]
|
||
public partial class ReadingImageTaskService : BaseService, IReadingImageTaskService
|
||
{
|
||
|
||
private readonly IRepository<NoneDicomStudy> _noneDicomStudyRepository;
|
||
private readonly IRepository<VisitTask> _visitTaskRepository;
|
||
private readonly IRepository<Trial> _trialRepository;
|
||
private readonly IRepository<ReadingTableQuestionAnswer> _readingTableQuestionAnswerRepository;
|
||
private readonly IRepository<ReadingOncologyTaskInfo> _readingOncologyTaskInfoRepository;
|
||
private readonly IVisitTaskHelpeService _visitTaskHelpeService;
|
||
private readonly IVisitTaskService _visitTaskService;
|
||
private readonly IReadingClinicalDataService _readingClinicalDataService;
|
||
private readonly IReadingCalculateService _readingCalculateService;
|
||
private readonly IRepository<SubjectVisit> _subjectVisitRepository;
|
||
private readonly IRepository<Subject> _subjectRepository;
|
||
private readonly IRepository<ReadingGlobalTaskInfo> _readingGlobalTaskInfoRepository;
|
||
private readonly IRepository<ReadingCriterionPage> _readingCriterionPageRepository;
|
||
private readonly IRepository<ReadingTaskRelation> _readingTaskRelationRepository;
|
||
private readonly IRepository<ReadingJudgeInfo> _readingJudgeInfoRepository;
|
||
private readonly IRepository<ReadModule> _readModuleRepository;
|
||
private readonly IRepository<DicomInstance> _dicomInstanceRepository;
|
||
private readonly IRepository<OrganInfo> _organInfoRepository;
|
||
private readonly IRepository<TrialDocument> _trialDocumentRepository;
|
||
private readonly IRepository<User> _userRepository;
|
||
private readonly IRepository<ReadingCustomTag> _readingCustomTagRepository;
|
||
private readonly IRepository<ReadingSystemCriterionDictionary> _readingCriterionDictionaryRepository;
|
||
private readonly IRepository<ReadingTrialCriterionDictionary> _readingTrialCriterionDictionaryRepository;
|
||
private readonly IRepository<TumorAssessment_RECIST1Point1> _tumorAssessmentRepository;
|
||
private readonly IRepository<ReadingTableAnswerRowInfo> _readingTableAnswerRowInfoRepository;
|
||
private readonly IRepository<ReadingTableQuestionSystem> _readingTableQuestionSystemRepository;
|
||
private readonly IRepository<ReadingTableQuestionTrial> _readingTableQuestionTrialRepository;
|
||
private readonly IRepository<ReadingTaskQuestionAnswer> _readingTaskQuestionAnswerRepository;
|
||
private readonly IRepository<ReadingQuestionCriterionTrial> _readingQuestionCriterionTrialRepository;
|
||
private readonly IRepository<ReadingQuestionCriterionSystem> _readingQuestionCriterionSystemRepository;
|
||
private readonly IRepository<ReadingQuestionSystem> _readingQuestionSystem;
|
||
private readonly IRepository<NoneDicomStudyFile> _noneDicomStudyFileSystem;
|
||
private readonly IRepository<ReadingQuestionTrial> _readingQuestionTrialRepository;
|
||
private readonly ISchedulerFactory _schedulerFactory;
|
||
private readonly IMemoryCache _cache;
|
||
private readonly ITrialEmailNoticeConfigService _trialEmailNoticeConfigService;
|
||
|
||
|
||
public ReadingImageTaskService(
|
||
IMapper mapper,
|
||
IRepository<NoneDicomStudy> noneDicomStudyRepository,
|
||
IRepository<VisitTask> visitTaskRepository,
|
||
IRepository<Trial> TrialRepository,
|
||
IRepository<ReadingTableQuestionAnswer> ReadingTableQuestionAnswerRepository,
|
||
IRepository<ReadingOncologyTaskInfo> ReadingOncologyTaskInfoRepository,
|
||
IVisitTaskHelpeService visitTaskHelpeService,
|
||
IVisitTaskService visitTaskService,
|
||
IReadingClinicalDataService readingClinicalDataService,
|
||
IReadingCalculateService readingCalculateService,
|
||
IRepository<SubjectVisit> subjectVisitRepository,
|
||
IRepository<Subject> subjectRepository,
|
||
IRepository<ReadingGlobalTaskInfo> readingGlobalTaskInfoRepository,
|
||
IRepository<ReadingCriterionPage> readingCriterionPageRepository,
|
||
IRepository<ReadingTaskRelation> readingTaskRelationRepository,
|
||
IRepository<ReadingJudgeInfo> readingJudgeInfoRepository,
|
||
IRepository<ReadModule> readModuleRepository,
|
||
IRepository<DicomInstance> dicomInstanceRepository,
|
||
IRepository<OrganInfo> organInfoRepository,
|
||
IRepository<TrialDocument> trialDocumentRepository,
|
||
IRepository<User> userRepository,
|
||
IRepository<ReadingCustomTag> readingCustomTagRepository,
|
||
IMemoryCache cache,
|
||
IRepository<ReadingSystemCriterionDictionary> readingCriterionDictionaryRepository,
|
||
IRepository<ReadingTrialCriterionDictionary> readingTrialCriterionDictionaryRepository,
|
||
IRepository<TumorAssessment_RECIST1Point1> tumorAssessmentRepository,
|
||
IRepository<ReadingTableAnswerRowInfo> readingTableAnswerRowInfoRepository,
|
||
IRepository<ReadingTableQuestionSystem> readingTableQuestionSystemRepository,
|
||
IRepository<ReadingTableQuestionTrial> readingTableQuestionTrialRepository,
|
||
IRepository<ReadingTaskQuestionAnswer> readingTaskQuestionAnswerRepository,
|
||
IRepository<ReadingQuestionCriterionTrial> readingQuestionCriterionTrialRepository,
|
||
IRepository<ReadingQuestionCriterionSystem> readingQuestionCriterionSystemRepository,
|
||
IRepository<ReadingQuestionSystem> ReadingQuestionSystem,
|
||
ITrialEmailNoticeConfigService trialEmailNoticeConfigService,
|
||
IRepository<NoneDicomStudyFile> noneDicomStudyFileSystem,
|
||
IRepository<ReadingQuestionTrial> readingQuestionTrialRepository,
|
||
ISchedulerFactory schedulerFactory
|
||
)
|
||
{
|
||
_schedulerFactory = schedulerFactory;
|
||
base._mapper = mapper;
|
||
this._noneDicomStudyRepository = noneDicomStudyRepository;
|
||
this._visitTaskRepository = visitTaskRepository;
|
||
this._trialRepository = TrialRepository;
|
||
this._readingTableQuestionAnswerRepository = ReadingTableQuestionAnswerRepository;
|
||
this._readingOncologyTaskInfoRepository = ReadingOncologyTaskInfoRepository;
|
||
this._visitTaskHelpeService = visitTaskHelpeService;
|
||
this._visitTaskService = visitTaskService;
|
||
this._readingClinicalDataService = readingClinicalDataService;
|
||
this._readingCalculateService = readingCalculateService;
|
||
this._subjectVisitRepository = subjectVisitRepository;
|
||
this._subjectRepository = subjectRepository;
|
||
this._readingGlobalTaskInfoRepository = readingGlobalTaskInfoRepository;
|
||
this._readingCriterionPageRepository = readingCriterionPageRepository;
|
||
this._readingTaskRelationRepository = readingTaskRelationRepository;
|
||
this._readingJudgeInfoRepository = readingJudgeInfoRepository;
|
||
this._readModuleRepository = readModuleRepository;
|
||
this._dicomInstanceRepository = dicomInstanceRepository;
|
||
this._organInfoRepository = organInfoRepository;
|
||
this._trialDocumentRepository = trialDocumentRepository;
|
||
this._userRepository = userRepository;
|
||
this._readingCustomTagRepository = readingCustomTagRepository;
|
||
this._readingCriterionDictionaryRepository = readingCriterionDictionaryRepository;
|
||
this._tumorAssessmentRepository = tumorAssessmentRepository;
|
||
this._readingTableAnswerRowInfoRepository = readingTableAnswerRowInfoRepository;
|
||
this._readingTableQuestionSystemRepository = readingTableQuestionSystemRepository;
|
||
this._readingTableQuestionTrialRepository = readingTableQuestionTrialRepository;
|
||
this._readingTaskQuestionAnswerRepository = readingTaskQuestionAnswerRepository;
|
||
this._readingQuestionCriterionTrialRepository = readingQuestionCriterionTrialRepository;
|
||
this._readingQuestionCriterionSystemRepository = readingQuestionCriterionSystemRepository;
|
||
this._readingTrialCriterionDictionaryRepository = readingTrialCriterionDictionaryRepository;
|
||
|
||
this._readingQuestionSystem = ReadingQuestionSystem;
|
||
this._noneDicomStudyFileSystem = noneDicomStudyFileSystem;
|
||
this._readingQuestionTrialRepository = readingQuestionTrialRepository;
|
||
this._cache = cache;
|
||
this._trialEmailNoticeConfigService = trialEmailNoticeConfigService;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 提交自定义标记
|
||
/// </summary>
|
||
/// <param name="inDto"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
public async Task<IResponseOutput> SubmitCustomTag(ReadingCustomTagDto inDto)
|
||
{
|
||
var entity = await _readingCustomTagRepository.InsertOrUpdateAsync(inDto, true);
|
||
return ResponseOutput.Ok(entity.Id.ToString());
|
||
}
|
||
|
||
/// <summary>
|
||
/// 删除自定义标记
|
||
/// </summary>
|
||
/// <param name="id"></param>
|
||
/// <returns></returns>
|
||
[HttpPost("{id:guid}")]
|
||
public async Task<IResponseOutput> DeleteCustomTag(Guid id)
|
||
{
|
||
var success = await _readingCustomTagRepository.DeleteFromQueryAsync(t => t.Id == id, true);
|
||
return ResponseOutput.Ok();
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 获取自定义标记
|
||
/// </summary>
|
||
/// <param name="inQuery"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
public async Task<List<ReadingCustomTagDto>> GetCustomTag(GetCustomTagInDto inQuery)
|
||
{
|
||
var result= await _readingCustomTagRepository.Where(x => x.VisitTaskId == inQuery.VisitTaskId).ProjectTo<ReadingCustomTagDto>(_mapper.ConfigurationProvider).ToListAsync();
|
||
return result;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取手册
|
||
/// </summary>
|
||
/// <param name="inDto"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
public async Task<List<GetManualListOutDto>> GetManualList(GetManualListInDto inDto)
|
||
{
|
||
UserTypeEnum userType = (UserTypeEnum)_userInfo.UserTypeEnumInt;
|
||
|
||
|
||
List<UserTypeEnum> canViewUserType = new List<UserTypeEnum>()
|
||
{
|
||
UserTypeEnum.IndependentReviewer,
|
||
UserTypeEnum.IQC,
|
||
|
||
};
|
||
|
||
return await _trialDocumentRepository.Where(x => x.TrialId == inDto.TrialId
|
||
&& x.TrialDocConfirmedUserList.Any(y => y.ConfirmUserId == _userInfo.Id && y.ConfirmTime != null)
|
||
&& x.NeedConfirmedUserTypeList.Any(y => y.NeedConfirmUserTypeId == _userInfo.UserTypeId))
|
||
.WhereIf(userType == UserTypeEnum.IndependentReviewer, t => t.FileType.Code == "2" || t.FileType.Code == "6")
|
||
.WhereIf(userType == UserTypeEnum.IQC, t => t.FileType.Code == "4" || t.FileType.Code == "5")
|
||
.WhereIf(!canViewUserType.Contains(userType), t => false)
|
||
.IgnoreQueryFilters()
|
||
.Select(x => new GetManualListOutDto()
|
||
{
|
||
Id = x.Id,
|
||
Name = x.Name,
|
||
Path = x.Path
|
||
}).ToListAsync();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取任务附加问题
|
||
/// </summary>
|
||
/// <param name="inDto"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
public async Task<(List<TrialAdditionaQuestion>, bool)> GetTaskAdditionalQuestion(GetTaskAdditionalQuestionInDto inDto)
|
||
{
|
||
|
||
var answerList = await _readingTaskQuestionAnswerRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId).IgnoreAutoIncludes().ToListAsync();
|
||
var taskInfo = await _visitTaskRepository.Where(x => inDto.VisitTaskId == x.Id).FirstNotNullAsync();
|
||
var result = await _readingQuestionTrialRepository.Where(x => x.IsAdditional && x.ReadingQuestionCriterionTrialId == taskInfo.TrialReadingCriterionId).IgnoreAutoIncludes().IgnoreQueryFilters().ProjectTo<TrialAdditionaQuestion>(_mapper.ConfigurationProvider).OrderBy(x => x.ShowOrder).ToListAsync();
|
||
|
||
result.ForEach(x =>
|
||
{
|
||
|
||
var answer = answerList.Where(y => y.ReadingQuestionTrialId == x.Id).FirstOrDefault();
|
||
if (answer != null)
|
||
{
|
||
x.Answer = answer.Answer;
|
||
}
|
||
});
|
||
|
||
|
||
var resultData = result.Where(x => x.Type == "group").ToList();
|
||
|
||
resultData.ForEach(x =>
|
||
{
|
||
x.Childrens = result.Where(y => y.GroupId == x.Id).ToList();
|
||
|
||
});
|
||
|
||
|
||
return (resultData, true);
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 提交附加问题
|
||
/// </summary>
|
||
/// <param name="inDto"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
public async Task<bool> SubmitTaskAdditionalQuestion(SubmitTaskAdditionalQuestionInDto inDto)
|
||
{
|
||
var taskInfo = await _visitTaskRepository.Where(x => inDto.VisitTaskId == x.Id).FirstNotNullAsync();
|
||
var questionids = inDto.AnswerList.Select(x => x.QuestionId).ToList();
|
||
await _readingTaskQuestionAnswerRepository.BatchDeleteNoTrackingAsync(x => x.VisitTaskId == inDto.VisitTaskId && questionids.Contains(x.ReadingQuestionTrialId));
|
||
|
||
await _readingTaskQuestionAnswerRepository.AddRangeAsync(inDto.AnswerList.Select(x => new ReadingTaskQuestionAnswer()
|
||
{
|
||
VisitTaskId = inDto.VisitTaskId,
|
||
ReadingQuestionCriterionTrialId = taskInfo.TrialReadingCriterionId,
|
||
Answer = x.Answer,
|
||
ReadingQuestionTrialId = x.QuestionId,
|
||
TrialId = taskInfo.TrialId,
|
||
SubjectId = taskInfo.SubjectId
|
||
}).ToList());
|
||
|
||
return await _readingTaskQuestionAnswerRepository.SaveChangesAsync();
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// 维护任务关系
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
public async Task MaintainTaskRelated()
|
||
{
|
||
List<ReadingTaskRelation> relations = new List<ReadingTaskRelation>();
|
||
var visitList = await _visitTaskRepository.Where(x => x.PastResultTaskIds != "[]" && x.RelatedVisitTaskIds != "[]").Select(x => new
|
||
{
|
||
x.Id,
|
||
x.RelatedVisitTaskIds,
|
||
x.PastResultTaskIds
|
||
}).ToListAsync();
|
||
|
||
|
||
List<Guid> relatedIds = new List<Guid>();
|
||
|
||
List<Guid> PastResultds = new List<Guid>();
|
||
|
||
foreach (var item in visitList)
|
||
{
|
||
try
|
||
{
|
||
PastResultds = JsonConvert.DeserializeObject<List<Guid>>(item.PastResultTaskIds) ?? new List<Guid>();
|
||
}
|
||
catch (Exception)
|
||
{
|
||
|
||
PastResultds = new List<Guid>();
|
||
}
|
||
|
||
try
|
||
{
|
||
relatedIds = JsonConvert.DeserializeObject<List<Guid>>(item.RelatedVisitTaskIds) ?? new List<Guid>();
|
||
}
|
||
catch (Exception)
|
||
{
|
||
|
||
relatedIds = new List<Guid>();
|
||
}
|
||
|
||
relations.AddRange(PastResultds.Select(x => new ReadingTaskRelation()
|
||
{
|
||
|
||
RelevanceTaskId = x,
|
||
TaskId = item.Id,
|
||
RelevanceType = RelevanceType.PastResult,
|
||
}));
|
||
|
||
relations.AddRange(relatedIds.Select(x => new ReadingTaskRelation()
|
||
{
|
||
|
||
RelevanceTaskId = x,
|
||
TaskId = item.Id,
|
||
RelevanceType = RelevanceType.Related,
|
||
}));
|
||
|
||
await _readingTaskRelationRepository.BatchDeleteNoTrackingAsync(x => x.TaskId == item.Id);
|
||
|
||
}
|
||
|
||
await _readingTaskRelationRepository.AddRangeAsync(relations);
|
||
await _readingTaskRelationRepository.SaveChangesAsync();
|
||
}
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// 修改计算问题
|
||
/// </summary>
|
||
/// <param name="inDto"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
||
public async Task ChangeCalculationAnswer(ChangeCalculationAnswerInDto inDto)
|
||
{
|
||
var visitTask = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).FirstNotNullAsync();
|
||
|
||
var questionAnswerList = await _readingTaskQuestionAnswerRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId).ToListAsync();
|
||
|
||
var tableQuestionAnswerList = await _readingTableQuestionAnswerRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId).ToListAsync();
|
||
|
||
var rowInfoList = await _readingTableAnswerRowInfoRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId).ToListAsync();
|
||
|
||
|
||
foreach (var item in inDto.QuestionAnswer)
|
||
{
|
||
if (questionAnswerList.Any(x => x.ReadingQuestionTrialId == item.QuestionId))
|
||
{
|
||
await _readingTaskQuestionAnswerRepository.UpdatePartialFromQueryAsync(x => x.VisitTaskId == inDto.VisitTaskId && x.ReadingQuestionTrialId == item.QuestionId, x => new ReadingTaskQuestionAnswer()
|
||
{
|
||
Answer = item.Answer,
|
||
});
|
||
}
|
||
else
|
||
{
|
||
await _readingTaskQuestionAnswerRepository.AddAsync(new ReadingTaskQuestionAnswer()
|
||
{
|
||
Answer = item.Answer,
|
||
ReadingQuestionCriterionTrialId = visitTask.TrialReadingCriterionId,
|
||
ReadingQuestionTrialId = item.QuestionId,
|
||
SubjectId = visitTask.SubjectId,
|
||
VisitTaskId = inDto.VisitTaskId,
|
||
TrialId = visitTask.TrialId
|
||
});
|
||
}
|
||
|
||
|
||
}
|
||
|
||
foreach (var item in inDto.TableQuestionAnswer)
|
||
{
|
||
|
||
if (tableQuestionAnswerList.Any(x => x.QuestionId == item.QuestionId && x.RowId == item.RowId && x.TableQuestionId == item.TableQuestionId))
|
||
{
|
||
await _readingTableQuestionAnswerRepository.UpdatePartialFromQueryAsync(x => x.VisitTaskId == inDto.VisitTaskId && x.RowId == item.RowId && x.TableQuestionId == item.TableQuestionId, x => new ReadingTableQuestionAnswer()
|
||
{
|
||
Answer = item.Answer,
|
||
});
|
||
}
|
||
else
|
||
{
|
||
|
||
var rowInfo = rowInfoList.Where(x => x.Id == item.RowId).FirstOrDefault() ?? new ReadingTableAnswerRowInfo();
|
||
|
||
await _readingTableQuestionAnswerRepository.AddAsync(new ReadingTableQuestionAnswer()
|
||
{
|
||
Answer = item.Answer,
|
||
QuestionId = item.QuestionId,
|
||
TableQuestionId = item.TableQuestionId,
|
||
RowIndex = rowInfo.RowIndex,
|
||
RowId = rowInfo.Id,
|
||
VisitTaskId = inDto.VisitTaskId,
|
||
TrialId = visitTask.TrialId
|
||
});
|
||
}
|
||
|
||
|
||
}
|
||
|
||
await _readingTableQuestionAnswerRepository.SaveChangesAsync();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 阅读临床数据
|
||
/// </summary>
|
||
/// <param name="inDto"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
||
public async Task ReadClinicalData(ReadClinicalDataInDto inDto)
|
||
{
|
||
await _visitTaskRepository.UpdatePartialFromQueryAsync(inDto.VisitTaskId, x => new VisitTask
|
||
{
|
||
IsReadClinicalData = true
|
||
});
|
||
await _visitTaskRepository.SaveChangesAsync();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 添加默认值到任务里面
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
[NonDynamicMethod]
|
||
public async Task AddDefaultValueToTask(Guid visitTaskId)
|
||
{
|
||
var visitTaskInfo = await _visitTaskRepository.Where(x => x.Id == visitTaskId).FirstNotNullAsync();
|
||
|
||
var questions = await _readingQuestionTrialRepository.Where(x => x.ReadingQuestionCriterionTrialId == visitTaskInfo.TrialReadingCriterionId).ToListAsync();
|
||
questions = questions.Where(x => !x.DefaultValue.IsNullOrEmpty()).ToList();
|
||
|
||
var taskAnswerIds = await _readingTaskQuestionAnswerRepository.Where(x => x.VisitTaskId == visitTaskId).Select(x => x.ReadingQuestionTrialId).ToListAsync();
|
||
questions = questions.Where(x => !taskAnswerIds.Contains(x.Id)).ToList();
|
||
|
||
List<ReadingTaskQuestionAnswer> questionAnswers = questions.Select(x => new ReadingTaskQuestionAnswer()
|
||
{
|
||
|
||
Answer = x.DefaultValue,
|
||
Id = NewId.NextGuid(),
|
||
ReadingQuestionCriterionTrialId = visitTaskInfo.TrialReadingCriterionId,
|
||
ReadingQuestionTrialId = x.Id,
|
||
SubjectId = visitTaskInfo.SubjectId,
|
||
TrialId = visitTaskInfo.TrialId,
|
||
VisitTaskId = visitTaskId,
|
||
|
||
}).ToList();
|
||
|
||
await _readingTaskQuestionAnswerRepository.AddRangeAsync(questionAnswers);
|
||
await _readingTaskQuestionAnswerRepository.SaveChangesAsync();
|
||
|
||
}
|
||
|
||
|
||
#region 阅片页面 关联信息查询 以及基本验证
|
||
|
||
/// <summary>
|
||
/// 根据任务ID获取ReadingTool
|
||
/// </summary>
|
||
/// <param name="indto"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
public async Task<GetReadingToolOutDto> GetReadingTool(GetReadingToolInDto indto)
|
||
{
|
||
var visitTaskInfo = await _visitTaskRepository.Where(x => x.Id == indto.VisitTaskId).FirstNotNullAsync();
|
||
|
||
var criterionTrialInfo = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == visitTaskInfo.TrialReadingCriterionId).FirstNotNullAsync();
|
||
GetReadingToolOutDto result = new GetReadingToolOutDto()
|
||
{
|
||
TrialReadingCriterionId = visitTaskInfo.TrialReadingCriterionId,
|
||
ReadingTool = criterionTrialInfo.ReadingTool,
|
||
CriterionType = criterionTrialInfo.CriterionType,
|
||
};
|
||
|
||
return result;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取关联的阅片任务
|
||
/// </summary>
|
||
/// <param name="inDto"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
public async Task<(List<GetRelatedVisitTaskOutDto>, object)> GetRelatedVisitTask(GetRelatedVisitTaskInDto inDto)
|
||
{
|
||
var taskInfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).Include(x => x.TrialReadingCriterion).FirstNotNullAsync();
|
||
var baselineVisitId = await _subjectVisitRepository.Where(x => x.SubjectId == taskInfo.SubjectId && x.IsBaseLine && !x.IsLostVisit).Select(x => x.Id).FirstNotNullAsync();
|
||
|
||
|
||
var taskQuery = _visitTaskRepository.Where(x =>
|
||
(x.TrialId == taskInfo.TrialId &&
|
||
x.SubjectId == taskInfo.SubjectId &&
|
||
x.ArmEnum == taskInfo.ArmEnum &&
|
||
//x.DoctorUserId == taskInfo.DoctorUserId &&
|
||
x.ReadingTaskState == ReadingTaskState.HaveSigned &&
|
||
x.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId &&
|
||
x.TaskState == TaskState.Effect &&
|
||
x.VisitTaskNum <= taskInfo.VisitTaskNum &&
|
||
x.IsAnalysisCreate == taskInfo.IsAnalysisCreate &&
|
||
x.ReadingCategory == ReadingCategory.Visit) || x.Id == inDto.VisitTaskId);
|
||
|
||
if (taskInfo.ReadingTaskState == ReadingTaskState.HaveSigned)
|
||
{
|
||
taskQuery = _visitTaskRepository.Where(x => taskInfo.RelatedVisitTaskIdList.Contains(x.Id) || x.Id == taskInfo.Id);
|
||
}
|
||
|
||
var result = await taskQuery.OrderBy(x => x.VisitTaskNum).ThenBy(x => x.TaskState)
|
||
.Select(x => new GetRelatedVisitTaskOutDto()
|
||
{
|
||
TaskBlindName = x.TaskBlindName,
|
||
TaskName = x.TaskName,
|
||
ReadingTaskState = x.ReadingTaskState,
|
||
VisitId = x.SourceSubjectVisitId,
|
||
VisitTaskId = x.Id,
|
||
VisitTaskNum = x.VisitTaskNum,
|
||
IsBaseLineTask = x.SourceSubjectVisitId == baselineVisitId,
|
||
IsCurrentTask = x.Id == inDto.VisitTaskId,
|
||
IsConvertedTask = x.IsConvertedTask,
|
||
IsFirstChangeTask = x.BeforeConvertedTaskId != null,
|
||
|
||
}).ToListAsync();
|
||
|
||
|
||
if (!taskInfo.TrialReadingCriterion.IsReadingTaskViewInOrder)
|
||
{
|
||
result = result.Where(x => x.VisitTaskId == inDto.VisitTaskId).ToList();
|
||
}
|
||
|
||
return (result, new
|
||
{
|
||
ReadingTaskState = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).Select(x => x.ReadingTaskState).FirstOrDefaultAsync()
|
||
});
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取既往任务名称和编号
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
public async Task<List<GetReadingPastResultListOutDto>> GetReadingPastResultList(GetReadingPastResultListInDto inDto)
|
||
{
|
||
var taskInfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).FirstNotNullAsync();
|
||
|
||
var taskQuery = _visitTaskRepository.Where(x =>
|
||
x.TrialId == taskInfo.TrialId &&
|
||
x.SubjectId == taskInfo.SubjectId &&
|
||
x.VisitTaskNum < taskInfo.VisitTaskNum &&
|
||
x.ArmEnum == taskInfo.ArmEnum &&
|
||
x.Id != inDto.VisitTaskId &&
|
||
//x.DoctorUserId == taskInfo.DoctorUserId &&
|
||
x.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId &&
|
||
x.ReadingTaskState == ReadingTaskState.HaveSigned &&
|
||
x.TaskState == TaskState.Effect &&
|
||
x.IsSelfAnalysis == taskInfo.IsSelfAnalysis &&
|
||
x.IsAnalysisCreate == taskInfo.IsAnalysisCreate &&
|
||
x.ReadingCategory == taskInfo.ReadingCategory
|
||
);
|
||
|
||
if (taskInfo.ReadingTaskState == ReadingTaskState.HaveSigned)
|
||
{
|
||
taskQuery = _visitTaskRepository.Where(x => taskInfo.PastResultTaskIdList.Contains(x.Id));
|
||
}
|
||
|
||
var readingPastResultList = await taskQuery.OrderBy(x => x.VisitTaskNum).ThenBy(x => x.TaskState).Select(x => new GetReadingPastResultListOutDto()
|
||
{
|
||
VisitTaskId = x.Id,
|
||
TaskBlindName = x.TaskBlindName,
|
||
TaskName = x.TaskName,
|
||
VisitTaskNum = x.VisitTaskNum,
|
||
JudgeResultArm = x.JudgeResultTask == null ? null : x.JudgeResultTask.ArmEnum,
|
||
|
||
}).ToListAsync();
|
||
return readingPastResultList;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取阅片的受试者信息
|
||
/// </summary>
|
||
/// <param name="inDto"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
public async Task<GetReadingSubjectInfoOutDto> GetReadingSubjectInfo(GetReadingSubjectInfoInDto inDto)
|
||
{
|
||
var visitTask = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).FirstOrDefaultAsync();
|
||
var subjectCode = await _subjectRepository.Where(x => x.Id == visitTask.SubjectId).Select(x => x.Code).FirstOrDefaultAsync();
|
||
|
||
var criterionInfo = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == visitTask.TrialReadingCriterionId).Select(x => new
|
||
{
|
||
x.IsReadingShowPreviousResults,
|
||
x.IsReadingShowSubjectInfo
|
||
}).FirstOrDefaultAsync();
|
||
var trialInfo = await _trialRepository.Where(x => x.Id == visitTask.TrialId).Select(x => new
|
||
{
|
||
x.ClinicalInformationTransmissionEnum,
|
||
}).FirstOrDefaultAsync();
|
||
|
||
return new GetReadingSubjectInfoOutDto()
|
||
{
|
||
VisitTaskId = visitTask.Id,
|
||
SubjectId = visitTask.SubjectId,
|
||
SubjectCode = visitTask.BlindSubjectCode.IsNullOrEmpty() ? subjectCode : visitTask.BlindSubjectCode,
|
||
ReadingCategory = visitTask.ReadingCategory,
|
||
TaskBlindName = visitTask.TaskBlindName,
|
||
IsReadingShowPreviousResults = criterionInfo.IsReadingShowPreviousResults,
|
||
IsReadingShowSubjectInfo = criterionInfo.IsReadingShowSubjectInfo,
|
||
|
||
};
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 验证是否为基线访视任务
|
||
/// </summary>
|
||
/// <param name="visitTaskId"></param>
|
||
/// <returns></returns>
|
||
/// <exception cref="BusinessValidationFailedException"></exception>
|
||
private async Task VerifyIsBaseLineTask(Guid visitTaskId)
|
||
{
|
||
var taskinfo = await _visitTaskRepository.Where(x => x.Id == visitTaskId).FirstNotNullAsync();
|
||
if (taskinfo.ReadingCategory != ReadingCategory.Visit)
|
||
{
|
||
throw new BusinessValidationFailedException(_localizer["ReadingImage_NotVisit"]);
|
||
}
|
||
|
||
if (await _subjectVisitRepository.AnyAsync(x => x.Id == taskinfo.SourceSubjectVisitId && x.IsBaseLine))
|
||
{
|
||
throw new BusinessValidationFailedException(_localizer["ReadingImage_CantSplit"]);
|
||
}
|
||
}
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// 验证任务是否签名
|
||
/// </summary>
|
||
/// <param name="visitTaskid"></param>
|
||
/// <returns></returns>
|
||
/// <exception cref="BusinessValidationFailedException"></exception>
|
||
private async Task VerifyTaskIsSign(Guid visitTaskid)
|
||
{
|
||
var taskInfo = await _visitTaskRepository.Where(x => x.Id == visitTaskid).FirstNotNullAsync();
|
||
|
||
if (await _visitTaskRepository.AnyAsync(x => x.Id == visitTaskid && x.ReadingTaskState == ReadingTaskState.HaveSigned))
|
||
{
|
||
throw new BusinessValidationFailedException(_localizer["ReadingImage_BeSigned"]);
|
||
}
|
||
|
||
if(await _visitTaskRepository.AnyAsync(x=> x.Id == visitTaskid && x.DoctorUserId != _userInfo.Id && x.SubjectCriterionClaimUserId != _userInfo.Id))
|
||
{
|
||
throw new BusinessValidationFailedException("当前任务领取人不是你,不允许提交签名");
|
||
}
|
||
|
||
if (await _visitTaskRepository.AnyAsync(x => x.Id == visitTaskid && x.TaskState != TaskState.Effect))
|
||
{
|
||
throw new BusinessValidationFailedException(_localizer["ReadingImage_Beinvalid"]);
|
||
}
|
||
|
||
if (await _visitTaskRepository.AnyAsync(x => x.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId
|
||
&& x.IsAnalysisCreate && taskInfo.IsAnalysisCreate
|
||
&& x.SubjectId == taskInfo.SubjectId && x.TaskState == TaskState.Effect &&
|
||
((x.ReReadingApplyState == ReReadingApplyState.DocotorHaveApplyed && x.DoctorUserId == taskInfo.DoctorUserId) || x.ReReadingApplyState == ReReadingApplyState.TrialGroupHaveApplyed)
|
||
|
||
))
|
||
{
|
||
throw new BusinessValidationFailedException(_localizer["ReadingImage_PresenceReview"]);
|
||
}
|
||
|
||
}
|
||
|
||
|
||
|
||
#endregion
|
||
|
||
|
||
#region 访视任务 - Dicom 阅片 表格问题相关查询
|
||
|
||
|
||
/// <summary>
|
||
/// 获取DIcom阅片问题答案
|
||
/// </summary>
|
||
/// <param name="inDto"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
public async Task<(List<DicomReadingQuestionAnswer>, object)> GetDicomReadingQuestionAnswer(GetDicomReadingQuestionAnswerInDto inDto)
|
||
{
|
||
//await AddDefaultValueToTask(inDto.VisitTaskId);
|
||
var taskInfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).FirstNotNullAsync();
|
||
var result = await GetReadingQuestion(taskInfo.TrialReadingCriterionId, taskInfo.Id);
|
||
|
||
return (result, new
|
||
{
|
||
|
||
ReadingTaskState = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).Select(x => x.ReadingTaskState).FirstOrDefaultAsync()
|
||
});
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取阅片外层问题
|
||
/// </summary>
|
||
/// <param name="trialReadingCriterionId"></param>
|
||
/// <param name="visitTaskId"></param>
|
||
/// <returns></returns>
|
||
[NonDynamicMethod]
|
||
public async Task<List<DicomReadingQuestionAnswer>> GetReadingQuestion(Guid trialReadingCriterionId, Guid? visitTaskId)
|
||
{
|
||
|
||
|
||
var criterionIdInfo = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == trialReadingCriterionId).FirstNotNullAsync();
|
||
|
||
|
||
//排除表格问题
|
||
var questions = await _readingQuestionTrialRepository
|
||
.WhereIf(criterionIdInfo.IseCRFShowInDicomReading, x => x.ReadingQuestionCriterionTrialId == trialReadingCriterionId && x.Type != ReadingQestionType.Table)
|
||
.WhereIf(!criterionIdInfo.IseCRFShowInDicomReading, x => x.IsShowInDicom && x.ReadingQuestionCriterionTrialId == trialReadingCriterionId && x.Type != ReadingQestionType.Table)
|
||
|
||
.ProjectTo<DicomReadingQuestionAnswer>(_mapper.ConfigurationProvider, new
|
||
{
|
||
isEn_Us = _userInfo.IsEn_Us
|
||
|
||
}).OrderBy(x => x.ShowOrder).ToListAsync();
|
||
|
||
|
||
var answers = new List<ReadingTaskQuestionAnswer>();
|
||
|
||
if (visitTaskId != null)
|
||
{
|
||
answers = await _readingTaskQuestionAnswerRepository.Where(x => x.VisitTaskId == visitTaskId).ToListAsync();
|
||
|
||
var taskinfo = await _visitTaskRepository.Where(x => x.Id == visitTaskId).ProjectTo<VisitTaskDto>(_mapper.ConfigurationProvider).FirstNotNullAsync();
|
||
|
||
questions.ForEach(x =>
|
||
{
|
||
x.CrterionDictionaryGroup = ReadingCommon.GetCrterionDictionaryGroup(taskinfo.IsConvertedTask);
|
||
});
|
||
|
||
if (taskinfo.IsConvertedTask && taskinfo.BeforeConvertedTaskId != null)
|
||
{
|
||
questions.ForEach(x =>
|
||
{
|
||
x.IsFirstChangeTask = true;
|
||
});
|
||
}
|
||
}
|
||
else
|
||
{
|
||
var crterionDictionaryGroup = new List<CrterionDictionaryGroup>() { CrterionDictionaryGroup.General, CrterionDictionaryGroup.BeforeConvert };
|
||
questions.ForEach(x =>
|
||
{
|
||
x.CrterionDictionaryGroup = crterionDictionaryGroup;
|
||
});
|
||
}
|
||
|
||
|
||
//排除表格问题 同时排除组问题
|
||
var groupids = questions.Where(x => x.Type != ReadingQestionType.Group).Select(x => x.GroupId).ToList();
|
||
|
||
var result = questions.Where(x => x.Type == ReadingQestionType.Group && groupids.Contains(x.Id)).ToList();
|
||
|
||
foreach (var item in result)
|
||
{
|
||
GetDicomReadingAnswer(item, questions, answers);
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
private void GetDicomReadingAnswer(DicomReadingQuestionAnswer item, List<DicomReadingQuestionAnswer> questions, List<ReadingTaskQuestionAnswer> answers)
|
||
{
|
||
var answer = answers.Where(x => x.ReadingQuestionTrialId == item.Id).Select(x => x.Answer).FirstIsNullReturnEmpty();
|
||
item.Answer = answer.IsNullOrEmpty() ? item.DefaultValue : answer;
|
||
|
||
|
||
item.Childrens = questions.Where(x => x.ParentId == item.Id || (x.GroupId == item.Id && x.ParentId == null)).ToList();
|
||
if (item.Childrens != null && item.Childrens.Count > 0)
|
||
{
|
||
foreach (var question in item.Childrens)
|
||
{
|
||
GetDicomReadingAnswer(question, questions, answers);
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取阅片报告
|
||
/// </summary>
|
||
/// <param name="indto"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
public async Task<GetReadingReportEvaluationOutDto> GetReadingReportEvaluation(GetReadingReportEvaluationInDto indto)
|
||
{
|
||
return await _readingCalculateService.GetReadingReportEvaluation(indto);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取表格答案行信息
|
||
/// </summary>
|
||
/// <param name="inDto"></param>
|
||
/// <remarks>
|
||
/// (QuestionId) 可为空
|
||
/// </remarks>
|
||
/// <returns></returns>
|
||
[HttpGet]
|
||
public async Task<List<GetTableAnswerRowInfoOutDto>> GetTableAnswerRowInfoList(GetTableAnswerRowInfoInDto inDto)
|
||
{
|
||
await _readingCalculateService.AddTaskLesionAnswerFromLastTask(new AddTaskLesionAnswerFromLastTaskInDto()
|
||
{
|
||
VisitTaskId = inDto.VisitTaskId
|
||
});
|
||
var result = await _readingTableAnswerRowInfoRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId)
|
||
.WhereIf(inDto.QuestionId != null, x => x.QuestionId == inDto.QuestionId)
|
||
.ProjectTo<GetTableAnswerRowInfoOutDto>(_mapper.ConfigurationProvider).OrderBy(x => x.ShowOrder).ThenBy(x => x.RowIndex)
|
||
.ToListAsync();
|
||
|
||
|
||
var taskInfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).ProjectTo<VisitTaskDto>(_mapper.ConfigurationProvider).FirstNotNullAsync();
|
||
|
||
if (taskInfo.IsConvertedTask && taskInfo.BeforeConvertedTaskId != null)
|
||
{
|
||
result.ForEach(x =>
|
||
{
|
||
x.IsFirstChangeTask = true;
|
||
});
|
||
|
||
}
|
||
|
||
result.ForEach(x =>
|
||
{
|
||
|
||
x.OrderMarkName = x.OrderMark + x.RowIndexNum.GetLesionMark();
|
||
});
|
||
return result;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取表格问题及答案(2022-08-26)
|
||
/// </summary>
|
||
/// <param name="inDto"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
public async Task<(GetReadingQuestionAndAnswerOutDto, object)> GetReadingQuestionAndAnswer(GetReadingQuestionAndAnswerInDto inDto)
|
||
{
|
||
|
||
//await AddDefaultValueToTask(inDto.VisitTaskId);
|
||
var result = new GetReadingQuestionAndAnswerOutDto();
|
||
|
||
var taskinfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).FirstNotNullAsync();
|
||
|
||
var criterionInfo = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == taskinfo.TrialReadingCriterionId).FirstNotNullAsync();
|
||
|
||
result.ReadingTaskState = taskinfo.ReadingTaskState;
|
||
var baseLineVisitId = await _subjectVisitRepository.Where(x => x.SubjectId == taskinfo.SubjectId && x.IsBaseLine).Select(x => x.Id).FirstOrDefaultAsync();
|
||
|
||
result.IsBaseLineTask = taskinfo.SourceSubjectVisitId == baseLineVisitId;
|
||
|
||
var visitTaskInfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).FirstNotNullAsync();
|
||
|
||
|
||
var tableAnswers = await _readingTableQuestionAnswerRepository
|
||
.ProjectTo<ReadingTableQuestionAnswerInfo>(_mapper.ConfigurationProvider)
|
||
.Where(x => x.VisitTaskId == inDto.VisitTaskId).ToListAsync();
|
||
|
||
var tableAnsweRowInfos = await _readingTableAnswerRowInfoRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId).ProjectTo<TableAnsweRowInfo>(_mapper.ConfigurationProvider).ToListAsync();
|
||
|
||
var organIds = tableAnsweRowInfos.Where(x => x.OrganInfoId != null).Select(x => x.OrganInfoId).Distinct().ToList();
|
||
var organList = await _organInfoRepository.Where(x => organIds.Contains(x.Id)).ToListAsync();
|
||
var questionPage = await GetReadingTableQuestion(
|
||
|
||
new GetReadingTableQuestionOrAnswerInDto()
|
||
{
|
||
|
||
TrialReadingCriterionId = taskinfo.TrialReadingCriterionId,
|
||
TaskId = inDto.VisitTaskId,
|
||
TableAnswers = tableAnswers,
|
||
TableAnsweRowInfos = tableAnsweRowInfos,
|
||
OrganInfos = organList,
|
||
}
|
||
|
||
|
||
);
|
||
|
||
result.SinglePage = questionPage.SinglePage;
|
||
result.MultiPage = questionPage.MultiPage;
|
||
result.PublicPage = questionPage.PublicPage;
|
||
result.BlindName = visitTaskInfo.TaskBlindName;
|
||
result.TaskNum = visitTaskInfo.VisitTaskNum;
|
||
|
||
return (result, new
|
||
{
|
||
readingTaskState = visitTaskInfo.ReadingTaskState,
|
||
FormType = criterionInfo.FormType,
|
||
TaskNum = visitTaskInfo.VisitTaskNum,
|
||
|
||
}); ;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取自定义问题以及答案
|
||
/// </summary>
|
||
/// <param name="inDto"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
public async Task<(GetReadingTableQuestionOutDto, object)> GetCustomTableQuestionAnswer(GetCustomTableQuestionAnswerInDto inDto)
|
||
{
|
||
|
||
//await _readingCalculateService.AddTaskLesionAnswerFromLastTask(new AddTaskLesionAnswerFromLastTaskInDto() {
|
||
//VisitTaskId=inDto.VisitTaskId
|
||
//});
|
||
var taskInfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).Include(x => x.SourceSubjectVisit).FirstNotNullAsync();
|
||
|
||
var tableAnswers = await _readingTableQuestionAnswerRepository
|
||
.ProjectTo<ReadingTableQuestionAnswerInfo>(_mapper.ConfigurationProvider)
|
||
.Where(x => x.VisitTaskId == inDto.VisitTaskId).ToListAsync();
|
||
|
||
var tableAnsweRowInfos = await _readingTableAnswerRowInfoRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId).ProjectTo<TableAnsweRowInfo>(_mapper.ConfigurationProvider).ToListAsync();
|
||
|
||
var organIds = tableAnsweRowInfos.Where(x => x.OrganInfoId != null).Select(x => x.OrganInfoId).Distinct().ToList();
|
||
var organList = await _organInfoRepository.Where(x => organIds.Contains(x.Id)).ToListAsync();
|
||
return (await this.GetReadingTableQuestion(
|
||
new GetReadingTableQuestionOrAnswerInDto()
|
||
{
|
||
TrialReadingCriterionId = taskInfo.TrialReadingCriterionId,
|
||
TaskId = taskInfo.Id,
|
||
TableAnswers = tableAnswers,
|
||
TableAnsweRowInfos = tableAnsweRowInfos,
|
||
IsGetallQuestion = true,
|
||
OrganInfos = organList
|
||
|
||
}
|
||
), new
|
||
{
|
||
IsBaseline = taskInfo.SourceSubjectVisit != null && taskInfo.SourceSubjectVisit.IsBaseLine,
|
||
ReadingTaskState = taskInfo.ReadingTaskState
|
||
});
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取表格问题及答案 只返回表格问题(任务和标准)
|
||
/// </summary>
|
||
/// <param name="inDto"></param>
|
||
/// <returns></returns>
|
||
[NonDynamicMethod]
|
||
public async Task<GetReadingTableQuestionOutDto> GetReadingTableQuestion(GetReadingTableQuestionOrAnswerInDto inDto)
|
||
{
|
||
var criterionInfo = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == inDto.TrialReadingCriterionId).FirstNotNullAsync();
|
||
|
||
var qusetionList = await _readingQuestionTrialRepository.Where(x => x.ReadingQuestionCriterionTrialId == inDto.TrialReadingCriterionId).ProjectTo<TrialReadQuestionData>(_mapper.ConfigurationProvider, new
|
||
{
|
||
|
||
isEn_Us = _userInfo.IsEn_Us
|
||
|
||
}).OrderBy(x => x.ShowOrder).ToListAsync();
|
||
var taskInfo = new VisitTaskDto();
|
||
if (inDto.TaskId != null)
|
||
{
|
||
taskInfo = await _visitTaskRepository.Where(x => x.Id == inDto.TaskId).ProjectTo<VisitTaskDto>(_mapper.ConfigurationProvider).FirstNotNullAsync();
|
||
|
||
qusetionList.ForEach(x =>
|
||
{
|
||
x.CrterionDictionaryGroup = ReadingCommon.GetCrterionDictionaryGroup(taskInfo.IsConvertedTask);
|
||
});
|
||
}
|
||
else
|
||
{
|
||
qusetionList.ForEach(x =>
|
||
{
|
||
|
||
x.CrterionDictionaryGroup = new List<CrterionDictionaryGroup>() { CrterionDictionaryGroup.General, CrterionDictionaryGroup.BeforeConvert };
|
||
});
|
||
}
|
||
|
||
//是否是预览
|
||
if (inDto.IsGetPreview == false)
|
||
{
|
||
// 是否获取所有问题
|
||
if (inDto.IsGetallQuestion)
|
||
{
|
||
if (!criterionInfo.IseCRFShowInDicomReading)
|
||
{
|
||
qusetionList = qusetionList.Where(x => x.IsShowInDicom).OrderBy(x => x.ShowOrder).ToList();
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (!criterionInfo.IseCRFShowInDicomReading)
|
||
{
|
||
qusetionList = qusetionList.Where(x => x.IsShowInDicom && (x.Type == ReadingQestionType.Table || x.Type == ReadingQestionType.Group)).OrderBy(x => x.ShowOrder).ToList();
|
||
}
|
||
|
||
|
||
if (inDto.TaskId != null)
|
||
{
|
||
if (taskInfo.IsConvertedTask)
|
||
{
|
||
qusetionList = qusetionList.Where(x => x.ConvertShowType == ConvertShowType.All || x.ConvertShowType == ConvertShowType.AfterShow).OrderBy(x => x.ShowOrder).ToList();
|
||
}
|
||
else
|
||
{
|
||
qusetionList = qusetionList.Where(x => x.ConvertShowType == ConvertShowType.All || x.ConvertShowType == ConvertShowType.BeforeShow).OrderBy(x => x.ShowOrder).ToList();
|
||
}
|
||
|
||
}
|
||
|
||
var usedGuropIds = qusetionList.Where(x => x.Type == ReadingQestionType.Table).Select(x => x.GroupId).ToList();
|
||
qusetionList = qusetionList.Where(x => usedGuropIds.Contains(x.Id) || usedGuropIds.Contains(x.GroupId)).ToList();
|
||
}
|
||
}
|
||
|
||
|
||
|
||
var answers = await _readingTaskQuestionAnswerRepository.Where(x => x.VisitTaskId == inDto.TaskId).ToListAsync();
|
||
qusetionList.ForEach(x =>
|
||
{
|
||
var answer = answers.Where(y => y.ReadingQuestionTrialId == x.Id).Select(x => x.Answer).FirstOrDefault() ?? string.Empty;
|
||
x.Answer = answer.IsNullOrEmpty() ? x.DefaultValue : answer;
|
||
});
|
||
|
||
#endregion
|
||
|
||
var groupList = new List<TrialReadQuestionData>();
|
||
var qusetionIds = qusetionList.Select(x => x.Id).ToList();
|
||
|
||
var tableQuestionList = await _readingTableQuestionTrialRepository.Where(x => qusetionIds.Contains(x.ReadingQuestionId))
|
||
.ProjectTo<TableQuestionTrial>(_mapper.ConfigurationProvider, new
|
||
{
|
||
|
||
isEn_Us = _userInfo.IsEn_Us
|
||
})
|
||
.OrderBy(x => x.ShowOrder).ToListAsync();
|
||
|
||
var result = new GetReadingTableQuestionOutDto();
|
||
|
||
|
||
List<ReadingTableQuestionAnswer> baseLineTableAnswer = new List<ReadingTableQuestionAnswer>();
|
||
List<ReadingTableQuestionAnswer> lastTaskTableAnswer = new List<ReadingTableQuestionAnswer>();
|
||
bool isFirstChangeTask = false;
|
||
|
||
if (inDto.TaskId != null)
|
||
{
|
||
taskInfo = await _visitTaskRepository.Where(x => x.Id == inDto.TaskId).ProjectTo<VisitTaskDto>(_mapper.ConfigurationProvider).FirstNotNullAsync();
|
||
// 取基线
|
||
var baseLineVisitId = await _subjectVisitRepository.Where(x => x.SubjectId == taskInfo.SubjectId && x.IsBaseLine).Select(x => x.Id).FirstNotNullAsync();
|
||
|
||
var baselineTaskId = await _visitTaskRepository.Where(x => x.SourceSubjectVisitId == baseLineVisitId
|
||
&& x.ArmEnum == taskInfo.ArmEnum
|
||
&& x.DoctorUserId == taskInfo.DoctorUserId
|
||
&& x.IsAnalysisCreate == taskInfo.IsAnalysisCreate
|
||
&& x.TaskState == TaskState.Effect
|
||
&& x.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId
|
||
).Select(x => x.Id).FirstNotNullAsync();
|
||
baseLineTableAnswer = await _readingTableQuestionAnswerRepository.Where(x => x.VisitTaskId == baselineTaskId).Include(x => x.ReadingTableQuestionTrial).ToListAsync();
|
||
|
||
|
||
var laskTaskId = await _visitTaskRepository.Where(x =>
|
||
(x.SubjectId == taskInfo.SubjectId && x.TaskState == TaskState.Effect
|
||
&& x.IsAnalysisCreate == taskInfo.IsAnalysisCreate
|
||
&& x.DoctorUserId == taskInfo.DoctorUserId
|
||
&& x.IsSelfAnalysis == taskInfo.IsSelfAnalysis
|
||
&& x.VisitTaskNum < taskInfo.VisitTaskNum
|
||
&& x.ArmEnum == taskInfo.ArmEnum
|
||
&& x.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId
|
||
&& x.ReadingCategory == ReadingCategory.Visit) || x.Id == taskInfo.BeforeConvertedTaskId
|
||
).OrderByDescending(x => x.VisitTaskNum).Select(x => x.Id).FirstOrDefaultAsync();
|
||
if (!criterionInfo.IsReadingTaskViewInOrder)
|
||
{
|
||
// 无序的话 不要查
|
||
laskTaskId = Guid.NewGuid();
|
||
}
|
||
|
||
lastTaskTableAnswer = await _readingTableQuestionAnswerRepository.Where(x => x.VisitTaskId == laskTaskId).Include(x => x.ReadingTableQuestionTrial).ToListAsync();
|
||
|
||
|
||
if (taskInfo.BeforeConvertedTaskId != null)
|
||
{
|
||
isFirstChangeTask = true;
|
||
|
||
|
||
}
|
||
}
|
||
if (criterionInfo.FormType == FormType.MultiplePage)
|
||
{
|
||
qusetionList = qusetionList.Where(x => x.ReadingCriterionPageId != null).ToList();
|
||
var readingCriterionPageIds = qusetionList.OrderBy(x => x.PageShowOrder).Select(x => x.ReadingCriterionPageId).Distinct().ToList();
|
||
foreach (var item in readingCriterionPageIds)
|
||
{
|
||
var newPageQusetionList = qusetionList.Where(x => x.ReadingCriterionPageId == item).ToList();
|
||
var firstData = newPageQusetionList.FirstOrDefault();
|
||
var page = new TrialReadQuestionData()
|
||
{
|
||
PageName = firstData.PageName,
|
||
IsPage = true,
|
||
IsPublicPage = firstData.IsPublicPage,
|
||
};
|
||
|
||
var pageGroupList = newPageQusetionList.Where(x => x.Type == ReadingQestionType.Group).ToList();
|
||
pageGroupList.ForEach(x =>
|
||
{
|
||
this.FindChildQuestion(x, newPageQusetionList, tableQuestionList, inDto.TableAnswers, inDto.TableAnsweRowInfos, inDto.OrganInfos, baseLineTableAnswer, isFirstChangeTask, lastTaskTableAnswer, inDto.TaskId);
|
||
});
|
||
|
||
page.Childrens = pageGroupList.Where(x => !(x.Type == ReadingQestionType.Group && x.Childrens.Count() == 0)).ToList();
|
||
groupList.Add(page);
|
||
}
|
||
|
||
result.PublicPage = groupList.Where(x => x.IsPublicPage.Value).ToList();
|
||
result.MultiPage = groupList.Where(x => !x.IsPublicPage.Value).ToList();
|
||
}
|
||
else
|
||
{
|
||
qusetionList = qusetionList.Where(x => x.ReadingCriterionPageId == null).ToList();
|
||
|
||
groupList = qusetionList.Where(x => x.Type == ReadingQestionType.Group).ToList();
|
||
groupList.ForEach(x =>
|
||
{
|
||
this.FindChildQuestion(x, qusetionList, tableQuestionList, inDto.TableAnswers, inDto.TableAnsweRowInfos, inDto.OrganInfos, baseLineTableAnswer, isFirstChangeTask, lastTaskTableAnswer, inDto.TaskId);
|
||
});
|
||
|
||
groupList = groupList.Where(x => !(x.Type == ReadingQestionType.Group && x.Childrens.Count() == 0)).ToList();
|
||
|
||
result.SinglePage = groupList;
|
||
|
||
|
||
}
|
||
|
||
|
||
return result;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取子元素
|
||
/// </summary>
|
||
/// <param name="item"></param>
|
||
/// <param name="questionlists"></param>
|
||
/// <param name="tableQuestionLists"></param>
|
||
private async void FindChildQuestion(TrialReadQuestionData item, List<TrialReadQuestionData> questionlists, List<TableQuestionTrial> tableQuestionLists, List<ReadingTableQuestionAnswerInfo> tableAnswers, List<TableAnsweRowInfo> tableAnsweRowInfos, List<OrganInfo> organInfos, List<ReadingTableQuestionAnswer> baseLineTableAnswer, bool isFirstChangeTask, List<ReadingTableQuestionAnswer> lastTaskTableAnswer, Guid? TaskId)
|
||
{
|
||
item.Childrens = questionlists.Where(x => x.ParentId == item.Id || (x.GroupId == item.Id && x.ParentId == null)).ToList();
|
||
item.TableQuestions = new TrialReadTableQuestion();
|
||
|
||
item.TableQuestions.Questions = tableQuestionLists.Where(x => x.ReadingQuestionId == item.Id).OrderBy(x => x.ShowOrder).ToList();
|
||
|
||
item.TableQuestions.Questions.ForEach(x =>
|
||
{
|
||
|
||
x.RelationQuestions = tableQuestionLists.Where(z => (z.DependParentId ?? default(Guid)) == x.Id).Select(x => new GetTrialReadingQuestionOutDto
|
||
{
|
||
Childrens = new List<GetTrialReadingQuestionOutDto>(),
|
||
ShowOrder = x.ShowOrder,
|
||
GroupName = string.Empty,
|
||
Id = x.Id,
|
||
DictionaryCode = x.DictionaryCode,
|
||
Type = x.Type,
|
||
TableQuestionType = x.TableQuestionType,
|
||
DependParentId = x.DependParentId,
|
||
IsDepend = x.IsDepend,
|
||
QuestionMark = x.QuestionMark,
|
||
TypeValue = x.TypeValue,
|
||
RelevanceId = x.RelevanceId,
|
||
RelevanceValue = x.RelevanceValue,
|
||
ImageCount = 0,
|
||
ParentId = item.Id,
|
||
DataTableColumn = x.DataTableColumn,
|
||
LesionType = item.LesionType,
|
||
QuestionName = x.QuestionName.LanguageName(x.QuestionEnName, _userInfo.IsEn_Us),
|
||
RelationQuestions = new List<GetTrialReadingQuestionOutDto>(),
|
||
Remark = x.Remark,
|
||
ValueType = x.ValueType,
|
||
Unit = x.Unit,
|
||
}).ToList();
|
||
});
|
||
|
||
var thisAnswer = tableAnswers.Where(x => x.QuestionId == item.Id).ToList();
|
||
var orders = thisAnswer.Select(x => x.RowIndex).Distinct().OrderBy(x => x).ToList();
|
||
item.TableQuestions.Answers = new List<Dictionary<string, string>>();
|
||
|
||
|
||
var needChangeType = new List<QuestionMark?>() {
|
||
QuestionMark.Organ,
|
||
QuestionMark.Location,
|
||
QuestionMark.Part,
|
||
};
|
||
|
||
foreach (var x in orders)
|
||
{
|
||
Dictionary<string, string> answers = new Dictionary<string, string>();
|
||
var rowInfo = tableAnsweRowInfos.First(y => y.RowIndex == x && y.QuestionId == item.Id);
|
||
if (rowInfo == null)
|
||
{
|
||
continue;
|
||
}
|
||
|
||
var rowAnswer = thisAnswer.Where(y => y.RowId == rowInfo.Id).OrderBy(y => y.ShowOrder).ToList();
|
||
|
||
var organInfo = organInfos.Where(x => x.Id == rowInfo.OrganInfoId).FirstOrDefault();
|
||
|
||
rowAnswer.ForEach(z =>
|
||
{
|
||
|
||
if (organInfo != null && needChangeType.Contains(z.QuestionMark))
|
||
{
|
||
if (_userInfo.IsEn_Us)
|
||
{
|
||
switch (z.QuestionMark)
|
||
{
|
||
case QuestionMark.Organ:
|
||
answers.Add(z.TableQuestionId.ToString(), organInfo.TULOCEN);
|
||
|
||
break;
|
||
case QuestionMark.Location:
|
||
if (organInfo.IsCanEditPosition)
|
||
{
|
||
answers.Add(z.TableQuestionId.ToString(), z.Answer);
|
||
}
|
||
else
|
||
{
|
||
answers.Add(z.TableQuestionId.ToString(), organInfo.TULATEN);
|
||
|
||
}
|
||
break;
|
||
case QuestionMark.Part:
|
||
answers.Add(z.TableQuestionId.ToString(), organInfo.PartEN);
|
||
break;
|
||
|
||
}
|
||
|
||
}
|
||
else
|
||
{
|
||
switch (z.QuestionMark)
|
||
{
|
||
case QuestionMark.Organ:
|
||
answers.Add(z.TableQuestionId.ToString(), organInfo.TULOC);
|
||
break;
|
||
case QuestionMark.Location:
|
||
if (organInfo.IsCanEditPosition)
|
||
{
|
||
answers.Add(z.TableQuestionId.ToString(), z.Answer);
|
||
}
|
||
else
|
||
{
|
||
answers.Add(z.TableQuestionId.ToString(), organInfo.TULAT);
|
||
|
||
}
|
||
break;
|
||
case QuestionMark.Part:
|
||
answers.Add(z.TableQuestionId.ToString(), organInfo.Part);
|
||
break;
|
||
|
||
}
|
||
}
|
||
|
||
}
|
||
else
|
||
{
|
||
answers.Add(z.TableQuestionId.ToString(), z.Answer);
|
||
}
|
||
|
||
});
|
||
|
||
|
||
answers.Add("LesionType", rowInfo.LesionType.GetEnumNullInt());
|
||
answers.Add("BlindName", rowInfo.BlindName);
|
||
answers.Add("IsFirstChangeTask", isFirstChangeTask.ToString());
|
||
answers.Add("FromMark", rowInfo.FromMark);
|
||
answers.Add("IsDicomReading", rowInfo.IsDicomReading.ToString());
|
||
answers.Add("MeasureData", rowInfo == null ? string.Empty : rowInfo.MeasureData);
|
||
answers.Add("RowIndex", x.ToString());
|
||
answers.Add("RowId", rowInfo.Id.ToString());
|
||
answers.Add("MarkTool", rowInfo.MarkTool);
|
||
answers.Add("StudyId", rowInfo.StudyId.ToString());
|
||
answers.Add("OrganInfoId", rowInfo.OrganInfoId.ToString());
|
||
answers.Add("IsFristAdd", (rowInfo.FristAddTaskId == TaskId).ToString());
|
||
answers.Add("IsCanEditPosition", rowInfo.IsCanEditPosition.ToString());
|
||
answers.Add("InstanceId", rowInfo == null ? string.Empty : rowInfo.InstanceId.ToString());
|
||
answers.Add("SeriesId", rowInfo == null ? string.Empty : rowInfo.SeriesId.ToString());
|
||
answers.Add("IsCurrentTaskAdd", rowInfo == null ? false.ToString() : rowInfo.IsCurrentTaskAdd.ToString());
|
||
answers.Add("SplitOrMergeLesionName", rowInfo.SplitName.IsNullOrEmpty() ? rowInfo.MergeName : rowInfo.SplitName);
|
||
answers.Add("SplitOrMergeType", rowInfo.SplitOrMergeType == null ? string.Empty : ((int)rowInfo.SplitOrMergeType).ToString());
|
||
answers.Add("LastTaskState", lastTaskTableAnswer.Where(n => n.QuestionId == item.Id && n.ReadingTableQuestionTrial.QuestionMark == QuestionMark.State && n.RowIndex == x).Select(n => n.Answer).FirstOrDefault() ?? string.Empty);
|
||
answers.Add("LastTaskMajorAxis", lastTaskTableAnswer.Where(n => n.QuestionId == item.Id && n.ReadingTableQuestionTrial.QuestionMark == QuestionMark.MajorAxis && n.RowIndex == x).Select(n => n.Answer).FirstOrDefault() ?? string.Empty);
|
||
answers.Add("LastTaskShortAxis", lastTaskTableAnswer.Where(n => n.QuestionId == item.Id && n.ReadingTableQuestionTrial.QuestionMark == QuestionMark.ShortAxis && n.RowIndex == x).Select(n => n.Answer).FirstOrDefault() ?? string.Empty);
|
||
if (rowInfo.LesionType == LesionType.BaselineLesions)
|
||
{
|
||
answers.Add("BaseLineLesionNumber", baseLineTableAnswer.Where(n => n.ReadingTableQuestionTrial.QuestionMark == QuestionMark.LesionNumber && n.RowIndex == rowInfo.RowIndex).Select(x => x.Answer).FirstIsNullReturnEmpty());
|
||
}
|
||
|
||
|
||
item.TableQuestions.Answers.Add(answers);
|
||
};
|
||
|
||
if (item.Childrens != null && item.Childrens.Count != 0)
|
||
{
|
||
item.Childrens.ForEach(x =>
|
||
{
|
||
this.FindChildQuestion(x, questionlists, tableQuestionLists, tableAnswers, tableAnsweRowInfos, organInfos, baseLineTableAnswer, isFirstChangeTask, lastTaskTableAnswer, TaskId);
|
||
});
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
#region 访视任务 - Dicom 阅片 表格问题 病灶的拆分与合并
|
||
|
||
|
||
/// <summary>
|
||
/// 拆分病灶
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
||
public async Task SplitLesion(SplitLesionInDto inDto)
|
||
{
|
||
await VerifyTaskIsSign(inDto.VisitTaskId);
|
||
await this.VerifyIsBaseLineTask(inDto.VisitTaskId);
|
||
var rowAnswer = await _readingTableAnswerRowInfoRepository.Where(x => x.Id == inDto.RowId).AsNoTracking().FirstNotNullAsync();
|
||
var tableAnswers = await _readingTableQuestionAnswerRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId && x.RowIndex == rowAnswer.RowIndex && x.QuestionId == inDto.QuestionId).Include(x => x.ReadingTableQuestionTrial).ToListAsync();
|
||
var maxRowIndex = await _readingTableAnswerRowInfoRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId && x.QuestionId == inDto.QuestionId && x.RowIndex < Math.Floor(rowAnswer.RowIndex + 1)).OrderByDescending(x => x.RowIndex).Select(x => x.RowIndex).FirstOrDefaultAsync();
|
||
var newRowIndex = maxRowIndex + (decimal)0.01;
|
||
|
||
rowAnswer.RowIndex = newRowIndex;
|
||
rowAnswer.MergeRowId = null;
|
||
rowAnswer.FristAddTaskId = inDto.VisitTaskId;
|
||
rowAnswer.SplitOrMergeType = SplitOrMergeType.Split;
|
||
rowAnswer.FromMark = string.Empty;
|
||
rowAnswer.ReportMark = string.Empty;
|
||
rowAnswer.SplitRowId = rowAnswer.Id;
|
||
rowAnswer.Id = NewId.NextGuid();
|
||
rowAnswer.InstanceId = null;
|
||
rowAnswer.SeriesId = null;
|
||
rowAnswer.IsCurrentTaskAdd = true;
|
||
rowAnswer.MeasureData = string.Empty;
|
||
|
||
List<QuestionMark?> needRemoveMark = new List<QuestionMark?>()
|
||
{
|
||
QuestionMark.MajorAxis,
|
||
QuestionMark.ShortAxis,
|
||
QuestionMark.State,
|
||
};
|
||
|
||
tableAnswers.ForEach(x =>
|
||
{
|
||
x.Id = NewId.NextGuid();
|
||
x.RowIndex = newRowIndex;
|
||
x.VisitTaskId = inDto.VisitTaskId;
|
||
x.RowId = rowAnswer.Id;
|
||
x.Answer = needRemoveMark.Contains(x.ReadingTableQuestionTrial.QuestionMark) ? string.Empty : x.Answer;
|
||
x.ReadingTableQuestionTrial = null;
|
||
});
|
||
await _readingTableAnswerRowInfoRepository.AddAsync(rowAnswer);
|
||
await _readingTableQuestionAnswerRepository.AddRangeAsync(tableAnswers);
|
||
await _readingTableAnswerRowInfoRepository.SaveChangesAsync();
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// 合并病灶
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
||
public async Task MergeLesion(MergeLesionInDto inDto)
|
||
{
|
||
await VerifyTaskIsSign(inDto.VisitTaskId);
|
||
await this.VerifyIsBaseLineTask(inDto.VisitTaskId);
|
||
|
||
var rowsInfo = await _readingTableAnswerRowInfoRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId && (x.Id == inDto.MainRowId || x.Id == inDto.MergeRowId)).ToListAsync();
|
||
|
||
if (rowsInfo.Count() != 2)
|
||
{
|
||
throw new BusinessValidationFailedException(_localizer["ReadingImage_NotaTask"]);
|
||
}
|
||
|
||
|
||
var minaid = rowsInfo.Where(x => x.Id == inDto.MainRowId).Select(x => x.Id).FirstOrDefault();
|
||
var mergeid = rowsInfo.Where(x => x.Id == inDto.MergeRowId).Select(x => x.Id).FirstOrDefault();
|
||
|
||
List<QuestionMark?> needRemoveMark = new List<QuestionMark?>()
|
||
{
|
||
QuestionMark.MajorAxis,
|
||
QuestionMark.ShortAxis,
|
||
};
|
||
|
||
var mainAnswer = await _readingTableQuestionAnswerRepository.Where(x => x.RowId == minaid).Include(x => x.ReadingTableQuestionTrial).ToListAsync();
|
||
|
||
foreach (var item in mainAnswer)
|
||
{
|
||
await _readingTableQuestionAnswerRepository.BatchUpdateNoTrackingAsync(x => x.RowId == mergeid && x.TableQuestionId == item.TableQuestionId, x => new ReadingTableQuestionAnswer()
|
||
{
|
||
Answer = needRemoveMark.Contains(item.ReadingTableQuestionTrial.QuestionMark) ? string.Empty : item.Answer,
|
||
});
|
||
}
|
||
|
||
|
||
|
||
await _readingTableAnswerRowInfoRepository.UpdatePartialFromQueryAsync(mergeid, x => new ReadingTableAnswerRowInfo()
|
||
{
|
||
MergeRowId = minaid,
|
||
SplitOrMergeType = SplitOrMergeType.Merge,
|
||
});
|
||
|
||
|
||
await _readingTableAnswerRowInfoRepository.UpdatePartialFromQueryAsync(mergeid, x => new ReadingTableAnswerRowInfo()
|
||
{
|
||
MergeRowId = minaid,
|
||
SplitOrMergeType = SplitOrMergeType.Merge,
|
||
});
|
||
|
||
await _readingTableAnswerRowInfoRepository.SaveChangesAsync();
|
||
|
||
|
||
}
|
||
|
||
|
||
#endregion
|
||
|
||
|
||
|
||
#region 访视任务 - Dicom 阅片 提交、修改
|
||
|
||
/// <summary>
|
||
/// 保存影像质量
|
||
/// </summary>
|
||
/// <param name="inDto"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
||
public async Task<IResponseOutput> SaveImageQuality(ChangeDicomReadingQuestionAnswerInDto inDto)
|
||
{
|
||
return await ChangeDicomReadingQuestionAnswer(inDto);
|
||
}
|
||
|
||
///// <summary>
|
||
///// 保存ECRF
|
||
///// </summary>
|
||
///// <param name="inDto"></param>
|
||
///// <returns></returns>
|
||
//[HttpPost]
|
||
//public async Task<IResponseOutput> SaveImageQuality(ChangeDicomReadingQuestionAnswerInDto inDto)
|
||
//{
|
||
// return await ChangeDicomReadingQuestionAnswer(inDto);
|
||
//}
|
||
|
||
|
||
/// <summary>
|
||
/// 修改肿瘤学评估结果
|
||
/// </summary>
|
||
/// <param name="inDto"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
||
public async Task<IResponseOutput> ChangeDicomReadingQuestionAnswer(ChangeDicomReadingQuestionAnswerInDto inDto)
|
||
{
|
||
await VerifyTaskIsSign(inDto.VisitTaskId);
|
||
|
||
|
||
|
||
var taskInfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).FirstNotNullAsync();
|
||
|
||
var tumorQuestionId = await _readingQuestionTrialRepository.Where(x => x.ReadingQuestionCriterionTrialId == taskInfo.TrialReadingCriterionId && x.QuestionType == QuestionType.Tumor).Select(x => x.Id).FirstOrDefaultAsync();
|
||
|
||
var tumorAnswer = inDto.Answers.Where(x => x.Id == tumorQuestionId).FirstOrDefault();
|
||
if (tumorAnswer != null)
|
||
{
|
||
var isConvertedTask = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).Select(x => x.IsConvertedTask).FirstOrDefaultAsync();
|
||
var reportVerify = await _readingCalculateService.GetReportVerify(new GetReportVerifyInDto()
|
||
{
|
||
BeforeConvertedTaskId = taskInfo.BeforeConvertedTaskId,
|
||
IsConvertTask = isConvertedTask,
|
||
VisitTaskId = inDto.VisitTaskId
|
||
});
|
||
|
||
if (tumorAnswer.Answer == reportVerify.TumorEvaluate)
|
||
{
|
||
await _visitTaskRepository.BatchUpdateNoTrackingAsync(x => x.Id == inDto.VisitTaskId, x => new VisitTask()
|
||
{
|
||
IsChangeTumorEvaluate = false
|
||
});
|
||
}
|
||
else
|
||
{
|
||
await _visitTaskRepository.BatchUpdateNoTrackingAsync(x => x.Id == inDto.VisitTaskId, x => new VisitTask()
|
||
{
|
||
IsChangeTumorEvaluate = true
|
||
});
|
||
}
|
||
}
|
||
|
||
|
||
var criterionId = taskInfo.TrialReadingCriterionId;
|
||
var questionIds = inDto.Answers.Select(x => x.Id).ToList();
|
||
await _readingTaskQuestionAnswerRepository.BatchDeleteNoTrackingAsync(x => x.VisitTaskId == inDto.VisitTaskId && questionIds.Contains(x.ReadingQuestionTrialId));
|
||
var needAddAnswer = inDto.Answers.Select(x => new ReadingTaskQuestionAnswer()
|
||
{
|
||
|
||
Answer = x.Answer,
|
||
SubjectId = taskInfo.SubjectId,
|
||
ReadingQuestionCriterionTrialId = criterionId,
|
||
ReadingQuestionTrialId = x.Id,
|
||
TrialId = taskInfo.TrialId,
|
||
VisitTaskId = inDto.VisitTaskId,
|
||
|
||
}).ToList();
|
||
await _readingTaskQuestionAnswerRepository.AddRangeAsync(needAddAnswer);
|
||
await _readingTaskQuestionAnswerRepository.SaveChangesAsync();
|
||
return ResponseOutput.Ok(true);
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// 删除表格行数据
|
||
/// </summary>
|
||
/// <param name="inDto"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
||
public async Task<IResponseOutput> DeleteReadingRowAnswer(DeleteReadingRowAnswerInDto inDto)
|
||
{
|
||
await VerifyTaskIsSign(inDto.VisitTaskId);
|
||
|
||
|
||
|
||
var deleteRowInfo = await _readingTableAnswerRowInfoRepository.Where(x => x.Id == inDto.RowId).FirstOrDefaultAsync();
|
||
|
||
if (deleteRowInfo == null)
|
||
{
|
||
return ResponseOutput.Ok(true);
|
||
}
|
||
|
||
inDto.QuestionId = deleteRowInfo.QuestionId;
|
||
|
||
if (await _readingTableAnswerRowInfoRepository.AnyAsync(x => x.SplitRowId == deleteRowInfo.Id && x.MergeRowId == deleteRowInfo.Id))
|
||
{
|
||
throw new BusinessValidationFailedException(_localizer["ReadingImage_DeleteError"]);
|
||
}
|
||
|
||
var index = await _readingCalculateService.GetDeleteLesionStatrIndex(inDto);
|
||
|
||
|
||
await _readingTableQuestionAnswerRepository.UpdatePartialFromQueryAsync(x => x.RowId == inDto.RowId, x => new ReadingTableQuestionAnswer()
|
||
{
|
||
|
||
IsDeleted = true
|
||
});
|
||
await _readingTableAnswerRowInfoRepository.UpdatePartialFromQueryAsync(x => x.Id == inDto.RowId, x => new ReadingTableAnswerRowInfo()
|
||
{
|
||
|
||
IsDeleted = true
|
||
});
|
||
await _readingTableAnswerRowInfoRepository.SaveChangesAsync();
|
||
|
||
|
||
if (inDto.IsNeedSort)
|
||
{
|
||
var rowInfoList = await _readingTableAnswerRowInfoRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId && x.QuestionId == inDto.QuestionId, true).Include(x => x.ReadingQuestionTrial).OrderBy(x => x.RowIndex).ToListAsync();
|
||
|
||
var answerlist = await _readingTableQuestionAnswerRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId && x.QuestionId == inDto.QuestionId, true).ToListAsync();
|
||
|
||
|
||
|
||
foreach (var item in rowInfoList.Where(x => x.RowIndex % 1 == 0))
|
||
{
|
||
string measureDataStr = string.Empty;
|
||
if (item.MeasureData != null && item.MeasureData != string.Empty)
|
||
{
|
||
dynamic measureData = JObject.Parse(item.MeasureData);
|
||
measureData.data.remark = item.ReadingQuestionTrial.OrderMark + ((decimal)index).GetLesionMark();
|
||
measureDataStr = JsonConvert.SerializeObject(measureData);
|
||
}
|
||
|
||
|
||
|
||
foreach (var answerItem in answerlist.Where(x => x.RowIndex == item.RowIndex))
|
||
{
|
||
|
||
answerItem.RowIndex = index;
|
||
|
||
}
|
||
|
||
|
||
foreach (var rowAnswerItem in rowInfoList.Where(x => x.RowIndex == item.RowIndex))
|
||
{
|
||
|
||
rowAnswerItem.RowIndex = index;
|
||
rowAnswerItem.MeasureData = measureDataStr;
|
||
|
||
}
|
||
|
||
//await _readingTableQuestionAnswerRepository.UpdatePartialFromQueryAsync(x => x.VisitTaskId == inDto.VisitTaskId && x.RowIndex == item.RowIndex && x.QuestionId == inDto.QuestionId, x => new ReadingTableQuestionAnswer()
|
||
//{
|
||
// RowIndex = index
|
||
//});
|
||
|
||
//await _readingTableAnswerRowInfoRepository.UpdatePartialFromQueryAsync(x => x.VisitTaskId == inDto.VisitTaskId && x.RowIndex == item.RowIndex && x.QuestionId == inDto.QuestionId, x => new ReadingTableAnswerRowInfo()
|
||
//{
|
||
// RowIndex = index,
|
||
// MeasureData = measureDataStr,
|
||
//});
|
||
var spiltList = rowInfoList.Where(x => x.RowIndex % 1 != 0 && x.RowIndex > item.RowIndex && x.RowIndex < Math.Floor(item.RowIndex + 1)).OrderBy(x => x.RowIndex).ToList();
|
||
decimal spiltindex = 0.01M;
|
||
foreach (var spiltitem in spiltList)
|
||
{
|
||
string spiltmeasureDataStr = string.Empty;
|
||
if (spiltitem.MeasureData != null && spiltitem.MeasureData != string.Empty)
|
||
{
|
||
dynamic spiltmeasureData = JObject.Parse(spiltitem.MeasureData);
|
||
spiltmeasureData.data.remark = item.ReadingQuestionTrial.OrderMark + ((decimal)index + spiltindex).GetLesionMark();
|
||
spiltmeasureDataStr = JsonConvert.SerializeObject(spiltmeasureData);
|
||
}
|
||
|
||
|
||
foreach (var answerItem in answerlist.Where(x => x.RowIndex == spiltitem.RowIndex))
|
||
{
|
||
answerItem.RowIndex = index + spiltindex;
|
||
|
||
}
|
||
|
||
|
||
foreach (var rowAnswerItem in rowInfoList.Where(x => x.RowIndex == spiltitem.RowIndex))
|
||
{
|
||
|
||
rowAnswerItem.RowIndex = index + spiltindex;
|
||
rowAnswerItem.MeasureData = spiltmeasureDataStr;
|
||
|
||
|
||
}
|
||
|
||
|
||
//await _readingTableQuestionAnswerRepository.UpdatePartialFromQueryAsync(x => x.VisitTaskId == inDto.VisitTaskId && x.RowIndex == spiltitem.RowIndex && x.QuestionId == inDto.QuestionId, x => new ReadingTableQuestionAnswer()
|
||
//{
|
||
// RowIndex = index + spiltindex
|
||
//});
|
||
//await _readingTableAnswerRowInfoRepository.UpdatePartialFromQueryAsync(x => x.VisitTaskId == inDto.VisitTaskId && x.RowIndex == spiltitem.RowIndex && x.QuestionId == inDto.QuestionId, x => new ReadingTableAnswerRowInfo()
|
||
//{
|
||
// RowIndex = index + spiltindex,
|
||
// MeasureData = spiltmeasureDataStr,
|
||
//});
|
||
|
||
spiltindex += 0.01M;
|
||
}
|
||
index++;
|
||
}
|
||
|
||
await _readingTableAnswerRowInfoRepository.SaveChangesAsync();
|
||
}
|
||
|
||
// 自动计算
|
||
await this._readingCalculateService.CalculateTask(new CalculateTaskInDto()
|
||
{
|
||
IsChangeOtherTask = false,
|
||
VisitTaskId = inDto.VisitTaskId,
|
||
});
|
||
return ResponseOutput.Ok(true);
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 提交表格问题答案 病灶
|
||
/// </summary>
|
||
/// <param name="inDto"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
||
public async Task<SubmitTableQuestionOutDto> SubmitTableQuestion(SubmitTableQuestionInDto inDto)
|
||
{
|
||
SubmitTableQuestionOutDto result = new SubmitTableQuestionOutDto();
|
||
|
||
await VerifyTaskIsSign(inDto.VisitTaskId);
|
||
|
||
if (inDto.InstanceId != null && inDto.IsDicomReading)
|
||
{
|
||
if (!(await _dicomInstanceRepository.AnyAsync(x => x.Id == inDto.InstanceId && x.SeriesId == inDto.SeriesId)))
|
||
{
|
||
throw new BusinessValidationFailedException(_localizer["ReadingImage_Idnotcorrespond"]);
|
||
}
|
||
}
|
||
|
||
var taskinfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).Include(x => x.TrialReadingCriterion).FirstNotNullAsync();
|
||
var criterionName = taskinfo.TrialReadingCriterion.CriterionName;
|
||
switch (taskinfo.TrialReadingCriterion.CriterionType)
|
||
{
|
||
// 对于非靶病灶,如果状态选择为显著增大,请验证:
|
||
// 1) 对于非淋巴结病灶,验证当前访视该病灶的长径 > 上一访视该病灶的长径。
|
||
// 约束条件:两次访视该病灶的长径有测量值。
|
||
// 提示语:当前访视该非淋巴结病灶的长径小于上一访视的值,不能设置为显著增大。
|
||
// 2) 对于淋巴结病灶,验证当前访视该病灶的短径 > 上一访视该病灶的短径。
|
||
// 约束条件:两次访视该病灶的短径有测量值。
|
||
// 提示语:当前访视该淋巴结病灶的短径小于上一访视的值,不能设置为显著增大。
|
||
case CriterionType.RECIST1Point1:
|
||
var lastTaskinfo = await _visitTaskRepository
|
||
.Where(x => x.IsAnalysisCreate == taskinfo.IsAnalysisCreate &&
|
||
x.SubjectId == taskinfo.SubjectId &&
|
||
x.ReadingCategory == taskinfo.ReadingCategory &&
|
||
x.DoctorUserId == taskinfo.DoctorUserId &&
|
||
x.ArmEnum == taskinfo.ArmEnum &&
|
||
x.TrialReadingCriterionId == taskinfo.TrialReadingCriterionId &&
|
||
x.ReadingTaskState == ReadingTaskState.HaveSigned &&
|
||
x.TaskState == TaskState.Effect &&
|
||
x.IsSelfAnalysis == taskinfo.IsSelfAnalysis &&
|
||
x.VisitTaskNum < taskinfo.VisitTaskNum
|
||
).OrderByDescending(x => x.VisitTaskNum).FirstOrDefaultAsync();
|
||
if (lastTaskinfo != null)
|
||
{
|
||
var tablequestionList = await _readingTableQuestionTrialRepository.Where(x => x.TrialCriterionId == taskinfo.TrialReadingCriterionId && x.ReadingQuestionTrial.LesionType == LesionType.NonTargetLesions).ToListAsync();
|
||
|
||
|
||
|
||
// 判断表格问题是否为空
|
||
if (tablequestionList.Count > 0)
|
||
{
|
||
// 找到状态值
|
||
var stateQuestion = tablequestionList.Where(x => x.QuestionMark == QuestionMark.State).FirstOrDefault();
|
||
|
||
if (stateQuestion != null)
|
||
{
|
||
// 判断是否为非靶病灶
|
||
if (inDto.QuestionId == tablequestionList[0].ReadingQuestionId && inDto.AnswerList.Any(x => x.TableQuestionId == stateQuestion.Id && x.Answer.EqEnum(NoTargetState.Increase)))
|
||
{
|
||
var lymphQuestion = tablequestionList.Where(x => x.QuestionMark == QuestionMark.IsLymph).FirstOrDefault();
|
||
if (lymphQuestion != null)
|
||
{
|
||
|
||
// 判断是否是淋巴结
|
||
if (inDto.AnswerList.Any(x => x.TableQuestionId == lymphQuestion.Id && x.Answer.EqEnum(YesOrNoOrNa.Yes)))
|
||
{
|
||
var shortAxisQuestion = tablequestionList.Where(x => x.QuestionMark == QuestionMark.ShortAxis).FirstOrDefault();
|
||
if (shortAxisQuestion != null)
|
||
{
|
||
var lastAnswer = await _readingTableQuestionAnswerRepository.Where(x => x.VisitTaskId == lastTaskinfo.Id && x.TableQuestionId == shortAxisQuestion.Id
|
||
&& x.RowIndex == inDto.RowIndex
|
||
).Select(x => x.Answer).FirstOrDefaultAsync();
|
||
|
||
var thisAnswer = inDto.AnswerList.Where(x => x.TableQuestionId == shortAxisQuestion.Id).Select(x => x.Answer).FirstOrDefault();
|
||
if (!lastAnswer.IsNullOrEmpty() && !thisAnswer.IsNullOrEmpty())
|
||
{
|
||
|
||
var lastvalue = 0m;
|
||
var thisvalue = 0m;
|
||
try
|
||
{
|
||
lastvalue = decimal.Parse(lastAnswer);
|
||
thisvalue = decimal.Parse(thisAnswer);
|
||
}
|
||
catch (Exception)
|
||
{
|
||
|
||
|
||
}
|
||
|
||
|
||
if (lastvalue >= thisvalue)
|
||
{
|
||
throw new BusinessValidationFailedException(_localizer["ReadingImage_IsLymphNotbigger"]);
|
||
}
|
||
|
||
|
||
}
|
||
}
|
||
}
|
||
else
|
||
|
||
{
|
||
var majorAxisQuestion = tablequestionList.Where(x => x.QuestionMark == QuestionMark.MajorAxis).FirstOrDefault();
|
||
if (majorAxisQuestion != null)
|
||
{
|
||
var lastAnswer = await _readingTableQuestionAnswerRepository.Where(x => x.VisitTaskId == lastTaskinfo.Id && x.TableQuestionId == majorAxisQuestion.Id
|
||
&& x.RowIndex == inDto.RowIndex
|
||
).Select(x => x.Answer).FirstOrDefaultAsync();
|
||
|
||
var thisAnswer = inDto.AnswerList.Where(x => x.TableQuestionId == majorAxisQuestion.Id).Select(x => x.Answer).FirstOrDefault();
|
||
if (!lastAnswer.IsNullOrEmpty() && !thisAnswer.IsNullOrEmpty())
|
||
{
|
||
var lastvalue = 0m;
|
||
var thisvalue = 0m;
|
||
try
|
||
{
|
||
lastvalue = decimal.Parse(lastAnswer);
|
||
thisvalue = decimal.Parse(thisAnswer);
|
||
}
|
||
catch (Exception)
|
||
{
|
||
|
||
|
||
}
|
||
|
||
|
||
if (lastvalue >= thisvalue)
|
||
{
|
||
throw new BusinessValidationFailedException(_localizer["ReadingImage_NotLymphNotbigger"]);
|
||
}
|
||
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
break;
|
||
}
|
||
|
||
var questionInfo = await _readingQuestionTrialRepository.Where(x => x.Id == inDto.QuestionId).FirstNotNullAsync();
|
||
var criterionId = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).Select(x => x.TrialReadingCriterionId).FirstOrDefaultAsync();
|
||
var criterionInfo = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == criterionId).FirstNotNullAsync();
|
||
var tableQuestionIds = inDto.AnswerList.Select(x => x.TableQuestionId).ToList();
|
||
var tableAnswerList = await _readingTableQuestionAnswerRepository.Where(x => x.RowId == inDto.RowId).ToListAsync();
|
||
|
||
var tableQuestionIdGroup = tableQuestionIds.GroupBy(x => new { TableQuestionId = x }).Select(x => new TableQuestionData
|
||
{
|
||
TableQuestionId = x.Key.TableQuestionId,
|
||
Count = x.Count()
|
||
}).ToList();
|
||
|
||
if (tableQuestionIdGroup.Any(x => x.Count > 1))
|
||
{
|
||
throw new BusinessValidationFailedException(_localizer["ReadingImage_Twice"]);
|
||
}
|
||
|
||
if (inDto.RowIndex % 1 == 0)
|
||
{
|
||
|
||
if (questionInfo.MaxQuestionCount != null && questionInfo.MaxQuestionCount != 0 && inDto.RowId == null)
|
||
{
|
||
if (questionInfo.MaxQuestionCount <
|
||
(
|
||
(await _readingTableAnswerRowInfoRepository.Where(x => ((x.RowIndex % 1) == 0) && x.VisitTaskId == inDto.VisitTaskId
|
||
&& x.QuestionId == inDto.QuestionId
|
||
).CountAsync()) + 1))
|
||
{
|
||
var errormsg = _localizer["ReadingImage_MaxQuestion", questionInfo.MaxQuestionCount].Value;
|
||
errormsg = errormsg.Replace("《独立影像评估章程》", criterionName + "评估标准");
|
||
throw new BusinessValidationFailedException(errormsg);
|
||
}
|
||
}
|
||
|
||
|
||
var tableQuestions = await _readingTableQuestionTrialRepository.Where(x => tableQuestionIds.Contains(x.Id) && x.MaxRowCount != null && x.MaxRowCount != 0).ToListAsync();
|
||
|
||
List<QuestionMark?> questionMarks = new List<QuestionMark?>()
|
||
{
|
||
QuestionMark.Part,
|
||
QuestionMark.Organ,
|
||
|
||
};
|
||
|
||
|
||
string msg = string.Empty;
|
||
foreach (var item in tableQuestions)
|
||
{
|
||
|
||
var answer = inDto.AnswerList.Where(x => x.TableQuestionId == item.Id).Select(x => x.Answer).FirstOrDefault();
|
||
if (!answer.IsNullOrEmpty())
|
||
{
|
||
Dictionary<CriterionType, string> errorMsgDic = new Dictionary<CriterionType, string>()
|
||
{
|
||
{CriterionType.RECIST1Point1, _localizer["ReadingImage_Maxlesion", item.MaxRowCount.Value]},
|
||
{CriterionType.PCWG3, _localizer["ReadingImage_PCWGMaximum", item.MaxRowCount.Value]},
|
||
};
|
||
var rowCount = 0;
|
||
if ((item.QuestionMark == QuestionMark.Part || item.QuestionMark == QuestionMark.Organ) && inDto.OrganInfoId != null)
|
||
{
|
||
var organIds = await _readingTableAnswerRowInfoRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId && x.QuestionId == inDto.QuestionId && ((x.RowIndex % 1) == 0) && x.OrganInfoId != null && x.RowIndex != inDto.RowIndex).Select(x => x.OrganInfoId).ToListAsync();
|
||
organIds.Add(inDto.OrganInfoId);
|
||
|
||
var orginInfos = await _organInfoRepository.Where(x => organIds.Contains(x.Id)).ToListAsync();
|
||
|
||
List<OrganInfo?> orginInfoList = new List<OrganInfo?>();
|
||
foreach (var organId in organIds)
|
||
{
|
||
orginInfoList.Add(orginInfos.Where(x => x.Id == organId).FirstOrDefault());
|
||
}
|
||
|
||
var currentOrginInfo = orginInfos.Where(x => x.Id == inDto.OrganInfoId).FirstOrDefault() ?? new OrganInfo();
|
||
|
||
if (item.QuestionMark == QuestionMark.Part)
|
||
{
|
||
rowCount = orginInfoList.Where(x => x.Part == currentOrginInfo.Part).Count();
|
||
}
|
||
else
|
||
{
|
||
rowCount = orginInfoList.Where(x => x.TULOC == currentOrginInfo.TULOC).Count();
|
||
}
|
||
|
||
if (rowCount > item.MaxRowCount.Value)
|
||
{
|
||
if (rowCount > item.MaxRowCount.Value)
|
||
{
|
||
|
||
|
||
try
|
||
{
|
||
msg = errorMsgDic[criterionInfo.CriterionType];
|
||
}
|
||
catch (Exception)
|
||
{
|
||
|
||
msg = _localizer["ReadingImage_Maximum", item.QuestionName.LanguageName(item.QuestionEnName, _userInfo.IsEn_Us), item.MaxRowCount.Value, item.MaxRowCount.Value];
|
||
msg = msg.Replace("《独立影像评估章程》", criterionName + "评估标准");
|
||
}
|
||
|
||
throw new BusinessValidationFailedException(msg);
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
else
|
||
{
|
||
rowCount = await _readingTableQuestionAnswerRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId && x.TableQuestionId == item.Id && ((x.RowIndex % 1) == 0) && x.Answer == answer && x.RowIndex != inDto.RowIndex).CountAsync();
|
||
|
||
if (rowCount > item.MaxRowCount.Value - 1)
|
||
{
|
||
|
||
|
||
try
|
||
{
|
||
msg = errorMsgDic[criterionInfo.CriterionType];
|
||
}
|
||
catch (Exception)
|
||
{
|
||
|
||
msg = _localizer["ReadingImage_Maximum", item.QuestionName.LanguageName(item.QuestionEnName, _userInfo.IsEn_Us), item.MaxRowCount.Value, rowCount];
|
||
msg = msg.Replace("《独立影像评估章程》", criterionName + "评估标准");
|
||
}
|
||
|
||
throw new BusinessValidationFailedException(msg);
|
||
}
|
||
}
|
||
|
||
|
||
|
||
}
|
||
}
|
||
}
|
||
var isCurrentTaskAddList = await _readingTableAnswerRowInfoRepository.Where(x => x.Id == (inDto.RowId ?? default(Guid))).Select(x => x.IsCurrentTaskAdd).ToListAsync();
|
||
bool isCurrentTaskAdd = true;
|
||
if (isCurrentTaskAddList.Count() > 0)
|
||
{
|
||
isCurrentTaskAdd = isCurrentTaskAddList[0];
|
||
}
|
||
|
||
|
||
ReadingTableAnswerRowInfo rowInfo = await _readingTableAnswerRowInfoRepository.Where(x => x.Id == (inDto.RowId ?? default(Guid))).FirstOrDefaultAsync();
|
||
|
||
rowInfo = rowInfo == null ? new ReadingTableAnswerRowInfo() : rowInfo;
|
||
|
||
//await _readingTableQuestionAnswerRepository.BatchDeleteNoTrackingAsync(x => x.RowId == (inDto.RowId ?? default(Guid)));
|
||
//await _readingTableAnswerRowInfoRepository.BatchDeleteNoTrackingAsync(x => x.Id == (inDto.RowId ?? default(Guid)));
|
||
|
||
rowInfo.Id = inDto.RowId == null ? NewId.NextGuid() : inDto.RowId.Value;
|
||
rowInfo.TrialId = inDto.TrialId;
|
||
rowInfo.QuestionId = inDto.QuestionId;
|
||
rowInfo.MeasureData = inDto.MeasureData;
|
||
rowInfo.BlindName = inDto.BlindName;
|
||
rowInfo.IsDicomReading = inDto.IsDicomReading;
|
||
rowInfo.IsCurrentTaskAdd = isCurrentTaskAdd;
|
||
rowInfo.NumberOfFrames = inDto.NumberOfFrames;
|
||
rowInfo.MarkTool = inDto.MarkTool;
|
||
rowInfo.ReportMark = inDto.ReportMark;
|
||
|
||
rowInfo.FristAddTaskNum = taskinfo.VisitTaskNum;
|
||
rowInfo.FristAddTaskId = inDto.VisitTaskId;
|
||
rowInfo.PicturePath = inDto.PicturePath;
|
||
rowInfo.RowIndex = inDto.RowIndex;
|
||
rowInfo.FromMark = inDto.FromMark;
|
||
rowInfo.OrganInfoId = inDto.OrganInfoId;
|
||
rowInfo.InstanceId = inDto.InstanceId;
|
||
rowInfo.SeriesId = inDto.SeriesId;
|
||
rowInfo.VisitTaskId = inDto.VisitTaskId;
|
||
rowInfo.OrderMark = questionInfo.OrderMark;
|
||
rowInfo.StudyId = inDto.StudyId;
|
||
rowInfo.IsCanEditPosition = inDto.IsCanEditPosition;
|
||
rowInfo.WL = inDto.WL;
|
||
rowInfo.WW = inDto.WW;
|
||
result.RowId = rowInfo.Id;
|
||
|
||
if (inDto.RowId == null)
|
||
{
|
||
|
||
//await _readingTableAnswerRowInfoRepository.BatchDeleteNoTrackingAsync(x => x.VisitTaskId == inDto.VisitTaskId && x.RowIndex == inDto.RowIndex && x.QuestionId == inDto.QuestionId);
|
||
|
||
List<ReadingTableQuestionAnswer> answerList = inDto.AnswerList.Select(x => new ReadingTableQuestionAnswer()
|
||
{
|
||
Answer = x.Answer,
|
||
Id = NewId.NextGuid(),
|
||
TrialId = inDto.TrialId,
|
||
QuestionId = inDto.QuestionId,
|
||
TableQuestionId = x.TableQuestionId,
|
||
RowIndex = inDto.RowIndex,
|
||
RowId = rowInfo.Id,
|
||
VisitTaskId = inDto.VisitTaskId
|
||
}).ToList();
|
||
|
||
|
||
await _readingTableAnswerRowInfoRepository.AddAsync(rowInfo);
|
||
await _readingTableQuestionAnswerRepository.AddRangeAsync(answerList);
|
||
|
||
}
|
||
|
||
else
|
||
{
|
||
await _readingTableAnswerRowInfoRepository.UpdatePartialFromQueryAsync(rowInfo.Id, x => new ReadingTableAnswerRowInfo()
|
||
{
|
||
TrialId = rowInfo.TrialId,
|
||
QuestionId = rowInfo.QuestionId,
|
||
MeasureData = rowInfo.MeasureData,
|
||
BlindName = rowInfo.BlindName,
|
||
IsDicomReading = rowInfo.IsDicomReading,
|
||
IsCurrentTaskAdd = isCurrentTaskAdd,
|
||
WL = rowInfo.WL,
|
||
WW = rowInfo.WW,
|
||
MarkTool = inDto.MarkTool,
|
||
OrganInfoId = rowInfo.OrganInfoId,
|
||
PicturePath = rowInfo.PicturePath,
|
||
NumberOfFrames = rowInfo.NumberOfFrames,
|
||
RowIndex = rowInfo.RowIndex,
|
||
InstanceId = rowInfo.InstanceId,
|
||
SeriesId = rowInfo.SeriesId,
|
||
VisitTaskId = rowInfo.VisitTaskId,
|
||
StudyId = rowInfo.StudyId,
|
||
IsCanEditPosition = rowInfo.IsCanEditPosition,
|
||
ReportMark = rowInfo.ReportMark
|
||
});
|
||
|
||
|
||
foreach (var item in inDto.AnswerList)
|
||
{
|
||
if (tableAnswerList.Any(x => x.TableQuestionId == item.TableQuestionId))
|
||
{
|
||
await _readingTableQuestionAnswerRepository.UpdatePartialFromQueryAsync(x => x.RowId == inDto.RowId && x.TableQuestionId == item.TableQuestionId, x => new ReadingTableQuestionAnswer()
|
||
{
|
||
|
||
Answer = item.Answer
|
||
|
||
});
|
||
}
|
||
else
|
||
{
|
||
await _readingTableQuestionAnswerRepository.AddAsync(new ReadingTableQuestionAnswer()
|
||
{
|
||
Answer = item.Answer,
|
||
QuestionId = inDto.QuestionId,
|
||
TableQuestionId = item.TableQuestionId,
|
||
RowId = inDto.RowId.Value,
|
||
TrialId = taskinfo.TrialId,
|
||
RowIndex = rowInfo.RowIndex,
|
||
VisitTaskId = inDto.VisitTaskId,
|
||
});
|
||
}
|
||
|
||
}
|
||
|
||
|
||
}
|
||
|
||
await _visitTaskRepository.UpdatePartialFromQueryAsync(inDto.VisitTaskId, x => new VisitTask()
|
||
{
|
||
ReadingTaskState = ReadingTaskState.Reading,
|
||
|
||
});
|
||
await _readingTableAnswerRowInfoRepository.SaveChangesAsync();
|
||
await this._readingCalculateService.CalculateTask(new CalculateTaskInDto()
|
||
{
|
||
IsChangeOtherTask = false,
|
||
VisitTaskId = inDto.VisitTaskId,
|
||
});
|
||
|
||
|
||
|
||
|
||
return result;
|
||
}
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// 提交Dicom阅片信息
|
||
/// </summary>
|
||
/// <param name="inDto"></param>
|
||
/// <returns></returns>
|
||
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
||
public async Task<IResponseOutput> SubmitDicomVisitTask(SubmitDicomVisitTaskInDto inDto)
|
||
{
|
||
|
||
await this.SubmitTaskChangeState(inDto.VisitTaskId);
|
||
return ResponseOutput.Ok(true);
|
||
}
|
||
|
||
|
||
|
||
|
||
#endregion
|
||
|
||
|
||
#region Dicom 非dicom 公用
|
||
|
||
/// <summary>
|
||
/// 验证默认问题是否回答
|
||
/// </summary>
|
||
/// <param name="inDto"></param>
|
||
/// <returns></returns>
|
||
/// <exception cref="BusinessValidationFailedException"></exception>
|
||
[HttpPost]
|
||
public async Task<IResponseOutput> VerifyDefaultQuestionBeAnswer(VerifyVisitTaskQuestionsInDto inDto)
|
||
{
|
||
|
||
var taskInfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).Include(x => x.TrialReadingCriterion).Include(x => x.SourceSubjectVisit).FirstNotNullAsync();
|
||
|
||
var criterion = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == taskInfo.TrialReadingCriterionId).FirstNotNullAsync();
|
||
|
||
var readingQuestionList = await _readingQuestionTrialRepository.Where(x => x.ReadingQuestionCriterionTrialId == taskInfo.TrialReadingCriterionId)
|
||
.WhereIf(taskInfo.SourceSubjectVisit.IsBaseLine, x => ((x.IsRequired == IsRequired.Required && x.ShowQuestion == ShowQuestion.Show) && (x.LimitEdit == LimitEdit.None || x.LimitEdit == LimitEdit.OnlyBaseLine)))
|
||
.WhereIf(!taskInfo.SourceSubjectVisit.IsBaseLine, x => ((x.IsRequired == IsRequired.Required && x.ShowQuestion == ShowQuestion.Show) && (x.LimitEdit == LimitEdit.None || x.LimitEdit == LimitEdit.OnlyVisit)))
|
||
.WhereIf(taskInfo.TrialReadingCriterion.CriterionType == CriterionType.PCWG3, x => x.QuestionType != QuestionType.SiteVisitForTumorEvaluation)
|
||
|
||
//.WhereIf(!criterion.IseCRFShowInDicomReading,x=>x.IsShowInDicom)
|
||
.ToListAsync();
|
||
|
||
var answerQuestionIds = await _readingTaskQuestionAnswerRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId && x.Answer != string.Empty).Select(x => x.ReadingQuestionTrialId).ToListAsync();
|
||
|
||
readingQuestionList = readingQuestionList.Where(x => !answerQuestionIds.Contains(x.Id)).ToList();
|
||
|
||
if (readingQuestionList.Count() > 0)
|
||
{
|
||
throw new BusinessValidationFailedException(_localizer["ReadingImage_RequiredQuestion", string.Join(',', readingQuestionList.Select(x => x.QuestionName.LanguageName(x.QuestionEnName, _userInfo.IsEn_Us)))]);
|
||
}
|
||
return ResponseOutput.Ok(true);
|
||
}
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// 验证访视提交
|
||
/// </summary>
|
||
/// <param name="inDto"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
public async Task<IResponseOutput> VerifyVisitTaskQuestions(VerifyVisitTaskQuestionsInDto inDto)
|
||
{
|
||
await VerifyTaskIsSign(inDto.VisitTaskId);
|
||
await VerifyDefaultQuestionBeAnswer(inDto);
|
||
|
||
// 转化后的任务不应该有新病灶
|
||
|
||
var isConvertedTask = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).Select(x => x.IsConvertedTask).FirstNotNullAsync();
|
||
|
||
if (isConvertedTask && (await _readingTableAnswerRowInfoRepository.AnyAsync(x => x.ReadingQuestionTrial.LesionType == LesionType.NewLesions && x.VisitTaskId == inDto.VisitTaskId)))
|
||
{
|
||
throw new BusinessValidationFailedException(_localizer["ReadingImage_NotNewFocus"]);
|
||
}
|
||
|
||
var taskInfo = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).FirstNotNullAsync();
|
||
var isBaseline = await _subjectVisitRepository.Where(x => x.Id == taskInfo.SourceSubjectVisitId).Select(x => x.IsBaseLine).FirstOrDefaultAsync();
|
||
var readingQuestionList = await _readingQuestionTrialRepository.Where(x => x.ReadingQuestionCriterionTrialId == taskInfo.TrialReadingCriterionId
|
||
&& (x.IsJudgeQuestion || (x.IsRequired == IsRequired.Required && x.ShowQuestion == ShowQuestion.Show))
|
||
).ToListAsync();
|
||
if (isBaseline)
|
||
{
|
||
readingQuestionList = readingQuestionList.Where(x => x.LimitEdit != LimitEdit.OnlyVisit).ToList();
|
||
}
|
||
else
|
||
{
|
||
readingQuestionList = readingQuestionList.Where(x => x.LimitEdit != LimitEdit.OnlyBaseLine).ToList();
|
||
}
|
||
var answerQuestionIds = await _readingTaskQuestionAnswerRepository.Where(x => x.VisitTaskId == inDto.VisitTaskId).Select(x => x.ReadingQuestionTrialId).ToListAsync();
|
||
|
||
readingQuestionList = readingQuestionList.Where(x => !answerQuestionIds.Contains(x.Id)).ToList();
|
||
|
||
if (readingQuestionList.Count() > 0)
|
||
{
|
||
throw new BusinessValidationFailedException(_localizer["ReadingImage_RequiredQuestion", string.Join(',', readingQuestionList.Select(x => x.QuestionName.LanguageName(x.QuestionEnName, _userInfo.IsEn_Us)))]);
|
||
}
|
||
|
||
await _readingCalculateService.VerifyVisitTaskQuestions(inDto);
|
||
|
||
var clinicalDataList = await _readingClinicalDataService.GetClinicalDataList(new GetReadingOrTaskClinicalDataListInDto()
|
||
{
|
||
|
||
SubjectId = taskInfo.SubjectId,
|
||
TrialId = taskInfo.TrialId,
|
||
VisitTaskId = taskInfo.Id,
|
||
|
||
});
|
||
|
||
var isBaseLine = false;
|
||
if (taskInfo.SourceSubjectVisitId != null)
|
||
{
|
||
isBaseLine = await _subjectVisitRepository.Where(x => x.Id == taskInfo.SourceSubjectVisitId).Select(x => x.IsBaseLine).FirstOrDefaultAsync();
|
||
}
|
||
|
||
var isNeedReadClinicalData = false;
|
||
|
||
if (isBaseLine)
|
||
{
|
||
isNeedReadClinicalData = clinicalDataList.Count() > 0;
|
||
}
|
||
else
|
||
{
|
||
isNeedReadClinicalData = clinicalDataList.Where(x => x.ClinicalDataLevel != ClinicalLevel.Subject).Count() > 0;
|
||
}
|
||
|
||
if (isNeedReadClinicalData && !taskInfo.IsReadClinicalData)
|
||
{
|
||
throw new BusinessValidationFailedException(_localizer["ReadingImage_ClinicalRead"]);
|
||
}
|
||
|
||
|
||
|
||
return ResponseOutput.Ok(true);
|
||
}
|
||
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// 获取下一个阅片任务
|
||
/// </summary>
|
||
/// <param name="inDto"></param>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
public async Task<GetReadingTaskDto> GetNextTask(GetNextTaskInDto inDto)
|
||
{
|
||
if (inDto.VisitTaskId == null)
|
||
{
|
||
await VerifyReadingRestTime();
|
||
}
|
||
|
||
GetReadingTaskDto? task = new GetReadingTaskDto();
|
||
|
||
var trialReadingCriterionId = inDto.TrialReadingCriterionId;
|
||
|
||
|
||
if (trialReadingCriterionId == null && inDto.VisitTaskId == null)
|
||
{
|
||
throw new BusinessValidationFailedException(_localizer["ReadingImage_IDMust"]);
|
||
}
|
||
|
||
//看已阅的任务
|
||
if (inDto.VisitTaskId != null)
|
||
{
|
||
task = await _visitTaskRepository.Where(x => x.Id == inDto.VisitTaskId).Select(x => new GetReadingTaskDto()
|
||
{
|
||
VisitTaskId = x.Id,
|
||
TaskBlindName = x.TaskBlindName,
|
||
SubjectId = x.SubjectId,
|
||
ReadingCategory = x.ReadingCategory,
|
||
ArmEnum = x.ArmEnum,
|
||
VisistId = x.SourceSubjectVisitId != null ? x.SourceSubjectVisitId.Value : default(Guid),
|
||
VisitNum = x.VisitTaskNum,
|
||
TrialReadingCriterionId = x.TrialReadingCriterionId,
|
||
|
||
}).FirstOrDefaultAsync();
|
||
|
||
trialReadingCriterionId = task.TrialReadingCriterionId;
|
||
|
||
}
|
||
else if (inDto.SubjectId != null)
|
||
{
|
||
var subjectTaskList = (await _visitTaskService.GetOrderReadingIQueryable(new GetOrderReadingIQueryableInDto()
|
||
{
|
||
TrialId = inDto.TrialId,
|
||
TrialReadingCriterionId = trialReadingCriterionId.Value,
|
||
Page = new PageInput()
|
||
{
|
||
PageIndex = 1,
|
||
PageSize = 99999,
|
||
}
|
||
})).Item2;
|
||
|
||
var index = 0;
|
||
subjectTaskList.ForEach(x =>
|
||
{
|
||
x.Index = index;
|
||
index++;
|
||
});
|
||
|
||
var subjectIndex = subjectTaskList.Where(x => x.SubjectId == inDto.SubjectId && x.SubjectCode == inDto.SubjectCode).Select(x => x.Index).FirstOrDefault();
|
||
|
||
var currentSubject = subjectTaskList.Where(x => x.Index >= subjectIndex && !x.ExistReadingApply).OrderBy(x => x.Index).FirstOrDefault();
|
||
|
||
if (currentSubject == null)
|
||
{
|
||
throw new BusinessValidationFailedException(_localizer["ReadingImage_TaskFinish"]);
|
||
}
|
||
|
||
task = currentSubject.UnReadCanReadTaskList.Select(x => new GetReadingTaskDto()
|
||
{
|
||
ReadingCategory = x.ReadingCategory,
|
||
SubjectCode = currentSubject.SubjectCode,
|
||
SubjectId = currentSubject.SubjectId,
|
||
TaskBlindName = x.TaskBlindName,
|
||
VisitNum = x.VisitNum,
|
||
ArmEnum = x.ArmEnum,
|
||
VisistId = x.VisistId ?? default(Guid),
|
||
VisitTaskId = x.Id,
|
||
TrialReadingCriterionId = x.TrialReadingCriterionId,
|
||
}).FirstOrDefault();
|
||
|
||
|
||
if (task != null)
|
||
{
|
||
// 有序 自动领取该Subject
|
||
await ClaimOrCancelSubjectAsync(new ClaimSubjectDto() { IsClaim = true, SubejctId = task.SubjectId, TrialReadingCriterionId=task.TrialReadingCriterionId, VisitTaskId=task.VisitTaskId, IsInOrder = true });
|
||
}
|
||
}
|
||
else
|
||
{
|
||
//无序取数据
|
||
task = await _visitTaskRepository.Where(x => x.TrialId == inDto.TrialId && x.TrialReadingCriterionId == trialReadingCriterionId && x.ReadingTaskState != ReadingTaskState.HaveSigned /*&& x.DoctorUserId == _userInfo.Id*/
|
||
&& x.TrialReadingCriterionId == trialReadingCriterionId
|
||
&& x.TaskState == TaskState.Effect)
|
||
.Where(x => (x.IsNeedClinicalDataSign && x.IsClinicalDataSign) || !x.IsNeedClinicalDataSign)
|
||
.Select(x => new GetReadingTaskDto()
|
||
{
|
||
VisitTaskId = x.Id,
|
||
ArmEnum = x.ArmEnum,
|
||
TaskBlindName = x.TaskBlindName,
|
||
ReadingCategory = x.ReadingCategory,
|
||
VisistId = x.SourceSubjectVisitId != null ? x.SourceSubjectVisitId.Value : x.ReadModule == null ? default(Guid) : x.ReadModule.SubjectVisitId,
|
||
VisitNum = x.VisitTaskNum,
|
||
SubjectId = x.SubjectId,
|
||
SubjectCode = x.Subject.Code,
|
||
TrialReadingCriterionId = x.TrialReadingCriterionId,
|
||
}).OrderByDescending(t => t.TaskBlindName).FirstOrDefaultAsync();
|
||
|
||
if (task != null)
|
||
{
|
||
// 无序
|
||
await ClaimOrCancelSubjectAsync(new ClaimSubjectDto() { IsClaim = true, VisitTaskId = task.VisitTaskId, IsInOrder = false });
|
||
}
|
||
}
|
||
|
||
if (task == null)
|
||
{
|
||
throw new BusinessValidationFailedException(_localizer["ReadingImage_TaskFinish"]);
|
||
}
|
||
|
||
if (task.SubjectCode.IsNullOrEmpty())
|
||
{
|
||
task.SubjectCode = await _subjectRepository.Where(x => x.Id == task.SubjectId).Select(x => x.Code).FirstOrDefaultAsync();
|
||
}
|
||
|
||
await _visitTaskRepository.BatchUpdateNoTrackingAsync(x => x.Id == task.VisitTaskId && x.FirstReadingTime == null, x => new VisitTask()
|
||
{
|
||
FirstReadingTime = DateTime.Now,
|
||
});
|
||
await _visitTaskRepository.SaveChangesAsync();
|
||
|
||
var visitTaskInfo = await _visitTaskRepository.Where(x => x.Id == task.VisitTaskId).ProjectTo<VisitTaskDto>(_mapper.ConfigurationProvider).FirstNotNullAsync();
|
||
|
||
task.SubjectCode = visitTaskInfo.BlindSubjectCode.IsNullOrEmpty() ? task.SubjectCode : visitTaskInfo.BlindSubjectCode;
|
||
|
||
|
||
var criterionInfo = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == visitTaskInfo.TrialReadingCriterionId).Select(x => new
|
||
{
|
||
x.IsReadingShowPreviousResults,
|
||
x.IsReadingShowSubjectInfo,
|
||
x.DigitPlaces,
|
||
x.CriterionType,
|
||
x.IseCRFShowInDicomReading,
|
||
x.IsReadingTaskViewInOrder,
|
||
}).FirstOrDefaultAsync();
|
||
|
||
task.IsReadingShowPreviousResults = criterionInfo.IsReadingShowPreviousResults;
|
||
task.IsReadingShowSubjectInfo = criterionInfo.IsReadingShowSubjectInfo;
|
||
task.IsReadingTaskViewInOrder = criterionInfo.IsReadingTaskViewInOrder;
|
||
var isBaseLine = false;
|
||
if (visitTaskInfo.SourceSubjectVisitId != null)
|
||
{
|
||
task.IsExistsNoDicomFile = await _noneDicomStudyRepository.AnyAsync(x => x.SubjectVisitId == visitTaskInfo.SourceSubjectVisitId && x.FileCount > 0);
|
||
isBaseLine = await _subjectVisitRepository.Where(x => x.Id == visitTaskInfo.SourceSubjectVisitId).Select(x => x.IsBaseLine).FirstOrDefaultAsync();
|
||
}
|
||
|
||
var clinicalDataList = await _readingClinicalDataService.GetClinicalDataList(new GetReadingOrTaskClinicalDataListInDto()
|
||
{
|
||
|
||
SubjectId = task.SubjectId,
|
||
TrialId = inDto.TrialId,
|
||
VisitTaskId = task.VisitTaskId,
|
||
});
|
||
|
||
task.IsExistsClinicalData = clinicalDataList.Count() > 0;
|
||
task.IsReadClinicalData = visitTaskInfo.IsReadClinicalData;
|
||
|
||
if (isBaseLine)
|
||
{
|
||
task.IsNeedReadClinicalData = clinicalDataList.Count() > 0;
|
||
}
|
||
else
|
||
{
|
||
task.IsNeedReadClinicalData = clinicalDataList.Where(x => x.ClinicalDataLevel != ClinicalLevel.Subject).Count() > 0;
|
||
}
|
||
|
||
// 如果已经签名 就不需要再读了
|
||
task.IsNeedReadClinicalData = visitTaskInfo.ReadingTaskState == ReadingTaskState.HaveSigned ? false : task.IsNeedReadClinicalData;
|
||
task.DigitPlaces = criterionInfo.DigitPlaces;
|
||
task.CriterionType = criterionInfo.CriterionType;
|
||
task.IseCRFShowInDicomReading = criterionInfo.IseCRFShowInDicomReading;
|
||
task.IsFirstChangeTask = visitTaskInfo.IsConvertedTask && visitTaskInfo.BeforeConvertedTaskId != null;
|
||
task.IsConvertedTask = visitTaskInfo.IsConvertedTask;
|
||
var blindSubjectCode = await _visitTaskRepository.Where(x => x.Id == task.VisitTaskId).Select(x => x.BlindSubjectCode).FirstNotNullAsync();
|
||
task.SubjectCode = blindSubjectCode.IsNullOrEmpty() ? task.SubjectCode : blindSubjectCode;
|
||
task.ExistsManual = (await GetManualList(new GetManualListInDto() { TrialId = visitTaskInfo.TrialId })).Count() > 0;
|
||
task.ReadingTaskState = visitTaskInfo.ReadingTaskState;
|
||
return task;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 验证阅片休息时间
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
public async Task VerifyReadingRestTime()
|
||
{
|
||
var cacheKey = _userInfo.Id.ToString();
|
||
var value = _cache.Get(cacheKey);
|
||
if (value == null)
|
||
{
|
||
_cache.Set(cacheKey, DateTime.Now.ToString(), TimeSpan.FromHours(5));
|
||
|
||
}
|
||
else
|
||
{
|
||
#region 两小时
|
||
var cacheDate = DateTime.Parse(value.ToString());
|
||
int timespanMin = (DateTime.Now - cacheDate).Minutes;
|
||
if (timespanMin > 120 && timespanMin < 140)
|
||
{
|
||
throw new BusinessValidationFailedException(_localizer["ReadingImage_NeedRest", 2, 20]);
|
||
}
|
||
else if (timespanMin > 140)
|
||
{
|
||
cacheDate = cacheDate.AddMinutes((Math.Floor((double)(timespanMin / 140))) * 140);
|
||
_cache.Set(cacheKey, cacheDate.ToString(), TimeSpan.FromHours(5));
|
||
|
||
}
|
||
#endregion
|
||
|
||
#region 测试用的5分钟
|
||
//var cacheDate = DateTime.Parse(value.ToString());
|
||
//int timespanMin = (DateTime.Now - cacheDate).Minutes;
|
||
//if (timespanMin >= 5 && timespanMin <= 10)
|
||
//{
|
||
// throw new BusinessValidationFailedException("您已连续阅片2个小时,请休息20分钟后,再继续阅片。");
|
||
//}
|
||
//else if (timespanMin > 10)
|
||
//{
|
||
// cacheDate = cacheDate.AddMinutes((Math.Floor((double)(timespanMin / 10))) * 10);
|
||
// _cache.Set(cacheKey, cacheDate.ToString(), TimeSpan.FromHours(5));
|
||
|
||
//}
|
||
#endregion
|
||
|
||
|
||
}
|
||
|
||
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// 前端 仅仅释放的时候使用,领取是后端调用该方法
|
||
/// </summary>
|
||
/// <param name="claimSubjectDto"></param>
|
||
/// <returns></returns>
|
||
/// <exception cref="BusinessValidationFailedException"></exception>
|
||
[HttpPost]
|
||
public async Task ClaimOrCancelSubjectAsync(ClaimSubjectDto claimSubjectDto)
|
||
{
|
||
IScheduler scheduler = await _schedulerFactory.GetScheduler();
|
||
|
||
//有序 用SubjectCriterionClaimUserId 某个标准的所有任务,该字段保持一致
|
||
if (claimSubjectDto.IsInOrder)
|
||
{
|
||
|
||
if (claimSubjectDto.IsClaim)
|
||
{
|
||
//每个subject 每个标准的领取放在 任务上 免得加表
|
||
if(_visitTaskRepository.Any(t=>t.Id== claimSubjectDto.SubejctId && t.TrialReadingCriterionId==claimSubjectDto.TrialReadingCriterionId
|
||
&& t.SubjectCriterionClaimUserId != _userInfo.Id && t.SubjectCriterionClaimUserId != null))
|
||
{
|
||
throw new BusinessValidationFailedException("当前任务已被其他人领取,请进行其他的阅片任务");
|
||
}
|
||
else
|
||
{
|
||
await _visitTaskRepository.BatchUpdateNoTrackingAsync(t => t.SubjectId == claimSubjectDto.SubejctId && t.TrialReadingCriterionId == claimSubjectDto.TrialReadingCriterionId , u => new VisitTask() { SubjectCriterionClaimUserId = _userInfo.Id });
|
||
|
||
//列表可以看到当前阅片人是谁
|
||
await _visitTaskRepository.BatchUpdateNoTrackingAsync(t => t.Id == claimSubjectDto.VisitTaskId, u => new VisitTask() { DoctorUserId = _userInfo.Id });
|
||
|
||
}
|
||
|
||
//定时任务24h取消
|
||
|
||
// 创建一个任务
|
||
IJobDetail job = JobBuilder.Create<CancelTaskQuartZJob>()
|
||
|
||
.UsingJobData("SubjectId", claimSubjectDto.SubejctId) // 传递GUID参数给任务
|
||
.UsingJobData("TrialReadingCriterionId", claimSubjectDto.TrialReadingCriterionId)
|
||
.UsingJobData("IsInOrder", claimSubjectDto.IsInOrder)
|
||
.Build();
|
||
|
||
// 创建一个触发器,设置任务执行时间为24小时后
|
||
ITrigger trigger = TriggerBuilder.Create()
|
||
.StartAt(DateTimeOffset.UtcNow.AddHours(24))
|
||
.Build();
|
||
|
||
// 将任务和触发器关联起来,将任务安排到调度器中
|
||
await scheduler.ScheduleJob(job, trigger);
|
||
|
||
//BackgroundJob.Schedule<IObtainTaskAutoCancelJob>(t => t.CancelQCObtaion(subjectVisitId, DateTime.Now), TimeSpan.FromHours(1));
|
||
|
||
}
|
||
else
|
||
{
|
||
await _visitTaskRepository.BatchUpdateNoTrackingAsync(t => t.SubjectId == claimSubjectDto.SubejctId && t.TrialReadingCriterionId == claimSubjectDto.TrialReadingCriterionId , u => new VisitTask() { SubjectCriterionClaimUserId = null });
|
||
}
|
||
}
|
||
//无序 直接用DoctorUserId 当做领取人
|
||
else
|
||
{
|
||
if (claimSubjectDto.IsClaim)
|
||
{
|
||
if (_visitTaskRepository.Any(t => t.Id == claimSubjectDto.VisitTaskId && t.DoctorUserId != _userInfo.Id && t.DoctorUserId != null))
|
||
{
|
||
throw new BusinessValidationFailedException("当前任务已被其他人领取,请进行其他的阅片任务");
|
||
}
|
||
else
|
||
{
|
||
await _visitTaskRepository.UpdatePartialFromQueryAsync(t => t.Id == claimSubjectDto.VisitTaskId, u => new VisitTask() { DoctorUserId = _userInfo.Id }, true);
|
||
|
||
}
|
||
|
||
|
||
IJobDetail job = JobBuilder.Create<CancelTaskQuartZJob>()
|
||
.UsingJobData("VisitTaskId",(Guid) claimSubjectDto.VisitTaskId) // 传递GUID参数给任务
|
||
.UsingJobData("IsInOrder", claimSubjectDto.IsInOrder).Build();
|
||
|
||
// 创建一个触发器,设置任务执行时间为24小时后
|
||
ITrigger trigger = TriggerBuilder.Create()
|
||
.StartAt(DateTimeOffset.UtcNow.AddHours(24))
|
||
.Build();
|
||
|
||
// 将任务和触发器关联起来,将任务安排到调度器中
|
||
await scheduler.ScheduleJob(job, trigger);
|
||
}
|
||
}
|
||
|
||
await scheduler.Start();
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// 签名提交任务修改状态
|
||
/// </summary>
|
||
/// <param name="visitTaskId"></param>
|
||
/// <returns></returns>
|
||
private async Task SubmitTaskChangeState(Guid visitTaskId)
|
||
{
|
||
await VerifyTaskIsSign(visitTaskId);
|
||
await _visitTaskRepository.UpdatePartialFromQueryAsync(visitTaskId, x => new VisitTask()
|
||
{
|
||
DoctorUserId=_userInfo.Id,
|
||
ReadingTaskState = ReadingTaskState.HaveSigned,
|
||
SignTime = DateTime.Now,
|
||
});
|
||
|
||
await _visitTaskRepository.SaveChangesAsync();
|
||
|
||
bool isConverted = false;
|
||
|
||
var taskinfo = await _visitTaskRepository.Where(x => x.Id == visitTaskId).Include(x => x.TrialReadingCriterion).FirstNotNullAsync();
|
||
|
||
var isConvertedTask = await _visitTaskRepository.Where(x => x.Id == visitTaskId).Select(x => x.IsConvertedTask).FirstNotNullAsync();
|
||
switch (taskinfo.TrialReadingCriterion.CriterionType)
|
||
{
|
||
case CriterionType.IRECIST1Point1:
|
||
|
||
|
||
|
||
if (!isConvertedTask &&
|
||
(await _readingTaskQuestionAnswerRepository.AnyAsync(x => x.VisitTaskId == visitTaskId
|
||
&& x.ReadingQuestionTrial.QuestionType == QuestionType.Tumor && x.Answer == (((int)OverallAssessment.PD)).ToString()))
|
||
)
|
||
{
|
||
|
||
isConverted = true;
|
||
}
|
||
break;
|
||
}
|
||
|
||
// 创建任务关联关系
|
||
await this.CreateTaskRelated(visitTaskId);
|
||
|
||
// 是否触发转变任务
|
||
if (isConverted)
|
||
{
|
||
await _visitTaskHelpeService.AddConvertedTask(visitTaskId);
|
||
}
|
||
else
|
||
{
|
||
// 触裁判任务
|
||
await this.TriggerJudgeQuestion(visitTaskId);
|
||
// 添加阅片期任务
|
||
await this.AddReadingTask(visitTaskId);
|
||
|
||
// 完成阅片修改状态
|
||
//await this.FinishReadUpdateState(visitTaskId);
|
||
|
||
|
||
|
||
await _visitTaskRepository.SaveChangesAsync();
|
||
|
||
//await _trialEmailNoticeConfigService.BaseBusinessScenarioSendEmailAsync(visitTaskId);
|
||
}
|
||
|
||
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 签名时创建任务关联
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
private async Task CreateTaskRelated(Guid visitTaskId)
|
||
{
|
||
var taskInfo = await _visitTaskRepository.Where(x => x.Id == visitTaskId).FirstNotNullAsync();
|
||
|
||
|
||
// 判断是否有序阅片
|
||
|
||
var isReadingTaskViewInOrder = await _readingQuestionCriterionTrialRepository.Where(x => x.Id == taskInfo.TrialReadingCriterionId).Select(x => x.IsReadingTaskViewInOrder).FirstNotNullAsync();
|
||
|
||
// 判断任务类型
|
||
|
||
// 关联访视Id
|
||
List<Guid> relatedVisitTaskIdList = new List<Guid>();
|
||
|
||
// 既往任务Id
|
||
List<Guid> pastResultTaskIdList = new List<Guid>();
|
||
|
||
// 冻结任务Id
|
||
List<Guid> reportRelatedTaskIdList = new List<Guid>();
|
||
|
||
|
||
if (isReadingTaskViewInOrder)
|
||
{
|
||
pastResultTaskIdList = await _visitTaskRepository.Where(x =>
|
||
x.TrialId == taskInfo.TrialId &&
|
||
x.SubjectId == taskInfo.SubjectId &&
|
||
x.VisitTaskNum < taskInfo.VisitTaskNum &&
|
||
x.ArmEnum == taskInfo.ArmEnum &&
|
||
//x.DoctorUserId == taskInfo.DoctorUserId &&
|
||
x.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId &&
|
||
x.ReadingTaskState == ReadingTaskState.HaveSigned &&
|
||
x.TaskState == TaskState.Effect &&
|
||
x.IsSelfAnalysis == taskInfo.IsSelfAnalysis &&
|
||
x.IsAnalysisCreate == taskInfo.IsAnalysisCreate &&
|
||
x.ReadingCategory == taskInfo.ReadingCategory &&
|
||
x.Id != taskInfo.Id
|
||
).OrderBy(x => x.VisitTaskNum).ThenBy(x => x.TaskState).Select(x => x.Id).ToListAsync();
|
||
|
||
|
||
reportRelatedTaskIdList = await _visitTaskRepository.Where(x =>
|
||
x.TrialId == taskInfo.TrialId &&
|
||
x.SubjectId == taskInfo.SubjectId &&
|
||
x.VisitTaskNum <= taskInfo.VisitTaskNum &&
|
||
x.ArmEnum == taskInfo.ArmEnum &&
|
||
//x.DoctorUserId == taskInfo.DoctorUserId &&
|
||
x.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId &&
|
||
x.ReadingTaskState == ReadingTaskState.HaveSigned &&
|
||
(x.TaskState == TaskState.Effect || x.TaskState == TaskState.Freeze) &&
|
||
x.IsSelfAnalysis == taskInfo.IsSelfAnalysis &&
|
||
x.IsAnalysisCreate == taskInfo.IsAnalysisCreate &&
|
||
x.ReadingCategory == taskInfo.ReadingCategory &&
|
||
x.Id != taskInfo.Id
|
||
).OrderBy(x => x.VisitTaskNum).ThenBy(x => x.TaskState).Select(x => x.Id).ToListAsync();
|
||
|
||
switch (taskInfo.ReadingCategory)
|
||
{
|
||
case ReadingCategory.Visit:
|
||
case ReadingCategory.Global:
|
||
case ReadingCategory.Oncology:
|
||
relatedVisitTaskIdList = await _visitTaskRepository.Where(x =>
|
||
x.TrialId == taskInfo.TrialId &&
|
||
x.SubjectId == taskInfo.SubjectId &&
|
||
x.ReadingCategory == ReadingCategory.Visit &&
|
||
x.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId &&
|
||
x.ReadingTaskState == ReadingTaskState.HaveSigned &&
|
||
x.IsAnalysisCreate == taskInfo.IsAnalysisCreate &&
|
||
x.ArmEnum == taskInfo.ArmEnum &&
|
||
x.IsSelfAnalysis == taskInfo.IsSelfAnalysis &&
|
||
//x.DoctorUserId == taskInfo.DoctorUserId &&
|
||
x.TaskState == TaskState.Effect && x.VisitTaskNum <= taskInfo.VisitTaskNum).Select(x => x.Id).ToListAsync();
|
||
break;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (taskInfo.ReadingCategory == ReadingCategory.Visit)
|
||
{
|
||
relatedVisitTaskIdList.Add(taskInfo.Id);
|
||
}
|
||
}
|
||
|
||
await _visitTaskRepository.UpdatePartialFromQueryAsync(taskInfo.Id, x => new VisitTask()
|
||
{
|
||
|
||
|
||
ReportRelatedTaskIds = JsonConvert.SerializeObject(reportRelatedTaskIdList),
|
||
PastResultTaskIds = JsonConvert.SerializeObject(pastResultTaskIdList),
|
||
RelatedVisitTaskIds = JsonConvert.SerializeObject(relatedVisitTaskIdList),
|
||
});
|
||
|
||
await _readingTaskRelationRepository.AddRangeAsync(pastResultTaskIdList.Select(x => new ReadingTaskRelation()
|
||
{
|
||
RelevanceTaskId = x,
|
||
TaskId = visitTaskId,
|
||
RelevanceType = RelevanceType.PastResult,
|
||
}));
|
||
|
||
await _readingTaskRelationRepository.AddRangeAsync(relatedVisitTaskIdList.Select(x => new ReadingTaskRelation()
|
||
{
|
||
RelevanceTaskId = x,
|
||
TaskId = visitTaskId,
|
||
RelevanceType = RelevanceType.Related,
|
||
}));
|
||
|
||
await _readingTaskRelationRepository.AddRangeAsync(reportRelatedTaskIdList.Select(x => new ReadingTaskRelation()
|
||
{
|
||
RelevanceTaskId = x,
|
||
TaskId = visitTaskId,
|
||
RelevanceType = RelevanceType.ReportResult,
|
||
}));
|
||
|
||
|
||
await _visitTaskRepository.SaveChangesAsync();
|
||
}
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// 阅片期 -全局和肿瘤学任务的生成
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
[HttpPost]
|
||
[TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
|
||
public async Task AddReadingTask(Guid visitTaskId, Guid? trialId = null)
|
||
{
|
||
// ****** 先生成阅片期 阅片期任务阅片完成之后生成肿瘤学的 如果没有阅片期 直接生成肿瘤学 *********////
|
||
#region 建立关系
|
||
// 访视阅完产生 全局
|
||
Dictionary<ModuleTypeEnum, ReadingCategory> typeChangeDic = new Dictionary<ModuleTypeEnum, ReadingCategory>();
|
||
typeChangeDic.Add(ModuleTypeEnum.InPlanSubjectVisit, ReadingCategory.Visit);
|
||
typeChangeDic.Add(ModuleTypeEnum.OutPlanSubjectVisit, ReadingCategory.Visit);
|
||
//typeChange.Add(ModuleTypeEnum.Read, ReadingCategory.ReadingPeriod);
|
||
typeChangeDic.Add(ModuleTypeEnum.Global, ReadingCategory.Global);
|
||
typeChangeDic.Add(ModuleTypeEnum.Referee, ReadingCategory.Judge);
|
||
typeChangeDic.Add(ModuleTypeEnum.Oncology, ReadingCategory.Oncology);
|
||
#endregion
|
||
var taskInfo = await _visitTaskRepository.Where(x => x.Id == visitTaskId).FirstNotNullAsync();
|
||
List<ReadingGenerataTaskDTO> needReadList = new List<ReadingGenerataTaskDTO>();
|
||
if (!taskInfo.IsAnalysisCreate)
|
||
{
|
||
// 任务类型
|
||
switch (taskInfo.ReadingCategory)
|
||
{
|
||
case ReadingCategory.Visit:
|
||
needReadList = await _readModuleRepository.Where(x => x.SubjectVisitId == taskInfo.SourceSubjectVisitId &&
|
||
|
||
x.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId &&
|
||
x.ReadingSetType == ReadingSetType.ImageReading)
|
||
.Select(x => new ReadingGenerataTaskDTO
|
||
{
|
||
IsUrgent = x.IsUrgent ?? false,
|
||
SubjectId = x.SubjectId,
|
||
VisitNum = x.SubjectVisit.VisitNum,
|
||
ReadingName = x.ModuleName,
|
||
ReadModuleId = x.Id,
|
||
ReadingCategory = typeChangeDic[x.ModuleType],
|
||
}).ToListAsync();
|
||
if (needReadList.Any(x => x.ReadingCategory == ReadingCategory.Global))
|
||
{
|
||
needReadList = needReadList.Where(x => x.ReadingCategory != ReadingCategory.Oncology).ToList();
|
||
}
|
||
//needReadList = needReadList.Where(x => _visitTaskRepository.Where(y => y.SouceReadModuleId == x.ReadModuleId).Count() == 0).ToList();
|
||
await _visitTaskHelpeService.AddTaskAsync(new GenerateTaskCommand()
|
||
{
|
||
OriginalVisitId = visitTaskId,
|
||
ReadingCategory = GenerateTaskCategory.Global,
|
||
TrialId = taskInfo.TrialId,
|
||
|
||
ReadingGenerataTaskList = needReadList
|
||
});
|
||
break;
|
||
// 肿瘤学
|
||
case ReadingCategory.Global:
|
||
var subjectVisitId = await _readModuleRepository.Where(x => x.Id == taskInfo.SouceReadModuleId).Select(x => x.SubjectVisitId).FirstOrDefaultAsync();
|
||
var oncologyReadId = await _readModuleRepository.Where(x => x.SubjectVisitId == subjectVisitId && x.ModuleType == ModuleTypeEnum.Oncology
|
||
&& x.TrialReadingCriterionId == taskInfo.TrialReadingCriterionId
|
||
|
||
|
||
).Select(x => x.Id).FirstOrDefaultAsync();
|
||
|
||
if (await _visitTaskRepository.AnyAsync(x => x.Id == visitTaskId && x.JudgeVisitTaskId == null))
|
||
{
|
||
await AddOncologyTask(oncologyReadId);
|
||
}
|
||
|
||
|
||
break;
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
}
|
||
|
||
#endregion
|
||
|
||
|
||
}
|
||
}
|