package thyyxxk.webserver.service.hospitalizationCosts; import cn.hutool.core.util.ObjectUtil; import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import thyyxxk.webserver.config.exception.BizException; import thyyxxk.webserver.config.exception.ExceptionEnum; import thyyxxk.webserver.dao.his.hospitalizationCosts.HospitalizationCostsDao; import thyyxxk.webserver.dao.his.inpatient.XiangMuLuRuDao; import thyyxxk.webserver.entity.ResultVo; import thyyxxk.webserver.entity.hospitalizationCosts.ZyDetailChargeTable; import thyyxxk.webserver.entity.hospitalizationCosts.ZyDetailRefundParam; import thyyxxk.webserver.entity.inpatient.ZyActpatient; import thyyxxk.webserver.entity.login.UserInfo; import thyyxxk.webserver.service.PublicServer; import thyyxxk.webserver.service.redislike.RedisLikeService; import thyyxxk.webserver.utils.*; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Set; @Service @Slf4j public class HospitalizationCostsService { private final HospitalizationCostsDao dao; private final RedisLikeService redisLikeService; private final XiangMuLuRuDao luRuDao; private final PublicServer publicServer; @Data public static class OrderInfo { private String classCode; private String drugClass; private String miniUnit; } public HospitalizationCostsService(HospitalizationCostsDao dao, RedisLikeService redisLikeService, XiangMuLuRuDao luRuDao, PublicServer publicServer) { this.dao = dao; this.redisLikeService = redisLikeService; this.luRuDao = luRuDao; this.publicServer = publicServer; } @Transactional(rollbackFor = Exception.class) public ResultVo refund(ZyDetailRefundParam param) { log.info("退费数组: {}", JSON.toJSONString(param)); UserInfo userInfo = redisLikeService.getUserInfoByToken(); if (userInfo == null) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "退费人员信息不存在,请重新登录。"); } // 婴儿标志 int infantFlag = PublicServer.getInfantFlag(param.getInpatientNo()); if (infantFlag == 1) { param.setInpatientNo(param.getInpatientNo().split("\\$")[0]); } preCheck(param, userInfo); // 获取 患者的账页号 Integer ledgerSn = publicServer.getLedgerSn(param.getInpatientNo(), param.getAdmissTimes()); // 查询原来的数据 QueryWrapper qw = new QueryWrapper<>(); qw.eq("inpatient_no", param.getInpatientNo()) .eq("admiss_times", param.getAdmissTimes()) .eq("ledger_sn", ledgerSn) .in("detail_sn", param.getDetailSn()); List tables = dao.selectList(qw); // 获取患者自己的科室和下面的子科室 Set deptList; if (userInfo.getDeptCode().startsWith("8")) { deptList = luRuDao.chaXunZhiZXinKeShi(userInfo.getDeptCode()); deptList.add(userInfo.getDeptCode()); } else { deptList = publicServer.getChildDeptByUserCode(); } // 需要生成退药单 List generateAReturnOrder = new ArrayList<>(); // 只退费 List refundOnly = new ArrayList<>(); // 医技录入的药品退费 List medicalTechnologyDrugReturnForm = new ArrayList<>(); // 是否是毒麻药品 CacheOnce drugKind = new CacheOnce<>(); // 药品的详细信息 CacheOnce orderCacheOnce = new CacheOnce<>(); // 患者最大的 detail_sn int maxDetailSn = publicServer.getMaxDetailSn(param.getInpatientNo(), param.getAdmissTimes()); StringBuilder error = new StringBuilder(); for (ZyDetailChargeTable item : tables) { maxDetailSn += 1; StringBuilder sb = new StringBuilder(); if (StringUtil.isBlank(item.getSerial())) { item.setSerial("00"); } // -3 退药申请,拒绝退药申请是可以重新申请的 if (item.getOriDetailSn() != null && item.getOriDetailSn().equals(-3)) { item.setOriDetailSn(null); } if (item.getOriDetailSn() != null && item.getOriDetailSn().equals(-2)) { sb.append("该药品在申请退药。"); } if (item.getOriDetailSn() != null) { sb.append("该数据为退费数据。"); } if (BigUtils.bigXiaoYu(item.getChargeFee(), 0) || BigUtils.bigXiaoYu(item.getChargeAmount(), 0)) { sb.append("该数据为负数。"); } if (StringUtil.isBlank(item.getExecUnit())) { item.setExecUnit(userInfo.getDeptCode()); } if ("BILL02".equals(item.getChargeCode())) { sb.append("中药无法退费。"); } String orderNo = item.getOrderNo() == null ? "" : item.getOrderNo().stripTrailingZeros().toPlainString(); // 项目判断 if ("00".equals(item.getSerial())) { if (publicServer.noNeedRule() && !deptList.contains(item.getExecUnit())) { sb.append("请对应的执行科室进行退费。"); } // 只退费设置 refundOnly.add(设置默认值以及自增(item, maxDetailSn, -1)); } else { // 药品判断 // 医技科室录入的费用 if ("3".equals(orderNo)) { if (!deptList.contains(item.getExecUnit())) { sb.append("此药品为医技科室录入,请对应的医技科室退费。"); } refundOnly.add(设置默认值以及自增(item, maxDetailSn, -1)); medicalTechnologyDrugReturnForm.add(设置默认值以及自增(item, maxDetailSn, -1)); } else { // 仅退费不退药品 if ("refundOnly".equals(param.getRefundFlag())) { refundOnly.add(设置默认值以及自增(item, maxDetailSn, -1)); } else { // 退费又退药.不需要向refundOnly中添加数据,且oriDetailSn 要设置为 -2 代表申请退费 generateAReturnOrder.add(设置默认值以及自增(item, maxDetailSn, -2)); } OrderInfo order = orderCacheOnce.get(orderNo, (key) -> dao.selectDrugClassByOrderNo(new BigDecimal(orderNo))); if (order == null) { sb.append("没有查询到原药品对应的医嘱"); } else { if (!"refundOnly".equals(param.getRefundFlag())) { // 口服药无法退费 包装规格是 09,盒,15,瓶 的可以退费 if ("1".equals(order.getClassCode())) { if (!(order.getMiniUnit().equals("09") || order.getMiniUnit().equals("15"))) { sb.append("医嘱给药方式为口服药,口服无法退费,药剂科要求只有包装规格为,瓶、盒可以退费有退药。"); } } if ("d".equals(order.getDrugClass())) { order.setDrugClass("j"); } // 医嘱表中会有 z 所以把所有 z 的换成 j item.setDrugClass("z".equals(order.getDrugClass()) ? "j" : order.getDrugClass()); } } } Integer count = drugKind.get(item.getChargeCodeMx().trim() + "_" + item.getSerial().trim(), (key) -> dao.getDrugKing(item.getChargeCodeMx().trim(), item.getSerial().trim())); if (count > 0 && "refundOnly".equals(param.getRefundFlag())) { sb.append("药剂科要求,毒麻药药品无法,仅退费不退药品,请选择退费且退药。"); } } if (StringUtil.notBlank(sb.toString())) { error.append("流水号:【").append(item.getDetailSn()).append("】").append(sb).append("
"); } } // 循环结束 if (StringUtil.notBlank(error.toString())) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_HTML_ERROR, error.toString()); } ZyActpatient patientInfo = publicServer.huoQuHuanZheXinXi(param.getInpatientNo()); // 需要生成退药单 if (ListUtil.notBlank(generateAReturnOrder)) { // 插入退费数据 dao.detailsOfDrugReturnForm(generateAReturnOrder, patientInfo.getInpatientNo(), patientInfo.getAdmissTimes(), patientInfo.getName(), patientInfo.getBedNo(), userInfo.getDeptCode(), infantFlag, param.getGroupNo(), TokenUtil.getTokenUserId(), ledgerSn); } // 直接退费 if (ListUtil.notBlank(refundOnly)) { // 插入退费数据 dao.insertRefundData(refundOnly); } // 医技科室退费数据 if (ListUtil.notBlank(medicalTechnologyDrugReturnForm)) { dao.shenQingYaoPing(patientInfo, medicalTechnologyDrugReturnForm, infantFlag, ledgerSn, userInfo.getCode()); } dao.updateOriFlag(tables); return ResultVoUtil.success(); } /** * 退费前置校验 * * @param param 参数 * @param userInfo 用户信息 */ private void preCheck(ZyDetailRefundParam param, UserInfo userInfo) { if (!userInfo.getRoles().contains(36) && !userInfo.getRoles().contains(1)) { throw new BizException(ExceptionEnum.LOGICAL_ERROR, "您没有权限退费。"); } if (param.getList() == null || param.getList().isEmpty()) { throw new BizException(ExceptionEnum.LOGICAL_ERROR, "请先选择需要退费的数据,一次性退费不得超过100条"); } else if (param.getList().size() > 100) { throw new BizException(ExceptionEnum.LOGICAL_ERROR, "项目退费一次性大于100条数据"); } if (StringUtil.isBlank(param.getInpatientNo()) || param.getAdmissTimes() == null || param.getList().size() == 0) { throw new BizException(ExceptionEnum.NULL_POINTER, "患者信息不全"); } if (luRuDao.getHuanZheSFZaiYuan(param.getInpatientNo(), param.getAdmissTimes()) == 0) { throw new BizException(ExceptionEnum.LOGICAL_ERROR, "该患者已出院"); } Integer settlementFlag = luRuDao.getHuanZheSFJieSuan(param.getInpatientNo(), param.getAdmissTimes()); if (settlementFlag == null || settlementFlag != 0) { throw new BizException(ExceptionEnum.LOGICAL_ERROR, "该患者已经结算了"); } } public ZyDetailChargeTable 设置默认值以及自增(ZyDetailChargeTable item, int maxDetailSn, int oriDetailSn) { String userCode = TokenUtil.getTokenUserId(); // 克隆一下 item 的数据 ZyDetailChargeTable clone = EntityCopy.Copy(item, ZyDetailChargeTable.class); // 取负数的费用 clone.setChargeFee(item.getChargeFee().negate()); clone.setChargeAmount(item.getChargeAmount().negate()); // 执行人 clone.setOpIdCode(userCode); clone.setConfirmId(userCode); // 设置原来的流水号 clone.setOriDetailSn(item.getDetailSn()); Date now = new Date(); clone.setGenTime(now); clone.setChargeDate(now); // 设置新的流水号 clone.setDetailSn(maxDetailSn); // 这个是唯一要改变的东西 item.setOriDetailSn(oriDetailSn); return clone; } }