package thyyxxk.webserver.service.medicalinsurance; import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 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 thyyxxk.webserver.config.exception.BizException; import thyyxxk.webserver.config.exception.ExceptionEnum; import thyyxxk.webserver.constants.sidicts.*; import thyyxxk.webserver.constants.YesOrNo; import thyyxxk.webserver.dao.his.inpatient.PatientDao; import thyyxxk.webserver.dao.his.medicalinsurance.*; import thyyxxk.webserver.entity.ResultVo; import thyyxxk.webserver.entity.inpatient.patient.NotUploadedFee; import thyyxxk.webserver.entity.medicalinsurance.log.SiLog; import thyyxxk.webserver.entity.medicalinsurance.inpatient.*; import thyyxxk.webserver.entity.medicalinsurance.manage.InsSetlDetlChkRslt; import thyyxxk.webserver.entity.medicalinsurance.manage.InstStlLdgChk; import thyyxxk.webserver.entity.medicalinsurance.query.SiPatInfo; import thyyxxk.webserver.entity.medicalinsurance.setlinfo.SiSetldetail; import thyyxxk.webserver.entity.medicalinsurance.setlinfo.SiSetlinfo; import thyyxxk.webserver.entity.inpatient.dismiss.MedinsSettleFee; import thyyxxk.webserver.entity.inpatient.patient.Overview; import thyyxxk.webserver.service.externalhttp.SiZySrvc; import thyyxxk.webserver.service.inpatient.DismissService; import thyyxxk.webserver.utils.*; import java.math.BigDecimal; import java.util.*; /** * @description: 住院医保交易 * @author: DingJie * @create: 2021-05-14 16:28:16 **/ @Slf4j @Service public class SiZyService { private static final String RESULT_CODE = "infcode"; private static final String ERROR_MESSAGE = "err_msg"; private static final String OUTPUT = "output"; private final SiZyDao dao; private final PatientDao patientDao; private final SiQueryService queryService; private final SiQueryDao queryDao; private final SiSetlinfoDao setlinfodao; private final SiSetldetailDao setldetldao; private final SiChargeTempDao chrgtmpdao; private final SiLogDao logDao; private final ExecService exec; private final DismissService dismissService; private final SiZySrvc zySrvc; private final SiManageService manageService; @Value("${si-zy-fee-url}") private String siZyFeeUrl; @Autowired public SiZyService(SiZyDao dao, PatientDao patientDao, SiQueryService queryService, SiQueryDao queryDao, SiSetlinfoDao setlinfoDao, SiSetldetailDao setldetldao, SiChargeTempDao chrgtmpdao, SiLogDao logDao, ExecService exec, DismissService dismissService, SiZySrvc zySrvc, SiManageService manageService) { this.dao = dao; this.patientDao = patientDao; this.queryService = queryService; this.queryDao = queryDao; this.setlinfodao = setlinfoDao; this.setldetldao = setldetldao; this.chrgtmpdao = chrgtmpdao; this.logDao = logDao; this.exec = exec; this.dismissService = dismissService; this.zySrvc = zySrvc; this.manageService = manageService; } public String admissRegister(ZyPatientInfo p, ZyOrJzYbData ybData) { AdmMdtrtinfo admMdtrtinfo = ybData.getAdmMdtrtinfo(p); List admDiseinfos = ybData.getAdmDiseinfo(p.getInpatientNo(), p.getAdmissTimes()); admDiseinfos.forEach(item -> { item.setDiseDorNo(admMdtrtinfo.getAtddrNo()); item.setDiseDorName(admMdtrtinfo.getChfpdrName()); }); ReadCardBizType readCardBizType = ReadCardBizType.get(p.getReadCardBizType()); if (readCardBizType != ReadCardBizType.ADMISSION && !p.getInsuplcAdmdvs().startsWith("43")) { throw new BizException(ExceptionEnum.LOGICAL_ERROR, "省外异地的患者请读社保卡登记!"); } if (readCardBizType == ReadCardBizType.ADMISSION) { MdtrtCertType mdtrtCertType = MdtrtCertType.getByLabel(p.getMdtrtCertType()); admMdtrtinfo.setMdtrtCertType(mdtrtCertType.getCode()); if (mdtrtCertType.getCode().equals(MdtrtCertType.SOCIAL_SECURITY_CARD.getCode())) { String[] out = p.getReadCardResult().split("\\|"); if (!p.getName().trim().equals(out[4].trim())) { throw new BizException(ExceptionEnum.LOGICAL_ERROR, "社保卡姓名与HIS姓名不一致,请确认是否人证相符。"); } admMdtrtinfo.setMdtrtCertNo(out[2]); admMdtrtinfo.setCardSn(out[3]); } else if (mdtrtCertType.getCode().equals(MdtrtCertType.MEDICAL_INSURANCE_ELECTRONIC_VOUCHER.getCode())) { JSONObject qrinfo = JSONObject.parseObject(p.getReadCardResult()); if (!p.getName().trim().equals(qrinfo.getString("userName").trim())) { throw new BizException(ExceptionEnum.LOGICAL_ERROR, "电子医保凭证姓名与HIS姓名不一致,请确认是否人证相符。"); } if (!p.getSocialNo().trim().equals(qrinfo.getString("idNo").trim())) { throw new BizException(ExceptionEnum.LOGICAL_ERROR, "电子医保凭证身份证与HIS身份证不一致,请确认是否人证相符。"); } admMdtrtinfo.setMdtrtCertNo(qrinfo.getString("ecToken")); } } if (StringUtil.isBlank(admMdtrtinfo.getDiseCodg())) { admMdtrtinfo.setDiseCodg(admDiseinfos.get(0).getDiagCode()); admMdtrtinfo.setDiseName(admDiseinfos.get(0).getDiagName()); } admMdtrtinfo.setInsutype(p.getInsutype()); admMdtrtinfo.setAdmDiagDscr(admDiseinfos.get(0).getDiagName()); admMdtrtinfo.setDscgMaindiagCode(admDiseinfos.get(0).getDiagCode()); admMdtrtinfo.setDscgMaindiagName(admDiseinfos.get(0).getDiagName()); admMdtrtinfo.setMatnType(p.getMatnType()); admMdtrtinfo.setLatechbFlag(p.getLatechbFlag()); admMdtrtinfo.setPretFlag(p.getPretFlag()); JSONObject input = exec.makeTradeHeaderWithInsureArea(SiFunction.ADMISSION_REGISTRATION, p.getInsuplcAdmdvs()); String ref = JSONObject.toJSONStringWithDateFormat(admMdtrtinfo, "yyyy-MM-dd HH:mm:ss"); input.getJSONObject("input").put("mdtrtinfo", JSONObject.parseObject(ref)); String diseRef = JSONArray.toJSONStringWithDateFormat(admDiseinfos, "yyyy-MM-dd HH:mm:ss"); input.getJSONObject("input").put("diseinfo", JSONArray.parse(diseRef)); JSONObject result = exec.executeTrade(input, SiFunction.ADMISSION_REGISTRATION); log.info("【操作员:{}】,医保入院登记:\n参数:{},\n结果:{}", TokenUtil.getInstance().getTokenUserId(), input, result); if (null == result) { throw new BizException(ExceptionEnum.NETWORK_ERROR, "网络异常"); } Integer infcode = result.getInteger(RESULT_CODE); if (null == infcode) { throw new BizException(ExceptionEnum.LOGICAL_ERROR, "医保中心报错:" + result.getString("message")); } logDao.insert(new SiLog(input, result, p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn(), infcode, admMdtrtinfo.getPsnNo())); if (result.getIntValue(RESULT_CODE) == 0) { JSONObject output = result.getJSONObject(OUTPUT); String mdtrtId = output.getJSONObject("result").getString("mdtrt_id"); p.setMdtrtId(mdtrtId); p.setAdmRegMsgid(input.getString("msgid")); dao.afterAdmissRegister(p); String restype = dao.selectResponceType(admMdtrtinfo.getMedType()); dao.updateResponceType(restype, admMdtrtinfo.getMedType(), p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn()); return "入院登记成功,就诊号为:" + mdtrtId; } throw new BizException(ExceptionEnum.LOGICAL_ERROR, result.getString(ERROR_MESSAGE)); } public ResultVo modifyAdmissionInfo(ZyPatientInfo p) { SiPatInfo siPatInfo = queryDao.selectSiPatInfo(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn()); if (null == siPatInfo || StringUtil.isBlank(siPatInfo.getMdtrtId())) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "患者医保不在院!"); } List admDiseinfos = dao.selectAdmDiags(p.getInpatientNo(), p.getAdmissTimes()); if (null == admDiseinfos || admDiseinfos.isEmpty()) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "请填写医保入院诊断!"); } admDiseinfos.forEach(item -> item.setMdtrtId(siPatInfo.getMdtrtId())); JSONObject input = exec.makeTradeHeaderWithInsureArea(SiFunction.MODIFY_ADMISSION_INFO, siPatInfo.getInsuplcAdmdvs()); JSONObject adminfo = new JSONObject(); adminfo.put("mdtrt_id", siPatInfo.getMdtrtId()); adminfo.put("psn_no", siPatInfo.getPsnNo()); adminfo.put("begntime", DateUtil.formatDatetime(p.getYbRegisterDate())); adminfo.put("mdtrt_cert_type", MdtrtCertType.RESIDENT_IDENTITY_CARD.getCode()); adminfo.put("med_type", siPatInfo.getMedType()); adminfo.put("ipt_otp_no", p.getInpatientNo()); adminfo.put("atddr_no", p.getReferPhysician()); adminfo.put("chfpdr_name", p.getReferPhysicianName()); adminfo.put("adm_diag_dscr", admDiseinfos.get(0).getDiagCode()); adminfo.put("adm_dept_codg", p.getSmallDept()); adminfo.put("adm_dept_name", p.getSmallDeptName()); adminfo.put("adm_bed", p.getBedNo()); adminfo.put("dscg_maindiag_code", admDiseinfos.get(0).getDiagCode()); adminfo.put("dscg_maindiag_name", admDiseinfos.get(0).getDiagName()); input.getJSONObject("input").put("adminfo", adminfo); String diseRef = JSONArray.toJSONStringWithDateFormat(admDiseinfos, "yyyy-MM-dd HH:mm:ss"); input.getJSONObject("input").put("diseinfo", JSONArray.parse(diseRef)); JSONObject result = exec.executeTrade(input, SiFunction.MODIFY_ADMISSION_INFO); log.info("【操作员:{}】,入院信息变更:\n参数:{},\n结果:{}", TokenUtil.getInstance().getTokenUserId(), input, result); Integer infcode = result.getInteger(RESULT_CODE); logDao.insert(new SiLog(input, result, p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn(), infcode, siPatInfo.getPsnNo())); return SiUtil.makeReturnWithoutOutput(result, "变更住院信息成功。"); } public String revokeAdmission(ZyPatientInfo p) { SiPatInfo siPatInfo = queryDao.selectSiPatInfo(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn()); if (null == siPatInfo || StringUtil.isBlank(siPatInfo.getMdtrtId())) { throw new BizException(ExceptionEnum.LOGICAL_ERROR, "此患者没有有效的医保在院信息!"); } revokeUploadFees(p); JSONObject input = exec.makeTradeHeaderWithInsureArea(SiFunction.REVOKE_ADMISSION, siPatInfo.getInsuplcAdmdvs()); JSONObject data = new JSONObject(); data.put("mdtrt_id", siPatInfo.getMdtrtId()); data.put("psn_no", siPatInfo.getPsnNo()); input.getJSONObject("input").put("data", data); JSONObject result = exec.executeTrade(input, SiFunction.REVOKE_ADMISSION); log.info("【操作员:{}】,取消入院登记:\n参数:{},\n结果:{}", TokenUtil.getInstance().getTokenUserId(), input, result); if (null == result) { throw new BizException(ExceptionEnum.NETWORK_ERROR); } Integer infcode = result.getInteger(RESULT_CODE); logDao.insert(new SiLog(input, result, p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn(), infcode, siPatInfo.getPsnNo())); if (null == infcode) { throw new BizException(ExceptionEnum.LOGICAL_ERROR, "医保中心报错:" + result.getString("message")); } if (infcode == 0) { queryDao.clearMdtrtIdForZy(siPatInfo.getPatNo(), siPatInfo.getTimes(), siPatInfo.getLedgerSn(), null); dao.updateResponceType("01", null, p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn()); return "取消入院登记成功。"; } throw new BizException(ExceptionEnum.LOGICAL_ERROR, result.getString(ERROR_MESSAGE)); } public ResultVo uploadFeeDetail(Overview o) { o.setStaffId(TokenUtil.getInstance().getTokenUserId()); return zySrvc.uploadFeeDetail(siZyFeeUrl, o); } public ResultVo multipleUpload(List overviews) { for (Overview o : overviews) { if (o.getStatus() == 0) { String message = String.format("【%s床,%s,%s】未进行医保登记,无法进行费用上传。", o.getBedNo(), o.getInpatientNo(), o.getName()); return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, message); } if (invalidMultipleUploadPatient(o.getMedType())) { String message = String.format("【%s床,%s,%s】是工伤患者,不支持批量上传。", o.getBedNo(), o.getInpatientNo(), o.getName()); return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, message); } o.setStaffId(TokenUtil.getInstance().getTokenUserId()); } return zySrvc.uploadMultiplePatientFees(siZyFeeUrl, overviews); } private boolean invalidMultipleUploadPatient(String medtype) { MedType medType = MedType.get(medtype); return null == medType || medType == MedType.INJURY_HOSPITALIZATION || medType == MedType.SELF_PAY || medType == MedType.GCP_EXPERIMENT || medType == MedType.INJURY_TBD; } public String hospitalizationPreSettlement(ZyPatientInfo p, ZyOrJzYbData ybData) { PreSetlmt preSetlmt = ybData.getPreSetlmt(p); preSetlmt.setMdtrtCertType(MdtrtCertType.RESIDENT_IDENTITY_CARD.getCode()); preSetlmt.setPsnSetlway(p.getDbg() ? PsnSetlWay.SETTLE_BY_QUOTA.getCode() : PsnSetlWay.SETTLE_BY_ITEMS.getCode()); preSetlmt.setAcctUsedFlag(YesOrNo.NO.getCodeStr()); preSetlmt.setMidSetlFlag(YesOrNo.NO.getCodeStr()); preSetlmt.setMdtrtareaAdmvs(SiUtil.getInstitutionArea(preSetlmt.getInsuplcAdmdvs())); preSetlmt.setDscgTime(dao.selectActOrderDisDate(p.getInpatientNo(), p.getAdmissTimes())); JSONObject input = exec.makeTradeHeaderWithInsureArea(SiFunction.HOSPITALIZATION_PRE_SETTLEMENT, preSetlmt.getInsuplcAdmdvs()); String ref = JSONObject.toJSONStringWithDateFormat(preSetlmt, "yyyy-MM-dd"); input.getJSONObject("input").put("data", JSONObject.parseObject(ref)); JSONObject result = exec.executeTrade(input, SiFunction.HOSPITALIZATION_PRE_SETTLEMENT); log.info("预结算:\n参数:{},\n结果:{}", input, result); if (null == result) { throw new BizException(ExceptionEnum.NETWORK_ERROR); } Integer infcode = result.getInteger(RESULT_CODE); logDao.insert(new SiLog(input, result, p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn(), infcode, preSetlmt.getPsnNo())); if (null == infcode) { throw new BizException(ExceptionEnum.LOGICAL_ERROR, "医保中心报错:" + result.getString("message")); } if (infcode == 0) { JSONObject setlinfo = result.getJSONObject(OUTPUT).getJSONObject("setlinfo"); String fundPay = setlinfo.getString("fund_pay_sumamt"); dao.updateFundPay(fundPay, p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn()); patientDao.recountDeposit(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn()); patientDao.updateBalance(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn()); String balance = patientDao.selectLedgerBalance(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn()); if (StringUtil.isBlank(balance)) { balance = "0"; } patientDao.updateZyActPatientBalance(p.getInpatientNo(), balance); return "患者【" + p.getName() + "】院内总费用与医保中心总费用一致,医保报销金额为:¥ " + fundPay + "。"; } throw new BizException(ExceptionEnum.LOGICAL_ERROR, result.getString(ERROR_MESSAGE)); } public String revokeUploadFees(ZyPatientInfo p) { SiPatInfo siPatInfo = queryDao.selectSiPatInfo(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn()); if (null == siPatInfo || StringUtil.isBlank(siPatInfo.getMdtrtId())) { throw new BizException(ExceptionEnum.LOGICAL_ERROR, "此患者没有有效的医保在院信息!"); } JSONObject input = exec.makeTradeHeaderWithInsureArea(SiFunction.REVOKE_HOSPITALIZATION_FEE_DETAILS, siPatInfo.getInsuplcAdmdvs()); JSONArray data = new JSONArray(); if (null == p.getDetailSns() || p.getDetailSns().isEmpty()) { JSONObject item = new JSONObject(); item.put("feedetl_sn", "0000"); item.put("mdtrt_id", siPatInfo.getMdtrtId()); item.put("psn_no", siPatInfo.getPsnNo()); data.add(item); } else { p.getDetailSns().forEach(detailSn -> { JSONObject item = new JSONObject(); item.put("feedetl_sn", detailSn); item.put("mdtrt_id", siPatInfo.getMdtrtId()); item.put("psn_no", siPatInfo.getPsnNo()); data.add(item); }); } input.getJSONObject("input").put("data", data); JSONObject result = exec.executeTrade(input, SiFunction.REVOKE_HOSPITALIZATION_FEE_DETAILS); log.info("【操作员:{}】撤销已上传的费用:\n参数:{},\n结果:{}", TokenUtil.getInstance().getTokenUserId(), input, result); if (null == result) { throw new BizException(ExceptionEnum.NETWORK_ERROR); } Integer infcode = result.getInteger(RESULT_CODE); logDao.insert(new SiLog(input, result, p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn(), infcode, siPatInfo.getPsnNo())); if (null == infcode) { throw new BizException(ExceptionEnum.LOGICAL_ERROR, "医保中心报错:" + result.getString("message")); } if (infcode == 0) { QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("pat_no", p.getInpatientNo()); wrapper.eq("times", p.getAdmissTimes()); wrapper.eq("ledger_sn", p.getLedgerSn()); if (null == p.getDetailSns() || p.getDetailSns().isEmpty()) { dao.revokeAllUploadFee(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn()); dao.resetFundpayAmt(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn()); chrgtmpdao.delete(wrapper); } else { wrapper.in("feedetl_sn", p.getDetailSns()); chrgtmpdao.delete(wrapper); dao.revokePartUploadFee(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn(), p.getDetailSns()); } return "撤销费用上传成功。"; } throw new BizException(ExceptionEnum.LOGICAL_ERROR, result.getString(ERROR_MESSAGE)); } public ResultVo pairNegativeFee(NotUploadedFee fee) { if (null == fee.getOriDetailSn()) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "请先处理违规退费。"); } SiPatInfo siPatInfo = queryDao.selectSiPatInfo(fee.getPatNo(), fee.getTimes(), fee.getLedgerSn()); JSONObject input = exec.makeTradeHeaderWithInsureArea(SiFunction.REVOKE_HOSPITALIZATION_FEE_DETAILS, siPatInfo.getInsuplcAdmdvs()); JSONArray data = new JSONArray(); JSONObject item = new JSONObject(); item.put("feedetl_sn", fee.getOriDetailSn()); item.put("mdtrt_id", siPatInfo.getMdtrtId()); item.put("psn_no", siPatInfo.getPsnNo()); data.add(item); input.getJSONObject("input").put("data", data); JSONObject result = exec.executeTrade(input, SiFunction.REVOKE_HOSPITALIZATION_FEE_DETAILS); log.info("【操作员:{}】退费处理:\n参数:{},\n结果:{}", TokenUtil.getInstance().getTokenUserId(), input, result); if (null == result) { return ResultVoUtil.fail(ExceptionEnum.NETWORK_ERROR); } Integer infcode = result.getInteger(RESULT_CODE); logDao.insert(new SiLog(input, result, fee.getPatNo(), fee.getTimes(), fee.getLedgerSn(), infcode, siPatInfo.getPsnNo())); if (null == infcode) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "医保中心报错:" + result.getString("message")); } if (infcode == 0) { QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("pat_no", fee.getPatNo()); wrapper.eq("times", fee.getTimes()); wrapper.eq("ledger_sn", fee.getLedgerSn()); wrapper.eq("feedetl_sn", fee.getOriDetailSn()); dao.updateTransFlag(fee.getPatNo(), fee.getTimes(), fee.getDetailSn(), fee.getOriDetailSn()); chrgtmpdao.delete(wrapper); } return ResultVoUtil.success("退费处理成功。"); } public ResultVo revokeSingleCharge(String patNo, int times, int ledgerSn, int detailSn) { SiPatInfo siPatInfo = queryDao.selectSiPatInfo(patNo, times, ledgerSn); JSONObject input = exec.makeTradeHeaderWithInsureArea(SiFunction.REVOKE_HOSPITALIZATION_FEE_DETAILS, siPatInfo.getInsuplcAdmdvs()); JSONArray data = new JSONArray(); JSONObject item = new JSONObject(); item.put("feedetl_sn", detailSn); item.put("mdtrt_id", siPatInfo.getMdtrtId()); item.put("psn_no", siPatInfo.getPsnNo()); data.add(item); input.getJSONObject("input").put("data", data); JSONObject result = exec.executeTrade(input, SiFunction.REVOKE_HOSPITALIZATION_FEE_DETAILS); log.info("【操作员:{}】退费处理:\n参数:{},\n结果:{}", TokenUtil.getInstance().getTokenUserId(), input, result); if (null == result) { return ResultVoUtil.fail(ExceptionEnum.NETWORK_ERROR); } Integer infcode = result.getInteger(RESULT_CODE); logDao.insert(new SiLog(input, result, patNo, times, ledgerSn, infcode, siPatInfo.getPsnNo())); if (null == infcode) { return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "医保中心报错:" + result.getString("message")); } if (infcode == 0) { QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("pat_no", patNo); wrapper.eq("times", times); wrapper.eq("ledger_sn", ledgerSn); wrapper.eq("feedetl_sn", detailSn); chrgtmpdao.delete(wrapper); } return ResultVoUtil.success("处理成功。"); } public String dischargeProcessing(ZyPatientInfo p, ZyOrJzYbData ybData) { if (null == p.getLedgerSn()) { p.setLedgerSn(dao.selectMaxLedgerSn(p.getInpatientNo(), p.getAdmissTimes())); } Dscginfo dscginfo = ybData.getDscginfo(p); List setlDises = ybData.getSetlDiseinfo(p); if (null == p.getStaffId()) { p.setStaffId(TokenUtil.getInstance().getTokenUserId()); } if (StringUtil.isBlank(p.getAcctUsedFlag())) { p.setAcctUsedFlag(YesOrNo.NO.getCodeStr()); } dscginfo.setDiseCodg(setlDises.get(0).getDiagCode()); dscginfo.setDiseName(setlDises.get(0).getDiagName()); dscginfo.setDscgWay(DscgWay.ORDER_TO_LEAVE_HOSPITAL.getCode()); String ref = JSONObject.toJSONStringWithDateFormat(dscginfo, "yyyy-MM-dd HH:mm:ss"); JSONObject input = exec.makeTradeHeaderWithInsureArea(SiFunction.DISCHARGE_PROCESSING, dao.selectAdmdvs(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn())); input.getJSONObject("input").put("dscginfo", JSONObject.parseObject(ref)); String diseRef = JSONArray.toJSONStringWithDateFormat(setlDises, "yyyy-MM-dd HH:mm:ss"); input.getJSONObject("input").put("diseinfo", JSONArray.parse(diseRef)); JSONObject result = exec.executeTrade(input, SiFunction.DISCHARGE_PROCESSING); log.info("【操作员:{}】,医保出院办理:\n参数:{},\n结果:{}", p.getStaffId(), input, result); if (null == result) { throw new BizException(ExceptionEnum.NETWORK_ERROR); } Integer infcode = result.getInteger(RESULT_CODE); logDao.insert(new SiLog(input, result, p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn(), infcode, dscginfo.getPsnNo())); if (null == infcode) { throw new BizException(ExceptionEnum.LOGICAL_ERROR, "医保中心报错:" + result.getString("message")); } if (infcode == 0) { if (p.getStopHere()) { return "出院办理成功。"; } p.setDismissDate(dscginfo.getEndtime()); return inpatientSettlement(p, ybData); } String errMsg = result.getString(ERROR_MESSAGE); if (null != errMsg && errMsg.contains("该人员已经是出院状态")) { p.setDismissDate(dscginfo.getEndtime()); return inpatientSettlement(p, ybData); } throw new BizException(ExceptionEnum.LOGICAL_ERROR, errMsg); } public String revokeDischarge(ZyPatientInfo p) { SiPatInfo siPatInfo = queryDao.selectSiPatInfo(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn()); if (null == siPatInfo || StringUtil.isBlank(siPatInfo.getMdtrtId())) { throw new BizException("此患者没有在院的医保业务。"); } p.setMdtrtId(siPatInfo.getMdtrtId()); JSONObject input = exec.makeTradeHeaderWithInsureArea(SiFunction.REVOKE_DISCHARGE, siPatInfo.getInsuplcAdmdvs()); JSONObject data = new JSONObject(); data.put("mdtrt_id", siPatInfo.getMdtrtId()); data.put("psn_no", siPatInfo.getPsnNo()); input.getJSONObject("input").put("data", data); JSONObject result = exec.executeTrade(input, SiFunction.REVOKE_DISCHARGE); log.info("【操作员:{}】取消医保出院办理:\n参数:{},\n结果:{}", TokenUtil.getInstance().getTokenUserId(), input, result); if (null == result) { throw new BizException(ExceptionEnum.NETWORK_ERROR); } Integer infcode = result.getInteger(RESULT_CODE); logDao.insert(new SiLog(input, result, p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn(), infcode, siPatInfo.getPsnNo())); if (null == infcode) { throw new BizException(ExceptionEnum.LOGICAL_ERROR, "医保中心报错:" + result.getString("message")); } if (infcode == 0) { dao.deleteSetlInfo(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn()); dao.deleteSetlDetail(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn()); transbackTables(p); return "取消医保出院办理成功。"; } throw new BizException(ExceptionEnum.LOGICAL_ERROR, result.getString(ERROR_MESSAGE)); } private void fillBeginTimeAndEndTime(ZyPatientInfo p) { if (null == p.getYbRegisterDate()) { Date beginTime = dismissService.getBegntime(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn(), "zy_actpatient"); p.setYbRegisterDate(beginTime); } if (null == p.getDismissDate()) { Date disdate = dao.selectDisdate(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn()); if (null == disdate) { throw new BizException(ExceptionEnum.LOGICAL_ERROR, "请先提交出院申请!"); } p.setDismissDate(disdate); } } private String inpatientSettlement(ZyPatientInfo p, ZyOrJzYbData ybData) { fillBeginTimeAndEndTime(p); PreSetlmt preSetlmt = ybData.getSetlmt(p); ReadCardBizType readCardBizType = ReadCardBizType.get(p.getReadCardBizType()); if (readCardBizType == ReadCardBizType.SETTLEMENT) { MdtrtCertType mdtrtCertType = MdtrtCertType.getByLabel(p.getMdtrtCertType()); preSetlmt.setMdtrtCertType(mdtrtCertType.getCode()); if (mdtrtCertType.getCode().equals(MdtrtCertType.SOCIAL_SECURITY_CARD.getCode())) { String[] out = p.getReadCardResult().split("\\|"); if (!p.getName().trim().equals(out[4].trim())) { revokeDischarge(p); throw new BizException(ExceptionEnum.LOGICAL_ERROR, "社保卡姓名与HIS姓名不一致,请确认是否人证相符。"); } preSetlmt.setMdtrtCertNo(out[2]); preSetlmt.setCardSn(out[3]); } else if (mdtrtCertType.getCode().equals(MdtrtCertType.MEDICAL_INSURANCE_ELECTRONIC_VOUCHER.getCode())) { JSONObject qrinfo = JSONObject.parseObject(p.getReadCardResult()); if (!p.getName().trim().equals(qrinfo.getString("userName").trim())) { revokeDischarge(p); throw new BizException(ExceptionEnum.LOGICAL_ERROR, "电子医保凭证姓名与HIS姓名不一致,请确认是否人证相符。"); } if (!p.getSocialNo().trim().equals(qrinfo.getString("idNo").trim())) { revokeDischarge(p); throw new BizException(ExceptionEnum.LOGICAL_ERROR, "电子医保凭证身份证与HIS身份证不一致,请确认是否人证相符。"); } preSetlmt.setMdtrtCertNo(qrinfo.getString("ecToken")); } } preSetlmt.setPsnSetlway(p.getDbg() ? PsnSetlWay.SETTLE_BY_QUOTA.getCode() : PsnSetlWay.SETTLE_BY_ITEMS.getCode()); preSetlmt.setAcctUsedFlag(p.getAcctUsedFlag()); preSetlmt.setMidSetlFlag(YesOrNo.NO.getCodeStr()); preSetlmt.setInvono(SnowFlakeId.instance().nextId()); JSONObject input = exec.makeTradeHeaderWithInsureArea(SiFunction.HOSPITALIZATION_SETTLEMENT, preSetlmt.getInsuplcAdmdvs()); String ref = JSONObject.toJSONString(preSetlmt); input.getJSONObject("input").put("data", JSONObject.parseObject(ref)); JSONObject result = exec.executeTrade(input, SiFunction.HOSPITALIZATION_SETTLEMENT); log.info("【操作员:{}】,医保出院结算:\n参数:{},\n结果:{}", p.getStaffId(), input, result); if (null == result) { revokeDischarge(p); throw new BizException(ExceptionEnum.NETWORK_ERROR); } Integer infcode = result.getInteger(RESULT_CODE); logDao.insert(new SiLog(input, result, p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn(), infcode, preSetlmt.getPsnNo())); if (null == infcode) { revokeDischarge(p); throw new BizException(ExceptionEnum.LOGICAL_ERROR, "医保中心报错:" + result.getString("message")); } if (infcode == 0) { p.setInsuplcAdmdvs(preSetlmt.getInsuplcAdmdvs()); return executeHisSettlement(result.getJSONObject(OUTPUT), p); } String message = result.getString(ERROR_MESSAGE); if (message.contains("服务提供者后端服务响应超时")) { return timeoutSettlement(p); } revokeDischarge(p); throw new BizException(ExceptionEnum.LOGICAL_ERROR, message); } public String timeoutSettlement(ZyPatientInfo p) { SiPatInfo siPatInfo = queryDao.selectSiPatInfo(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn()); if (null == siPatInfo) { throw new BizException(ExceptionEnum.LOGICAL_ERROR, "[t_si_pat_info]没有此患者的就诊信息。"); } fillBeginTimeAndEndTime(p); p.setInsuplcAdmdvs(siPatInfo.getInsuplcAdmdvs()); JSONObject output = queryService.execute5203(siPatInfo); return executeHisSettlement(output, p); } private String executeHisSettlement(JSONObject output, ZyPatientInfo p) { dao.deleteSetlDetail(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn()); JSONObject setlinfo = output.getJSONObject("setlinfo"); SiSetlinfo setlinfoEntity = JSONObject.parseObject(setlinfo.toJSONString(), SiSetlinfo.class); setlinfoEntity.setPatNo(p.getInpatientNo()); setlinfoEntity.setTimes(p.getAdmissTimes()); setlinfoEntity.setLedgerSn(p.getLedgerSn()); setlinfoEntity.setStaffId(TokenUtil.getInstance().getTokenUserId()); setlinfoEntity.setRevoked(YesOrNo.NO.getCode()); setlinfoEntity.setSetlType(ClrType.INPATIENT.getCode()); setlinfoEntity.setInsuplcAdmdvs(p.getInsuplcAdmdvs()); setlinfoEntity.setBegntime(p.getYbRegisterDate()); setlinfoEntity.setEndtime(p.getDismissDate()); setlinfoEntity.setHiPaymtd(CommonUtil.calcHiPaymtd(setlinfoEntity.getInsuplcAdmdvs(),setlinfoEntity.getMedType(),setlinfoEntity.getInsutype(),setlinfoEntity.getSetlTime())); setlinfoEntity.setMedinsType(MedInsTypeUtil.getMedInsType(setlinfoEntity)); if (null == setlinfoEntity.getPsnPartAmt()) { Double psnPay = setlinfo.getDouble("psn_pay"); setlinfoEntity.setPsnPartAmt(psnPay); } if (null == setlinfoEntity.getPsnCashPay()) { Double cashPay = setlinfo.getDouble("cash_payamt"); setlinfoEntity.setPsnCashPay(cashPay); } JSONArray setldetail = output.getJSONArray("setldetail"); BigDecimal hospitalPart = BigDecimal.ZERO; int setlCount = setlinfodao.getSetlCount(setlinfoEntity.getSetlId()); for (int i = 0; i < setldetail.size(); i++) { SiSetldetail setldetailEntity = JSONObject.parseObject(setldetail.getJSONObject(i).toJSONString(), SiSetldetail.class); setldetailEntity.setSetlId(setlinfoEntity.getSetlId()); setldetailEntity.setSortNo(i + 1); setldetailEntity.setPatNo(p.getInpatientNo()); setldetailEntity.setTimes(p.getAdmissTimes()); setldetailEntity.setLedgerSn(p.getLedgerSn()); if (setldetailEntity.getFundPayType().equals("999996") || setldetailEntity.getSetlProcInfo().equals("999996")) { hospitalPart = hospitalPart.add(setldetailEntity.getFundPayamt()); } if (setlCount == 0) { setldetldao.insert(setldetailEntity); } } setlinfoEntity.setHospPartAmt(hospitalPart.doubleValue()); if (setlCount == 0) { setlinfodao.insert(setlinfoEntity); } setlinfodao.updateSiZyInfoSetlId(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn(), setlinfoEntity.getSetlId(), setlinfoEntity.getMedinsSetlId(), setlinfoEntity.getMedinsSetlId()); setlinfodao.updateApplySettled(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn(), YesOrNo.YES.getCode()); // 跨省异地数据不参与对账,对总账时无需统计进去。 if (setlinfoEntity.getFundPaySumamt() > 0 && setlinfoEntity.getInsuplcAdmdvs().startsWith("43")) { InstStlLdgChk ldgChk = new InstStlLdgChk(); ldgChk.setInsutype(setlinfoEntity.getInsutype()); ldgChk.setClrType(setlinfoEntity.getClrType()); ldgChk.setSetlOptins(setlinfoEntity.getClrOptins()); ldgChk.setStmtBegndate(setlinfoEntity.getSetlTime()); ldgChk.setStmtEnddate(setlinfoEntity.getSetlTime()); ResultVo totalLedgerCheck = manageService.institutionSettlementLedgerCheck(ldgChk); if (totalLedgerCheck.getCode() != ExceptionEnum.SUCCESS.getCode()) { InstStlLdgChk detlChk = new InstStlLdgChk(); detlChk.setSetlOptins(ldgChk.getSetlOptins()); detlChk.setStmtBegndate(ldgChk.getStmtBegndate()); detlChk.setStmtEnddate(ldgChk.getStmtEnddate()); detlChk.setClrType(ldgChk.getClrType()); detlChk.setRefdSetlFlag(YesOrNo.NO.getCodeStr()); ResultVo> detailLedgerCheck = manageService.institutionSettlementDetailCheck(detlChk); if (detailLedgerCheck.getCode() != ExceptionEnum.SUCCESS.getCode()) { revokeSettlement(p); throw new BizException(ExceptionEnum.LOGICAL_ERROR, detailLedgerCheck.getMessage()); } for (InsSetlDetlChkRslt insSetlDetlChkRslt : detailLedgerCheck.getData()) { if (Objects.equals(insSetlDetlChkRslt.getSetlId(), setlinfoEntity.getSetlId())) { if (!Objects.equals(insSetlDetlChkRslt.getStmtRslt(), "0")) { revokeSettlement(p); throw new BizException(ExceptionEnum.LOGICAL_ERROR, insSetlDetlChkRslt.getMemo()); } break; } } } } queryService.saveCumInfo(setlinfoEntity); if (null != p.getMedType() && p.getMedType().equals(MedType.EMERGENCY_RESCUE.getCode())) { return StrUtil.format("出院结算成功。患者总费用:{}。其中基金支付:{};个账支付:{};现金支付:{}", setlinfoEntity.getMedfeeSumamt(), setlinfoEntity.getFundPaySumamt(), setlinfoEntity.getAcctPay(), setlinfoEntity.getPsnCashPay()); } MedinsSettleFee settleFee = new MedinsSettleFee(); if (p.getMidSetl()) { settleFee.setZjdzDatetime(p.getZjdzDatetime()); } settleFee.setMidSetl(p.getMidSetl()); settleFee.setStaffId(TokenUtil.getInstance().getTokenUserId()); settleFee.setInpatientNo(p.getInpatientNo()); settleFee.setAdmissTimes(p.getAdmissTimes()); settleFee.setBedNo(p.getBedNo()); settleFee.setWardCode(p.getAdmissWard()); settleFee.setDeptCode(p.getAdmissDept()); settleFee.setTotalCost(setlinfo.getString("medfee_sumamt")); settleFee.setTczf(setlinfo.getString("fund_pay_sumamt")); settleFee.setHospitalPay(setlinfo.getString("hosp_part_amt")); settleFee.setGrzhzf(setlinfo.getString("acct_pay")); settleFee.setDbzf(setlinfo.getString("hifmi_pay")); settleFee.setXjzf(setlinfo.getString("psn_cash_pay")); settleFee.setTable(p.getTable()); return dismissService.executeDischarging(settleFee); } public String revokeSettlement(ZyPatientInfo p) { if (null == p.getStaffId()) { p.setStaffId(TokenUtil.getInstance().getTokenUserId()); } if (null == p.getLedgerSn()) { p.setLedgerSn(dao.selectMaxLedgerSn(p.getInpatientNo(), p.getAdmissTimes())); } SiPatInfo siPatInfo = queryDao.selectSiPatInfo(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn()); if (null == siPatInfo || StringUtil.isBlank(siPatInfo.getSetlId())) { return revokeDischarge(p); } p.setMdtrtId(siPatInfo.getMdtrtId()); JSONObject input = exec.makeTradeHeaderWithInsureArea(SiFunction.REVOKE_HOSPITALIZATION_SETTLEMENT, siPatInfo.getInsuplcAdmdvs()); JSONObject data = new JSONObject(); data.put("mdtrt_id", siPatInfo.getMdtrtId()); data.put("setl_id", siPatInfo.getSetlId()); data.put("psn_no", siPatInfo.getPsnNo()); input.getJSONObject("input").put("data", data); JSONObject result = exec.executeTrade(input, SiFunction.REVOKE_HOSPITALIZATION_SETTLEMENT); log.info("【操作员:{}】取消医保结算:\n参数:{},\n结果:{}", p.getStaffId(), input, result); if (null == result) { throw new BizException(ExceptionEnum.NETWORK_ERROR); } Integer infcode = result.getInteger(RESULT_CODE); logDao.insert(new SiLog(input, result, p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn(), infcode, siPatInfo.getPsnNo())); if (null == infcode) { throw new BizException(ExceptionEnum.NETWORK_ERROR); } if (infcode != 0) { throw new BizException(ExceptionEnum.LOGICAL_ERROR, result.getString("err_msg")); } String rvkDischrgRslt = revokeDischarge(p); dao.updateRvkSetlMsgid(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn(), input.getString("msgid")); setlinfodao.updateApplySettled(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn(), YesOrNo.NO.getCode()); transbackTables(p); return rvkDischrgRslt; } private void transbackTables(ZyPatientInfo p) { dao.deleteSiSetlFeeDetl(p.getMdtrtId()); dao.deleteZyLedgerFileYb(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn()); dao.deleteZyReceipt(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn()); dao.updateSettleType(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn()); dao.updateChargeStatus(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn()); } }