package thyyxxk.webserver.service.inpatient; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; 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.constants.Capacity; import thyyxxk.webserver.constants.sidicts.MedType; import thyyxxk.webserver.dao.his.inpatient.DismissDao; import thyyxxk.webserver.entity.ResultVo; import thyyxxk.webserver.entity.inpatient.dismiss.*; import thyyxxk.webserver.entity.inpatient.patient.Overview; import thyyxxk.webserver.entity.inpatient.patient.Patient; import thyyxxk.webserver.service.externalhttp.SiInjuryFeeUpld; import thyyxxk.webserver.service.externalhttp.SiZySrvc; import thyyxxk.webserver.utils.*; import java.math.BigDecimal; import java.util.*; /** * @author dj */ @Slf4j @Service public class DismissService { private final DismissDao dao; private final SiZySrvc zySrvc; private final SiInjuryFeeUpld injuryFeeUpld; @Value("${si-zy-fee-url}") private String siZyFeeUrl; @Value("${si-injury-fee-url}") private String siInjuryFeeUrl; @Autowired public DismissService(DismissDao dao, SiZySrvc zySrvc, SiInjuryFeeUpld injuryFeeUpld) { this.dao = dao; this.zySrvc = zySrvc; this.injuryFeeUpld = injuryFeeUpld; } public ResultVo dismiss(Patient param) { ResultVo> actOrders = getActOrders(param.getInpatientNo(), param.getAdmissTimes()); if (actOrders.getCode() != ExceptionEnum.SUCCESS.getCode()) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, actOrders.getMessage()); } if (!actOrders.getData().isEmpty()) { return ResultVoUtil.fail(ExceptionEnum.ABNORMAL_YZ_ACT_ORDER, actOrders.getData()); } ResultVo> calculate = calculateForDismiss(param); if (calculate.getCode() == ExceptionEnum.EXIST_NEGATIVE_FEES.getCode()) { return ResultVoUtil.fail(ExceptionEnum.EXIST_NEGATIVE_FEES, calculate.getData()); } if (calculate.getCode() != ExceptionEnum.SUCCESS.getCode()) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, calculate.getMessage()); } return ResultVoUtil.success(); } public ResultVo> getActOrders(String patNo, Integer times) { final Integer ledgerSn = dao.getLedgerSn(patNo, times); if (ledgerSn < 1) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "获取帐页数失败。"); } dao.acceptFeeStepOne(patNo, times); if (dao.acceptFeeStepTwo(patNo, times) < 0) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "接收费用失败。"); } if (dao.getOrderList(patNo, times) < 0) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "查询医嘱失败。"); } List allOrders = dao.getActOrderDetail(); if (allOrders == null) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "查询医嘱失败。"); } return analyzeActOrders(allOrders); } private ResultVo> analyzeActOrders(List allOrders) { HashMap temp = new HashMap<>(Capacity.DEFAULT); for (ActOrderDetail item : allOrders) { String actOrderNo = item.getActOrderNo(); String fee = item.getChargeFee(); if (!temp.containsKey(actOrderNo)) { ActOrderGroup aModel = new ActOrderGroup(actOrderNo, fee, item.getChargeStatus(), item.getCxFlag()); if (aModel.getList() == null) { aModel.setList(new ArrayList<>()); } aModel.getList().add(item); temp.put(actOrderNo, aModel); } else { temp.get(actOrderNo).setFee(DecimalUtil.add(fee, temp.get(actOrderNo).getFee())); temp.get(actOrderNo).getList().add(item); } } List list = new ArrayList<>(); for (HashMap.Entry modelEntry : temp.entrySet()) { list.add(modelEntry.getValue()); } return ResultVoUtil.success(list); } public ResultVo> calculateForDismiss(Patient param) { final String patNo = param.getInpatientNo(); final Integer times = param.getAdmissTimes(); if (!param.getMidSetl()) { Integer disActOrderCount = dao.countDisActOrders(patNo, times); if (null == disActOrderCount || disActOrderCount == 0) { disActOrderCount = dao.countDisActOrders2(patNo, times); if (null == disActOrderCount) { disActOrderCount = 0; } } if (disActOrderCount < 1) { ExceptionEnum exception = ExceptionEnum.LOGICAL_ERROR; exception.setMessage("此患者没有出院医嘱,请检查。"); throw new BizException(exception); } if (disActOrderCount > 1) { ExceptionEnum exception = ExceptionEnum.LOGICAL_ERROR; exception.setMessage("此患者的出院医嘱不止一条,请检查。"); throw new BizException(exception); } } if (StringUtil.isBlank(param.getDutyNurse())) { ExceptionEnum exception = ExceptionEnum.LOGICAL_ERROR; exception.setMessage("患者责任护士不能为空,请前往入院登记页面填写并保存。"); throw new BizException(exception); } if (StringUtil.isBlank(param.getCountry())) { ExceptionEnum exception = ExceptionEnum.LOGICAL_ERROR; exception.setMessage("患者国籍不能为空,请前往入院登记页面填写并保存。"); throw new BizException(exception); } if (StringUtil.isBlank(param.getNation())) { ExceptionEnum exception = ExceptionEnum.LOGICAL_ERROR; exception.setMessage("患者民族不能为空,请前往入院登记页面填写并保存。"); throw new BizException(exception); } if (StringUtil.isBlank(param.getContactName())) { ExceptionEnum exception = ExceptionEnum.LOGICAL_ERROR; exception.setMessage("患者联系人不能为空,请前往入院登记页面填写并保存。"); throw new BizException(exception); } if (StringUtil.isBlank(param.getContactRelation())) { ExceptionEnum exception = ExceptionEnum.LOGICAL_ERROR; exception.setMessage("患者联系人关系不能为空,请前往入院登记页面填写并保存。"); throw new BizException(exception); } if (StringUtil.isBlank(param.getContactAddrName())) { ExceptionEnum exception = ExceptionEnum.LOGICAL_ERROR; exception.setMessage("患者联系人地址不能为空,请前往入院登记页面填写并保存。"); throw new BizException(exception); } if (StringUtil.isBlank(param.getContactPhone())) { ExceptionEnum exception = ExceptionEnum.LOGICAL_ERROR; exception.setMessage("患者联系人电话不能为空,请前往入院登记页面填写并保存。"); throw new BizException(exception); } if (null == param.getAdmissDate()) { ExceptionEnum exception = ExceptionEnum.LOGICAL_ERROR; exception.setMessage("没有找到入院时间,请重新获取病人信息。"); throw new BizException(exception); } if (!IdCardUtil.isValidatedIdCard(param.getSocialNo())) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "身份证不合法!"); } int age = IdCardUtil.getAgeByIdCard(param.getSocialNo()); if (age < 16 || age > 60) { if (param.getName().equals(param.getContactName()) || param.getContactRelation().equals("0")) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "16岁以下或60岁以上的患者,联系人不能填写本人。"); } } Date endtime = getEndtime(param.getMidSetl(), patNo, times, param.getZjdzDatetime()); Date tmpendtime = param.getMidSetl() ? endtime : DateUtil.parse("2999-12-31 23:59:59"); final int ledgerSn = dao.getLedgerSn(patNo, times); if (dao.hasUnsettledStepOne(patNo, times, ledgerSn) < 0) { ExceptionEnum exception = ExceptionEnum.LOGICAL_ERROR; exception.setMessage("获取记账信息失败。"); throw new BizException(exception); } if (dao.hasUnsettledStepTwo(patNo, times) > 0) { ExceptionEnum exception = ExceptionEnum.LOGICAL_ERROR; exception.setMessage("此患者有未结算的记账金额,请联系收费窗口。"); throw new BizException(exception); } if (dao.hasNotAccounted(patNo, times) > 0) { ExceptionEnum exception = ExceptionEnum.LOGICAL_ERROR; exception.setMessage("此患者有未上账金额。"); throw new BizException(exception); } List unreceivedDrug = dao.hasUnreceivedDrugList(patNo, times); if (ListUtil.notBlank(unreceivedDrug)) { throw new BizException(ExceptionEnum.LOGICAL_HTML_ERROR, dischargeErrorMessage(unreceivedDrug)); } if (dao.hasUnreceivedFees(patNo, times, tmpendtime) > 0) { ExceptionEnum exception = ExceptionEnum.LOGICAL_ERROR; exception.setMessage("此患者有未接收的费用。"); throw new BizException(exception); } if (dao.hasUnSubmitDrugList(patNo, times) > 0) { // 有未提交药物清单 ExceptionEnum exception = ExceptionEnum.LOGICAL_ERROR; exception.setMessage("此患者有未提交的药单。"); throw new BizException(exception); } if (dao.hasUntreatedDrugWithdrawalOrder(patNo, times) > 0) { ExceptionEnum exception = ExceptionEnum.LOGICAL_ERROR; exception.setMessage("此患者有未处理的药品退药单。"); throw new BizException(exception); } if (dao.hasUnconfirmedMedicalTech(patNo, times, tmpendtime) > 0) { ExceptionEnum exception = ExceptionEnum.LOGICAL_ERROR; exception.setMessage("此患者有未确认的医技。"); throw new BizException(exception); } List feeNegativeList = dao.feeOrderNegative(patNo, times); if (feeNegativeList.size() > 0) { return ResultVoUtil.fail(ExceptionEnum.EXIST_NEGATIVE_FEES, feeNegativeList); } if (dao.hasSettled(patNo, times, ledgerSn) != 0) { ExceptionEnum exception = ExceptionEnum.LOGICAL_ERROR; exception.setMessage("此患者已存在结算信息。"); throw new BizException(exception); } if (dao.hasUncheckedFee(patNo, times, ledgerSn) > 0) { ExceptionEnum exception = ExceptionEnum.LOGICAL_ERROR; exception.setMessage("此患者有未结账的费用。"); throw new BizException(exception); } Date begntime = getBegntime(patNo, times, ledgerSn,"zy_actpatient"); dismissFeeAnalyse(patNo, times, ledgerSn, begntime, tmpendtime); BigDecimal feeOffset = dao.getFeeOffset(patNo, times, ledgerSn); if (feeOffset.compareTo(BigDecimal.ZERO) != 0) { ExceptionEnum exception = ExceptionEnum.LOGICAL_ERROR; BigDecimal beforeAdmFee = dao.selectOverTimeLimitFee(patNo, times, ledgerSn, "<", begntime); if (beforeAdmFee.compareTo(BigDecimal.ZERO) != 0) { exception.setMessage("此患者明细费用与账页费用不一致,有【" + beforeAdmFee + "元】小于入院时间的费用。"); throw new BizException(exception); } if (!param.getMidSetl()) { BigDecimal afterDisFee = dao.selectOverTimeLimitFee(patNo, times, ledgerSn, ">", tmpendtime); if (afterDisFee.compareTo(BigDecimal.ZERO) != 0) { exception.setMessage("此患者明细费用与账页费用不一致,有【" + afterDisFee + "元】大于出院时间的费用。"); throw new BizException(exception); } exception.setMessage("此患者明细费用与账页费用不一致,请确认所有医嘱、药单等都已接收。"); throw new BizException(exception); } } dao.deleteTemporaryTable(patNo, times); BriefMdtrtInfo medinfo = dao.selectMdtrtId(patNo, times, ledgerSn); if (null == medinfo) { medinfo = new BriefMdtrtInfo(); } if (StringUtil.notBlank(medinfo.getMdtrtId())) { if (dao.hasDismissDiag(patNo, times) == 0) { ExceptionEnum exception = ExceptionEnum.LOGICAL_ERROR; exception.setMessage("此患者没有医保出院诊断。"); throw new BizException(exception); } if (medinfo.getMedType().equals(MedType.INJURY_HOSPITALIZATION.getCode())) { if (param.getMidSetl()) { param.setBegntime(begntime); param.setEndtime(tmpendtime); } ResultVo feeCheck = injuryFeeUpld.uploadFees(siInjuryFeeUrl, param); if (feeCheck.getCode() != 0) { ExceptionEnum exception = ExceptionEnum.LOGICAL_ERROR; exception.setMessage(feeCheck.getMessage()); throw new BizException(exception); } } else { Overview o = new Overview(); o.setInpatientNo(patNo); o.setAdmissTimes(times); o.setLedgerSn(ledgerSn); o.setStaffId(param.getStaffId()); o.setSid(param.getSid()); o.setMidSetl(param.getMidSetl()); if (o.getMidSetl()) { o.setBegntime(begntime); o.setEndtime(tmpendtime); } ResultVo feeCheck = zySrvc.uploadFeeDetail(siZyFeeUrl, o); if (feeCheck.getCode() != ExceptionEnum.SUCCESS.getCode()) { ExceptionEnum exception = ExceptionEnum.LOGICAL_ERROR; exception.setMessage(feeCheck.getMessage()); throw new BizException(exception); } } } return ResultVoUtil.success(); } private String dischargeErrorMessage(List messages) { StringBuilder str = new StringBuilder("此患者有未接收的药单" + "
"); for (String message : messages) { str.append(message).append("
"); } return str.toString(); } @Transactional(rollbackFor = Exception.class) public ResultVo executeDischarging(MedinsSettleFee settleFee) throws BizException { updateHicNo(settleFee.getInpatientNo()); settleFee.setLedgerSn(dao.getLedgerSn(settleFee.getInpatientNo(), settleFee.getAdmissTimes())); BriefMdtrtInfo medinfo = dao.selectMdtrtId(settleFee.getInpatientNo(), settleFee.getAdmissTimes(), settleFee.getLedgerSn()); if (null == medinfo) { medinfo = new BriefMdtrtInfo(); } // 医保病人进行医保结算 if (StringUtil.notBlank(medinfo.getMdtrtId())) { dao.deleteZyLedgerFileYb(settleFee.getInpatientNo(), settleFee.getAdmissTimes(), settleFee.getLedgerSn()); // 如果医院支付为正,则 现金支付 = 现金支付 + 医院支付 if (!settleFee.getHospitalPay().startsWith("-")) { settleFee.setXjzf(DecimalUtil.add(settleFee.getXjzf(), settleFee.getHospitalPay())); } if (dao.insertZyLedgerFileYb(settleFee) < 1) { ExceptionEnum exception = ExceptionEnum.LOGICAL_ERROR; exception.setMessage("写医保结算表失败。"); throw new BizException(exception); } } else { dao.clearMedinsInfo(settleFee.getInpatientNo(), settleFee.getAdmissTimes(), null); } if (writeReceiptTable(settleFee) < 1) { ExceptionEnum exception = ExceptionEnum.LOGICAL_ERROR; exception.setMessage("写发票表失败。"); throw new BizException(exception); } int code = settleFee.getMidSetl() ? hisMiddleSettle(settleFee) : setHisStatusOut(settleFee); if (updateCostStatusToSettled(settleFee, StringUtil.notBlank(medinfo.getMdtrtId())) < 1) { ExceptionEnum exception = ExceptionEnum.LOGICAL_ERROR; exception.setMessage("更新费用状态失败。"); throw new BizException(exception); } if (code < 1) { ExceptionEnum exception = ExceptionEnum.LOGICAL_ERROR; exception.setMessage("更新操作日志失败。" + code); throw new BizException(exception); } return ResultVoUtil.success(); } private int writeReceiptTable(MedinsSettleFee indata) { if (dao.beforeWriteReceiptTable(indata.getInpatientNo(), indata.getAdmissTimes(), indata.getLedgerSn()) < 1) { return -1; } Date admissDate = getBegntime(indata.getInpatientNo(), indata.getAdmissTimes(), indata.getLedgerSn(), indata.getTable()); Date dismissDate = getEndtime(indata.getMidSetl(), indata.getInpatientNo(), indata.getAdmissTimes(), indata.getZjdzDatetime()); Date tempendtime = indata.getMidSetl() ? dismissDate : DateUtil.parse("2999-12-31 23:59:59"); ReceiptEntity receiptEntity = dismissFeeAnalyse(indata.getInpatientNo(), indata.getAdmissTimes(), indata.getLedgerSn(), admissDate, tempendtime); if (indata.getLedgerSn() > 1) { admissDate = DateUtil.addOneSecond(admissDate); } if (dao.writeReceiptTable(indata.getInpatientNo(), indata.getAdmissTimes(), indata.getLedgerSn(), 1, admissDate, dismissDate, indata.getWardCode(), indata.getDeptCode(), dismissDate, "01", indata.getStaffId(), receiptEntity.getAdult()) < 1) { return -1; } if (null != receiptEntity.getInfant()) { return dao.writeReceiptTable(indata.getInpatientNo(), indata.getAdmissTimes(), indata.getLedgerSn(), 4, admissDate, dismissDate, indata.getWardCode(), indata.getDeptCode(), dismissDate, "04", indata.getStaffId(), receiptEntity.getInfant()); } return 1; } private ReceiptEntity dismissFeeAnalyse(String patNo, int times, int ledgerSn, Date begntime, Date endtime) { Map ledgerMap = initReceiptMap(); Map infantMap = initReceiptMap(); Map adultMap = initReceiptMap(); List ledgerFees = dao.selectLedgerFees(patNo, times, ledgerSn, begntime, endtime); if (null == ledgerFees) { ledgerFees = new ArrayList<>(); } for (ReceiptFee fee : ledgerFees) { ledgerMap.replace(fee.getBillCode(), fee.getLedgerFee()); ledgerMap.replace("total", DecimalUtil.add(ledgerMap.get("total"), fee.getLedgerFee())); infantMap.replace(fee.getBillCode(), fee.getInfantFee()); infantMap.replace("total", DecimalUtil.add(infantMap.get("total"), fee.getInfantFee())); adultMap.replace(fee.getBillCode(), fee.getAdultFee()); adultMap.replace("total", DecimalUtil.add(adultMap.get("total"), fee.getAdultFee())); } String restype = dao.selectResponceType(patNo, times, ledgerSn); if (StringUtil.isBlank(restype)) { restype = "01"; } if (restype.equals("01")) { String injurySerialNo = dao.selectInjurySerialNo(patNo, times, ledgerSn); if (StringUtil.notBlank(injurySerialNo)) { restype = "al"; } } String deposit = dao.selectDepositSumamt(patNo, times, ledgerSn); if (StringUtil.isBlank(deposit)) { deposit = "0"; } String balance = DecimalUtil.minus(deposit, ledgerMap.get("total")); dao.updateZyLedgerFileCharges(patNo, times, ledgerSn, deposit, balance, restype, ledgerMap); ReceiptEntity entity = new ReceiptEntity(); if (DecimalUtil.compare(infantMap.get("total"), "0") == 1) { String patNo1 = patNo + "$1"; String patNo6 = patNo + "$6"; dao.updateInfantfee(patNo1, patNo6, times, infantMap); entity.setInfant(infantMap); } String totalCost = dao.selectTotalCharge(patNo, times); dao.updateZyActpatientCharges(patNo, totalCost, balance, restype, ledgerMap); entity.setAdult(adultMap); return entity; } private Map initReceiptMap() { Map map = new HashMap<>(); map.put("total", "0.00"); List billCodes = dao.selectBillCodes(); billCodes.forEach(itm -> map.put(itm, "0.00")); return map; } public Date getBegntime(String patNo, int times, int ledgerSn, String table) { return ledgerSn > 1 ? dao.selectLastLedgerAccountDate(patNo, times, ledgerSn) : dao.selectAdmissDate(patNo, times, table); } private Date getEndtime(Boolean midsetl, String patNo, Integer times, Date zjdzDate) { if (midsetl) { return zjdzDate; } Date disdate = dao.selectActOrderDisDate(patNo, times); if (null == disdate) { disdate = dao.selectActOrderDisDate2(patNo, times); } return disdate; } private int updateCostStatusToSettled(MedinsSettleFee settle, boolean medins) { if (dao.updateZyDetailCharge(settle.getInpatientNo(), settle.getAdmissTimes(), settle.getLedgerSn()) < 1) { return -1; } if (!settle.getMidSetl()) { settle.setZjdzDatetime(new Date()); } if (medins) { int hasInfant = dao.hasInfant(settle.getInpatientNo(), settle.getAdmissTimes()); if (hasInfant == 0) { return dao.updateCostStatusWithoutInfant(settle); } return dao.updateCostStatusWithInfant(settle); } return dao.updateZifeiCostStatus(settle); } private int setHisStatusOut(MedinsSettleFee settle) { final Date disDate; String patNo = settle.getInpatientNo(); int times = settle.getAdmissTimes(); if ("zy_actpatient".equals(settle.getTable())) { disDate = dao.selectActOrderDisDate(patNo, times); } else { disDate = dao.selectActOrderDisDate2(patNo, times); } if (dao.updateZyActpatient(patNo, times, disDate, settle.getStaffId(), settle.getTable()) < 1) { return -1; } if ("zy_actpatient".equals(settle.getTable())) { dao.deleteZyInactpatient(patNo, times); if (dao.insertZyInactpatient(patNo, times) < 1) { return -2; } } final String patNo1 = patNo + "$1"; final String patNo6 = patNo + "$6"; dao.updateZyActpatientAgain(patNo1, patNo6, times, disDate, settle.getTable()); if ("zy_actpatient".equals(settle.getTable())) { dao.insertZyInactpatientAgain(patNo1, patNo6, times); } if (dao.updateZyAdt(patNo, times, settle.getWardCode(), settle.getDeptCode(), settle.getBedNo(), disDate) < 1) { return -3; } dao.updateZyBedMi(patNo, times); dao.deleteZyActpatient(patNo); dao.deleteZyActpatientAgain(patNo1, patNo6, times); dao.deleteZjdzSettleDeposit(patNo, times); return insertNewZyWorkLog(settle); } private int insertNewZyWorkLog(MedinsSettleFee param) { final String userName = dao.getOperateName(param.getStaffId()); String logType = param.getMidSetl() ? "zjdz" : "cyjs"; return dao.insertNewZyWorkLog(param.getInpatientNo(), param.getAdmissTimes(), param.getLedgerSn(), param.getWardCode(), logType, param.getDeptCode(), param.getStaffId(), userName); } private int hisMiddleSettle(MedinsSettleFee param) { String patNo = param.getInpatientNo(); int times = param.getAdmissTimes(); int currentLedgerSn = dao.getLedgerSn(patNo, times); int newLedgerSn = currentLedgerSn + 1; dao.updateTimesBilledByIncreaseOne(patNo, times, param.getTable()); dao.insertNewLedgerFile(patNo, times, newLedgerSn); dao.updateFeesLedgerSn(patNo, times, newLedgerSn, currentLedgerSn, param.getZjdzDatetime()); dao.updateZyLedgerFileTotalCharge(patNo, times, currentLedgerSn); dao.updateZyLedgerFileTotalCharge(patNo, times, newLedgerSn); DepositFile depositFile = dao.selectLatestDepositFile(patNo, times); if (null == depositFile) { depositFile = new DepositFile(patNo, times, newLedgerSn); } depositFile.initZjdzSettleDeposit(dao.selectLastLedgerSettle(patNo, times, currentLedgerSn)); dao.insertNewDeposit(depositFile); dao.clearMedinsInfo(patNo, times, DateUtil.addOneSecond(param.getZjdzDatetime())); param.setLedgerSn(currentLedgerSn); return insertNewZyWorkLog(param); } private void updateHicNo(String zyh) { String hicNoNew = dao.getHicNoNew(zyh); if (null != hicNoNew) { if (hicNoNew.length() > 16) { hicNoNew = hicNoNew.substring(0, 16); } dao.updateCpy(zyh, hicNoNew); if (hicNoNew.length() > 10) { hicNoNew = hicNoNew.substring(0, 10); } dao.updateHic(zyh, hicNoNew); } } }