SiZyService.java 55 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037
  1. package thyyxxk.webserver.service.medicalinsurance;
  2. import cn.hutool.core.util.StrUtil;
  3. import com.alibaba.fastjson.JSONArray;
  4. import com.alibaba.fastjson.JSONObject;
  5. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  6. import lombok.extern.slf4j.Slf4j;
  7. import org.springframework.beans.factory.annotation.Autowired;
  8. import org.springframework.beans.factory.annotation.Value;
  9. import org.springframework.stereotype.Service;
  10. import org.yaml.snakeyaml.util.UriEncoder;
  11. import thyyxxk.webserver.config.envionment.MedinsurConfig;
  12. import thyyxxk.webserver.config.exception.BizException;
  13. import thyyxxk.webserver.config.exception.ExceptionEnum;
  14. import thyyxxk.webserver.constants.sidicts.*;
  15. import thyyxxk.webserver.constants.YesOrNo;
  16. import thyyxxk.webserver.dao.his.inpatient.DoctorsAdviseDao;
  17. import thyyxxk.webserver.dao.his.inpatient.PatientDao;
  18. import thyyxxk.webserver.dao.his.medicalinsurance.*;
  19. import thyyxxk.webserver.entity.ResultVo;
  20. import thyyxxk.webserver.entity.inpatient.patient.NotUploadedFee;
  21. import thyyxxk.webserver.entity.medicalinsurance.log.SiLog;
  22. import thyyxxk.webserver.entity.medicalinsurance.inpatient.*;
  23. import thyyxxk.webserver.entity.medicalinsurance.query.SiPatInfo;
  24. import thyyxxk.webserver.entity.medicalinsurance.setlinfo.SiSetldetail;
  25. import thyyxxk.webserver.entity.medicalinsurance.setlinfo.SiSetlinfo;
  26. import thyyxxk.webserver.entity.inpatient.dismiss.MedinsSettleFee;
  27. import thyyxxk.webserver.entity.inpatient.patient.Overview;
  28. import thyyxxk.webserver.service.externalhttp.SiZySrvc;
  29. import thyyxxk.webserver.service.inpatient.DismissService;
  30. import thyyxxk.webserver.utils.*;
  31. import java.math.BigDecimal;
  32. import java.util.*;
  33. import java.util.ArrayList;
  34. /**
  35. * @description: 住院医保交易
  36. * @author: DingJie
  37. * @create: 2021-05-14 16:28:16
  38. **/
  39. @Slf4j
  40. @Service
  41. public class SiZyService {
  42. private static final String RESULT_CODE = "infcode";
  43. private static final String ERROR_MESSAGE = "err_msg";
  44. private static final String OUTPUT = "output";
  45. private final SiZyDao dao;
  46. private final DoctorsAdviseDao doctorsAdviseDao;
  47. private final PatientDao patientDao;
  48. private final SiQueryService queryService;
  49. private final SiQueryDao queryDao;
  50. private final SiSetlinfoDao setlinfodao;
  51. private final SiSetldetailDao setldetldao;
  52. private final SiChargeTempDao chrgtmpdao;
  53. private final SiLogDao logDao;
  54. private final ExecService exec;
  55. private final DismissService dismissService;
  56. private final SiZySrvc zySrvc;
  57. private final MedinsurConfig cfg;
  58. @Value("${si-zy-fee-url}")
  59. private String siZyFeeUrl;
  60. @Autowired
  61. public SiZyService(SiZyDao dao, PatientDao patientDao, SiQueryService queryService, SiQueryDao queryDao, SiSetlinfoDao setlinfoDao,
  62. SiSetldetailDao setldetldao, SiChargeTempDao chrgtmpdao, SiLogDao logDao, ExecService exec,
  63. DismissService dismissService, SiZySrvc zySrvc, MedinsurConfig cfg, DoctorsAdviseDao doctorsAdviseDao) {
  64. this.dao = dao;
  65. this.patientDao = patientDao;
  66. this.doctorsAdviseDao = doctorsAdviseDao;
  67. this.queryService = queryService;
  68. this.queryDao = queryDao;
  69. this.setlinfodao = setlinfoDao;
  70. this.setldetldao = setldetldao;
  71. this.chrgtmpdao = chrgtmpdao;
  72. this.logDao = logDao;
  73. this.exec = exec;
  74. this.dismissService = dismissService;
  75. this.zySrvc = zySrvc;
  76. this.cfg = cfg;
  77. }
  78. public String admissRegister(ZyPatientInfo p, ZyOrJzYbData ybData) {
  79. AdmMdtrtinfo admMdtrtinfo = ybData.getAdmMdtrtinfo(p);
  80. // 当医生有医保姓名时,优先使用医保姓名
  81. try {
  82. String ybName = doctorsAdviseDao.getYbName(admMdtrtinfo.getChfpdrName());
  83. if(StringUtil.isNotEmpty(ybName)) {
  84. log.info("门诊挂号医生{},使用医保姓名:{}", admMdtrtinfo.getChfpdrName(), ybName);
  85. admMdtrtinfo.setChfpdrName(ybName);
  86. }
  87. } catch (Exception e) {
  88. log.error(e.getMessage());
  89. log.error("获取医保姓名出错:{}", admMdtrtinfo.getAtddrNo());
  90. }
  91. List<AdmDiseinfo> admDiseinfos = ybData.getAdmDiseinfo(p.getInpatientNo(), p.getAdmissTimes());
  92. admDiseinfos.forEach(item -> {
  93. item.setDiseDorNo(admMdtrtinfo.getAtddrNo());
  94. item.setDiseDorName(admMdtrtinfo.getChfpdrName());
  95. });
  96. ReadCardBizType readCardBizType = ReadCardBizType.get(p.getReadCardBizType());
  97. if (readCardBizType != ReadCardBizType.ADMISSION) {
  98. String bizarea = cfg.getHospArea();
  99. if (StringUtil.notBlank(bizarea) && bizarea.length() > 2) {
  100. String areaHeader = bizarea.substring(0, 2);
  101. if (!p.getInsuplcAdmdvs().startsWith(areaHeader)) {
  102. throw new BizException(ExceptionEnum.LOGICAL_ERROR, "省外异地的患者请读社保卡登记!");
  103. }
  104. }
  105. }
  106. if (readCardBizType == ReadCardBizType.ADMISSION) {
  107. MdtrtCertType mdtrtCertType = MdtrtCertType.getByLabel(p.getMdtrtCertType());
  108. admMdtrtinfo.setMdtrtCertType(mdtrtCertType.getCode());
  109. if (mdtrtCertType.getCode().equals(MdtrtCertType.SOCIAL_SECURITY_CARD.getCode())) {
  110. String[] out = p.getReadCardResult().split("\\|");
  111. if (!p.getName().trim().equals(out[4].trim())) {
  112. throw new BizException(ExceptionEnum.LOGICAL_ERROR, "社保卡姓名与HIS姓名不一致,请确认是否人证相符。");
  113. }
  114. admMdtrtinfo.setMdtrtCertNo(out[2] + "|" + p.getBusCardInfo());
  115. admMdtrtinfo.setCardSn(out[3]);
  116. } else if (mdtrtCertType.getCode().equals(MdtrtCertType.MEDICAL_INSURANCE_ELECTRONIC_VOUCHER.getCode())) {
  117. JSONObject qrinfo = JSONObject.parseObject(p.getReadCardResult());
  118. String userName = UriEncoder.decode(qrinfo.getString("userName"));
  119. if (!p.getName().trim().equals(userName.trim())) {
  120. throw new BizException(ExceptionEnum.LOGICAL_ERROR, "电子医保凭证姓名与HIS姓名不一致,请确认是否人证相符。");
  121. }
  122. if (!p.getSocialNo().trim().equals(qrinfo.getString("idNo").trim())) {
  123. throw new BizException(ExceptionEnum.LOGICAL_ERROR, "电子医保凭证身份证与HIS身份证不一致,请确认是否人证相符。");
  124. }
  125. admMdtrtinfo.setMdtrtCertNo(qrinfo.getString("ecToken"));
  126. }
  127. }
  128. if (StringUtil.isBlank(admMdtrtinfo.getDiseCodg())) {
  129. admMdtrtinfo.setDiseCodg(admDiseinfos.get(0).getDiagCode());
  130. admMdtrtinfo.setDiseName(admDiseinfos.get(0).getDiagName());
  131. }
  132. admMdtrtinfo.setInsutype(p.getInsutype());
  133. admMdtrtinfo.setAdmDiagDscr(admDiseinfos.get(0).getDiagName());
  134. admMdtrtinfo.setDscgMaindiagCode(admDiseinfos.get(0).getDiagCode());
  135. admMdtrtinfo.setDscgMaindiagName(admDiseinfos.get(0).getDiagName());
  136. admMdtrtinfo.setMatnType(p.getMatnType());
  137. admMdtrtinfo.setLatechbFlag(p.getLatechbFlag());
  138. admMdtrtinfo.setPretFlag(p.getPretFlag());
  139. JSONObject input = exec.makeTradeHeaderWithInsureArea(SiFunction.ADMISSION_REGISTRATION, p.getInsuplcAdmdvs());
  140. String ref = JSONObject.toJSONStringWithDateFormat(admMdtrtinfo, "yyyy-MM-dd HH:mm:ss");
  141. input.getJSONObject("input").put("mdtrtinfo", JSONObject.parseObject(ref));
  142. String diseRef = JSONArray.toJSONStringWithDateFormat(admDiseinfos, "yyyy-MM-dd HH:mm:ss");
  143. input.getJSONObject("input").put("diseinfo", JSONArray.parse(diseRef));
  144. JSONObject result = exec.executeTrade(input, SiFunction.ADMISSION_REGISTRATION);
  145. if (null == result) {
  146. throw new BizException(ExceptionEnum.NETWORK_ERROR, "网络异常");
  147. }
  148. Integer infcode = result.getInteger(RESULT_CODE);
  149. if (null == infcode) {
  150. throw new BizException(ExceptionEnum.LOGICAL_ERROR, "医保中心报错:" + result.getString("message"));
  151. }
  152. logDao.insert(new SiLog(input, result, p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn(), infcode, admMdtrtinfo.getPsnNo()));
  153. if (result.getIntValue(RESULT_CODE) == 0) {
  154. JSONObject output = result.getJSONObject(OUTPUT);
  155. String mdtrtId = output.getJSONObject("result").getString("mdtrt_id");
  156. p.setMdtrtId(mdtrtId);
  157. p.setAdmRegMsgid(input.getString("msgid"));
  158. dao.afterAdmissRegister(p);
  159. String restype = dao.selectResponceType(admMdtrtinfo.getMedType());
  160. dao.updateResponceType(restype, admMdtrtinfo.getMedType(), p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn());
  161. return "入院登记成功,就诊号为:" + mdtrtId;
  162. }
  163. throw new BizException(ExceptionEnum.LOGICAL_ERROR, result.getString(ERROR_MESSAGE));
  164. }
  165. public ResultVo<String> modifyAdmissionInfo(ZyPatientInfo p) {
  166. SiPatInfo siPatInfo = queryDao.selectSiPatInfo(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn());
  167. if (null == siPatInfo || StringUtil.isBlank(siPatInfo.getMdtrtId())) {
  168. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "患者医保不在院!");
  169. }
  170. List<AdmDiseinfo> admDiseinfos = dao.selectAdmDiags(p.getInpatientNo(), p.getAdmissTimes());
  171. if (null == admDiseinfos || admDiseinfos.isEmpty()) {
  172. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "请填写医保入院诊断!");
  173. }
  174. admDiseinfos.forEach(item -> item.setMdtrtId(siPatInfo.getMdtrtId()));
  175. JSONObject input = exec.makeTradeHeaderWithInsureArea(SiFunction.MODIFY_ADMISSION_INFO, siPatInfo.getInsuplcAdmdvs());
  176. JSONObject adminfo = new JSONObject();
  177. adminfo.put("mdtrt_id", siPatInfo.getMdtrtId());
  178. adminfo.put("psn_no", siPatInfo.getPsnNo());
  179. adminfo.put("begntime", DateUtil.formatDatetime(p.getYbRegisterDate()));
  180. adminfo.put("mdtrt_cert_type", MdtrtCertType.RESIDENT_IDENTITY_CARD.getCode());
  181. adminfo.put("med_type", siPatInfo.getMedType());
  182. adminfo.put("ipt_otp_no", p.getInpatientNo());
  183. adminfo.put("atddr_no", p.getReferPhysician());
  184. adminfo.put("chfpdr_name", p.getReferPhysicianName());
  185. adminfo.put("adm_diag_dscr", admDiseinfos.get(0).getDiagCode());
  186. adminfo.put("adm_dept_codg", p.getSmallDept());
  187. adminfo.put("adm_dept_name", p.getSmallDeptName());
  188. adminfo.put("adm_bed", p.getBedNo());
  189. adminfo.put("dscg_maindiag_code", admDiseinfos.get(0).getDiagCode());
  190. adminfo.put("dscg_maindiag_name", admDiseinfos.get(0).getDiagName());
  191. input.getJSONObject("input").put("adminfo", adminfo);
  192. String diseRef = JSONArray.toJSONStringWithDateFormat(admDiseinfos, "yyyy-MM-dd HH:mm:ss");
  193. input.getJSONObject("input").put("diseinfo", JSONArray.parse(diseRef));
  194. JSONObject result = exec.executeTrade(input, SiFunction.MODIFY_ADMISSION_INFO);
  195. Integer infcode = result.getInteger(RESULT_CODE);
  196. logDao.insert(new SiLog(input, result, p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn(), infcode, siPatInfo.getPsnNo()));
  197. return SiUtil.makeReturnWithoutOutput(result, "变更住院信息成功。");
  198. }
  199. public String revokeAdmission(ZyPatientInfo p) {
  200. SiPatInfo siPatInfo = queryDao.selectSiPatInfo(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn());
  201. if (null == siPatInfo || StringUtil.isBlank(siPatInfo.getMdtrtId())) {
  202. throw new BizException(ExceptionEnum.LOGICAL_ERROR, "此患者没有有效的医保在院信息!");
  203. }
  204. int uploadedFees = queryDao.getUploadedCount(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn());
  205. if (uploadedFees > 0) {
  206. revokeUploadFees(p);
  207. }
  208. JSONObject input = exec.makeTradeHeaderWithInsureArea(SiFunction.REVOKE_ADMISSION, siPatInfo.getInsuplcAdmdvs());
  209. JSONObject data = new JSONObject();
  210. data.put("mdtrt_id", siPatInfo.getMdtrtId());
  211. data.put("psn_no", siPatInfo.getPsnNo());
  212. input.getJSONObject("input").put("data", data);
  213. JSONObject result = exec.executeTrade(input, SiFunction.REVOKE_ADMISSION);
  214. if (null == result) {
  215. throw new BizException(ExceptionEnum.NETWORK_ERROR);
  216. }
  217. Integer infcode = result.getInteger(RESULT_CODE);
  218. logDao.insert(new SiLog(input, result, p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn(), infcode, siPatInfo.getPsnNo()));
  219. if (null == infcode) {
  220. throw new BizException(ExceptionEnum.LOGICAL_ERROR, "医保中心报错:" + result.getString("message"));
  221. }
  222. if (infcode == 0) {
  223. queryDao.clearMdtrtIdForZy(siPatInfo.getPatNo(), siPatInfo.getTimes(), siPatInfo.getLedgerSn(), null);
  224. dao.updateResponceType("01", null, p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn());
  225. return "取消入院登记成功。";
  226. }
  227. throw new BizException(ExceptionEnum.LOGICAL_ERROR, result.getString(ERROR_MESSAGE));
  228. }
  229. public ResultVo<String> uploadFeeDetail(Overview o) {
  230. o.setStaffId(TokenUtil.getInstance().getTokenUserId());
  231. return zySrvc.uploadFeeDetail(siZyFeeUrl, o);
  232. }
  233. public ResultVo<String> multipleUpload(List<Overview> overviews) {
  234. for (Overview o : overviews) {
  235. if (o.getStatus() == 0) {
  236. String message = String.format("【%s床,%s,%s】未进行医保登记,无法进行费用上传。",
  237. o.getBedNo(), o.getInpatientNo(), o.getName());
  238. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, message);
  239. }
  240. if (invalidMultipleUploadPatient(o.getMedType())) {
  241. String message = String.format("【%s床,%s,%s】是工伤患者,不支持批量上传。",
  242. o.getBedNo(), o.getInpatientNo(), o.getName());
  243. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, message);
  244. }
  245. if (isSelfPayPatient(o.getMedType())) {
  246. String message = String.format("【%s床,%s,%s】是自费患者,不支持批量上传。",
  247. o.getBedNo(), o.getInpatientNo(), o.getName());
  248. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, message);
  249. }
  250. o.setStaffId(TokenUtil.getInstance().getTokenUserId());
  251. }
  252. return zySrvc.uploadMultiplePatientFees(siZyFeeUrl, overviews);
  253. }
  254. public ResultVo<String> injuryMultipleUpload(List<Overview> overviews) {
  255. for (Overview o : overviews) {
  256. if (o.getStatus() == 0) {
  257. String message = String.format("【%s床,%s,%s】未进行工伤登记,无法进行费用上传。",
  258. o.getBedNo(), o.getInpatientNo(), o.getName());
  259. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, message);
  260. }
  261. if (!invalidMultipleUploadPatient(o.getMedType())) {
  262. String message = String.format("【%s床,%s,%s】是非工伤患者,不支持批量上传。",
  263. o.getBedNo(), o.getInpatientNo(), o.getName());
  264. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, message);
  265. }
  266. o.setStaffId(TokenUtil.getInstance().getTokenUserId());
  267. }
  268. return zySrvc.uploadWorkInjuryFees(siZyFeeUrl, overviews);
  269. }
  270. private boolean invalidMultipleUploadPatient(String medtype) {
  271. MedType medType = MedType.get(medtype);
  272. return null == medType || medType == MedType.ZHUYUAN_ZHITI_CAN || medType == MedType.ZHUYUAN_ZHIYE_BING || medType == MedType.ZHUYUAN_KANGFU;
  273. }
  274. private boolean isSelfPayPatient(String medtype) {
  275. MedType medType = MedType.get(medtype);
  276. return medType == MedType.SELF_PAY;
  277. }
  278. public String hospitalizationPreSettlement(ZyPatientInfo p, ZyOrJzYbData ybData) {
  279. PreSetlmt preSetlmt = ybData.getPreSetlmt(p);
  280. preSetlmt.setMdtrtCertType(MdtrtCertType.RESIDENT_IDENTITY_CARD.getCode());
  281. preSetlmt.setPsnSetlway(p.getDbg() ? PsnSetlWay.SETTLE_BY_QUOTA.getCode() : PsnSetlWay.SETTLE_BY_ITEMS.getCode());
  282. preSetlmt.setAcctUsedFlag(YesOrNo.NO.getCodeStr());
  283. preSetlmt.setMidSetlFlag(YesOrNo.NO.getCodeStr());
  284. preSetlmt.setMdtrtareaAdmvs(exec.getInstitutionArea(preSetlmt.getInsuplcAdmdvs()));
  285. preSetlmt.setDscgTime(dao.selectActOrderDisDate(p.getInpatientNo(), p.getAdmissTimes()));
  286. JSONObject input = exec.makeTradeHeaderWithInsureArea(SiFunction.HOSPITALIZATION_PRE_SETTLEMENT, preSetlmt.getInsuplcAdmdvs());
  287. String ref = JSONObject.toJSONStringWithDateFormat(preSetlmt, "yyyy-MM-dd");
  288. input.getJSONObject("input").put("data", JSONObject.parseObject(ref));
  289. JSONObject result = exec.executeTrade(input, SiFunction.HOSPITALIZATION_PRE_SETTLEMENT);
  290. if (null == result) {
  291. throw new BizException(ExceptionEnum.NETWORK_ERROR);
  292. }
  293. Integer infcode = result.getInteger(RESULT_CODE);
  294. logDao.insert(new SiLog(input, result, p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn(), infcode, preSetlmt.getPsnNo()));
  295. if (null == infcode) {
  296. throw new BizException(ExceptionEnum.LOGICAL_ERROR, "医保中心报错:" + result.getString("message"));
  297. }
  298. if (infcode == 0) {
  299. JSONObject setlinfo = result.getJSONObject(OUTPUT).getJSONObject("setlinfo");
  300. String fundPay = setlinfo.getString("fund_pay_sumamt");
  301. dao.updateFundPay(fundPay, p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn());
  302. patientDao.recountDeposit(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn());
  303. patientDao.updateBalance(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn());
  304. String balance = patientDao.selectLedgerBalance(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn());
  305. if (StringUtil.isBlank(balance)) {
  306. balance = "0";
  307. }
  308. patientDao.updateZyActPatientBalance(p.getInpatientNo(), balance);
  309. return "患者【" + p.getName() + "】院内总费用与医保中心总费用一致,医保报销金额为:¥ " + fundPay + "。";
  310. }
  311. throw new BizException(ExceptionEnum.LOGICAL_ERROR, result.getString(ERROR_MESSAGE));
  312. }
  313. public String revokeUploadFees(ZyPatientInfo p) {
  314. SiPatInfo siPatInfo = queryDao.selectSiPatInfo(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn());
  315. if (null == siPatInfo || StringUtil.isBlank(siPatInfo.getMdtrtId())) {
  316. throw new BizException(ExceptionEnum.LOGICAL_ERROR, "此患者没有有效的医保在院信息!");
  317. }
  318. JSONObject input = exec.makeTradeHeaderWithInsureArea(SiFunction.REVOKE_HOSPITALIZATION_FEE_DETAILS, siPatInfo.getInsuplcAdmdvs());
  319. JSONArray data = new JSONArray();
  320. if (null == p.getDetailSns() || p.getDetailSns().isEmpty()) {
  321. JSONObject item = new JSONObject();
  322. item.put("feedetl_sn", "0000");
  323. item.put("mdtrt_id", siPatInfo.getMdtrtId());
  324. item.put("psn_no", siPatInfo.getPsnNo());
  325. data.add(item);
  326. } else {
  327. p.getDetailSns().forEach(detailSn -> {
  328. JSONObject item = new JSONObject();
  329. item.put("feedetl_sn", detailSn);
  330. item.put("mdtrt_id", siPatInfo.getMdtrtId());
  331. item.put("psn_no", siPatInfo.getPsnNo());
  332. data.add(item);
  333. });
  334. }
  335. input.getJSONObject("input").put("data", data);
  336. JSONObject result = exec.executeTrade(input, SiFunction.REVOKE_HOSPITALIZATION_FEE_DETAILS);
  337. if (null == result) {
  338. throw new BizException(ExceptionEnum.NETWORK_ERROR);
  339. }
  340. Integer infcode = result.getInteger(RESULT_CODE);
  341. logDao.insert(new SiLog(input, result, p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn(), infcode, siPatInfo.getPsnNo()));
  342. if (null == infcode) {
  343. throw new BizException(ExceptionEnum.LOGICAL_ERROR, "医保中心报错:" + result.getString("message"));
  344. }
  345. if (infcode == 0) {
  346. QueryWrapper<SiChargeTemp> wrapper = new QueryWrapper<>();
  347. wrapper.eq("pat_no", p.getInpatientNo());
  348. wrapper.eq("times", p.getAdmissTimes());
  349. wrapper.eq("ledger_sn", p.getLedgerSn());
  350. if (null == p.getDetailSns() || p.getDetailSns().isEmpty()) {
  351. dao.revokeAllUploadFee(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn());
  352. dao.resetFundpayAmt(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn());
  353. chrgtmpdao.delete(wrapper);
  354. } else {
  355. wrapper.in("feedetl_sn", p.getDetailSns());
  356. chrgtmpdao.delete(wrapper);
  357. dao.revokePartUploadFee(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn(), p.getDetailSns());
  358. }
  359. return "撤销费用上传成功。";
  360. }
  361. throw new BizException(ExceptionEnum.LOGICAL_ERROR, result.getString(ERROR_MESSAGE));
  362. }
  363. public ResultVo<String> pairNegativeFee(NotUploadedFee fee) {
  364. if (null == fee.getOriDetailSn()) {
  365. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "请先处理违规退费。");
  366. }
  367. SiPatInfo siPatInfo = queryDao.selectSiPatInfo(fee.getPatNo(), fee.getTimes(), fee.getLedgerSn());
  368. JSONObject input = exec.makeTradeHeaderWithInsureArea(SiFunction.REVOKE_HOSPITALIZATION_FEE_DETAILS,
  369. siPatInfo.getInsuplcAdmdvs());
  370. JSONArray data = new JSONArray();
  371. JSONObject item = new JSONObject();
  372. item.put("feedetl_sn", fee.getOriDetailSn());
  373. item.put("mdtrt_id", siPatInfo.getMdtrtId());
  374. item.put("psn_no", siPatInfo.getPsnNo());
  375. data.add(item);
  376. input.getJSONObject("input").put("data", data);
  377. JSONObject result = exec.executeTrade(input, SiFunction.REVOKE_HOSPITALIZATION_FEE_DETAILS);
  378. if (null == result) {
  379. return ResultVoUtil.fail(ExceptionEnum.NETWORK_ERROR);
  380. }
  381. Integer infcode = result.getInteger(RESULT_CODE);
  382. logDao.insert(new SiLog(input, result, fee.getPatNo(), fee.getTimes(), fee.getLedgerSn(), infcode, siPatInfo.getPsnNo()));
  383. if (null == infcode) {
  384. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "医保中心报错:" + result.getString("message"));
  385. }
  386. if (infcode == 0) {
  387. QueryWrapper<SiChargeTemp> wrapper = new QueryWrapper<>();
  388. wrapper.eq("pat_no", fee.getPatNo());
  389. wrapper.eq("times", fee.getTimes());
  390. wrapper.eq("ledger_sn", fee.getLedgerSn());
  391. wrapper.eq("feedetl_sn", fee.getOriDetailSn());
  392. dao.updateTransFlag(fee.getPatNo(), fee.getTimes(), fee.getDetailSn(), fee.getOriDetailSn());
  393. chrgtmpdao.delete(wrapper);
  394. return ResultVoUtil.success("退费处理成功。");
  395. }
  396. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, result.getString(ERROR_MESSAGE));
  397. }
  398. public ResultVo<String> revokeSingleCharge(String patNo, int times, int ledgerSn, int detailSn) {
  399. SiPatInfo siPatInfo = queryDao.selectSiPatInfo(patNo, times, ledgerSn);
  400. JSONObject input = exec.makeTradeHeaderWithInsureArea(SiFunction.REVOKE_HOSPITALIZATION_FEE_DETAILS,
  401. siPatInfo.getInsuplcAdmdvs());
  402. JSONArray data = new JSONArray();
  403. JSONObject item = new JSONObject();
  404. item.put("feedetl_sn", detailSn);
  405. item.put("mdtrt_id", siPatInfo.getMdtrtId());
  406. item.put("psn_no", siPatInfo.getPsnNo());
  407. data.add(item);
  408. input.getJSONObject("input").put("data", data);
  409. JSONObject result = exec.executeTrade(input, SiFunction.REVOKE_HOSPITALIZATION_FEE_DETAILS);
  410. if (null == result) {
  411. return ResultVoUtil.fail(ExceptionEnum.NETWORK_ERROR);
  412. }
  413. Integer infcode = result.getInteger(RESULT_CODE);
  414. logDao.insert(new SiLog(input, result, patNo, times, ledgerSn, infcode, siPatInfo.getPsnNo()));
  415. if (null == infcode) {
  416. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "医保中心报错:" + result.getString("message"));
  417. }
  418. if (infcode == 0) {
  419. QueryWrapper<SiChargeTemp> wrapper = new QueryWrapper<>();
  420. wrapper.eq("pat_no", patNo);
  421. wrapper.eq("times", times);
  422. wrapper.eq("ledger_sn", ledgerSn);
  423. wrapper.eq("feedetl_sn", detailSn);
  424. chrgtmpdao.delete(wrapper);
  425. }
  426. return ResultVoUtil.success("处理成功。");
  427. }
  428. public String dischargeProcessing(ZyPatientInfo p, ZyOrJzYbData ybData) {
  429. if (null == p.getLedgerSn()) {
  430. p.setLedgerSn(dao.selectMaxLedgerSn(p.getInpatientNo(), p.getAdmissTimes()));
  431. }
  432. Dscginfo dscginfo = ybData.getDscginfo(p);
  433. List<SetlDiseinfo> setlDises = ybData.getSetlDiseinfo(p);
  434. if (null == p.getStaffId()) {
  435. p.setStaffId(TokenUtil.getInstance().getTokenUserId());
  436. }
  437. if (StringUtil.isBlank(p.getAcctUsedFlag())) {
  438. p.setAcctUsedFlag(YesOrNo.NO.getCodeStr());
  439. }
  440. dscginfo.setDiseCodg(setlDises.get(0).getDiagCode());
  441. dscginfo.setDiseName(setlDises.get(0).getDiagName());
  442. dscginfo.setDscgWay(DscgWay.ORDER_TO_LEAVE_HOSPITAL.getCode());
  443. String ref = JSONObject.toJSONStringWithDateFormat(dscginfo, "yyyy-MM-dd HH:mm:ss");
  444. JSONObject input = exec.makeTradeHeaderWithInsureArea(SiFunction.DISCHARGE_PROCESSING,
  445. dao.selectAdmdvs(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn()));
  446. input.getJSONObject("input").put("dscginfo", JSONObject.parseObject(ref));
  447. String diseRef = JSONArray.toJSONStringWithDateFormat(setlDises, "yyyy-MM-dd HH:mm:ss");
  448. input.getJSONObject("input").put("diseinfo", JSONArray.parse(diseRef));
  449. JSONObject result = exec.executeTrade(input, SiFunction.DISCHARGE_PROCESSING);
  450. if (null == result) {
  451. throw new BizException(ExceptionEnum.NETWORK_ERROR);
  452. }
  453. Integer infcode = result.getInteger(RESULT_CODE);
  454. logDao.insert(new SiLog(input, result, p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn(), infcode, dscginfo.getPsnNo()));
  455. if (null == infcode) {
  456. throw new BizException(ExceptionEnum.LOGICAL_ERROR, "医保中心报错:" + result.getString("message"));
  457. }
  458. if (infcode == 0) {
  459. if (p.getStopHere()) {
  460. return "出院办理成功。";
  461. }
  462. p.setDismissDate(dscginfo.getEndtime());
  463. return inpatientSettlement(p, ybData);
  464. }
  465. String errMsg = result.getString(ERROR_MESSAGE);
  466. if (null != errMsg && errMsg.contains("该人员已经是出院状态")) {
  467. p.setDismissDate(dscginfo.getEndtime());
  468. return inpatientSettlement(p, ybData);
  469. }
  470. throw new BizException(ExceptionEnum.LOGICAL_ERROR, errMsg);
  471. }
  472. public String revokeDischarge(ZyPatientInfo p) {
  473. SiPatInfo siPatInfo = queryDao.selectSiPatInfo(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn());
  474. if (null == siPatInfo || StringUtil.isBlank(siPatInfo.getMdtrtId())) {
  475. throw new BizException("此患者没有在院的医保业务。");
  476. }
  477. p.setMdtrtId(siPatInfo.getMdtrtId());
  478. JSONObject input = exec.makeTradeHeaderWithInsureArea(SiFunction.REVOKE_DISCHARGE, siPatInfo.getInsuplcAdmdvs());
  479. JSONObject data = new JSONObject();
  480. data.put("mdtrt_id", siPatInfo.getMdtrtId());
  481. data.put("psn_no", siPatInfo.getPsnNo());
  482. input.getJSONObject("input").put("data", data);
  483. JSONObject result = exec.executeTrade(input, SiFunction.REVOKE_DISCHARGE);
  484. if (null == result) {
  485. throw new BizException(ExceptionEnum.NETWORK_ERROR);
  486. }
  487. Integer infcode = result.getInteger(RESULT_CODE);
  488. logDao.insert(new SiLog(input, result, p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn(), infcode, siPatInfo.getPsnNo()));
  489. if (null == infcode) {
  490. throw new BizException(ExceptionEnum.LOGICAL_ERROR, "医保中心报错:" + result.getString("message"));
  491. }
  492. if (infcode == 0) {
  493. dao.deleteSetlInfo(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn());
  494. dao.deleteSetlDetail(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn());
  495. transbackTables(p);
  496. return "取消医保出院办理成功。";
  497. }
  498. throw new BizException(ExceptionEnum.LOGICAL_ERROR, result.getString(ERROR_MESSAGE));
  499. }
  500. private void fillBeginTimeAndEndTime(ZyPatientInfo p) {
  501. if (null == p.getYbRegisterDate()) {
  502. Date beginTime = dismissService.getBegntime(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn(), "zy_actpatient");
  503. p.setYbRegisterDate(beginTime);
  504. }
  505. if (null == p.getDismissDate()) {
  506. Date disdate = dao.selectDisdate(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn());
  507. if (null == disdate) {
  508. throw new BizException(ExceptionEnum.LOGICAL_ERROR, "请先提交出院申请!");
  509. }
  510. p.setDismissDate(disdate);
  511. }
  512. }
  513. private String inpatientSettlement(ZyPatientInfo p, ZyOrJzYbData ybData) {
  514. fillBeginTimeAndEndTime(p);
  515. PreSetlmt preSetlmt = ybData.getSetlmt(p);
  516. ReadCardBizType readCardBizType = ReadCardBizType.get(p.getReadCardBizType());
  517. if (readCardBizType == ReadCardBizType.SETTLEMENT) {
  518. MdtrtCertType mdtrtCertType = MdtrtCertType.getByLabel(p.getMdtrtCertType());
  519. preSetlmt.setMdtrtCertType(mdtrtCertType.getCode());
  520. if (mdtrtCertType.getCode().equals(MdtrtCertType.SOCIAL_SECURITY_CARD.getCode())) {
  521. String[] out = p.getReadCardResult().split("\\|");
  522. if (!p.getName().trim().equals(out[4].trim())) {
  523. revokeDischarge(p);
  524. throw new BizException(ExceptionEnum.LOGICAL_ERROR, "社保卡姓名与HIS姓名不一致,请确认是否人证相符。");
  525. }
  526. preSetlmt.setMdtrtCertNo(out[2] + "|" + p.getBusCardInfo());
  527. preSetlmt.setCardSn(out[3]);
  528. } else if (mdtrtCertType.getCode().equals(MdtrtCertType.MEDICAL_INSURANCE_ELECTRONIC_VOUCHER.getCode())) {
  529. JSONObject qrinfo = JSONObject.parseObject(p.getReadCardResult());
  530. String userName = UriEncoder.decode(qrinfo.getString("userName"));
  531. if (!p.getName().trim().equals(userName.trim())) {
  532. revokeDischarge(p);
  533. throw new BizException(ExceptionEnum.LOGICAL_ERROR, "电子医保凭证姓名与HIS姓名不一致,请确认是否人证相符。");
  534. }
  535. if (!p.getSocialNo().trim().equals(qrinfo.getString("idNo").trim())) {
  536. revokeDischarge(p);
  537. throw new BizException(ExceptionEnum.LOGICAL_ERROR, "电子医保凭证身份证与HIS身份证不一致,请确认是否人证相符。");
  538. }
  539. preSetlmt.setMdtrtCertNo(qrinfo.getString("ecToken"));
  540. }
  541. }
  542. preSetlmt.setPsnSetlway(p.getDbg() ? PsnSetlWay.SETTLE_BY_QUOTA.getCode() : PsnSetlWay.SETTLE_BY_ITEMS.getCode());
  543. preSetlmt.setAcctUsedFlag(p.getAcctUsedFlag());
  544. preSetlmt.setMidSetlFlag(YesOrNo.NO.getCodeStr());
  545. preSetlmt.setInvono(SnowFlakeId.instance().nextId());
  546. JSONObject input = exec.makeTradeHeaderWithInsureArea(SiFunction.HOSPITALIZATION_SETTLEMENT, preSetlmt.getInsuplcAdmdvs());
  547. String ref = JSONObject.toJSONString(preSetlmt);
  548. input.getJSONObject("input").put("data", JSONObject.parseObject(ref));
  549. JSONObject result = exec.executeTrade(input, SiFunction.HOSPITALIZATION_SETTLEMENT);
  550. if (null == result) {
  551. revokeDischarge(p);
  552. throw new BizException(ExceptionEnum.NETWORK_ERROR);
  553. }
  554. Integer infcode = result.getInteger(RESULT_CODE);
  555. logDao.insert(new SiLog(input, result, p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn(), infcode, preSetlmt.getPsnNo()));
  556. if (null == infcode) {
  557. revokeDischarge(p);
  558. throw new BizException(ExceptionEnum.LOGICAL_ERROR, "医保中心报错:" + result.getString("message"));
  559. }
  560. if (infcode == 0) {
  561. p.setInsuplcAdmdvs(preSetlmt.getInsuplcAdmdvs());
  562. p.setInsuplcAdmdvsName(queryDao.getInsuplcAdmdvsName(p));
  563. return executeHisSettlement(result.getJSONObject(OUTPUT), p);
  564. }
  565. String message = result.getString(ERROR_MESSAGE);
  566. if (message.contains("服务提供者后端服务响应超时")) {
  567. return timeoutSettlement(p);
  568. }
  569. revokeDischarge(p);
  570. throw new BizException(ExceptionEnum.LOGICAL_ERROR, message);
  571. }
  572. public String timeoutSettlement(ZyPatientInfo p) {
  573. SiPatInfo siPatInfo = queryDao.selectSiPatInfo(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn());
  574. if (null == siPatInfo) {
  575. throw new BizException(ExceptionEnum.LOGICAL_ERROR, "[t_si_pat_info]没有此患者的就诊信息。");
  576. }
  577. fillBeginTimeAndEndTime(p);
  578. p.setInsuplcAdmdvs(siPatInfo.getInsuplcAdmdvs());
  579. p.setInsuplcAdmdvsName(siPatInfo.getInsuplcAdmdvsName());
  580. JSONObject output = queryService.execute5203(siPatInfo);
  581. return executeHisSettlement(output, p);
  582. }
  583. private String executeHisSettlement(JSONObject output, ZyPatientInfo p) {
  584. dao.deleteSetlDetail(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn());
  585. JSONObject setlinfo = output.getJSONObject("setlinfo");
  586. SiSetlinfo setlinfoEntity = JSONObject.parseObject(setlinfo.toJSONString(), SiSetlinfo.class);
  587. setlinfoEntity.setPatNo(p.getInpatientNo());
  588. setlinfoEntity.setTimes(p.getAdmissTimes());
  589. setlinfoEntity.setLedgerSn(p.getLedgerSn());
  590. setlinfoEntity.setStaffId(TokenUtil.getInstance().getTokenUserId());
  591. setlinfoEntity.setRevoked(YesOrNo.NO.getCode());
  592. setlinfoEntity.setSetlType(ClrType.INPATIENT.getCode());
  593. setlinfoEntity.setInsuplcAdmdvs(p.getInsuplcAdmdvs());
  594. setlinfoEntity.setInsuplcAdmdvsName(p.getInsuplcAdmdvsName());
  595. setlinfoEntity.setBegntime(p.getYbRegisterDate());
  596. setlinfoEntity.setEndtime(p.getDismissDate());
  597. setlinfoEntity.setHiPaymtd(CommonUtil.calcHiPaymtd(setlinfoEntity.getInsuplcAdmdvs(),setlinfoEntity.getMedType(),setlinfoEntity.getInsutype(),setlinfoEntity.getSetlTime()));
  598. setlinfoEntity.setMedinsType(MedInsTypeUtil.getMedInsType(setlinfoEntity));
  599. if (null == setlinfoEntity.getPsnPartAmt()) {
  600. Double psnPay = setlinfo.getDouble("psn_pay");
  601. setlinfoEntity.setPsnPartAmt(psnPay);
  602. }
  603. if (null == setlinfoEntity.getPsnCashPay()) {
  604. Double cashPay = setlinfo.getDouble("cash_payamt");
  605. setlinfoEntity.setPsnCashPay(cashPay);
  606. }
  607. JSONArray setldetail = output.getJSONArray("setldetail");
  608. BigDecimal hospitalPart = BigDecimal.ZERO;
  609. int setlCount = setlinfodao.getSetlCount(setlinfoEntity.getSetlId());
  610. for (int i = 0; i < setldetail.size(); i++) {
  611. SiSetldetail setldetailEntity = JSONObject.parseObject(setldetail.getJSONObject(i).toJSONString(), SiSetldetail.class);
  612. setldetailEntity.setSetlId(setlinfoEntity.getSetlId());
  613. setldetailEntity.setSortNo(i + 1);
  614. setldetailEntity.setPatNo(p.getInpatientNo());
  615. setldetailEntity.setTimes(p.getAdmissTimes());
  616. setldetailEntity.setLedgerSn(p.getLedgerSn());
  617. if ("999996".equals(setldetailEntity.getFundPayType()) || "999996".equals(setldetailEntity.getSetlProcInfo())) {
  618. hospitalPart = hospitalPart.add(setldetailEntity.getFundPayamt());
  619. }
  620. if (setlCount == 0) {
  621. setldetldao.insert(setldetailEntity);
  622. }
  623. }
  624. setlinfoEntity.setHospPartAmt(hospitalPart.doubleValue());
  625. if (setlCount == 0) {
  626. setlinfodao.insert(setlinfoEntity);
  627. }
  628. setlinfodao.updateSiZyInfoSetlId(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn(),
  629. setlinfoEntity.getSetlId(), setlinfoEntity.getMedinsSetlId(), setlinfoEntity.getMedinsSetlId());
  630. setlinfodao.updateApplySettled(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn(), YesOrNo.YES.getCode());
  631. // 跨省异地数据不参与对账,对总账时无需统计进去。
  632. // String hospArea = cfg.getHospArea();
  633. // if (null != hospArea && hospArea.length() > 2) {
  634. // String areaHeader = hospArea.substring(0, 2);
  635. // if (setlinfoEntity.getFundPaySumamt() > 0 && setlinfoEntity.getInsuplcAdmdvs().startsWith(areaHeader)) {
  636. // InstStlLdgChk ldgChk = new InstStlLdgChk();
  637. // ldgChk.setInsutype(setlinfoEntity.getInsutype());
  638. // ldgChk.setClrType(setlinfoEntity.getClrType());
  639. // ldgChk.setSetlOptins(setlinfoEntity.getClrOptins());
  640. // ldgChk.setStmtBegndate(setlinfoEntity.getSetlTime());
  641. // ldgChk.setStmtEnddate(setlinfoEntity.getSetlTime());
  642. // ResultVo<String> totalLedgerCheck = manageService.institutionSettlementLedgerCheck(ldgChk);
  643. // if (totalLedgerCheck.getCode() != ExceptionEnum.SUCCESS.getCode()) {
  644. // InstStlLdgChk detlChk = new InstStlLdgChk();
  645. // detlChk.setSetlOptins(ldgChk.getSetlOptins());
  646. // detlChk.setStmtBegndate(ldgChk.getStmtBegndate());
  647. // detlChk.setStmtEnddate(ldgChk.getStmtEnddate());
  648. // detlChk.setClrType(ldgChk.getClrType());
  649. // detlChk.setRefdSetlFlag(YesOrNo.NO.getCodeStr());
  650. // ResultVo<List<InsSetlDetlChkRslt>> detailLedgerCheck = manageService.institutionSettlementDetailCheck(detlChk);
  651. // if (detailLedgerCheck.getCode() != ExceptionEnum.SUCCESS.getCode()) {
  652. // revokeSettlement(p);
  653. // throw new BizException(ExceptionEnum.LOGICAL_ERROR, detailLedgerCheck.getMessage());
  654. // }
  655. // for (InsSetlDetlChkRslt insSetlDetlChkRslt : detailLedgerCheck.getData()) {
  656. // if (Objects.equals(insSetlDetlChkRslt.getSetlId(), setlinfoEntity.getSetlId())) {
  657. // if (!Objects.equals(insSetlDetlChkRslt.getStmtRslt(), "0")) {
  658. // revokeSettlement(p);
  659. // throw new BizException(ExceptionEnum.LOGICAL_ERROR, insSetlDetlChkRslt.getMemo());
  660. // }
  661. // break;
  662. // }
  663. // }
  664. // }
  665. // }
  666. // }
  667. queryService.saveCumInfo(setlinfoEntity);
  668. if (p.getLedgerSn() == 0) {
  669. return StrUtil.format("出院结算成功。患者总费用:{}。其中基金支付:{};个账支付:{};现金支付:{}",
  670. setlinfoEntity.getMedfeeSumamt(), setlinfoEntity.getFundPaySumamt(), setlinfoEntity.getAcctPay(), setlinfoEntity.getPsnCashPay());
  671. }
  672. MedinsSettleFee settleFee = new MedinsSettleFee();
  673. if (p.getMidSetl()) {
  674. settleFee.setZjdzDatetime(p.getZjdzDatetime());
  675. }
  676. settleFee.setMidSetl(p.getMidSetl());
  677. settleFee.setStaffId(TokenUtil.getInstance().getTokenUserId());
  678. settleFee.setInpatientNo(p.getInpatientNo());
  679. settleFee.setAdmissTimes(p.getAdmissTimes());
  680. settleFee.setBedNo(p.getBedNo());
  681. settleFee.setWardCode(p.getAdmissWard());
  682. settleFee.setDeptCode(p.getAdmissDept());
  683. settleFee.setTotalCost(setlinfo.getString("medfee_sumamt"));
  684. settleFee.setTczf(setlinfo.getString("fund_pay_sumamt"));
  685. settleFee.setHospitalPay(setlinfo.getString("hosp_part_amt"));
  686. settleFee.setGrzhzf(setlinfo.getString("acct_pay"));
  687. settleFee.setDbzf(setlinfo.getString("hifmi_pay"));
  688. settleFee.setXjzf(String.valueOf(setlinfoEntity.getPsnCashPay()));
  689. settleFee.setTable(p.getTable());
  690. return dismissService.executeDischarging(settleFee);
  691. }
  692. public String revokeSettlement(ZyPatientInfo p) {
  693. if (null == p.getStaffId()) {
  694. p.setStaffId(TokenUtil.getInstance().getTokenUserId());
  695. }
  696. if (null == p.getLedgerSn()) {
  697. p.setLedgerSn(dao.selectMaxLedgerSn(p.getInpatientNo(), p.getAdmissTimes()));
  698. }
  699. SiPatInfo siPatInfo = queryDao.selectSiPatInfo(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn());
  700. if (null == siPatInfo || StringUtil.isBlank(siPatInfo.getSetlId())) {
  701. return revokeDischarge(p);
  702. }
  703. p.setMdtrtId(siPatInfo.getMdtrtId());
  704. JSONObject input = exec.makeTradeHeaderWithInsureArea(SiFunction.REVOKE_HOSPITALIZATION_SETTLEMENT, siPatInfo.getInsuplcAdmdvs());
  705. JSONObject data = new JSONObject();
  706. data.put("mdtrt_id", siPatInfo.getMdtrtId());
  707. data.put("setl_id", siPatInfo.getSetlId());
  708. data.put("psn_no", siPatInfo.getPsnNo());
  709. input.getJSONObject("input").put("data", data);
  710. JSONObject result = exec.executeTrade(input, SiFunction.REVOKE_HOSPITALIZATION_SETTLEMENT);
  711. if (null == result) {
  712. throw new BizException(ExceptionEnum.NETWORK_ERROR);
  713. }
  714. Integer infcode = result.getInteger(RESULT_CODE);
  715. logDao.insert(new SiLog(input, result, p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn(), infcode, siPatInfo.getPsnNo()));
  716. if (null == infcode) {
  717. throw new BizException(ExceptionEnum.NETWORK_ERROR);
  718. }
  719. if (infcode != 0) {
  720. throw new BizException(ExceptionEnum.LOGICAL_ERROR, result.getString("err_msg"));
  721. }
  722. String rvkDischrgRslt = revokeDischarge(p);
  723. dao.updateRvkSetlMsgid(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn(), input.getString("msgid"));
  724. setlinfodao.updateApplySettled(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn(), YesOrNo.NO.getCode());
  725. transbackTables(p);
  726. return rvkDischrgRslt;
  727. }
  728. private void transbackTables(ZyPatientInfo p) {
  729. dao.deleteSiSetlFeeDetl(p.getMdtrtId());
  730. dao.deleteZyLedgerFileYb(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn());
  731. dao.deleteZyReceipt(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn());
  732. dao.updateSettleType(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn());
  733. dao.updateChargeStatus(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn());
  734. }
  735. public String revokeWorkInjuryUploadFees(ZyPatientInfo p) {
  736. SiPatInfo siPatInfo = queryDao.selectSiPatInfo(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn());
  737. if (null == siPatInfo || StringUtil.isBlank(siPatInfo.getMdtrtId())) {
  738. throw new BizException(ExceptionEnum.LOGICAL_ERROR, "此患者没有有效的工伤在院信息!");
  739. }
  740. // 根据传入的明细号决定撤销方式
  741. if (null == p.getDetailSns() || p.getDetailSns().isEmpty()) {
  742. // 撤销全部:只传门诊/住院流水号,处方号和处方流水号为空
  743. return revokeAllWorkInjuryFees(p, siPatInfo);
  744. } else {
  745. // 撤销指定明细:需要遍历每个明细号
  746. return revokeSpecificWorkInjuryFees(p, siPatInfo);
  747. }
  748. }
  749. /**
  750. * 撤销全部工伤费用
  751. */
  752. private String revokeAllWorkInjuryFees(ZyPatientInfo p, SiPatInfo siPatInfo) {
  753. // 构建工伤撤销请求(处方明细撤销)
  754. JSONObject input = new JSONObject();
  755. input.put("action", "transaction");
  756. input.put("transactionName", "2205");
  757. JSONObject businessParams = new JSONObject();
  758. businessParams.put("ipt_otp_no", siPatInfo.getMdtrtId()); // 门诊/住院流水号
  759. businessParams.put("rxno", ""); // 处方号为空
  760. businessParams.put("feedetl_sn", ""); // 处方流水号为空
  761. input.put("businessParams", businessParams);
  762. // 调用工伤撤销接口
  763. JSONObject result = exec.executeWorkInjuryTrade(input);
  764. if (null == result) {
  765. throw new BizException(ExceptionEnum.NETWORK_ERROR, "工伤撤销接口调用失败");
  766. }
  767. // 工伤接口返回结果处理(支持模拟接口和真实接口切换)
  768. Integer infcode = extractWorkInjuryResultCode(result);
  769. if (null == infcode) {
  770. throw new BizException(ExceptionEnum.LOGICAL_ERROR, "工伤撤销接口返回结果解析失败");
  771. }
  772. // 构造工伤日志input(参考工伤预结算写法)
  773. JSONObject logInput = new JSONObject();
  774. if (result != null && result.containsKey("data")) {
  775. JSONObject data = result.getJSONObject("data");
  776. if (data.containsKey("transformed_parameters")) {
  777. JSONObject transformedParams = data.getJSONObject("transformed_parameters");
  778. logInput.put("infno", transformedParams.getString("infno"));
  779. logInput.put("insuplc_admdvs", "");
  780. logInput.put("msgid", transformedParams.getString("msgid"));
  781. logInput.put("opter", transformedParams.getString("opter"));
  782. } else {
  783. logInput.put("infno", "2205"); // 工伤撤销接口号
  784. logInput.put("insuplc_admdvs", "");
  785. logInput.put("msgid", "WORK_INJURY_" + System.currentTimeMillis());
  786. logInput.put("opter", p.getStaffId());
  787. }
  788. } else {
  789. logInput.put("infno", "2205");
  790. logInput.put("insuplc_admdvs", "");
  791. logInput.put("msgid", "WORK_INJURY_" + System.currentTimeMillis());
  792. logInput.put("opter", p.getStaffId());
  793. }
  794. logDao.insert(new SiLog(logInput, result, p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn(), infcode, siPatInfo.getPsnNo()));
  795. if (infcode == 0) {
  796. // 撤销成功,更新数据库状态
  797. dao.revokeAllUploadFee(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn());
  798. dao.resetFundpayAmt(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn());
  799. QueryWrapper<SiChargeTemp> wrapper = new QueryWrapper<>();
  800. wrapper.eq("pat_no", p.getInpatientNo());
  801. wrapper.eq("times", p.getAdmissTimes());
  802. wrapper.eq("ledger_sn", p.getLedgerSn());
  803. chrgtmpdao.delete(wrapper);
  804. return "工伤撤销费用成功。";
  805. } else {
  806. String errorMsg = extractWorkInjuryErrorMessage(result);
  807. throw new BizException(ExceptionEnum.LOGICAL_ERROR, "工伤撤销失败:" + errorMsg);
  808. }
  809. }
  810. /**
  811. * 撤销指定工伤费用明细
  812. */
  813. private String revokeSpecificWorkInjuryFees(ZyPatientInfo p, SiPatInfo siPatInfo) {
  814. List<Integer> successDetailSns = new ArrayList<>();
  815. List<Integer> failedDetailSns = new ArrayList<>();
  816. // 遍历每个明细号,逐个撤销
  817. for (Integer detailSn : p.getDetailSns()) {
  818. // 构建工伤撤销请求(处方明细撤销)
  819. JSONObject input = new JSONObject();
  820. input.put("action", "transaction");
  821. input.put("transactionName", "2205");
  822. JSONObject businessParams = new JSONObject();
  823. businessParams.put("ipt_otp_no", siPatInfo.getMdtrtId()); // 门诊/住院流水号
  824. // 获取对应的处方号
  825. String rxno = dao.selectRxnoByDetailSn(p.getInpatientNo(), p.getAdmissTimes(), detailSn);
  826. if (StringUtil.isBlank(rxno)) {
  827. // 如果处方号为空,只传门诊/住院流水号,不传处方号和处方流水号
  828. // 这样会撤销该门诊/住院流水号下所有未结算处方
  829. businessParams.put("rxno", "");
  830. businessParams.put("feedetl_sn", "");
  831. } else {
  832. // 如果处方号有值,传完整的参数
  833. businessParams.put("rxno", rxno);
  834. businessParams.put("feedetl_sn", detailSn.toString());
  835. }
  836. input.put("businessParams", businessParams);
  837. // 调用工伤撤销接口
  838. JSONObject result = exec.executeWorkInjuryTrade(input);
  839. if (null == result) {
  840. log.error("工伤撤销接口调用失败,明细:{}", detailSn);
  841. failedDetailSns.add(detailSn);
  842. continue; // 继续撤销下一个,不中断整个流程
  843. }
  844. // 工伤接口返回结果处理(支持模拟接口和真实接口切换)
  845. Integer infcode = extractWorkInjuryResultCode(result);
  846. if (null == infcode) {
  847. log.error("工伤撤销接口返回结果解析失败,明细:{}", detailSn);
  848. failedDetailSns.add(detailSn);
  849. continue;
  850. }
  851. // 构造工伤日志input(参考工伤预结算写法)
  852. JSONObject logInput = new JSONObject();
  853. if (result != null && result.containsKey("data")) {
  854. JSONObject data = result.getJSONObject("data");
  855. if (data.containsKey("transformed_parameters")) {
  856. JSONObject transformedParams = data.getJSONObject("transformed_parameters");
  857. logInput.put("infno", transformedParams.getString("infno"));
  858. logInput.put("insuplc_admdvs", "");
  859. logInput.put("msgid", transformedParams.getString("msgid"));
  860. logInput.put("opter", transformedParams.getString("opter"));
  861. } else {
  862. logInput.put("infno", "2205"); // 工伤撤销接口号
  863. logInput.put("insuplc_admdvs", "");
  864. logInput.put("msgid", "WORK_INJURY_" + System.currentTimeMillis());
  865. logInput.put("opter", p.getStaffId());
  866. }
  867. } else {
  868. logInput.put("infno", "2205");
  869. logInput.put("insuplc_admdvs", "");
  870. logInput.put("msgid", "WORK_INJURY_" + System.currentTimeMillis());
  871. logInput.put("opter", p.getStaffId());
  872. }
  873. logDao.insert(new SiLog(logInput, result, p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn(), infcode, siPatInfo.getPsnNo()));
  874. if (infcode == 0) {
  875. log.info("工伤撤销成功,明细:{}", detailSn);
  876. successDetailSns.add(detailSn);
  877. } else {
  878. String errorMsg = extractWorkInjuryErrorMessage(result);
  879. log.error("工伤撤销失败,明细:{},错误:{}", detailSn, errorMsg);
  880. failedDetailSns.add(detailSn);
  881. }
  882. }
  883. // 根据撤销结果分别更新数据库状态
  884. if (successDetailSns.isEmpty()) {
  885. log.warn("工伤撤销全部失败,患者:{},明细数:{}", p.getInpatientNo(), p.getDetailSns().size());
  886. throw new BizException(ExceptionEnum.LOGICAL_ERROR, "工伤撤销全部失败,请检查网络连接和接口状态。");
  887. }
  888. // 更新数据库
  889. if (successDetailSns.size() == p.getDetailSns().size()) {
  890. // 全部撤销成功
  891. log.info("工伤撤销全部成功,患者:{},明细数:{}", p.getInpatientNo(), successDetailSns.size());
  892. dao.revokePartUploadFee(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn(), successDetailSns);
  893. QueryWrapper<SiChargeTemp> wrapper = new QueryWrapper<>();
  894. wrapper.eq("pat_no", p.getInpatientNo());
  895. wrapper.eq("times", p.getAdmissTimes());
  896. wrapper.eq("ledger_sn", p.getLedgerSn());
  897. wrapper.in("feedetl_sn", successDetailSns);
  898. chrgtmpdao.delete(wrapper);
  899. } else {
  900. // 部分撤销成功,只更新成功撤销的明细
  901. log.info("工伤撤销部分成功,患者:{},成功:{},失败:{}",
  902. p.getInpatientNo(), successDetailSns.size(), failedDetailSns.size());
  903. dao.revokePartUploadFee(p.getInpatientNo(), p.getAdmissTimes(), p.getLedgerSn(), successDetailSns);
  904. QueryWrapper<SiChargeTemp> wrapper = new QueryWrapper<>();
  905. wrapper.eq("pat_no", p.getInpatientNo());
  906. wrapper.eq("times", p.getAdmissTimes());
  907. wrapper.eq("ledger_sn", p.getLedgerSn());
  908. wrapper.in("feedetl_sn", successDetailSns);
  909. chrgtmpdao.delete(wrapper);
  910. }
  911. log.info("工伤撤销流程完成,患者:{},成功撤销:{},失败撤销:{}",
  912. p.getInpatientNo(), successDetailSns.size(), failedDetailSns.size());
  913. if (failedDetailSns.isEmpty()) {
  914. return "工伤撤销费用成功。";
  915. } else {
  916. return String.format("工伤撤销部分成功。成功:%d,失败:%d", successDetailSns.size(), failedDetailSns.size());
  917. }
  918. }
  919. /**
  920. * 工伤接口返回结果代码提取(支持模拟接口和真实接口切换)
  921. */
  922. private Integer extractWorkInjuryResultCode(JSONObject result) {
  923. if (result == null) {
  924. return null;
  925. }
  926. // 模拟接口返回结构:result.getJSONObject("data").getJSONObject("data").getString("infcode")
  927. // 真实接口返回结构:result.getJSONObject("data").getString("infcode")
  928. // 模拟接口处理(当前使用)
  929. if (result.containsKey("data") && result.getJSONObject("data").containsKey("data")) {
  930. JSONObject innerData = result.getJSONObject("data").getJSONObject("data");
  931. return innerData != null ? innerData.getInteger(RESULT_CODE) : null;
  932. }
  933. // 真实接口处理(注释掉,需要时手动切换)
  934. // else if (result.containsKey("data")) {
  935. // JSONObject data = result.getJSONObject("data");
  936. // return data != null ? data.getInteger(RESULT_CODE) : null;
  937. // }
  938. return null;
  939. }
  940. /**
  941. * 工伤接口错误信息提取(支持模拟接口和真实接口切换)
  942. */
  943. private String extractWorkInjuryErrorMessage(JSONObject result) {
  944. if (result == null) {
  945. return "未知错误";
  946. }
  947. // 模拟接口返回结构:result.getJSONObject("data").getJSONObject("data").getString("err_msg")
  948. // 真实接口返回结构:result.getJSONObject("data").getString("err_msg")
  949. // 模拟接口处理(当前使用)
  950. if (result.containsKey("data") && result.getJSONObject("data").containsKey("data")) {
  951. JSONObject innerData = result.getJSONObject("data").getJSONObject("data");
  952. if (innerData != null) {
  953. String errorMsg = innerData.getString(ERROR_MESSAGE);
  954. return StringUtil.isBlank(errorMsg) ? "未知错误" : errorMsg;
  955. }
  956. }
  957. // 真实接口处理(注释掉,需要时手动切换)
  958. // else if (result.containsKey("data")) {
  959. // JSONObject data = result.getJSONObject("data");
  960. // if (data != null) {
  961. // String errorMsg = data.getString(ERROR_MESSAGE);
  962. // return StringUtil.isBlank(errorMsg) ? "未知错误" : errorMsg;
  963. // }
  964. // }
  965. return "未知错误";
  966. }
  967. }