|
|
package com.supervision.service.impl;
|
|
|
|
|
|
|
|
|
import cn.hutool.core.bean.BeanUtil;
|
|
|
import cn.hutool.core.collection.CollUtil;
|
|
|
import cn.hutool.core.collection.CollectionUtil;
|
|
|
import cn.hutool.core.util.NumberUtil;
|
|
|
import cn.hutool.core.util.ObjectUtil;
|
|
|
import cn.hutool.core.util.StrUtil;
|
|
|
import com.supervision.exception.BusinessException;
|
|
|
import com.supervision.model.Process;
|
|
|
import com.supervision.model.*;
|
|
|
import com.supervision.pojo.vo.*;
|
|
|
import com.supervision.service.*;
|
|
|
import com.supervision.vo.ask.TreatmentPlanRecordVo;
|
|
|
import com.supervision.vo.manage.DiseaseAncillaryResVo;
|
|
|
import com.supervision.vo.manage.DiseasePhysicalResVo;
|
|
|
import com.supervision.vo.manage.DiseaseTreatmentPlanResVo;
|
|
|
import com.supervision.vo.result.AncillaryRecordByResultDTO;
|
|
|
import com.supervision.vo.result.PhysicalRecordByResultDTO;
|
|
|
import lombok.RequiredArgsConstructor;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
import java.math.BigDecimal;
|
|
|
import java.math.RoundingMode;
|
|
|
import java.util.*;
|
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
|
import java.util.function.BiFunction;
|
|
|
import java.util.function.Function;
|
|
|
import java.util.function.Predicate;
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
@Service
|
|
|
@RequiredArgsConstructor
|
|
|
public class AskDiagnosisResultServiceImpl implements AskDiagnosisResultService {
|
|
|
|
|
|
private final DiagnosisPrimaryService diagnosisPrimaryService;
|
|
|
|
|
|
private final AskPatientAnswerService askPatientAnswerService;
|
|
|
|
|
|
private final MedicalRecService medicalRecService;
|
|
|
|
|
|
private final DiagnosisQaRecordService diagnosisQaRecordService;
|
|
|
|
|
|
private final DiagnosisPhysicalRecordService diagnosisPhysicalRecordService;
|
|
|
|
|
|
private final DiagnosisAncillaryRecordService diagnosisAncillaryRecordService;
|
|
|
|
|
|
private final ProcessService processService;
|
|
|
|
|
|
private final ProcessEvaluationService processEvaluationService;
|
|
|
|
|
|
private final DiseaseService diseaseService;
|
|
|
|
|
|
private final TreatmentPlanRecordService treatmentPlanRecordService;
|
|
|
|
|
|
private final DiseaseTreatmentPlanService diseaseTreatmentPlanService;
|
|
|
|
|
|
private final DiseaseTreatmentPlanDrugService diseaseTreatmentPlanDrugService;
|
|
|
|
|
|
private final DiseasePhysicalService diseasePhysicalService;
|
|
|
|
|
|
private final DiseaseAncillaryService diseaseAncillaryService;
|
|
|
|
|
|
|
|
|
@Override
|
|
|
public DiagnosisResultResVO queryDiagnosisResult(String processId) {
|
|
|
DiagnosisResultResVO diagnosisResultResVO = new DiagnosisResultResVO();
|
|
|
diagnosisResultResVO.setId(processId);
|
|
|
Process process = processService.getById(processId);
|
|
|
MedicalRec medicalRec = medicalRecService.getById(process.getMedicalRecId());
|
|
|
List<Disease> diseasesList = diseaseService.listDiseaseNestIfComposite(medicalRec.getDiseaseId());
|
|
|
// 1.生成预期诊断结果
|
|
|
diagnosisResultResVO.setExpertDiagnosisResult(creatExpertDiagnosisResult(medicalRec, diseasesList, processId));
|
|
|
// 2.生成初步诊断依据
|
|
|
diagnosisResultResVO.setBasisPrimaryResultResVO(createBasisPrimaryResult(medicalRec, process));
|
|
|
// 3.生成证实诊断依据
|
|
|
diagnosisResultResVO.setBasisConfirmResultResVO(createBasisConfirmResult(medicalRec, processId));
|
|
|
// 4.生成鉴别诊断依据
|
|
|
diagnosisResultResVO.setBasisIdentificationResult(createBasisIdentificationResult(medicalRec, processId));
|
|
|
// 5.全面检查-(暂无相关数据) 后面再看
|
|
|
diagnosisResultResVO.setFullCheck(null);
|
|
|
// 6.处置方案
|
|
|
diagnosisResultResVO.setDealPlan(createDealPlan(process.getDiseaseId(), processId));
|
|
|
return diagnosisResultResVO;
|
|
|
}
|
|
|
|
|
|
private DealPlanResVO createDealPlan(String diseaseId, String processId) {
|
|
|
|
|
|
DealPlanResVO dealPlanResVO = new DealPlanResVO();
|
|
|
|
|
|
// 1. 查询处置计划记录
|
|
|
List<? extends TreatmentPlanRecord> treatmentPlanRecordList = treatmentPlanRecordService.queryByProcessId(processId);
|
|
|
if (CollectionUtil.isEmpty(treatmentPlanRecordList)) {
|
|
|
return dealPlanResVO;
|
|
|
}
|
|
|
|
|
|
// 2. 查询出疾病处置计划(疾病配置的处置计划)
|
|
|
List<DiseaseTreatmentPlanResVo> diseaseTreatmentPlanResVos = diseaseTreatmentPlanService.queryListByDiseaseId(diseaseId);
|
|
|
List<String> treatmentPlanId = diseaseTreatmentPlanResVos.stream().map(DiseaseTreatmentPlanResVo::getTreatmentPlanId).distinct().collect(Collectors.toList());
|
|
|
|
|
|
// 3. 查出疾病处置计划用药(疾病配置的用药计划)
|
|
|
List<DiseaseTreatmentPlanDrug> diseaseTreatmentPlanDrugList = diseaseTreatmentPlanDrugService.lambdaQuery().eq(DiseaseTreatmentPlanDrug::getDiseaseId, diseaseId).list();
|
|
|
List<String> drugIds = diseaseTreatmentPlanDrugList.stream().map(DiseaseTreatmentPlanDrug::getDrugId).distinct().collect(Collectors.toList());
|
|
|
|
|
|
// 4. 组装数据
|
|
|
ArrayList<TreatmentPlanRecordVo> drugTreatmentPlanResults = new ArrayList<>();
|
|
|
ArrayList<TreatmentPlanRecordVo> otherTreatmentPlanResults = new ArrayList<>();
|
|
|
for (TreatmentPlanRecord treatmentPlanRecord : treatmentPlanRecordList) {
|
|
|
TreatmentPlanRecordVo bean = BeanUtil.toBean(treatmentPlanRecord, TreatmentPlanRecordVo.class);
|
|
|
// 是否正确
|
|
|
boolean flag = StrUtil.isNotEmpty(bean.getDrugId()) ? drugIds.contains(bean.getDrugId()) : treatmentPlanId.contains(bean.getTreatmentPlanId());
|
|
|
bean.setFlag(flag ? 1 : 0);
|
|
|
if (StrUtil.isNotEmpty(bean.getDrugId())) {
|
|
|
drugTreatmentPlanResults.add(bean);
|
|
|
} else {
|
|
|
otherTreatmentPlanResults.add(bean);
|
|
|
}
|
|
|
|
|
|
}
|
|
|
dealPlanResVO.setUserTreatmentPlanType(CollectionUtil.getFirst(treatmentPlanRecordList).getDisposalMethod());
|
|
|
dealPlanResVO.setDrugTreatmentPlan(drugTreatmentPlanResults);
|
|
|
dealPlanResVO.setOtherTreatmentPlan(otherTreatmentPlanResults.stream().sorted(
|
|
|
Comparator.comparing(TreatmentPlanRecord::getDisposalPlan)).collect(Collectors.toList()));
|
|
|
return dealPlanResVO;
|
|
|
|
|
|
}
|
|
|
|
|
|
private BasisIdentificationResultResVO createBasisIdentificationResult(MedicalRec medicalRec, String processId) {
|
|
|
BasisIdentificationResultResVO basisIdentificationResultResVO = new BasisIdentificationResultResVO();
|
|
|
// 鉴别诊断依据,来自于medicalRec的DifferentialDiagnosisCriteria
|
|
|
basisIdentificationResultResVO.setIdentificationDiagnosis(medicalRec.getDifferentialDiagnosisCriteria());
|
|
|
// 2.2 获取体格检查
|
|
|
List<PhysicalRecordByResultDTO> physicalRecordList = diagnosisPhysicalRecordService.queryPhysicalResultByProcessId(processId);
|
|
|
List<DiseasePhysicalResVo> diseasePhysicalResVos = diseasePhysicalService.queryListByDiseaseId(medicalRec.getDiseaseId());
|
|
|
|
|
|
List<BasisDiagnosisNodeResVO> nodeList = physicalRecordMergeListsIdentification(physicalRecordList, diseasePhysicalResVos);
|
|
|
|
|
|
// 2.3 获取辅助检查
|
|
|
List<AncillaryRecordByResultDTO> ancillaryRecordList = diagnosisAncillaryRecordService.queryAncillaryResultByProcessId(processId);
|
|
|
List<DiseaseAncillaryResVo> diseaseAncillaryResVos = diseaseAncillaryService.queryListByDiseaseId(medicalRec.getDiseaseId());
|
|
|
|
|
|
nodeList.addAll(ancillaryRecordMergeListsIdentification(ancillaryRecordList, diseaseAncillaryResVos));
|
|
|
|
|
|
basisIdentificationResultResVO.setNodeList(nodeList);
|
|
|
return basisIdentificationResultResVO;
|
|
|
}
|
|
|
|
|
|
private BasisConfirmResultResVO createBasisConfirmResult(MedicalRec medicalRec, String processId) {
|
|
|
BasisConfirmResultResVO basisConfirmResultResVO = new BasisConfirmResultResVO();
|
|
|
// 证实诊断依据,来自于medicalRec的ConfirmDiagnosisCriteria
|
|
|
basisConfirmResultResVO.setConfirmingDiagnosis(medicalRec.getConfirmDiagnosisCriteria());
|
|
|
// 2.2 获取体格检查的证实诊断依据
|
|
|
List<PhysicalRecordByResultDTO> physicalRecordList = diagnosisPhysicalRecordService.queryPhysicalResultByProcessId(processId);
|
|
|
List<DiseasePhysicalResVo> diseasePhysicalResVos = diseasePhysicalService.queryListByDiseaseId(medicalRec.getDiseaseId());
|
|
|
|
|
|
List<BasisDiagnosisNodeResVO> nodeList = physicalRecordMergeListsConfirm(physicalRecordList, diseasePhysicalResVos);
|
|
|
|
|
|
// 2.3 获取辅助检查
|
|
|
List<AncillaryRecordByResultDTO> ancillaryRecordList = diagnosisAncillaryRecordService.queryAncillaryResultByProcessId(processId);
|
|
|
List<DiseaseAncillaryResVo> diseaseAncillaryResVos = diseaseAncillaryService.queryListByDiseaseId(medicalRec.getDiseaseId());
|
|
|
nodeList.addAll(ancillaryRecordMergeListsConfirm(ancillaryRecordList, diseaseAncillaryResVos));
|
|
|
|
|
|
basisConfirmResultResVO.setNodeList(nodeList);
|
|
|
return basisConfirmResultResVO;
|
|
|
}
|
|
|
|
|
|
private BasisPrimaryResultResVO createBasisPrimaryResult(MedicalRec medicalRec, Process process) {
|
|
|
BasisPrimaryResultResVO basisPrimaryResultResVO = new BasisPrimaryResultResVO();
|
|
|
// 初步诊断依据 vp_medical_rec的primarily_diagnosis_criteria
|
|
|
basisPrimaryResultResVO.setPreliminaryDiagnosis(medicalRec.getPrimarilyDiagnosisCriteria());
|
|
|
// 根据record记录寻找符合初步诊断依据的项目
|
|
|
// 2.1 首先获取对话
|
|
|
List<DiagnosisQaRecord> qaRecordList = diagnosisQaRecordService.lambdaQuery().eq(DiagnosisQaRecord::getProcessId, process.getId()).list();
|
|
|
List<AskPatientAnswer> list = askPatientAnswerService.lambdaQuery()
|
|
|
.eq(AskPatientAnswer::getMedicalId, medicalRec.getId()).list();
|
|
|
// 获取配置了答案的项目(配置了答案的,认为是正确,没有配置答案的,走默认回答的,不标记为以正确)
|
|
|
List<BasisDiagnosisNodeResVO> basisDiagnosisNodeResVOS = new ArrayList<>(qaRecordMergeListsBasisPrimary(qaRecordList, list));
|
|
|
|
|
|
// 2.2 获取体格检查
|
|
|
List<PhysicalRecordByResultDTO> physicalRecordList = diagnosisPhysicalRecordService.queryPhysicalResultByProcessId(process.getId());
|
|
|
List<DiseasePhysicalResVo> diseasePhysicalResVos = diseasePhysicalService.queryListByDiseaseId(medicalRec.getDiseaseId());
|
|
|
|
|
|
basisDiagnosisNodeResVOS.addAll(physicalRecordMergeListsBasisPrimary(physicalRecordList, diseasePhysicalResVos));
|
|
|
|
|
|
// 2.3 获取辅助检查
|
|
|
List<AncillaryRecordByResultDTO> ancillaryRecordList = diagnosisAncillaryRecordService.queryAncillaryResultByProcessId(process.getId());
|
|
|
List<DiseaseAncillaryResVo> diseaseAncillaryResVos = diseaseAncillaryService.queryListByDiseaseId(medicalRec.getDiseaseId());
|
|
|
|
|
|
basisDiagnosisNodeResVOS.addAll(ancillaryRecordMergeListsBasisPrimary(ancillaryRecordList, diseaseAncillaryResVos));
|
|
|
|
|
|
basisPrimaryResultResVO.setNodeList(basisDiagnosisNodeResVOS);
|
|
|
return basisPrimaryResultResVO;
|
|
|
}
|
|
|
|
|
|
|
|
|
private List<BasisDiagnosisNodeResVO> qaRecordMergeListsBasisPrimary(List<DiagnosisQaRecord> qaRecordList, List<AskPatientAnswer> list) {
|
|
|
|
|
|
BiFunction<DiagnosisQaRecord, AskPatientAnswer, Boolean> biFunction = (qaRecord, qa) -> qa.getLibraryQuestionId().equals(qaRecord.getQuestionLibraryId());
|
|
|
|
|
|
list = list.stream().filter(item -> !Integer.valueOf("0").equals(item.getAnswerType())).collect(Collectors.toList());
|
|
|
Set<String> requireCheckIdSet = list.stream().map(AskPatientAnswer::getId).collect(Collectors.toSet());
|
|
|
|
|
|
Function<DiagnosisQaRecord, BasisDiagnosisNodeResVO> t1 = r -> new BasisDiagnosisNodeResVO(0, r.getQuestion(), r.getId(),
|
|
|
requireCheckIdSet.contains(r.getAnswerId()) ? 1 : 0);
|
|
|
Function<AskPatientAnswer, BasisDiagnosisNodeResVO> t2 = item -> new BasisDiagnosisNodeResVO(0, item.getQuestion(), item.getId(), 0);
|
|
|
|
|
|
return mergeListsBasedOnCondition(qaRecordList, list, biFunction, t1, t2);
|
|
|
}
|
|
|
|
|
|
|
|
|
private List<BasisDiagnosisNodeResVO> physicalRecordMergeLists(List<PhysicalRecordByResultDTO> physicalRecordList,
|
|
|
List<DiseasePhysicalResVo> diseasePhysicalResVos,
|
|
|
Function<PhysicalRecordByResultDTO, Integer> functionCorrect) {
|
|
|
physicalRecordList = physicalRecordList.stream()
|
|
|
.filter(distinctPredicateNotNull(PhysicalRecordByResultDTO::getToolLocationName)).collect(Collectors.toList());
|
|
|
|
|
|
// 工具id相等且 位置为空或者位置id相等
|
|
|
BiFunction<PhysicalRecordByResultDTO, DiseasePhysicalResVo, Boolean> biFunction = (r, diseasePhysical) -> StrUtil.equals(diseasePhysical.getToolId(), r.getToolId())
|
|
|
&& ((StrUtil.isEmpty(diseasePhysical.getLocationId()) && StrUtil.isEmpty(diseasePhysical.getLocationId()))
|
|
|
|| StrUtil.equals(diseasePhysical.getLocationId(), (r.getLocationId())));
|
|
|
|
|
|
Function<PhysicalRecordByResultDTO, BasisDiagnosisNodeResVO> t1 = r -> new BasisDiagnosisNodeResVO(1, r.getToolLocationName(),
|
|
|
r.getRecordId(), functionCorrect.apply(r));
|
|
|
|
|
|
// 这里的recordId只为了展示用diseasePhysical.getId()代替。只是为展示使用correct的值固定为不正确
|
|
|
Function<DiseasePhysicalResVo, BasisDiagnosisNodeResVO> t2 = diseasePhysical -> new BasisDiagnosisNodeResVO(1,
|
|
|
diseasePhysical.getToolName() + (StrUtil.isEmpty(diseasePhysical.getLocationName()) ? "" : "|" + diseasePhysical.getLocationName()),
|
|
|
diseasePhysical.getId(), 0);
|
|
|
|
|
|
return mergeListsBasedOnCondition(physicalRecordList, diseasePhysicalResVos, biFunction, t1, t2);
|
|
|
}
|
|
|
|
|
|
private List<BasisDiagnosisNodeResVO> ancillaryRecordMergeLists(List<AncillaryRecordByResultDTO> ancillaryRecordList,
|
|
|
List<DiseaseAncillaryResVo> diseaseAncillaryResVos,
|
|
|
Function<AncillaryRecordByResultDTO, Integer> functionCorrect) {
|
|
|
ancillaryRecordList = ancillaryRecordList.stream()
|
|
|
.filter(distinctPredicateNotNull(AncillaryRecordByResultDTO::getItemName)).collect(Collectors.toList());
|
|
|
|
|
|
BiFunction<AncillaryRecordByResultDTO, DiseaseAncillaryResVo, Boolean> biFunction = (r, diseaseAncillary) -> StrUtil.equals(diseaseAncillary.getItemId(), r.getItemId());
|
|
|
|
|
|
Function<AncillaryRecordByResultDTO, BasisDiagnosisNodeResVO> t1 = record -> new BasisDiagnosisNodeResVO(2, record.getItemName(), record.getRecordId(),
|
|
|
functionCorrect.apply(record));
|
|
|
|
|
|
// 这里的recordId只为了展示用diseaseAncillary.getId()代替。只是为展示使用correct的值固定为不正确
|
|
|
Function<DiseaseAncillaryResVo, BasisDiagnosisNodeResVO> t2 = diseaseAncillary -> new BasisDiagnosisNodeResVO(2, diseaseAncillary.getItemName(),
|
|
|
diseaseAncillary.getId(), 0);
|
|
|
|
|
|
return mergeListsBasedOnCondition(ancillaryRecordList, diseaseAncillaryResVos, biFunction, t1, t2);
|
|
|
}
|
|
|
|
|
|
private List<BasisDiagnosisNodeResVO> physicalRecordMergeListsBasisPrimary(List<PhysicalRecordByResultDTO> physicalRecordList,
|
|
|
List<DiseasePhysicalResVo> diseasePhysicalResVos) {
|
|
|
|
|
|
diseasePhysicalResVos = diseasePhysicalResVos.stream()
|
|
|
.filter(diseasePhysicalResVo -> Integer.valueOf(1).equals(diseasePhysicalResVo.getPrimarilyDiagnosisCriteriaFlag())).collect(Collectors.toList());
|
|
|
return physicalRecordMergeLists(physicalRecordList, diseasePhysicalResVos, PhysicalRecordByResultDTO::getPrimarilyDiagnosisCriteriaFlag);
|
|
|
}
|
|
|
|
|
|
private List<BasisDiagnosisNodeResVO> physicalRecordMergeListsConfirm(List<PhysicalRecordByResultDTO> physicalRecordList,
|
|
|
List<DiseasePhysicalResVo> diseasePhysicalResVos) {
|
|
|
|
|
|
Function<PhysicalRecordByResultDTO, Integer> functionCorrect = record -> (ObjectUtil.isNotNull(record.getBasisConfirm()) && 1 == record.getBasisConfirm()
|
|
|
&& Objects.equals(record.getBasisConfirm(), record.getRecordBasisConfirmFlag())) ? 1 : 0;
|
|
|
|
|
|
diseasePhysicalResVos = diseasePhysicalResVos.stream()
|
|
|
.filter(diseasePhysicalResVo -> Integer.valueOf(1).equals(diseasePhysicalResVo.getBasisConfirmFlag())).collect(Collectors.toList());
|
|
|
return physicalRecordMergeLists(physicalRecordList, diseasePhysicalResVos, functionCorrect);
|
|
|
}
|
|
|
|
|
|
private List<BasisDiagnosisNodeResVO> physicalRecordMergeListsIdentification(List<PhysicalRecordByResultDTO> physicalRecordList,
|
|
|
List<DiseasePhysicalResVo> diseasePhysicalResVos) {
|
|
|
|
|
|
Function<PhysicalRecordByResultDTO, Integer> functionCorrect = record -> (Integer.valueOf(1).equals(record.getBasisIdentification())
|
|
|
&& Objects.equals(record.getBasisIdentification(), record.getRecordBasisIdentificationFlag())) ? 1 : 0;
|
|
|
|
|
|
diseasePhysicalResVos = diseasePhysicalResVos.stream()
|
|
|
.filter(diseasePhysicalResVo -> Integer.valueOf(1).equals(diseasePhysicalResVo.getBasisIdentificationFlag())).collect(Collectors.toList());
|
|
|
return physicalRecordMergeLists(physicalRecordList, diseasePhysicalResVos, functionCorrect);
|
|
|
}
|
|
|
|
|
|
private List<BasisDiagnosisNodeResVO> ancillaryRecordMergeListsBasisPrimary(List<AncillaryRecordByResultDTO> ancillaryRecordList,
|
|
|
List<DiseaseAncillaryResVo> diseaseAncillaryResVos) {
|
|
|
|
|
|
diseaseAncillaryResVos = diseaseAncillaryResVos.stream()
|
|
|
.filter(diseaseAncillaryResVo -> Integer.valueOf(1).equals(diseaseAncillaryResVo.getPrimarilyDiagnosisCriteriaFlag())).collect(Collectors.toList());
|
|
|
|
|
|
return ancillaryRecordMergeLists(ancillaryRecordList, diseaseAncillaryResVos,
|
|
|
AncillaryRecordByResultDTO::getPrimarilyDiagnosisCriteriaFlag);
|
|
|
}
|
|
|
|
|
|
|
|
|
private List<BasisDiagnosisNodeResVO> ancillaryRecordMergeListsConfirm(List<AncillaryRecordByResultDTO> ancillaryRecordList,
|
|
|
List<DiseaseAncillaryResVo> diseaseAncillaryResVos) {
|
|
|
|
|
|
Function<AncillaryRecordByResultDTO, Integer> functionCorrect = record -> ObjectUtil.isNotNull(record.getBasisConfirm()) && 1 == record.getBasisConfirm()
|
|
|
&& Objects.equals(record.getBasisConfirm(), record.getRecordBasisConfirmFlag()) ? 1 : 0;
|
|
|
|
|
|
diseaseAncillaryResVos = diseaseAncillaryResVos.stream()
|
|
|
.filter(diseaseAncillaryResVo -> Integer.valueOf(1).equals(diseaseAncillaryResVo.getBasisConfirmFlag())).collect(Collectors.toList());
|
|
|
return ancillaryRecordMergeLists(ancillaryRecordList, diseaseAncillaryResVos, functionCorrect);
|
|
|
}
|
|
|
|
|
|
private List<BasisDiagnosisNodeResVO> ancillaryRecordMergeListsIdentification(List<AncillaryRecordByResultDTO> ancillaryRecordList,
|
|
|
List<DiseaseAncillaryResVo> diseaseAncillaryResVos) {
|
|
|
|
|
|
Function<AncillaryRecordByResultDTO, Integer> functionCorrect = record -> (Integer.valueOf(1).equals(record.getBasisIdentification())
|
|
|
&& Objects.equals(record.getBasisIdentification(), record.getRecordBasisIdentificationFlag())) ? 1 : 0;
|
|
|
|
|
|
diseaseAncillaryResVos = diseaseAncillaryResVos.stream()
|
|
|
.filter(diseaseAncillaryResVo -> Integer.valueOf(1).equals(diseaseAncillaryResVo.getBasisIdentificationFlag())).collect(Collectors.toList());
|
|
|
return ancillaryRecordMergeLists(ancillaryRecordList, diseaseAncillaryResVos, functionCorrect);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 根据指定条件合并两个列表。
|
|
|
*
|
|
|
* @param simpleList 要处理的简单列表。
|
|
|
* @param poolList 用于比较的池列表。
|
|
|
* @param biFunction 定义合并元素条件。
|
|
|
* @param t1 用于处理简单列表中元素的函数。
|
|
|
* @param t2 用于处理池列表中元素的函数。
|
|
|
* @return 包含根据条件合并的元素的列表。
|
|
|
*/
|
|
|
private <T, M, R> List<R> mergeListsBasedOnCondition(List<T> simpleList, List<M> poolList,
|
|
|
BiFunction<T, M, Boolean> biFunction,
|
|
|
Function<T, R> t1, Function<M, R> t2) {
|
|
|
List<R> rs = new ArrayList<>();
|
|
|
|
|
|
// 检查两个列表是否都为空,在这种情况下返回空列表
|
|
|
if (CollUtil.isEmpty(simpleList) && CollUtil.isEmpty(poolList)) {
|
|
|
return CollUtil.newArrayList();
|
|
|
}
|
|
|
|
|
|
// 如果简单列表为空但池列表不为空,则映射和收集池列表元素
|
|
|
if (CollUtil.isEmpty(simpleList) && CollUtil.isNotEmpty(poolList)) {
|
|
|
return poolList.stream().map(t2).collect(Collectors.toList());
|
|
|
}
|
|
|
|
|
|
// 根据定义的条件合并列表
|
|
|
for (M m : poolList) {
|
|
|
boolean find = false;
|
|
|
for (T t : simpleList) {
|
|
|
if (biFunction.apply(t, m)) {
|
|
|
rs.add(t1.apply(t));
|
|
|
find = true;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
if (!find) {
|
|
|
rs.add(t2.apply(m));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return rs;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 预期诊断结果
|
|
|
*/
|
|
|
private ExpertDiagnosisResultResVO creatExpertDiagnosisResult(MedicalRec medicalRec, List<Disease> diseasesList, String processId) {
|
|
|
ExpertDiagnosisResultResVO expertDiagnosisResultResVO = new ExpertDiagnosisResultResVO();
|
|
|
expertDiagnosisResultResVO.setDiagnosis(diseasesList.stream().map(Disease::getDiseaseNameAlias).collect(Collectors.joining(";")));
|
|
|
Set<String> expertDiseaseIdSet = diseasesList.stream().map(Disease::getId).collect(Collectors.toSet());
|
|
|
// 从vp_diagnosis_primary中找到确认诊断时,确认的
|
|
|
List<DiagnosisPrimary> userPrimaryDiseaseList = diagnosisPrimaryService.lambdaQuery()
|
|
|
.eq(DiagnosisPrimary::getProcessId, processId)
|
|
|
// 1确诊
|
|
|
.eq(DiagnosisPrimary::getExcludeFlag, 1).list();
|
|
|
|
|
|
List<Disease> userDiagnosisDiseaseList = CollUtil.isEmpty(userPrimaryDiseaseList) ? CollUtil.newArrayList()
|
|
|
: diseaseService.listByIds(userPrimaryDiseaseList.stream().map(DiagnosisPrimary::getPrimaryDiagnosisId).collect(Collectors.toList()));
|
|
|
// 用户的诊断
|
|
|
expertDiagnosisResultResVO.setUserDiagnosisResult(userDiagnosisDiseaseList.stream().map(e -> {
|
|
|
DiagnosisDiseaseResultNodeVO userNode = new DiagnosisDiseaseResultNodeVO();
|
|
|
userNode.setDiseaseName(e.getDiseaseNameAlias());
|
|
|
// 如果用户诊断在预期诊断里面,则正确,否则错误
|
|
|
userNode.setCorrect(expertDiseaseIdSet.contains(e.getId()) ? 1 : 0);
|
|
|
userNode.setDiseaseId(e.getId());
|
|
|
return userNode;
|
|
|
}).collect(Collectors.toList()));
|
|
|
|
|
|
// 预期诊断
|
|
|
expertDiagnosisResultResVO.setExpertDiagnosisResult(diseasesList.stream().map(e -> {
|
|
|
DiagnosisDiseaseResultNodeVO node = new DiagnosisDiseaseResultNodeVO();
|
|
|
node.setDiseaseName(e.getDiseaseNameAlias());
|
|
|
node.setDiseaseId(e.getId());
|
|
|
return node;
|
|
|
}).collect(Collectors.toList()));
|
|
|
return expertDiagnosisResultResVO;
|
|
|
}
|
|
|
|
|
|
|
|
|
public static <K> Predicate<K> distinctPredicateNotNull(Function<K, Object> function) {
|
|
|
ConcurrentHashMap<Object, Boolean> map = new ConcurrentHashMap<>();
|
|
|
// 根据key进行去重,并排除为null的数据
|
|
|
return t -> null != function.apply(t) && null == map.putIfAbsent(function.apply(t), true);
|
|
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 生成雷达图
|
|
|
* <p>
|
|
|
* ( 用户命中病历配置问题数 / 病历问题总数 ) * (用户提问命中病历配置问题数 / 用户实际提问的数量 )
|
|
|
* <p>
|
|
|
* Q:是否要区分是否是正常的检查结果?
|
|
|
* A:雷达图 不管正常异常检查结果 只看该不该检查这个项目
|
|
|
* Q:该不该,指的是病历的配置项是吗?只要配置了,就是该检查的
|
|
|
* A:是的
|
|
|
*
|
|
|
* @param processId
|
|
|
*/
|
|
|
@Override
|
|
|
public RadarChartResVO queryRadarChart(String processId) {
|
|
|
Process process = Optional.ofNullable(processService.getById(processId)).orElseThrow(() -> new BusinessException("未找到流程"));
|
|
|
// 生成问诊雷达图
|
|
|
ChartNodeVO askChart = computeAskChart(process);
|
|
|
// 生成体格检查雷达图
|
|
|
ChartNodeVO physicalChart = computePhysicalChart(process);
|
|
|
// 生成辅助检查雷达图
|
|
|
ChartNodeVO ancillaryChart = computeAncillaryChart(process);
|
|
|
// 生成处置计划雷达图
|
|
|
ChartNodeVO treatmentPlanChart = computeTreatmentPlanChart(process);
|
|
|
RadarChartResVO radarChartResVO = new RadarChartResVO();
|
|
|
radarChartResVO.setAskChart(askChart);
|
|
|
radarChartResVO.setPhysicalChart(physicalChart);
|
|
|
radarChartResVO.setAncillaryChart(ancillaryChart);
|
|
|
radarChartResVO.setTreatmentPlanChart(treatmentPlanChart);
|
|
|
BigDecimal clinicalThinking = NumberUtil.add(askChart.getNodePer(), physicalChart.getNodePer(), ancillaryChart.getNodePer(), treatmentPlanChart.getNodePer()).divide(BigDecimal.valueOf(4), 1, RoundingMode.HALF_UP);
|
|
|
ChartNodeVO chartNodeVO = new ChartNodeVO();
|
|
|
chartNodeVO.setNodePer(clinicalThinking);
|
|
|
chartNodeVO.setScoreLevel(chartNodeVO.computeScoreLevel());
|
|
|
chartNodeVO.setTotal(NumberUtil.add(askChart.getTotal(), physicalChart.getTotal(), ancillaryChart.getTotal(), treatmentPlanChart.getTotal()).intValue());
|
|
|
chartNodeVO.setCorrect(NumberUtil.add(askChart.getCorrect(), physicalChart.getCorrect(), ancillaryChart.getCorrect(), treatmentPlanChart.getCorrect()).intValue());
|
|
|
chartNodeVO.setUnCorrect(NumberUtil.add(askChart.getUnCorrect(), physicalChart.getUnCorrect(), ancillaryChart.getUnCorrect(), treatmentPlanChart.getUnCorrect()).intValue());
|
|
|
chartNodeVO.setStandard(NumberUtil.add(askChart.getStandard(), physicalChart.getStandard(), ancillaryChart.getStandard(), treatmentPlanChart.getStandard()).intValue());
|
|
|
radarChartResVO.setClinicalThinking(chartNodeVO);
|
|
|
|
|
|
// 查询考核评估内容
|
|
|
ProcessEvaluation processEvaluation = processEvaluationService.lambdaQuery().eq(ProcessEvaluation::getProcessId, processId).one();
|
|
|
radarChartResVO.setProcessEvaluation(processEvaluation);
|
|
|
|
|
|
return radarChartResVO;
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 生成处置计划雷达图
|
|
|
* ( 用户命中病历治疗计划配置问题数 / 疾病配置的治疗计划总数 ) * (用户命中病历治疗计划配置问题数 / 用户实际填写的治疗计划的数量 )
|
|
|
*/
|
|
|
private ChartNodeVO computeTreatmentPlanChart(Process process) {
|
|
|
// 查询用户填写的治疗计划(包含处置计划和用药计划)
|
|
|
List<TreatmentPlanRecord> userTreatmentPlanRecordList = treatmentPlanRecordService.lambdaQuery().eq(TreatmentPlanRecord::getProcessId, process.getId()).list();
|
|
|
int userTreatmentPlanCount = userTreatmentPlanRecordList.size();
|
|
|
|
|
|
// 2. 查询出疾病处置计划(疾病配置的处置计划)
|
|
|
List<DiseaseTreatmentPlanResVo> diseaseTreatmentPlanResVos = diseaseTreatmentPlanService.queryListByDiseaseId(process.getDiseaseId());
|
|
|
Set<String> treatmentPlanIdSet = diseaseTreatmentPlanResVos.stream().map(DiseaseTreatmentPlanResVo::getTreatmentPlanId).collect(Collectors.toSet());
|
|
|
|
|
|
// 3. 查出疾病处置计划用药(疾病配置的用药计划)
|
|
|
List<DiseaseTreatmentPlanDrug> diseaseTreatmentPlanDrugList = diseaseTreatmentPlanDrugService.lambdaQuery().eq(DiseaseTreatmentPlanDrug::getDiseaseId, process.getDiseaseId()).list();
|
|
|
Set<String> drugIdSet = diseaseTreatmentPlanDrugList.stream().map(DiseaseTreatmentPlanDrug::getDrugId).collect(Collectors.toSet());
|
|
|
|
|
|
// 计算总数时,只看疾病配置的处置计划(用药计划来自于处置计划)
|
|
|
int medicalCount = diseaseTreatmentPlanResVos.size();
|
|
|
|
|
|
// 疾病配置的治疗计划ID集合,用来计算命中的数量
|
|
|
Collection<String> planIdSet = CollUtil.union(treatmentPlanIdSet, drugIdSet);
|
|
|
int hitPlanCount = 0;
|
|
|
for (TreatmentPlanRecord treatmentPlanRecord : userTreatmentPlanRecordList) {
|
|
|
// 需要分别看是否是药物计划
|
|
|
if (StrUtil.isNotBlank(treatmentPlanRecord.getTreatmentPlanId()) && planIdSet.contains(treatmentPlanRecord.getTreatmentPlanId())) {
|
|
|
hitPlanCount++;
|
|
|
continue;
|
|
|
}
|
|
|
if (StrUtil.isNotBlank(treatmentPlanRecord.getDrugId()) && planIdSet.contains(treatmentPlanRecord.getDrugId())) {
|
|
|
hitPlanCount++;
|
|
|
}
|
|
|
}
|
|
|
// 过程数据3:问诊vs问诊正确率
|
|
|
BigDecimal num3 = BigDecimal.ZERO;
|
|
|
if (userTreatmentPlanCount > 0) {
|
|
|
num3 = BigDecimal.valueOf(hitPlanCount).divide(BigDecimal.valueOf(userTreatmentPlanCount), 2, RoundingMode.HALF_UP);
|
|
|
}
|
|
|
// 过程数据2:问诊vs标准正确率
|
|
|
BigDecimal num2 = BigDecimal.ZERO;
|
|
|
if (medicalCount > 0) {
|
|
|
num2 = BigDecimal.valueOf(hitPlanCount).divide(BigDecimal.valueOf(medicalCount), 2, RoundingMode.HALF_UP);
|
|
|
}
|
|
|
ChartNodeVO chartNodeVO = new ChartNodeVO();
|
|
|
chartNodeVO.setNodePer(num2.multiply(num3).multiply(BigDecimal.valueOf(100)));
|
|
|
chartNodeVO.setScoreLevel(chartNodeVO.computeScoreLevel());
|
|
|
chartNodeVO.setCorrect(hitPlanCount);
|
|
|
chartNodeVO.setUnCorrect(medicalCount - hitPlanCount);
|
|
|
chartNodeVO.setStandard(medicalCount);
|
|
|
chartNodeVO.setTotal(NumberUtil.add(chartNodeVO.getUnCorrect(), chartNodeVO.getStandard(), chartNodeVO.getCorrect()).intValue());
|
|
|
|
|
|
return chartNodeVO;
|
|
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 生成辅助检查雷达图
|
|
|
* ( 用户命中病历配置问题数 / 病历问题总数 ) * (用户提问命中病历配置问题数 / 用户实际提问的数量 )
|
|
|
*/
|
|
|
private ChartNodeVO computeAncillaryChart(Process process) {
|
|
|
Long userHitCount = diagnosisAncillaryRecordService.lambdaQuery().isNotNull(DiagnosisAncillaryRecord::getAncillaryId)
|
|
|
.eq(DiagnosisAncillaryRecord::getProcessId, process.getId()).count();
|
|
|
Long userCount = diagnosisAncillaryRecordService.lambdaQuery().eq(DiagnosisAncillaryRecord::getProcessId, process.getId()).count();
|
|
|
Long medicalCount = diseaseAncillaryService.lambdaQuery().eq(DiseaseAncillary::getDiseaseId, process.getDiseaseId()).count();
|
|
|
// 过程数据3:问诊vs问诊正确率
|
|
|
BigDecimal num3 = BigDecimal.ZERO;
|
|
|
if (userCount > 0) {
|
|
|
num3 = BigDecimal.valueOf(userHitCount).divide(BigDecimal.valueOf(userCount), 2, RoundingMode.HALF_UP);
|
|
|
}
|
|
|
// 过程数据2:问诊vs标准正确率
|
|
|
BigDecimal num2 = BigDecimal.ZERO;
|
|
|
if (medicalCount > 0) {
|
|
|
num2 = BigDecimal.valueOf(userHitCount).divide(BigDecimal.valueOf(medicalCount), 2, RoundingMode.HALF_UP);
|
|
|
}
|
|
|
|
|
|
ChartNodeVO chartNodeVO = new ChartNodeVO();
|
|
|
chartNodeVO.setNodePer(num2.multiply(num3).multiply(BigDecimal.valueOf(100)));
|
|
|
chartNodeVO.setScoreLevel(chartNodeVO.computeScoreLevel());
|
|
|
chartNodeVO.setCorrect(Math.toIntExact(userHitCount));
|
|
|
chartNodeVO.setUnCorrect((int) (medicalCount - userHitCount));
|
|
|
chartNodeVO.setStandard(Math.toIntExact(medicalCount));
|
|
|
chartNodeVO.setTotal(NumberUtil.add(chartNodeVO.getUnCorrect(), chartNodeVO.getStandard(), chartNodeVO.getCorrect()).intValue());
|
|
|
|
|
|
return chartNodeVO;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 计算体格检查雷达图
|
|
|
* 2. 体格检查:( 用户命中病历配置问题数 / 病历问题总数 ) * (用户提问命中病历配置问题数 / 用户实际提问的数量 )
|
|
|
*/
|
|
|
private ChartNodeVO computePhysicalChart(Process process) {
|
|
|
// 查询用户命中病历配置问题数
|
|
|
Long userHitCount = diagnosisPhysicalRecordService.lambdaQuery().isNotNull(DiagnosisPhysicalRecord::getPhysicalId)
|
|
|
.eq(DiagnosisPhysicalRecord::getProcessId, process.getId()).count();
|
|
|
// 查询用户实际检查数量
|
|
|
Long userCount = diagnosisPhysicalRecordService.lambdaQuery().eq(DiagnosisPhysicalRecord::getProcessId, process.getId()).count();
|
|
|
// 查询病例配置的数量
|
|
|
Long medicalCount = diseasePhysicalService.lambdaQuery().eq(DiseasePhysical::getDiseaseId, process.getDiseaseId()).count();
|
|
|
// 过程数据3:问诊vs问诊正确率
|
|
|
BigDecimal num3 = BigDecimal.ZERO;
|
|
|
if (userCount > 0) {
|
|
|
num3 = BigDecimal.valueOf(userHitCount).divide(BigDecimal.valueOf(userCount), 2, RoundingMode.HALF_UP);
|
|
|
}
|
|
|
// 过程数据2:问诊vs标准正确率
|
|
|
BigDecimal num2 = BigDecimal.ZERO;
|
|
|
if (medicalCount > 0) {
|
|
|
num2 = BigDecimal.valueOf(userHitCount).divide(BigDecimal.valueOf(medicalCount), 2, RoundingMode.HALF_UP);
|
|
|
}
|
|
|
ChartNodeVO chartNodeVO = new ChartNodeVO();
|
|
|
chartNodeVO.setNodePer(num2.multiply(num3).multiply(BigDecimal.valueOf(100)));
|
|
|
chartNodeVO.setScoreLevel(chartNodeVO.computeScoreLevel());
|
|
|
chartNodeVO.setCorrect(Math.toIntExact(userHitCount));
|
|
|
chartNodeVO.setUnCorrect((int) (medicalCount - userHitCount));
|
|
|
chartNodeVO.setStandard(Math.toIntExact(medicalCount));
|
|
|
chartNodeVO.setTotal(NumberUtil.add(chartNodeVO.getUnCorrect(), chartNodeVO.getStandard(), chartNodeVO.getCorrect()).intValue());
|
|
|
|
|
|
return chartNodeVO;
|
|
|
}
|
|
|
|
|
|
|
|
|
/**
|
|
|
* 生成问诊雷达图数据
|
|
|
* 1. 问诊: ( 用户提问命中病历配置问题数 / 病历问题总数 ) * (用户提问命中病历配置问题数 / 用户实际提问的数量 )
|
|
|
* 问诊vs标准正确率 * 问诊vs问诊正确率 = 综合正确率
|
|
|
* 上面的数量都是去重的,未识别出来的问题,不包含在用户提问的数据里面
|
|
|
* 默认语句不参与统计
|
|
|
*/
|
|
|
public ChartNodeVO computeAskChart(Process process) {
|
|
|
// 首先查询用户提问的病历问题(这里questionId不为null,即为识别出来的用户问题)
|
|
|
List<DiagnosisQaRecord> qaRecordList = diagnosisQaRecordService.lambdaQuery().isNotNull(DiagnosisQaRecord::getQuestionLibraryId)
|
|
|
.eq(DiagnosisQaRecord::getProcessId, process.getId()).list();
|
|
|
// 用户实际提问数量(包含默认问题)
|
|
|
Set<String> userQuestionIdSet = qaRecordList.stream().map(DiagnosisQaRecord::getQuestionLibraryId).collect(Collectors.toSet());
|
|
|
// 查询病例配置的问题
|
|
|
List<AskPatientAnswer> answerList = askPatientAnswerService.lambdaQuery().eq(AskPatientAnswer::getMedicalId, process.getMedicalRecId()).list();
|
|
|
// 病历问题总数(统计非默认语句的病历问题总数)
|
|
|
long medicalQuestionCount = answerList.stream().filter(e -> ObjectUtil.isNotEmpty(e.getAnswerType()) && 1 == e.getAnswerType()).count();
|
|
|
Set<String> defaultqQuestionIdSet = answerList.stream().filter(e -> ObjectUtil.isNotEmpty(e.getAnswerType()) && 0 == e.getAnswerType()).map(AskPatientAnswer::getLibraryQuestionId).collect(Collectors.toSet());
|
|
|
userQuestionIdSet.removeAll(defaultqQuestionIdSet);
|
|
|
// 用户实际提问的数量(去除默认问题)
|
|
|
int userQuestionCount = userQuestionIdSet.size();
|
|
|
// 用户提问命中病历配置问题数(去除默认问题之后的数量)
|
|
|
userQuestionIdSet.removeAll(defaultqQuestionIdSet);
|
|
|
int userHitQuestionCount = userQuestionIdSet.size();
|
|
|
|
|
|
// 过程数据3:问诊vs问诊正确率
|
|
|
BigDecimal num3 = BigDecimal.ZERO;
|
|
|
if (userQuestionCount > 0) {
|
|
|
num3 = BigDecimal.valueOf(userHitQuestionCount).divide(BigDecimal.valueOf(userQuestionCount), 2, RoundingMode.HALF_UP);
|
|
|
}
|
|
|
// 过程数据2:问诊vs标准正确率
|
|
|
BigDecimal num2 = BigDecimal.ZERO;
|
|
|
if (medicalQuestionCount > 0) {
|
|
|
num2 = BigDecimal.valueOf(userHitQuestionCount).divide(BigDecimal.valueOf(medicalQuestionCount), 2, RoundingMode.HALF_UP);
|
|
|
}
|
|
|
ChartNodeVO chartNodeVO = new ChartNodeVO();
|
|
|
chartNodeVO.setNodePer(num2.multiply(num3).multiply(BigDecimal.valueOf(100)));
|
|
|
chartNodeVO.setScoreLevel(chartNodeVO.computeScoreLevel());
|
|
|
chartNodeVO.setCorrect(userHitQuestionCount);
|
|
|
chartNodeVO.setStandard(Integer.parseInt(String.valueOf(medicalQuestionCount)));
|
|
|
chartNodeVO.setUnCorrect(NumberUtil.sub(chartNodeVO.getStandard(), chartNodeVO.getCorrect()).intValue());
|
|
|
chartNodeVO.setTotal(NumberUtil.add(chartNodeVO.getUnCorrect(), chartNodeVO.getStandard(), chartNodeVO.getCorrect()).intValue());
|
|
|
|
|
|
return chartNodeVO;
|
|
|
}
|
|
|
}
|