|
@@ -0,0 +1,344 @@
|
|
|
+package com.lantone.security.facade.analyze.compute;
|
|
|
+
|
|
|
+import cn.hutool.core.bean.BeanUtil;
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
|
+import com.google.common.base.Splitter;
|
|
|
+import com.google.common.collect.Lists;
|
|
|
+import com.google.common.collect.Maps;
|
|
|
+import com.google.common.collect.Range;
|
|
|
+import com.lantone.common.dto.analyze.AlgorithmDTO;
|
|
|
+import com.lantone.common.enums.IsDeleteEnum;
|
|
|
+import com.lantone.common.exception.Asserts;
|
|
|
+import com.lantone.common.util.BigDecimalUtil;
|
|
|
+import com.lantone.common.util.ListUtil;
|
|
|
+import com.lantone.common.util.StringUtil;
|
|
|
+import com.lantone.common.vo.analyze.AlgorithmVO;
|
|
|
+import com.lantone.common.vo.analyze.MedQcresultCasesVO;
|
|
|
+import com.lantone.common.vo.analyze.QcCasesHospitalVO;
|
|
|
+import com.lantone.common.vo.analyze.QcResultAlgVO;
|
|
|
+import com.lantone.dblayermbg.entity.HospitalSet;
|
|
|
+import com.lantone.dblayermbg.entity.analyze.MedQcresultDetail;
|
|
|
+import com.lantone.dblayermbg.facade.HospitalSetFacade;
|
|
|
+import com.lantone.dblayermbg.facade.analyze.MedQcresultDetailFacade;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.stereotype.Component;
|
|
|
+
|
|
|
+import java.math.BigDecimal;
|
|
|
+import java.math.RoundingMode;
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.Arrays;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+/**
|
|
|
+ * @Description: 评分算法
|
|
|
+ * @author: gaodm
|
|
|
+ * @time: 2020/4/14 9:52
|
|
|
+ */
|
|
|
+@Component
|
|
|
+public class AlgorithmFacade_New {
|
|
|
+ private final static List<Integer> types = Arrays.asList(0, 1, 2, 3, 4);
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private HospitalSetFacade sysHospitalSetFacade;
|
|
|
+ @Autowired
|
|
|
+ private MedQcresultDetailFacade qcresultDetailFacade;
|
|
|
+ @Autowired
|
|
|
+ private HospitalSetFacade hospitalSetFacade;
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 评结果分数
|
|
|
+ *
|
|
|
+ * @param algorithmVO 操作条目的所有信息
|
|
|
+ * @return 评分结果对象
|
|
|
+ */
|
|
|
+ public AlgorithmDTO getScoreDto(AlgorithmVO algorithmVO) {
|
|
|
+ AlgorithmDTO algorithmDTO = new AlgorithmDTO();
|
|
|
+ if (!types.contains(algorithmVO.getType())) {
|
|
|
+ Asserts.fail("操作类型只有0,1,2,3,4!");
|
|
|
+ }
|
|
|
+ //处理数据
|
|
|
+ dataDeal(algorithmVO);
|
|
|
+ //获取本医院相关评分配置
|
|
|
+ Map<String, String> scoreSet = hospitalSetFacade.getHospitalCodeMap(algorithmVO.getHospitalId() + "", "score_set");
|
|
|
+ //合格率配置
|
|
|
+ JSONObject qualifiedJSON = JSONObject.parseObject(scoreSet.get("qualified"));
|
|
|
+ //结果等级配置
|
|
|
+ JSONObject resultJSON = JSONObject.parseObject(scoreSet.get("level"));
|
|
|
+ //该医院总分
|
|
|
+ BigDecimal totalScore = new BigDecimal(JSONObject.parseObject(scoreSet.get("score")).getLong("totalScore"));
|
|
|
+ BigDecimal notHomePageScore = new BigDecimal(JSONObject.parseObject(scoreSet.get("score")).getLong("notHomePageScore"));
|
|
|
+ //生成各模块扣分条目map
|
|
|
+ Map<Long, List<QcResultAlgVO>> casesQcResultAlgMap = new HashMap<>();
|
|
|
+ if (ListUtil.isNotEmpty(algorithmVO.getQcResultAlgVOList())) {
|
|
|
+ casesQcResultAlgMap = algorithmVO.getQcResultAlgVOList().stream()
|
|
|
+ .collect(Collectors.groupingBy(QcResultAlgVO::getCasesId));
|
|
|
+ }
|
|
|
+ if (ListUtil.isNotEmpty(algorithmVO.getQcCasesHospitalVOS())) {
|
|
|
+ //遍历各个模块
|
|
|
+ for (QcCasesHospitalVO qcCasesHospitalVO : algorithmVO.getQcCasesHospitalVOS()) {
|
|
|
+ //计算各个模块分值
|
|
|
+ BigDecimal casesRes = casesCal(casesQcResultAlgMap.get(qcCasesHospitalVO.getCasesId()), qcCasesHospitalVO.getScore());
|
|
|
+ //合格率计算
|
|
|
+ String level = getLevel(qualifiedJSON.getJSONObject(qcCasesHospitalVO.getCasesId() + ""), casesRes.longValue());
|
|
|
+ //添加各个模块要保存的评分结果
|
|
|
+ addSaveQcResultCasesInfo(casesRes, qcCasesHospitalVO.getCasesId(), level, algorithmVO);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //非病案首页模块分值计算
|
|
|
+ List<QcResultAlgVO> notHomePageQcResultAlg = algorithmVO.getQcResultAlgVOList().stream()
|
|
|
+ .filter(qcResultAlgVO -> !"243".equals(qcResultAlgVO.getCasesId().toString())).collect(Collectors.toList());
|
|
|
+ BigDecimal casesRes = casesCal(notHomePageQcResultAlg, notHomePageScore.longValue());
|
|
|
+ //合格率计算
|
|
|
+ String notHomePageLevel = getLevel(qualifiedJSON.getJSONObject("0"), casesRes.longValue());
|
|
|
+ //添加各个模块要保存的评分结果
|
|
|
+ addSaveQcResultCasesInfo(casesRes, 0l, notHomePageLevel, algorithmVO);
|
|
|
+
|
|
|
+ //总分算分
|
|
|
+ BigDecimal res = casesCal(algorithmVO.getQcResultAlgVOList(), totalScore.longValue());
|
|
|
+ //等级计算
|
|
|
+ String level = getLevel(resultJSON, res.longValue());
|
|
|
+ //结果转为100进制
|
|
|
+ res = res.multiply(new BigDecimal(100))
|
|
|
+ .divide(totalScore, 1, RoundingMode.HALF_UP);
|
|
|
+ algorithmDTO.setLevel(level);
|
|
|
+ algorithmDTO.setScore(res);
|
|
|
+ return algorithmDTO;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @param casesRes 模块分值
|
|
|
+ * @param casesId 模块id
|
|
|
+ * @param level 合格率
|
|
|
+ * @param algorithmVO 算分对象
|
|
|
+ * @Description拼装要保存的med_qcresult_cases表信息
|
|
|
+ * @Return void
|
|
|
+ */
|
|
|
+ private void addSaveQcResultCasesInfo(BigDecimal casesRes, Long casesId, String level, AlgorithmVO algorithmVO) {
|
|
|
+
|
|
|
+ if (ListUtil.isEmpty(algorithmVO.getMedQcresultCasesVOList())) {
|
|
|
+ algorithmVO.setMedQcresultCasesVOList(new ArrayList<>());
|
|
|
+ }
|
|
|
+ //拼装要保存的med_qcresult_cases 表信息
|
|
|
+ MedQcresultCasesVO medQcresultCasesVOHp = new MedQcresultCasesVO();
|
|
|
+ medQcresultCasesVOHp.setHospitalId(algorithmVO.getHospitalId());
|
|
|
+ medQcresultCasesVOHp.setBehospitalCode(algorithmVO.getBehospitalCode());
|
|
|
+ medQcresultCasesVOHp.setCasesId(casesId);
|
|
|
+ medQcresultCasesVOHp.setScoreRes(casesRes);
|
|
|
+ medQcresultCasesVOHp.setLevel(level);
|
|
|
+ algorithmVO.getMedQcresultCasesVOList().add(medQcresultCasesVOHp);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据分数评定等级
|
|
|
+ *
|
|
|
+ * @param getLevJSON 区间及对应区间等级json
|
|
|
+ * @param value 字符串区间用逗号隔开
|
|
|
+ * @return 等级
|
|
|
+ */
|
|
|
+ private String getLevel(JSONObject getLevJSON, Long value) {
|
|
|
+ if (getLevJSON == null) {
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+ String strSection = getLevJSON.getString("section");
|
|
|
+ String strLevs = getLevJSON.getString("lev");
|
|
|
+ if (StringUtil.isNotBlank(strSection) && StringUtil.isNotBlank(strLevs)) {
|
|
|
+ List<String> sections = Lists.newArrayList(Splitter.on(",").split(strSection));
|
|
|
+ List<String> levs = Lists.newArrayList(Splitter.on(",").split(strLevs));
|
|
|
+ int i = 0;
|
|
|
+ for (; i <= sections.size(); i++) {
|
|
|
+ //区间采用左开右闭原则
|
|
|
+ if (i == 0) {
|
|
|
+ //(-∞..b]
|
|
|
+ if (Range.atMost(Long.parseLong(sections.get(i))).contains(value)) {
|
|
|
+ return getLev(levs, i);
|
|
|
+ }
|
|
|
+ } else if (i == sections.size()) {
|
|
|
+ //(a..+∞)
|
|
|
+ if (Range.greaterThan(Long.parseLong(sections.get(i - 1))).contains(value)) {
|
|
|
+ return getLev(levs, i);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ //(a..b]
|
|
|
+ if (Range.openClosed(Long.parseLong(sections.get(i - 1)), Long.parseLong(sections.get(i))).contains(value)) {
|
|
|
+ return getLev(levs, i);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @param levs
|
|
|
+ * @param index
|
|
|
+ * @Description根据位置获取数组指定位置的值
|
|
|
+ * @Return java.lang.String
|
|
|
+ */
|
|
|
+ private String getLev(List<String> levs, int index) {
|
|
|
+ if (Range.closedOpen(0, levs.size()).contains(index)) {
|
|
|
+ return levs.get(index);
|
|
|
+ }
|
|
|
+ return "无对应结果区间";
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理数据
|
|
|
+ *
|
|
|
+ * @param algorithmVO 操作条目的所有信息
|
|
|
+ */
|
|
|
+ private void dataDeal(AlgorithmVO algorithmVO) {
|
|
|
+ List<QcResultAlgVO> qcResultAlgVOList = algorithmVO.getQcResultAlgVOList();
|
|
|
+ //新增
|
|
|
+ if (algorithmVO.getType().equals(1)) {
|
|
|
+ if (null == algorithmVO.getOptResultAlgVO()) {
|
|
|
+ Asserts.fail("新增操作条目不能为空!");
|
|
|
+ }
|
|
|
+ //验证和操作数据
|
|
|
+ if (ListUtil.isNotEmpty(qcResultAlgVOList)) {
|
|
|
+ for (QcResultAlgVO qcResultAlgVO : qcResultAlgVOList) {
|
|
|
+ if (qcResultAlgVO.getCasesId().equals(algorithmVO.getOptResultAlgVO().getCasesId())
|
|
|
+ && qcResultAlgVO.getCasesEntryId().equals(algorithmVO.getOptResultAlgVO().getCasesEntryId())) {
|
|
|
+ Asserts.fail("不能重复加入已经评分的条目");
|
|
|
+ } else {
|
|
|
+ if (algorithmVO.getOptResultAlgVO().getCasesId().equals(qcResultAlgVO.getCasesId())) {
|
|
|
+ algorithmVO.getOptResultAlgVO().setCasesScore(qcResultAlgVO.getCasesScore());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ qcResultAlgVOList.add(algorithmVO.getOptResultAlgVO());
|
|
|
+ }
|
|
|
+ if (ListUtil.isEmpty(qcResultAlgVOList)) {
|
|
|
+ qcResultAlgVOList = new ArrayList<>();
|
|
|
+ qcResultAlgVOList.add(algorithmVO.getOptResultAlgVO());
|
|
|
+ algorithmVO.setQcResultAlgVOList(qcResultAlgVOList);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //删除
|
|
|
+ else if (algorithmVO.getType().equals(2) || (algorithmVO.getType().equals(4) && 0 == algorithmVO.getDelStatus())) {
|
|
|
+ if (null == algorithmVO.getOptResultAlgVO()) {
|
|
|
+ Asserts.fail("删除操作条目不能为空!");
|
|
|
+ }
|
|
|
+ //操作数据
|
|
|
+ if (ListUtil.isNotEmpty(qcResultAlgVOList)) {
|
|
|
+ Boolean hasData = false;
|
|
|
+ Long optId = algorithmVO.getOptResultAlgVO().getId(); // 操作id
|
|
|
+ for (QcResultAlgVO qcResultAlgVO : qcResultAlgVOList) {
|
|
|
+ if (qcResultAlgVO.getId().equals(optId)) {
|
|
|
+ qcResultAlgVOList.remove(qcResultAlgVO);
|
|
|
+ hasData = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (!hasData) {
|
|
|
+ Asserts.fail("删除的条目不存在!");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //恢复
|
|
|
+ else if (algorithmVO.getType().equals(4) && 1 == algorithmVO.getDelStatus()) {
|
|
|
+ if (null == algorithmVO.getOptResultAlgVO()) {
|
|
|
+ Asserts.fail("恢复操作条目不能为空!");
|
|
|
+ }
|
|
|
+ //操作数据
|
|
|
+ Boolean hasData = false;
|
|
|
+ Long optId = algorithmVO.getOptResultAlgVO().getId(); // 操作id
|
|
|
+ MedQcresultDetail qcresultDetail = qcresultDetailFacade.getOne(new QueryWrapper<MedQcresultDetail>()
|
|
|
+ .eq("id", optId));
|
|
|
+ if (qcresultDetail != null) {
|
|
|
+ QcResultAlgVO qcResultAlgVO = new QcResultAlgVO();
|
|
|
+ qcResultAlgVO.setScore(qcresultDetail.getScore());
|
|
|
+ qcResultAlgVO.setId(qcresultDetail.getId());
|
|
|
+ qcResultAlgVO.setCasesEntryId(qcresultDetail.getCasesEntryId());
|
|
|
+ qcResultAlgVO.setCasesId(qcresultDetail.getCasesId());
|
|
|
+ qcResultAlgVO.setMsg(qcresultDetail.getMsg());
|
|
|
+ qcResultAlgVO.setIsReject(qcresultDetail.getIsReject());
|
|
|
+ qcResultAlgVO.setCasesScore(qcresultDetail.getCasesScore());
|
|
|
+ if (ListUtil.isNotEmpty(qcResultAlgVOList)) {
|
|
|
+ qcResultAlgVOList.add(qcResultAlgVO);
|
|
|
+ } else {
|
|
|
+ qcResultAlgVOList = new ArrayList<>();
|
|
|
+ qcResultAlgVOList.add(qcResultAlgVO);
|
|
|
+ algorithmVO.setQcResultAlgVOList(qcResultAlgVOList);
|
|
|
+ }
|
|
|
+ hasData = true;
|
|
|
+ }
|
|
|
+ if (!hasData) {
|
|
|
+ Asserts.fail("恢复的条目不存在!");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //修改
|
|
|
+ else if (algorithmVO.getType().equals(3)) {
|
|
|
+ if (null == algorithmVO.getOptResultAlgVO()) {
|
|
|
+ Asserts.fail("修改操作条目不能为空!");
|
|
|
+ }
|
|
|
+ //操作数据
|
|
|
+ if (ListUtil.isNotEmpty(qcResultAlgVOList)) {
|
|
|
+ Boolean hasData = false;
|
|
|
+ for (QcResultAlgVO qcResultAlgVO : qcResultAlgVOList) {
|
|
|
+ if (qcResultAlgVO.getId().equals(algorithmVO.getOptResultAlgVO().getId())) {
|
|
|
+ qcResultAlgVOList.remove(qcResultAlgVO);
|
|
|
+ qcResultAlgVOList.add(algorithmVO.getOptResultAlgVO());
|
|
|
+ hasData = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (!hasData) {
|
|
|
+ Asserts.fail("修改的条目不存在!");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 计算分数
|
|
|
+ *
|
|
|
+ * @param qcResultAlgVOList 扣分条目
|
|
|
+ * @return 评分分数
|
|
|
+ */
|
|
|
+ private BigDecimal casesCal(List<QcResultAlgVO> qcResultAlgVOList, Long totalScore) {
|
|
|
+ //总分
|
|
|
+ BigDecimal res = new BigDecimal(totalScore);
|
|
|
+ //模块内单票否决扣分
|
|
|
+ BigDecimal subRejectScore = BigDecimal.ZERO;
|
|
|
+ //模块内其他扣分
|
|
|
+ BigDecimal subOrderScore = BigDecimal.ZERO;
|
|
|
+ if (ListUtil.isNotEmpty(qcResultAlgVOList)) {
|
|
|
+ //遍历扣分条目
|
|
|
+ for (QcResultAlgVO qcResultAlgVO : qcResultAlgVOList) {
|
|
|
+ if (qcResultAlgVO.getIsReject().equals(1)) {
|
|
|
+ //单票否决扣分
|
|
|
+ subRejectScore = subRejectScore.add(qcResultAlgVO.getScore());
|
|
|
+ } else {
|
|
|
+ //非单票否决扣分
|
|
|
+ subOrderScore = subOrderScore.add(qcResultAlgVO.getScore());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //总分小于等于其他扣分时
|
|
|
+ if (BigDecimalUtil.le(new BigDecimal(totalScore), subOrderScore)) {
|
|
|
+ subOrderScore = new BigDecimal(totalScore);
|
|
|
+ }
|
|
|
+ //模块总分减去模块单票否决扣分
|
|
|
+ res = res.subtract(subRejectScore);
|
|
|
+ //结果小于0按0返回
|
|
|
+ if (BigDecimalUtil.lt(res, BigDecimal.ZERO)) {
|
|
|
+ return BigDecimal.ZERO;
|
|
|
+ } else {
|
|
|
+ //模块总分减去其他扣分
|
|
|
+ res = res.subtract(subOrderScore);
|
|
|
+ }
|
|
|
+ //结果小于0按0计算
|
|
|
+ if (BigDecimalUtil.lt(res, BigDecimal.ZERO)) {
|
|
|
+ res = BigDecimal.ZERO;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return res;
|
|
|
+ }
|
|
|
+}
|