package thyyxxk.webserver.service.yibao; import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.ListUtils; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import thyyxxk.webserver.config.exception.ExceptionEnum; import thyyxxk.webserver.dao.his.yibao.XiangMuLuRuDao; import thyyxxk.webserver.entity.ResultVo; import thyyxxk.webserver.entity.datamodify.FeiYongLeiXin; import thyyxxk.webserver.entity.datamodify.GetDropdownBox; import thyyxxk.webserver.entity.datamodify.ZyDetailCharge; import thyyxxk.webserver.entity.yibao.ZyActpatient; import thyyxxk.webserver.service.PublicServer; import thyyxxk.webserver.utils.*; import java.math.BigDecimal; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; /** *

* 描述: 项目录入 *

* * @author xc * @date 2021-08-02 10:37 */ @Service @Slf4j public class XiangMuLuRuService { private final XiangMuLuRuDao dao; private final PublicServer publicServer; @Autowired public XiangMuLuRuService(XiangMuLuRuDao dao, PublicServer publicServer) { this.dao = dao; this.publicServer = publicServer; } /** * 获取患者费用 * 费用 类型 1 - 医嘱 2 - 项目费用 3 - 医技 4 - 全部 5 -药品费用 * * @param param 查询条件 * @return 返回患者费用 */ public ResultVo> getHuanZheFeiYong(ZyDetailCharge param) { if (StringUtil.isBlank(param.getInpatientNo()) || param.getAdmissTimes() == null) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "住院号或住院次数为空
๑乛◡乛๑"); } Integer ledgerSn = publicServer.getLedgerSn(param.getInpatientNo(), param.getAdmissTimes()); log.info("查询患者费用==》住院号{},住院次数:{},项目名称:{},费用类型:{},科室:{},当前页:{},页大小:{},退费:{},总数:{},账页号:{}", param.getInpatientNo(), param.getAdmissTimes(), param.getChargeCode(), param.getOrderNo(), param.getDept(), param.getCurrentPage(), param.getPageSize(), param.getTuiFeiFlag(), param.getTotal(), ledgerSn); int infantFlag = 0; // 如果是婴儿的话那么就需要截取 字符串了 在通过婴儿标识来判断 if (param.getInpatientNo().contains("$")) { param.setInpatientNo(param.getInpatientNo().split("\\$")[0]); infantFlag = 1; } if (param.getTuiFeiFlag() == null) { param.setTuiFeiFlag(2); } Page page = new Page<>(); if (param.getFeiYongLeiXingCode() == 0) { if (param.getTotal() == 0) { page.setTotal(dao.huanZheFeiYongToatal(param.getInpatientNo(), param.getAdmissTimes(), ledgerSn, param.getChargeCode(), infantFlag, param.getStartTime(), param.getEndTime(), param.getOrderNo(), param.getDept(), param.getTuiFeiFlag())); } page.setRecords(dao.huanZheXiangMuFeiYong(param.getCurrentPage(), param.getPageSize(), param.getInpatientNo(), param.getAdmissTimes(), ledgerSn, param.getChargeCode(), infantFlag, param.getStartTime(), param.getEndTime(), param.getOrderNo(), param.getDept(), param.getRiQiPaiXu(), param.getTuiFeiFlag())); } else { if (param.getTotal() == 0) { page.setTotal(dao.huanZheYaoPinFeiYongTotal(param.getInpatientNo(), param.getAdmissTimes(), ledgerSn, param.getChargeCode(), infantFlag, param.getStartTime(), param.getEndTime(), param.getOrderNo(), param.getDept(), param.getTuiFeiFlag())); } page.setRecords(dao.huanZheYaoPinFeiYong(param.getCurrentPage(), param.getPageSize(), param.getInpatientNo(), param.getAdmissTimes(), ledgerSn, param.getChargeCode(), infantFlag, param.getStartTime(), param.getEndTime(), param.getOrderNo(), param.getDept(), param.getRiQiPaiXu(), param.getTuiFeiFlag())); } if (ListUtil.isBlank(page.getRecords())) { return ResultVoUtil.fail(ExceptionEnum.NO_DATA_EXIST, "没有查询到符合费用。"); } return ResultVoUtil.success(page); } /** * 搜索项目信息 * * @param pyCode 拼音码 * @return 返回项目信息 */ public ResultVo> getChargeCode(String pyCode) { log.info("获取编码:{}", pyCode); return ResultVoUtil.success(dao.getChargeCode(StringUtil.isContainChinese(pyCode))); } /** * @param param 需要生成退费 的数据 * @return 返回 */ @Transactional(rollbackFor = Exception.class) public ResultVo xiangMuTuiFei(ZyDetailCharge param) { List yongHuJueSe = dao.huoQuJueSe(TokenUtil.getTokenUserId()); log.info("角色:{}", JSON.toJSONString(yongHuJueSe)); if (!yongHuJueSe.contains(36) && !yongHuJueSe.contains(1)) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "您没有权限退费。"); } if (param.getList() == null || param.getList().isEmpty()) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "请先选择需要退费的数据,一次性退费不得超过100条
╮( •́ω•̀ )╭"); } else if (param.getList().size() > 100) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "项目退费一次性大于100条数据
╮(﹀_﹀”)╭"); } if (StringUtil.isBlank(param.getInpatientNo()) || param.getAdmissTimes() == null || param.getList().size() == 0) { return ResultVoUtil.fail(ExceptionEnum.NULL_POINTER, "患者信息不全 (;´д`)ゞ"); } if (dao.getHuanZheSFZaiYuan(param.getInpatientNo(), param.getAdmissTimes()) == 0) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "该患者已出院 /(ㄒoㄒ)/~~"); } // 判断数据是否为 退费数据 List chaKanSFtuiFei = dao.chaKanSFYiJingTuiFeiLe(param.getInpatientNo(), param.getAdmissTimes(), param.getList()); for (ZyDetailCharge charge : chaKanSFtuiFei) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, String.format("流水号为:【%s】已退费,请勿重复退费
···(。•́︿•̀。) ", charge.getOriDetailSn())); } int infantFlag = 0; // 判断是否为婴儿 if (param.getInpatientNo().contains("$")) { param.setInpatientNo(param.getInpatientNo().split("\\$")[0]); infantFlag = 1; } if (dao.getHuanZheSFJieSuan(param.getInpatientNo(), param.getAdmissTimes()) == null || dao.getHuanZheSFJieSuan(param.getInpatientNo(), param.getAdmissTimes()) != 0) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "该患者已经结算了"); } // 获取原来的数据 List yuanTuiFeiList = dao.huoQuJuTiFeiYong(param.getInpatientNo(), param.getAdmissTimes(), param.getList()); // 获取患者的总费用 BigDecimal sum = new BigDecimal(0); // 退费的list // 获取最大值 Integer maxDetailSn = publicServer.getMaxDetailSn(param.getInpatientNo(), param.getAdmissTimes()); List yaoPingDan = new ArrayList<>(); List genXingZhenShuTuiFeiLiuShui = new ArrayList<>(); List tuiFeiList = new ArrayList<>(); // 获取到用户角色 管理员角色可以无视 List zhiXinKeShi = dao.chaXunZhiZXinKeShi(param.getDeptCode()); for (ZyDetailCharge pojo : yuanTuiFeiList) { // 判断患者的费用是否存在负数 if (pojo.getChargeFee().signum() == -1 || pojo.getChargeAmount().signum() == -1) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, String.format("患者费用存在负数,流水号:【%s】,该数据为退费数据。
( ´Д`)y━・~~", pojo.getDetailSn())); } if (pojo.getChargeCode().startsWith("BILL")) { yaoPingDan.add(pojo); } // 在这里判断执行科室 ResultVo LOGICAL_ERROR = getStringResultVo(yongHuJueSe, zhiXinKeShi, param, pojo); if (LOGICAL_ERROR != null) return LOGICAL_ERROR; // 数据库有个 触发器 如果带了医嘱号且有篆刻那么这里就需要改成 0 if (BigUtils.bigDaYu(pojo.getOrderNo(), 10)) { pojo.setOrderNo(new BigDecimal(0)); } sum = sum.add(pojo.getChargeFee().multiply(pojo.getChargeAmount())); pojo.setChargeFee(pojo.getChargeFee().negate()); pojo.setChargeAmount(pojo.getChargeAmount().negate()); pojo.setOpIdCode(TokenUtil.getTokenUserId()); pojo.setOriDetailSn(pojo.getDetailSn()); pojo.setDetailSn(maxDetailSn += 1); pojo.setOldGenTime(DateUtil.formatDatetime(pojo.getGenTime(), DateUtil.DEFAULT_PATTERN)); // 向退费 list 里面添加 tuiFeiList.add(pojo); genXingZhenShuTuiFeiLiuShui.add(pojo.getOriDetailSn()); } // 总费用计算 FeiYongLeiXin fy = JiSuanFeiYong.jiSuan(yuanTuiFeiList, false); // 计算出这一次 总退的费用 fy.setTotalCharge(sum.negate()); // 执行退费的操作 20 条的退费 if (tuiFeiList.isEmpty()) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "查询不到患者原数据,请联系管理员。( ´Д`)y━・~~"); } else { log.info("操作项目退费 ==》 操作人:{},数据:{}", TokenUtil.getTokenUserId(), JSON.toJSONString(tuiFeiList)); List> fenGe = ListUtils.partition(tuiFeiList, 20); if (ListUtil.notBlank(yaoPingDan)) { dao.shenQingYaoPing(param, yaoPingDan, infantFlag, publicServer.getLedgerSn(param.getInpatientNo(), param.getAdmissTimes()), TokenUtil.getTokenUserId()); } fenGe.forEach(dao::xiangMuTuiFei); dao.genXinZhenShuTuiFeiLiuShui(param.getInpatientNo(), param.getAdmissTimes(), publicServer.getLedgerSn(param.getInpatientNo(), param.getAdmissTimes()), genXingZhenShuTuiFeiLiuShui); return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_NOTIFICATION, "项目退费操作成功。乁( ˙ ω˙乁)"); } } private ResultVo getStringResultVo(List yongHuJueSe, List zhiXinKeShi, ZyDetailCharge xuYaoTuiDeShuJu, ZyDetailCharge piPeiDeShuJu) { // 获取到用户角色 管理员角色可以无视 if (!yongHuJueSe.contains(1)) { // 科室开头 是 8 就不是医技科室 只有医技科室可以退药品 if (xuYaoTuiDeShuJu.getDeptCode().startsWith("8")) { //获取到这个人是否属于这个科室 if (!zhiXinKeShi.contains(piPeiDeShuJu.getExecUnit())) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, String.format("流水号为【%s】,请对应的执行科室进行退费。
( ´Д`)y━・~~", piPeiDeShuJu.getDetailSn())); } // 护士是不可以退药品的 if (xuYaoTuiDeShuJu.isYaoPing()) { if (piPeiDeShuJu.getChargeCode().startsWith("BILL")) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, String.format("流水号为【%s】,包含药品费用,无法退费。
( ´Д`)y━・~~", piPeiDeShuJu.getDetailSn())); } } } else if (!xuYaoTuiDeShuJu.getDeptCode().equals(piPeiDeShuJu.getExecUnit())) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, String.format("流水号为【%s】,请对应的执行科室进行退费。
( ´Д`)y━・~~", piPeiDeShuJu.getDetailSn())); } else if (!BigUtils.dengYu(piPeiDeShuJu.getOrderNo(), 3)) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, String.format("流水号为【%s】,只能退本科室录入的药品。
( ´Д`)y━・~~", piPeiDeShuJu.getDetailSn())); } } return null; } /** * 获取模板 * * @param deptCode 根据科室搜索 * @return 返回模板 */ public ResultVo> getMuBan(String deptCode) { return ResultVoUtil.success(dao.getMuBan(deptCode, 1)); } /** * 获取模板的具体信息 * * @param patternName 模板名称 * @param opIdCode 存模板的人 * @return 返回具体的模板 */ public ResultVo> getMuBanXinXi(String patternName, String opIdCode) { return ResultVoUtil.success(dao.getMuBanXinXi(patternName, opIdCode)); } /** * 获取科室 * * @return 返回科室信息 */ public ResultVo> getDept() { return ResultVoUtil.success(dao.getDpet()); } /** * 获取病区 * * @return 返回科室信息 */ public ResultVo> getWard() { return ResultVoUtil.success(dao.getWard()); } /** * 通过拼音码 来搜索项目 * * @param pyCode 拼音码 * @param xiangMuHuoYaoPinFlag 判断是查询项目还是药品 0 - 项目 1- 药品 * @return 返回项目 */ public ResultVo> queryXiangMu(String pyCode, Integer xiangMuHuoYaoPinFlag) { if (xiangMuHuoYaoPinFlag == 0) { return ResultVoUtil.success(dao.queryXiangMu("%" + pyCode.toUpperCase() + "%")); } return ResultVoUtil.success(dao.queryYaoPin("%" + pyCode.toUpperCase() + "%")); } /** * 这个项目录入 * * @param param 参数 * @return 返回提示语句 */ @Transactional(rollbackFor = Exception.class) public ResultVo xiangMuFeiYongShangChuan(ZyDetailCharge param) { log.info("param:{}", JSON.toJSONStringWithDateFormat(param, DateUtil.DEFAULT_PATTERN)); if (param.getList().size() > 50) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "一次性项目录入大于50条,๑乛◡乛๑"); } StringBuilder errorStr = new StringBuilder(); if (StringUtil.isBlank(param.getInpatientNo()) || param.getAdmissTimes() == null) { errorStr.append("住院号和住院次数为空
"); } if (param.getList().size() == 0) { errorStr.append("没有要录入的项目
"); } if (StringUtil.isBlank(param.getWard())) { errorStr.append("病区为空
"); } if (StringUtil.isBlank(param.getDept())) { errorStr.append("申请科室为空
"); } if (StringUtil.isBlank(param.getZySerialNo())) { errorStr.append("住院流水号为空
"); } if (dao.getHuanZheSFZaiYuan(param.getInpatientNo(), param.getAdmissTimes()) == 0) { errorStr.append("没有患者的在院信息
"); } if (errorStr.length() > 3) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, errorStr.toString()); } List shiFouTingYongXiangMu = new ArrayList<>(); param.getList().forEach(item -> { shiFouTingYongXiangMu.add(item.getChargeCodeMx()); }); List yiTingYong = dao.chaXunFeiYongShiFouTingYong(shiFouTingYongXiangMu); if (ListUtil.notBlank(yiTingYong)) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "项目录入错误,包含已停用的项目 【" + JSON.toJSONString(yiTingYong) + "】"); } // 婴儿 要特殊处理 // 如果带有这个 $ 说明是婴儿 int infantFlag = publicServer.getInfantFlag(param.getInpatientNo()); param.setInpatientNo(publicServer.getInpatientNo(param.getInpatientNo())); // 获取最大流水号 Integer maxDetailSn = publicServer.getMaxDetailSn(param.getInpatientNo(), param.getAdmissTimes()); // 获取项目的 总费用 BigDecimal sum = new BigDecimal(0); // 录入人的id param.setOpIdCode(TokenUtil.getTokenUserId()); List yaoPingShenQingDan = new ArrayList<>(); // 药品 for (ZyDetailCharge zyDetailCharge : param.getList()) { switch (zyDetailCharge.getBillItemCode()) { case "001": zyDetailCharge.setSerial("01"); zyDetailCharge.setChargeCode("BILL01"); break; case "002": zyDetailCharge.setSerial("01"); zyDetailCharge.setChargeCode("BILL02"); break; case "028": zyDetailCharge.setSerial("01"); zyDetailCharge.setChargeCode("BILL28"); break; default: // Serial 00 项目标志 01 药品标志 zyDetailCharge.setSerial("00"); zyDetailCharge.setChargeCode(zyDetailCharge.getChargeCodeMx()); break; } if (zyDetailCharge.getChargeAmount() == null || zyDetailCharge.getAmount() == null) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "数量或金额不能为空。(▼ヘ▼#)"); } // 判断患者的费用是否存在负数 if (zyDetailCharge.getChargeAmount().signum() == -1 || zyDetailCharge.getAmount().signum() == -1) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "不能录入负数,(〃>皿<)"); } if (zyDetailCharge.getChargeAmount().compareTo(new BigDecimal(0)) == 0 || zyDetailCharge.getAmount().compareTo(new BigDecimal(0)) == 0) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "录入费用为 0 (╯°Д°)╯"); } if (StringUtil.isBlank(zyDetailCharge.getChargeCodeMx())) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "项目编码空值。( ´•︵•` )"); } if (StringUtil.isBlank(zyDetailCharge.getDeptCode())) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "执行科室为空。( ´•︵•` )"); } if (zyDetailCharge.getChargeCodeMx() == null) { zyDetailCharge.setChargeCodeMx(zyDetailCharge.getChargeCode()); } if (dao.getHuanZheSFJieSuan(param.getInpatientNo(), param.getAdmissTimes()) == null || dao.getHuanZheSFJieSuan(param.getInpatientNo(), param.getAdmissTimes()) != 0) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "该患者已经结算了"); } // 0 - 住院费用 3 - 门急诊 6 - 医技 if (param.getOrderNo() != null) { zyDetailCharge.setOrderNo(param.getOrderNo()); } else { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "医嘱号为空"); } sum = sum.add(zyDetailCharge.getChargeAmount().multiply(zyDetailCharge.getAmount())); // 这里不会保存单价 只会总价 zyDetailCharge.setChargeAmount(zyDetailCharge.getChargeAmount().multiply(zyDetailCharge.getAmount())); zyDetailCharge.setDetailSn(maxDetailSn += 1); if (zyDetailCharge.getSerial().equals("01")) { ZyDetailCharge shenQing = new ZyDetailCharge(); BeanUtils.copyProperties(zyDetailCharge, shenQing); shenQing.setChargeFee(zyDetailCharge.getChargeAmount()); shenQing.setChargeAmount((zyDetailCharge.getAmount())); yaoPingShenQingDan.add(shenQing); } } FeiYongLeiXin fy = JiSuanFeiYong.jiSuan(param.getList(), true); fy.setTotalCharge(sum); Integer ledgerSn = publicServer.getLedgerSn(param.getInpatientNo(), param.getAdmissTimes()); // 在此处 插入费用 dao.chaRuFeiYong(param, param.getList(), infantFlag, ledgerSn); if (ListUtil.notBlank(yaoPingShenQingDan)) { dao.shenQingYaoPing(param, yaoPingShenQingDan, infantFlag, ledgerSn, TokenUtil.getTokenUserId()); } log.info("项目录入费用上传 ==》 操作人:{},数据:{}", param.getOpIdCode(), JSON.toJSONString(param)); return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_NOTIFICATION, "费用上传成功。<( ̄︶ ̄)>"); } /** * 上传以及修改项目录入模板 * * @param zyDetailCharge 模板的一些数据 * @return 返回成功提示 */ @Transactional(rollbackFor = Exception.class) public ResultVo shangChuanMuBan(ZyDetailCharge zyDetailCharge) { if (dao.chaKanMuBanMingChengSFcunZi(zyDetailCharge.getName(), TokenUtil.getTokenUserId()) > 0) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "模板名称重复,๐·°(৹˃̵﹏˂̵৹)°·๐"); } zyDetailCharge.setOpIdCode(TokenUtil.getTokenUserId()); for (ZyDetailCharge detailCharge : zyDetailCharge.getList()) { if (StringUtil.notBlank(zyDetailCharge.getBillItemCode())) { if (detailCharge.getBillItemCode().equals("001") || detailCharge.getBillItemCode().equals("002")) { detailCharge.setSerial("01"); detailCharge.setGroupNo("73"); } else if (zyDetailCharge.getBillItemCode().equals("028")) { zyDetailCharge.setSerial("01"); zyDetailCharge.setChargeCode("BILL28"); } else { // Serial 00 项目标志 01 药品标志 detailCharge.setSerial("00"); } } } // 在创建新的模板之前 需要先删除 原来的 dao.delMuBan(zyDetailCharge.getName(), zyDetailCharge.getOpIdCode()); dao.baoCunMuBan(zyDetailCharge); log.info("保存项目录入模板 ==》 操作人 :{},数据:{}", zyDetailCharge.getOpIdCode(), JSON.toJSONString(zyDetailCharge)); return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_NOTIFICATION, "保存模板成功。ㄟ(≧◇≦)ㄏ"); } /** * 医嘱退费匹配 * 第一次匹配使用 收费日期,数量,项目编码,医嘱号,账页号 来进行匹配 * 第二次匹配使用,数量,项目编码,账页号,执行科室来进行匹配的 * * @param inpatientNo 住院号 * @param admissTimes 住院次数 * @return 返回是否匹配成功 */ @Transactional(rollbackFor = Exception.class) public ResultVo yiZhuTuiFeiPiPei(String inpatientNo, Integer admissTimes, String deptCode) { if (StringUtil.isBlank(inpatientNo) || admissTimes == null || StringUtil.isBlank(deptCode)) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "患者信息不全。"); } int infantFlag = publicServer.getInfantFlag(inpatientNo); inpatientNo = publicServer.getInpatientNo(inpatientNo); Integer ledgerSn = publicServer.getLedgerSn(inpatientNo, admissTimes); List keShiLeiBiao = publicServer.huoQuBingFangDeKeShi(deptCode); // 获取正的医嘱费用 List getYiZhuFeiYongZhenShu = dao.getYiZhuFeiYong(inpatientNo, admissTimes, ledgerSn, ">", infantFlag, keShiLeiBiao); // 获取负的医嘱费用 List getYiZhuFeiYongFuShu = dao.getYiZhuFeiYong(inpatientNo, admissTimes, ledgerSn, "<", infantFlag, keShiLeiBiao); // 获取负数的退费数据 主要是用来判断 这一条正的是否退费了。 List tuiFeiList = dao.tuiFeiList(inpatientNo, admissTimes, infantFlag); if (!tuiFeiList.isEmpty()) { Map map = new HashMap<>(); for (ZyDetailCharge zyDetailCharge : tuiFeiList) { map.put(zyDetailCharge.getOriDetailSn(), zyDetailCharge.getDetailSn()); } getYiZhuFeiYongZhenShu.forEach(item -> { if (map.containsKey(item.getDetailSn())) { item.setTuiFeiFlag(1); } }); } // 需要保存需要匹配的一些流水数据 List piPei = new ArrayList<>(); // 此处是需要二次匹配的 list List erCiPiPei = new ArrayList<>(); // 用map 来保存正数的信息,但是有可能匹配的条件中map 的 key会一致 所以在这里使用 java8 的新特性 stream 流来进行分组 这样就不会因为key 一样导致数据被覆盖了 // 第一次 匹配 根据 医嘱号 收费时间 项目编码 数量 账页号 Map> zhenShuMap = getYiZhuFeiYongZhenShu.stream().collect( Collectors.groupingBy(item -> item.getOrderNo() + DateUtil.formatDatetime(item.getChargeDate()) + item.getChargeCodeMx() + item.getChargeAmount() + item.getChargeFee() + item.getLedgerSn()) ); // 用负数拼接的 key 去查找 for (ZyDetailCharge fuShu : getYiZhuFeiYongFuShu) { String key = fuShu.getOrderNo() + DateUtil.formatDatetime(fuShu.getChargeDate()) + fuShu.getChargeCodeMx() + fuShu.getChargeAmount().negate() + fuShu.getChargeFee().negate() + fuShu.getLedgerSn(); if (zhenShuMap.containsKey(key)) { for (ZyDetailCharge zyDetailCharge : zhenShuMap.get(key)) { if (zyDetailCharge.getTuiFeiFlag() == null && zyDetailCharge.getOriDetailSn() == null) { fuShu.setOriDetailSn(zyDetailCharge.getDetailSn()); zyDetailCharge.setTuiFeiFlag(1); piPei.add(fuShu); log.info("第一次匹配==》流水:{},匹配流水:{},", fuShu.getDetailSn(), fuShu.getOriDetailSn()); break; } } } else { // 这个是需要进行二次匹配的 erCiPiPei.add(fuShu); } } // 下面是二次匹配 if (erCiPiPei.size() > 0) { // 二次匹配 条件为 执行科室 项目编码 数量 账页号 Map> erCiPiPeiZhenShu = getYiZhuFeiYongZhenShu.stream().collect( Collectors.groupingBy(item -> item.getExecUnit() + item.getChargeCodeMx() + item.getChargeAmount() + item.getChargeFee() + item.getLedgerSn()) ); // 开始二次匹配 for (ZyDetailCharge zyDetailCharge : erCiPiPei) { String key = zyDetailCharge.getExecUnit() + zyDetailCharge.getChargeCodeMx() + zyDetailCharge.getChargeAmount().negate() + zyDetailCharge.getChargeFee().negate() + zyDetailCharge.getLedgerSn(); if (erCiPiPeiZhenShu.containsKey(key)) { for (ZyDetailCharge detailCharge : erCiPiPeiZhenShu.get(key)) { if (detailCharge.getTuiFeiFlag() == null && detailCharge.getOriDetailSn() == null) { zyDetailCharge.setOriDetailSn(detailCharge.getDetailSn()); detailCharge.setTuiFeiFlag(1); piPei.add(zyDetailCharge); log.info("第二次匹配==》流水:{},匹配流水:{}", zyDetailCharge.getDetailSn(), zyDetailCharge.getOriDetailSn()); break; } } } } } // 开始匹配 if (piPei.size() > 0) { // 100 条的更新 ListUtils.partition 用来拆分 list size 是拆分的条数 List> fenDuan = ListUtils.partition(piPei, 100); for (List list : fenDuan) { dao.yiZhuTuiFeiPiPei(inpatientNo, admissTimes, list, infantFlag); } publicServer.genXingYuanLiuShuiBiaoZhi(inpatientNo, admissTimes, ledgerSn); log.info("医嘱退费匹配 ==》 操作人:{},住院号:{},住院次数:{}", TokenUtil.getTokenUserId(), inpatientNo, admissTimes); return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_NOTIFICATION, String.format("匹配成功共:{%d}条,匹配成功:{%s}条", getYiZhuFeiYongFuShu.size(), piPei.size())); } publicServer.genXingYuanLiuShuiBiaoZhi(inpatientNo, admissTimes, ledgerSn); return ResultVoUtil.fail(ExceptionEnum.NO_DATA_EXIST, String.format("该患者有【%d】条,未能匹配 |д・)っ", getYiZhuFeiYongFuShu.size())); } /** * 此处删除模板 这个模板是录入住院费用的 模板 * * @param patterName 模板名称 * @param opIdCode 创建模板人的姓名 * @return 返回提示 */ public ResultVo shanChuMuBan(String patterName, String opIdCode) { log.info("删除项目模板 ==》操作人:{},模板名称:{}", TokenUtil.getTokenUserId(), patterName); dao.delMuBan(patterName, opIdCode); return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_NOTIFICATION, "删除成功,o(^▽^)o"); } /** * 生成拼音和五笔码 * * @param inputStr 中文 * @return 返回编码 */ public ResultVo getPyCode(String inputStr) { ZyDetailCharge zyDetailCharge = new ZyDetailCharge(); zyDetailCharge.setPyCode(PingYinUtils.getAllPinYinHeadChar(inputStr)); zyDetailCharge.setWbCode(PingYinUtils.getWBCode(inputStr)); return ResultVoUtil.success(zyDetailCharge); } /** * 根据对应的病区来获取科室 * * @param ward 科室编码 * @return 返回对应的 */ public ResultVo> getBingQuDuiYingKeShi(String ward) { return ResultVoUtil.success(dao.getBingQuDuiYingKeShi(ward)); } @Transactional(rollbackFor = Exception.class) public ResultVo cheXiaoTuiFei(String inpatientNo, Integer admissTimes, Integer ledger, Integer detailSn) { if (StringUtil.isBlank(inpatientNo) || admissTimes == null || ledger == null || detailSn == null) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "患者信息不全。"); } inpatientNo = publicServer.getInpatientNo(inpatientNo); ZyDetailCharge zyDetailCharge = dao.beiTuiFeiYongXinXi(inpatientNo, admissTimes, ledger, detailSn); if (zyDetailCharge == null) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "未查询到对应信息,可能该费用可能已经被撤销了或被正负相抵了。"); } if (!zyDetailCharge.getTransFlagYb().equals("0")) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "费用已经被上传了,无法撤销。"); } if (zyDetailCharge.getOriDetailSn() != null && zyDetailCharge.getOriDetailSn() == -1) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "被退数据无法删除。"); } dao.cheXiaoFeiYong(inpatientNo, admissTimes, ledger, detailSn); dao.cheXiaoHouHuanYuanZhenShuJu(inpatientNo, admissTimes, ledger, zyDetailCharge.getOriDetailSn()); log.info("撤销退费 ==> 操作人:{},住院号:{},住院次数:{},账页号:{},流水号:{},原流水号:{}", TokenUtil.getTokenUserId(), inpatientNo, admissTimes, ledger, detailSn, zyDetailCharge.getOriDetailSn()); return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_NOTIFICATION, "撤销成功,请刷新数据。"); } @Transactional(rollbackFor = Exception.class) public ResultVo weiGuiFeiYongFenXi(String inpatientNo, String execUnit) { ZyActpatient patient = publicServer.huoQuHuanZheXinXi(inpatientNo); inpatientNo = publicServer.getInpatientNo(inpatientNo); int infantFlag = publicServer.getInfantFlag(inpatientNo); Integer ledger = publicServer.getLedgerSn(inpatientNo, patient.getAdmissTimes()); List keShi = publicServer.huoQuBingFangDeKeShi(execUnit); publicServer.genXingYuanLiuShuiBiaoZhi(inpatientNo, patient.getAdmissTimes(), ledger); // 药品 分大包装和小包装 可能大包装 匹配了 小包装没有 匹配 所以这里编码同步 一下 List yaoPingBianMaTongBu = dao.weiGuiYaoPinInt(inpatientNo, patient.getAdmissTimes(), ledger, infantFlag); if (BigUtils.bigDaYu(dao.zhenFuXingDiFeiYong(inpatientNo, patient.getAdmissTimes(), ledger), 0)) { dao.chongXingZhengFuXiangDi(inpatientNo, patient.getAdmissTimes(), ledger); } // 这里退药 医嘱 有可能会没有携带 执行科室 List huoQuYaoPingZhongKeShiWeiKongDe = dao.huoQuYaoPingZhongKeShiWeiKongDe(inpatientNo, patient.getAdmissTimes(), ledger); if (!huoQuYaoPingZhongKeShiWeiKongDe.isEmpty()) { dao.yiZhuTuiFeiGenXingZhiXingKeShi(inpatientNo, patient.getAdmissTimes(), ledger, huoQuYaoPingZhongKeShiWeiKongDe); } if (yaoPingBianMaTongBu.size() > 0) { dao.genXinYaoPingPiPeiXinXi(yaoPingBianMaTongBu); } patient.setWeiPiPei(new ArrayList<>()); patient.setWeiXieDaiYuanLiuShui(new ArrayList<>()); patient.getWeiPiPei().addAll(dao.weiGuiYaoPin(inpatientNo, patient.getAdmissTimes(), ledger, infantFlag)); patient.getWeiPiPei().addAll(dao.weiGuiXiangMu(inpatientNo, patient.getAdmissTimes(), ledger, infantFlag)); patient.getWeiXieDaiYuanLiuShui().addAll(dao.weiXieDaiYuanLiuShuiXiangMu(inpatientNo, patient.getAdmissTimes(), ledger, infantFlag, keShi)); patient.getWeiXieDaiYuanLiuShui().addAll(dao.weiXieDaiYuanLiuShuiYaoPing(inpatientNo, patient.getAdmissTimes(), ledger, infantFlag, keShi)); log.info("查询违规费用 =>>住院号{}次数{}执行科室{}", inpatientNo, patient.getAdmissTimes(), JSON.toJSONString(keShi)); return ResultVoUtil.success(patient); } public ResultVo> huoQuZhenShuKePiPei(String inpatientNo, Integer admissTimes, Integer ledgerSn, String chargeCodeMx, String execUnit, String startTime, String endTime, String riQiPaiXu) { log.info("获取可以匹配的费用==》 住院号:{},次数:{},账页号:{},项目编码:{},执行科室:{}", inpatientNo, admissTimes, ledgerSn, chargeCodeMx, execUnit); List zhenShuFeiYong = dao.weiGuiZhenShuPiPei(publicServer.getInpatientNo(inpatientNo), admissTimes, ledgerSn, publicServer.getInfantFlag(inpatientNo), chargeCodeMx, execUnit, startTime, endTime, riQiPaiXu); List yuEr = dao.tuiFeiYuEr1(publicServer.getInpatientNo(inpatientNo), admissTimes, ledgerSn, publicServer.getInfantFlag(inpatientNo), chargeCodeMx, execUnit); Map yuErPiPei = new HashMap<>(); for (ZyDetailCharge item : yuEr) { String key = item.getInpatientNo() + item.getAdmissTimes() + item.getDetailSn() + item.getChargeCodeMx(); yuErPiPei.put(key, item); } for (int i = 0, len = zhenShuFeiYong.size(); i < len; i++) { ZyDetailCharge zy = zhenShuFeiYong.get(i); String key = zy.getInpatientNo() + zy.getAdmissTimes() + zy.getDetailSn() + zy.getChargeCodeMx(); if (yuErPiPei.containsKey(key)) { if (BigUtils.dengYu(yuErPiPei.get(key).getYiTuiFei(), 0)) { zhenShuFeiYong.remove(i); len--; i--; } else { zy.setYiTuiFei(zy.getChargeFee().subtract(yuErPiPei.get(key).getYiTuiFei())); log.info("原来:{},已退:{},余额:{}", zy.getChargeFee(), yuErPiPei.get(key).getYiTuiFei(), zy.getYiTuiFei()); } } } log.info("可匹配的费用:{}", JSON.toJSONString(zhenShuFeiYong)); return ResultVoUtil.success(zhenShuFeiYong); } @Transactional(rollbackFor = Exception.class) public ResultVo caiFenPiPei(ZyDetailCharge zyDetailCharge) { String inpatientNo = publicServer.getInpatientNo(zyDetailCharge.getInpatientNo()); Integer infantFlag = publicServer.getInfantFlag(zyDetailCharge.getInpatientNo()); if (ListUtil.isBlank(zyDetailCharge.getList())) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "请选择数据。"); } int[] detailSnList = new int[zyDetailCharge.getList().size()]; for (int i = 0; i < zyDetailCharge.getList().size(); i++) { detailSnList[i] = zyDetailCharge.getList().get(i).getDetailSn(); } ZyDetailCharge zy = dao.piPeiXinXiFuShu(inpatientNo, zyDetailCharge.getAdmissTimes(), zyDetailCharge.getLedgerSn(), infantFlag, zyDetailCharge.getDetailSn()); if (zy == null) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "未找到负数费用信息,可能已经被删除了,请刷新页面重试。"); } else if (zy.getTransFlagYb().equals("2") || zy.getOriDetailSn() != null) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "该负数费用已被正负相抵。"); } List zhenShuShuJu = dao.piPeiXinXi(inpatientNo, zyDetailCharge.getAdmissTimes(), zyDetailCharge.getLedgerSn(), infantFlag, detailSnList); Map tuiFeiYuErPiPei = dao.tuiFeiYuEr2(inpatientNo, zyDetailCharge.getAdmissTimes(), zyDetailCharge.getLedgerSn(), infantFlag, detailSnList).stream().collect( Collectors.toMap(ZyDetailCharge::getOriDetailSn, a -> a, (k1, k2) -> k1)); BigDecimal chargeFeeSum = new BigDecimal(0); BigDecimal chargeAmountSum = new BigDecimal(0); List yongHuJueSe = dao.huoQuJueSe(TokenUtil.getTokenUserId()); List zhiXinKeShi = dao.chaXunZhiZXinKeShi(zyDetailCharge.getDeptCode()); for (ZyDetailCharge detailCharge : zhenShuShuJu) { zyDetailCharge.setYaoPing(false); ResultVo LOGICAL_ERROR = getStringResultVo(yongHuJueSe, zhiXinKeShi, zyDetailCharge, detailCharge); if (LOGICAL_ERROR != null) return LOGICAL_ERROR; if (detailCharge.getTransFlagYb().equals("2")) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, String.format("流水号为:{%d},已被正负抵消。", detailCharge.getDetailSn())); } if (tuiFeiYuErPiPei.containsKey(detailCharge.getDetailSn())) { detailCharge.setChargeFee(detailCharge.getChargeFee().add(tuiFeiYuErPiPei.get(detailCharge.getDetailSn()).getChargeFee())); } chargeFeeSum = chargeFeeSum.add(detailCharge.getChargeFee()); chargeAmountSum = chargeAmountSum.add(detailCharge.getChargeAmount()); } if (BigUtils.bigDaYu(chargeFeeSum, zy.getChargeFee().negate()) || BigUtils.dengYu(chargeFeeSum, zy.getChargeFee().negate())) { if (zhenShuShuJu.size() == 1) { dao.zhiYouYiGeJiuGenXingFuShuLiuShui(zyDetailCharge.getInpatientNo(), zyDetailCharge.getAdmissTimes(), zyDetailCharge.getLedgerSn(), zyDetailCharge.getDetailSn(), zhenShuShuJu.get(0).getDetailSn()); publicServer.genXingYuanLiuShuiBiaoZhi(inpatientNo, zyDetailCharge.getAdmissTimes(), zyDetailCharge.getLedgerSn()); return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_NOTIFICATION, "费用匹配成功。"); } else { ResultVo tuiFei = xiangMuTuiFei(zyDetailCharge); if (tuiFei.getCode() != 201) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, tuiFei.getMessage()); } dao.cheXiaoFeiYong(inpatientNo, zyDetailCharge.getAdmissTimes(), zyDetailCharge.getLedgerSn(), zyDetailCharge.getDetailSn()); return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_NOTIFICATION, "费用拆分成功。"); } } return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, String.format("负数费用:{%.2f},匹配费用:{%.2f}
负数数量:{%.2f},匹配数量:{%.2f}", zy.getChargeFee().negate(), chargeFeeSum, zy.getChargeAmount().negate(), chargeAmountSum)); } }