SiMzFeeService.java 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997
  1. package thyyxxk.simzfeeoprnsystm.service;
  2. import com.alibaba.fastjson.JSONArray;
  3. import com.alibaba.fastjson.JSONObject;
  4. import com.alibaba.fastjson2.JSON;
  5. import org.springframework.web.client.RestTemplate;
  6. import thyyxxk.simzfeeoprnsystm.config.HisApiConfig;
  7. import thyyxxk.simzfeeoprnsystm.dao.*;
  8. import thyyxxk.simzfeeoprnsystm.dicts.*;
  9. import thyyxxk.simzfeeoprnsystm.external.WebHisService;
  10. import thyyxxk.simzfeeoprnsystm.pojo.*;
  11. import thyyxxk.simzfeeoprnsystm.pojo.ResultVo;
  12. import thyyxxk.simzfeeoprnsystm.pojo.SiPatInfo;
  13. import thyyxxk.simzfeeoprnsystm.utils.*;
  14. import lombok.extern.slf4j.Slf4j;
  15. import org.springframework.beans.factory.annotation.Autowired;
  16. import org.springframework.stereotype.Service;
  17. import java.math.BigDecimal;
  18. import java.math.RoundingMode;
  19. import java.util.*;
  20. import java.util.concurrent.TimeUnit;
  21. @Slf4j
  22. @Service
  23. public class SiMzFeeService {
  24. private final SiMzDao mzDao;
  25. private final SiSetlinfoDao setlinfoDao;
  26. private final SiSetldetailDao setldetailDao;
  27. private final ScheduledDao scheduledDao;
  28. private final ExecService exec;
  29. private final WebHisService webHisService;
  30. private static final String RESULT_CODE = "infcode";
  31. private static final String ERROR_MESSAGE = "err_msg";
  32. private static final String OUTPUT = "output";
  33. private final SiLogDao logDao;
  34. private final HisApiConfig hisApi;
  35. @Autowired
  36. public SiMzFeeService(SiMzDao mzDao, SiSetlinfoDao setlinfoDao,
  37. SiSetldetailDao setldetailDao, ScheduledDao scheduledDao, ExecService exec,
  38. WebHisService webHisService, SiLogDao logDao, HisApiConfig hisApi) {
  39. this.mzDao = mzDao;
  40. this.setlinfoDao = setlinfoDao;
  41. this.setldetailDao = setldetailDao;
  42. this.scheduledDao = scheduledDao;
  43. this.exec = exec;
  44. this.webHisService = webHisService;
  45. this.logDao = logDao;
  46. this.hisApi = hisApi;
  47. }
  48. private boolean mipSettled(String hisOrdNum) {
  49. int count = mzDao.getMipSettleCount(hisOrdNum);
  50. return count > 0;
  51. }
  52. private boolean inMipSettleProcess(String hisOrdNum) {
  53. int count = mzDao.getLockedCount(hisOrdNum);
  54. return count > 0;
  55. }
  56. public ResultVo<String> outpatientRegistration(MzPatientInfo p) {
  57. Regstrtn regstrtn;
  58. if (null != p.getVisitDate() && StringUtil.notBlank(p.getDeptCode())
  59. && StringUtil.notBlank(p.getDoctorCode())) {
  60. regstrtn = mzDao.selectRegstrtn2(p);
  61. if (null != regstrtn) {
  62. regstrtn.setBegntime(p.getVisitDate());
  63. regstrtn.setDeptCode(p.getDeptCode());
  64. }
  65. } else {
  66. regstrtn = mzDao.selectRegstrtn(p.getPatNo(), p.getTimes());
  67. }
  68. // 当医生有医保姓名时,优先使用医保姓名
  69. try {
  70. String ybName = mzDao.getYbName(p.getDoctorCode());
  71. if(StringUtil.isNotEmpty(ybName) && regstrtn != null) {
  72. log.info("门诊挂号医生{},使用医保姓名:{}", p.getDoctorName(), ybName);
  73. regstrtn.setDrName(ybName);
  74. }
  75. } catch (Exception e) {
  76. log.error(e.getMessage());
  77. log.error("获取医保姓名出错:{}", p.getDoctorCode());
  78. }
  79. if (null == regstrtn) {
  80. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR,
  81. "mz_visit_table或t_si_pat_info 信息为空,请联系医生重开处方。");
  82. }
  83. if (StringUtil.notBlank(regstrtn.getMdtrtId())) {
  84. return ResultVoUtil.success("本次就诊已有医保登记[mdtrtId:" + regstrtn.getMdtrtId() + "],请勿重复办理。");
  85. }
  86. String hisOrdNum = p.getPatNo() + "_" + p.getTimes() + "_1";
  87. if (mipSettled(hisOrdNum)) {
  88. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR,
  89. "患者已完成移动医保支付,请勿重复办理。");
  90. }
  91. if (inMipSettleProcess(hisOrdNum)) {
  92. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR,
  93. "患者已进入移动医保支付流程,无法办理。");
  94. }
  95. if (!p.abortBeforeUploadFees()) {
  96. List<String> chargeCodeList = mzDao.selectHisChargeCodes(p.getPatNo(), p.getTimes());
  97. if (chargeCodeList.isEmpty()) {
  98. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "未找到收费明细,请先生成医保处方。");
  99. }
  100. // 查询处方是否有折扣
  101. String discount = queryDiscount(p.getPatNo(), p.getTimes(), chargeCodeList);
  102. if (!discount.equals("OK")) {
  103. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, discount);
  104. }
  105. }
  106. if (null == p.getInsutype()) {
  107. SiPatInfo siPatInfo = mzDao.selectSiPatInfoForMz(p.getPatNo(), p.getTimes());
  108. p.setInsuplcAdmdvs(siPatInfo.getInsuplcAdmdvs());
  109. p.setInsutype(siPatInfo.getInsutype());
  110. p.setPsnType(siPatInfo.getPsnType());
  111. p.setName(siPatInfo.getPsnName());
  112. p.setSocialNo(siPatInfo.getCertno());
  113. }
  114. ReadCardBizType readCardBizType = ReadCardBizType.get(p.getReadCardBizType());
  115. if (readCardBizType != ReadCardBizType.REGISTRATION && !p.getInsuplcAdmdvs().startsWith("32")) {
  116. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "省外异地的患者请读社保卡或医保电子凭证登记!");
  117. }
  118. if (existSettledButNotPay(p.getPatNo(), p.getTimes())) {
  119. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR,
  120. "有HIS未缴费的医保结算,无法办理医保登记。请先完成门诊缴费再重新办理。");
  121. }
  122. if (readCardBizType == ReadCardBizType.REGISTRATION) {
  123. MdtrtCertType mdtrtCertType = MdtrtCertType.getByLabel(p.getMdtrtCertType());
  124. regstrtn.setMdtrtCertType(mdtrtCertType.getCode());
  125. if (mdtrtCertType.getCode().equals(MdtrtCertType.SOCIAL_SECURITY_CARD.getCode())) {
  126. String[] out = p.getReadCardResult().split("\\|");
  127. regstrtn.setMdtrtCertNo(out[2] + "|" + p.getBusCardInfo());
  128. regstrtn.setCardSn(out[3]);
  129. } else if (mdtrtCertType.getCode().equals(MdtrtCertType.ELECTRONIC_VOUCHER.getCode())) {
  130. JSONObject qrinfo = JSONObject.parseObject(p.getReadCardResult());
  131. /*JSONObject qrdata = qrinfo.getJSONObject("data");
  132. if (null != qrdata) {
  133. qrinfo = qrdata;
  134. }*/
  135. regstrtn.setMdtrtCertNo(qrinfo.getString("ecToken"));
  136. }
  137. }
  138. JSONObject input = exec.makeTradeHeaderWithInsureArea(SiFunction.OUTPATIENT_REGISTRATION,
  139. p.getInsuplcAdmdvs(), p.getStaffId());
  140. regstrtn.setInsutype(p.getInsutype());
  141. regstrtn.setPsnType(p.getPsnType());
  142. regstrtn.setIptOtpNo(p.getPatNo());
  143. String ref = JSONObject.toJSONStringWithDateFormat(regstrtn, "yyyy-MM-dd HH:mm:ss");
  144. input.getJSONObject("input").put("data", JSONObject.parseObject(ref));
  145. JSONObject result = exec.executeTrade(input, SiFunction.OUTPATIENT_REGISTRATION);
  146. log.info("【操作员:{}】,门诊挂号:\n参数:{},\n结果:{}", p.getStaffId(), input, result);
  147. Integer infcode = result.getInteger(RESULT_CODE);
  148. logDao.insert(new SiLog(input, result, p.getPatNo(), p.getTimes(), infcode, regstrtn.getPsnNo()));
  149. if (infcode == 0) {
  150. setlinfoDao.deletePreSettleInfo(p.getPatNo(), p.getTimes());
  151. JSONObject output = result.getJSONObject(OUTPUT).getJSONObject("data");
  152. p.setMdtrtId(output.getString("mdtrt_id"));
  153. p.setVisitDate(regstrtn.getBegntime());
  154. mzDao.afterRegistrtn(p);
  155. return ResultVoUtil.success(p.getMdtrtId());
  156. }
  157. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, result.getString(ERROR_MESSAGE));
  158. }
  159. public ResultVo<String> revokeOutpatientRegistration(MzPatientInfo p) {
  160. if (null == p.getTimes()) {
  161. p.setTimes(mzDao.selectMaxTimes(p.getPatNo()));
  162. }
  163. SiPatInfo siPatInfo = mzDao.selectSiPatInfoForMz(p.getPatNo(), p.getTimes());
  164. if (null == siPatInfo || StringUtil.isBlank(siPatInfo.getMdtrtId())) {
  165. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "此患者没有有效的医保挂号信息。");
  166. }
  167. MzgjUtil.finishProcessing(p.getPatNo());
  168. RevokeRegRequest request = new RevokeRegRequest();
  169. request.setInsuplcAdmdvs(siPatInfo.getInsuplcAdmdvs()); ;
  170. request.setStaffId(p.getStaffId());
  171. request.setPsnNo(siPatInfo.getPsnNo());
  172. request.setMdtrtId(siPatInfo.getMdtrtId());
  173. request.setPatNo(p.getPatNo());
  174. request.setTimes(p.getTimes());
  175. return executeOutpatientRegRevoke(request);
  176. }
  177. public ResultVo<String> executeOutpatientRegRevoke(RevokeRegRequest request) {
  178. int upldfCnt = mzDao.getUpldfCnt(request.getPatNo(), request.getTimes());
  179. if (upldfCnt > 0) {
  180. MzPatientInfo ptnt = new MzPatientInfo();
  181. ptnt.setPatNo(request.getPatNo());
  182. ptnt.setTimes(request.getTimes());
  183. ptnt.setStaffId(request.getStaffId());
  184. revokeOutpatientFeeDetails(ptnt);
  185. }
  186. JSONObject input = exec.makeTradeHeaderWithInsureArea(SiFunction.REVOKE_OUTPATIENT_REGISTRATION,
  187. request.getInsuplcAdmdvs(), request.getStaffId());
  188. JSONObject data = new JSONObject();
  189. data.put("psn_no", request.getPsnNo());
  190. data.put("mdtrt_id", request.getMdtrtId());
  191. data.put("ipt_otp_no", request.getPatNo());
  192. input.getJSONObject("input").put("data", data);
  193. JSONObject result = exec.executeTrade(input, SiFunction.REVOKE_OUTPATIENT_REGISTRATION);
  194. log.info("【操作员:{}】,取消门诊挂号:\n参数:{},\n结果:{}", request.getStaffId(), input, result);
  195. Integer infcode = result.getInteger(RESULT_CODE);
  196. logDao.insert(new SiLog(input, result, request.getPatNo(), request.getTimes(), infcode, request.getPsnNo()));
  197. String errMsg = result.getString(ERROR_MESSAGE);
  198. if (infcode == 0 || noMdtrtData(errMsg)) {
  199. mzDao.clearMdtrtIdForMz(request.getPatNo(), request.getTimes(), null);
  200. setlinfoDao.deletePreSettleInfo(request.getPatNo(), request.getTimes());
  201. return ResultVoUtil.success("取消门诊挂号成功。");
  202. }
  203. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, errMsg);
  204. }
  205. private boolean noMdtrtData(String msg) {
  206. if (null == msg) {
  207. return false;
  208. }
  209. return msg.contains("未查询到任何就诊登记信息") || msg.contains("不存在该就诊信息");
  210. }
  211. public ResultVo<String> uploadOutpatientInfo(MzPatientInfo mzptnt, SpcChrDiseAcct spcChrDiseAcct, SiPatInfo siPatInfo) {
  212. JSONObject input = exec.makeTradeHeaderWithInsureArea(SiFunction.UPLOAD_OUTPATIENT_INFO,
  213. siPatInfo.getInsuplcAdmdvs(), spcChrDiseAcct.getStaffId());
  214. JSONObject mdtrtinfo = new JSONObject();
  215. List<Diagnoses> diagnosesList = new ArrayList<>();
  216. String icdCodeNew = mzDao.selectIcdCodeNew(siPatInfo.getPatNo(), siPatInfo.getTimes());
  217. if (StringUtil.isBlank(icdCodeNew) && null != mzptnt) {
  218. icdCodeNew = mzptnt.getIcdCodeNew();
  219. }
  220. if (StringUtil.notBlank(icdCodeNew)) {
  221. Diagnoses base = mzDao.selectDiseinfo(siPatInfo.getPatNo(), siPatInfo.getTimes());
  222. if (null == base && null != mzptnt) {
  223. CodeName dor = mzDao.getDorCodeAndName(mzptnt.getDoctorCode());
  224. base = new Diagnoses();
  225. base.setDiagDept(mzptnt.getDeptCode());
  226. base.setDiagTime(mzptnt.getVisitDate());
  227. base.setDiseDorNo(dor.getCode());
  228. base.setDiseDorName(dor.getName());
  229. }
  230. // 当有医保姓名时,优先使用医保姓名
  231. try {
  232. // String ybName = mzDao.getYbName(base.getDiseDorNo());
  233. if(StringUtil.isNotEmpty(base.getYbName())){
  234. log.info("门诊就诊信息上传医生{},使用医保姓名:{}", base.getDiseDorName(), base.getYbName());
  235. base.setDiseDorName(base.getYbName());
  236. }
  237. } catch (Exception e) {
  238. log.error(e.getMessage());
  239. log.error("获取医保姓名出错:{}", base.getDiseDorNo());
  240. }
  241. String[] icds = icdCodeNew.split(",");
  242. for (int i = 0; i < icds.length; i++) {
  243. String icd = icds[i];
  244. String icdTextNew = mzDao.selectIcdTextNew(icd);
  245. Diagnoses diag = new Diagnoses();
  246. diag.setDiagCode(icd);
  247. diag.setDiagName(icdTextNew);
  248. diag.setDiagSrtNo(i + 1);
  249. diag.setDiagType("1");
  250. diag.setValiFlag("1");
  251. diag.setDiagDept(base.getDiagDept());
  252. diag.setDiagTime(base.getDiagTime());
  253. diag.setDiseDorNo(base.getDiseDorNo());
  254. diag.setDiseDorName(base.getDiseDorName());
  255. diagnosesList.add(diag);
  256. }
  257. } else {
  258. diagnosesList = mzDao.selectMzDiags(siPatInfo.getPatNo(), siPatInfo.getTimes());
  259. if (null == diagnosesList || diagnosesList.isEmpty()) {
  260. log.info("【{}】 上传就诊信息失败,门诊诊断为空。", siPatInfo.getPatNo());
  261. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "患者的门诊诊断为空,请联系医生填写。");
  262. }
  263. }
  264. if (Objects.equals(siPatInfo.getMedType(), "140104") || Objects.equals(siPatInfo.getMedType(), "1402")) {
  265. if (StringUtil.isBlank(spcChrDiseAcct.getOpspDiseCode())) {
  266. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "慢特病门诊病种不能为空 !");
  267. }
  268. }
  269. mdtrtinfo.put("mdtrt_id", siPatInfo.getMdtrtId());
  270. mdtrtinfo.put("psn_no", siPatInfo.getPsnNo());
  271. mdtrtinfo.put("med_type", siPatInfo.getMedType());
  272. mdtrtinfo.put("begntime", DateUtil.formatDatetime(siPatInfo.getVisitDatetime()));
  273. mdtrtinfo.put("main_cond_dscr", "");
  274. mdtrtinfo.put("dise_codg", spcChrDiseAcct.getOpspDiseCode());
  275. mdtrtinfo.put("dise_name", spcChrDiseAcct.getOpspDiseName());
  276. mdtrtinfo.put("matn_type", siPatInfo.getMatnType());
  277. mdtrtinfo.put("birctrl_type", "");
  278. mdtrtinfo.put("birctrl_matn_date", "");
  279. mdtrtinfo.put("exp_content", spcChrDiseAcct.getExpContent());
  280. String ref = JSONObject.toJSONString(diagnosesList);
  281. input.getJSONObject("input").put("mdtrtinfo", mdtrtinfo);
  282. input.getJSONObject("input").put("diseinfo", JSONArray.parse(ref));
  283. JSONObject result = exec.executeTrade(input, SiFunction.UPLOAD_OUTPATIENT_INFO);
  284. log.info("【操作员:{}】门诊就诊信息上传:\n参数:{},\n结果:{}", spcChrDiseAcct.getStaffId(), input, result);
  285. Integer infcode = result.getInteger(RESULT_CODE);
  286. logDao.insert(new SiLog(input, result, siPatInfo.getPatNo(), siPatInfo.getTimes(), infcode, siPatInfo.getPsnNo()));
  287. if (result.getIntValue(RESULT_CODE) == 0) {
  288. Diagnoses main = diagnosesList.get(0);
  289. mzDao.updatePatDiseinfo(siPatInfo.getPatNo(), siPatInfo.getTimes(), main.getDiagCode(), main.getDiagName());
  290. return ResultVoUtil.success("门诊就诊信息上传成功。");
  291. }
  292. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, result.getString(ERROR_MESSAGE));
  293. }
  294. public ResultVo<SiPatInfo> uploadOutpatientFeeDetails(SpcChrDiseAcct p) {
  295. String patNo = p.getPatNo();
  296. if (null == p.getTimes()) {
  297. p.setTimes(mzDao.selectMaxTimes(patNo));
  298. }
  299. SiPatInfo siPatInfo = mzDao.selectSiPatInfoForMz(patNo, p.getTimes());
  300. if (null == siPatInfo || StringUtil.isBlank(siPatInfo.getMdtrtId())) {
  301. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "【门诊号:" + patNo +
  302. "】未找到此患者的医保挂号信息,请核实。");
  303. }
  304. if (!p.getFromDirectReg()) {
  305. ResultVo<String> uplRes = uploadOutpatientInfo(null, p, siPatInfo);
  306. if (null != uplRes && uplRes.getCode() != ExceptionEnum.SUCCESS.getCode()) {
  307. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, uplRes.getMessage());
  308. }
  309. }
  310. List<FeeDetail> feeDetails = mzDao.selectOutpatientFees(patNo, p.getTimes());
  311. if (null == feeDetails || feeDetails.isEmpty()) {
  312. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "此患者没有需要上传的费用。");
  313. }
  314. feeDetails.removeIf(item -> StringUtil.isBlank(item.getMedListCodg()));
  315. MzVisit mzVisit = mzDao.selectMzVisitInfo(patNo, p.getTimes());
  316. if (null == mzVisit || StringUtil.isBlank(mzVisit.getVisitDeptCode())) {
  317. log.info("【{},{}】就诊科室没有匹配医保码,无法使用门诊统筹。", patNo, p.getTimes());
  318. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "就诊科室没有匹配医保码,无法使用门诊统筹。");
  319. }
  320. String batchNo = patNo + "_" + p.getTimes();
  321. feeDetails.forEach(item -> {
  322. item.setMdtrtId(siPatInfo.getMdtrtId());
  323. item.setPsnNo(siPatInfo.getPsnNo());
  324. item.setChrgBchno(batchNo);
  325. item.setRxCircFlag(YesOrNo.NO.getCodeStr());
  326. item.setBilgDeptCodg(mzVisit.getVisitDeptCode());
  327. item.setBilgDeptName(mzVisit.getVisitDeptName());
  328. if (Objects.equals(item.getHospApprFlag(), "0")) {
  329. item.setHospApprFlag("1");
  330. }
  331. if (siPatInfo.getMedType().equals("51")) {
  332. item.setMatnFeeFlag("1");
  333. }
  334. try {
  335. if (Objects.equals(item.getClassCode(), "J")) {
  336. JSONObject expContent = new JSONObject();
  337. expContent.put("mcs_prov_code", item.getHnsybCode());
  338. item.setExpContent(expContent);
  339. log.info("门诊费用明细信息上传耗材:\n参数:{}", JSONObject.toJSONString(item));
  340. }
  341. } catch (Exception e) {
  342. log.info("门诊费用明细信息上传耗材失败:\n错误信息:{}", e.getMessage());
  343. }
  344. // 当医生有医保姓名时,优先使用医保姓名
  345. try {
  346. if(StringUtil.isNotEmpty(item.getYbName())) {
  347. log.info("门诊费用上传医生{},使用医保姓名:{}", item.getBilgDrName(), item.getYbName());
  348. item.setBilgDrName(item.getYbName());
  349. }
  350. } catch (Exception e) {
  351. log.error(e.getMessage());
  352. log.error("获取医保姓名出错:{}", item.getYbName());
  353. }
  354. });
  355. JSONObject input = exec.makeTradeHeaderWithInsureArea(SiFunction.UPLOAD_OUTPATIENT_FEE_DETAILS,
  356. siPatInfo.getInsuplcAdmdvs(), p.getStaffId());
  357. String ref = JSONArray.toJSONStringWithDateFormat(feeDetails, "yyyy-MM-dd HH:mm:ss");
  358. JSONArray feedetail = JSONArray.parseArray(ref);
  359. input.getJSONObject("input").put("feedetail", feedetail);
  360. JSONObject result = exec.executeTrade(input, SiFunction.UPLOAD_OUTPATIENT_FEE_DETAILS);
  361. log.info("【操作员:{}】门诊费用明细信息上传:\n参数:{},\n结果:{}", p.getStaffId(), input, result);
  362. Integer infcode = result.getInteger(RESULT_CODE);
  363. logDao.insert(new SiLog(input, result, p.getPatNo(), p.getTimes(), infcode, siPatInfo.getPsnNo()));
  364. if (infcode == 0) {
  365. JSONArray feeRes = result.getJSONObject(OUTPUT).getJSONArray("result");
  366. double fulamtOwnpayAmt = 0d;
  367. double overlmtAmt = 0d;
  368. double preselfpayAmt = 0d;
  369. double inscpScpAmt = 0d;
  370. for (int i = 0; i < feeRes.size(); i++) {
  371. JSONObject fee = feeRes.getJSONObject(i);
  372. fulamtOwnpayAmt += fee.getDoubleValue("fulamt_ownpay_amt");
  373. overlmtAmt += fee.getDoubleValue("overlmt_amt");
  374. preselfpayAmt += fee.getDoubleValue("preselfpay_amt");
  375. inscpScpAmt += fee.getDoubleValue("inscp_scp_amt");
  376. String detlSn = fee.getString("feedetl_sn");
  377. String chrgLv = fee.getString("chrgitm_lv");
  378. String chrgType = fee.getString("med_chrgitm_type");
  379. String[] sns = detlSn.split("_");
  380. int times = Integer.parseInt(sns[1]);
  381. int recNo = Integer.parseInt(sns[2]);
  382. int odrNo = Integer.parseInt(sns[3]);
  383. int itmNo = Integer.parseInt(sns[4]);
  384. mzDao.afterUploadFees(patNo, times, recNo, odrNo, itmNo, chrgLv, chrgType);
  385. }
  386. siPatInfo.setFulamtOwnpayAmt(fulamtOwnpayAmt);
  387. siPatInfo.setOverlmtAmt(overlmtAmt);
  388. siPatInfo.setPreselfpayAmt(preselfpayAmt);
  389. siPatInfo.setInscpScpAmt(inscpScpAmt);
  390. mzDao.updateSortOfAmt(siPatInfo);
  391. setlinfoDao.deletePreSettleInfo(p.getPatNo(), p.getTimes());
  392. return ResultVoUtil.success(siPatInfo);
  393. }
  394. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, result.getString(ERROR_MESSAGE));
  395. }
  396. public ResultVo<String> revokeOutpatientFeeDetails(MzPatientInfo p) {
  397. if (null == p.getTimes()) {
  398. p.setTimes(mzDao.selectMaxTimes(p.getPatNo()));
  399. }
  400. SiPatInfo siPatInfo = mzDao.selectSiPatInfoForMz(p.getPatNo(), p.getTimes());
  401. if (null == siPatInfo || StringUtil.isBlank(siPatInfo.getMdtrtId())) {
  402. return ResultVoUtil.fail(ExceptionEnum.NULL_POINTER, "没有此患者的医保挂号信息!");
  403. }
  404. JSONObject input = exec.makeTradeHeaderWithInsureArea(SiFunction.REVOKE_OUTPATIENT_FEE_DETAILS,
  405. siPatInfo.getInsuplcAdmdvs(), p.getStaffId());
  406. JSONObject data = new JSONObject();
  407. data.put("mdtrt_id", siPatInfo.getMdtrtId());
  408. data.put("psn_no", siPatInfo.getPsnNo());
  409. data.put("chrg_bchno", "0000");
  410. input.getJSONObject("input").put("data", data);
  411. JSONObject result = exec.executeTrade(input, SiFunction.REVOKE_OUTPATIENT_FEE_DETAILS);
  412. log.info("【操作员:{}】门诊费用明细信息撤销,参数:{},结果:{}", p.getStaffId(), input, result);
  413. Integer infcode = result.getInteger(RESULT_CODE);
  414. logDao.insert(new SiLog(input, result, p.getPatNo(), p.getTimes(), infcode, siPatInfo.getPsnNo()));
  415. if (infcode == 0) {
  416. mzDao.afterRevokeFees(p.getPatNo(), p.getTimes());
  417. setlinfoDao.deletePreSettleInfo(p.getPatNo(), p.getTimes());
  418. return ResultVoUtil.success("门诊费用明细信息撤销成功。");
  419. }
  420. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, result.getString(ERROR_MESSAGE));
  421. }
  422. public ResultVo<FundDetail> outpatientPreSettlement(MzPatientInfo p) {
  423. if (null == p.getTimes()) {
  424. p.setTimes(mzDao.selectMaxTimes(p.getPatNo()));
  425. }
  426. ResultVo<FundDetail> setlfund = getFundDetailByPatientInfo(p.getPatNo(), p.getTimes(), false);
  427. if (setlfund != null) {
  428. return setlfund;
  429. }
  430. MzPreSetlmt mzPreSetlmt = mzDao.selectPreSetlmt(p.getPatNo(), p.getTimes());
  431. if (null == mzPreSetlmt || null == mzPreSetlmt.getMedfeeSumamt()) {
  432. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "患者没有已上传的费用。");
  433. }
  434. ReadCardBizType readCardBizType = ReadCardBizType.get(p.getReadCardBizType());
  435. if (readCardBizType == ReadCardBizType.SETTLEMENT) {
  436. MdtrtCertType mdtrtCertType = MdtrtCertType.getByLabel(p.getMdtrtCertType());
  437. mzPreSetlmt.setMdtrtCertType(mdtrtCertType.getCode());
  438. if (mdtrtCertType.getCode().equals(MdtrtCertType.SOCIAL_SECURITY_CARD.getCode())) {
  439. String[] out = p.getReadCardResult().split("\\|");
  440. mzPreSetlmt.setMdtrtCertNo(out[2]);
  441. mzPreSetlmt.setCardSn(out[3]);
  442. } else if (mdtrtCertType.getCode().equals(MdtrtCertType.ELECTRONIC_VOUCHER.getCode())) {
  443. String socialNo = mzDao.selectSocialNo(p.getPatNo());
  444. JSONObject qrinfo = JSONObject.parseObject(p.getReadCardResult());
  445. JSONObject qrdata = qrinfo.getJSONObject("data");
  446. if (null != qrdata) {
  447. qrinfo = qrdata;
  448. }
  449. if (!Objects.equals(socialNo, qrinfo.getString("idNo").trim())) {
  450. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "电子医保凭证身份证与HIS身份证不一致,请确认是否人证相符。");
  451. }
  452. mzPreSetlmt.setMdtrtCertNo(qrinfo.getString("ecToken"));
  453. }
  454. }
  455. mzPreSetlmt.setMedfeeSumamt(mzPreSetlmt.getMedfeeSumamt().setScale(2, RoundingMode.HALF_UP));
  456. JSONObject input = exec.makeTradeHeaderWithInsureArea(SiFunction.OUTPATIENT_PRE_SETTLEMENT,
  457. mzPreSetlmt.getInsuplcAdmdvs(), p.getStaffId());
  458. mzPreSetlmt.setPsnSetlway(PsnSetlWay.SETTLE_BY_ITEMS.getCode());
  459. if (p.getAcctUsedFlag() == 2) {
  460. p.setAcctUsedFlag(1);
  461. }
  462. mzPreSetlmt.setAcctUsedFlag(String.valueOf(p.getAcctUsedFlag()));
  463. mzPreSetlmt.setChrgBchno(p.getPatNo() + "_" + p.getTimes());
  464. mzPreSetlmt.setExpContent(p.getExpContent());
  465. String ref = JSONObject.toJSONString(mzPreSetlmt);
  466. input.getJSONObject("input").put("data", JSONObject.parseObject(ref));
  467. JSONObject result = exec.executeTrade(input, SiFunction.OUTPATIENT_PRE_SETTLEMENT);
  468. log.info("【操作员:{}】门诊预结算:\n参数:{},\n结果:{}", p.getStaffId(), input, result);
  469. Integer infcode = result.getInteger(RESULT_CODE);
  470. logDao.insert(new SiLog(input, result, p.getPatNo(), p.getTimes(), infcode, mzPreSetlmt.getPsnNo()));
  471. if (infcode == 0) {
  472. setlinfoDao.deletePreSettleInfo(p.getPatNo(), p.getTimes());
  473. JSONObject setlinfo = result.getJSONObject(OUTPUT).getJSONObject("setlinfo");
  474. FundDetail fundDetail = new FundDetail();
  475. fundDetail.setTotalCost(setlinfo.getString("medfee_sumamt"));
  476. fundDetail.setFundPay(setlinfo.getString("fund_pay_sumamt"));
  477. fundDetail.setCashPay(setlinfo.getString("psn_cash_pay"));
  478. fundDetail.setAcctPay(setlinfo.getString("acct_pay"));
  479. fundDetail.setSelfPay(setlinfo.getString("psn_part_amt"));
  480. fundDetail.setCardType(getCardType(mzPreSetlmt.getInsuplcAdmdvs()));
  481. SiSetlinfo setlEntity = JSONObject.parseObject(setlinfo.toJSONString(), SiSetlinfo.class);
  482. setlEntity.setPatNo(p.getPatNo());
  483. setlEntity.setTimes(p.getTimes());
  484. setlEntity.setLedgerSn(0);
  485. setlEntity.setStaffId(p.getStaffId());
  486. setlEntity.setSetlType(ClrType.OUTPATIENT.getCode());
  487. setlEntity.setInsuplcAdmdvs(mzPreSetlmt.getInsuplcAdmdvs());
  488. log.info("开始插入预结算临时信息:{}_{}", p.getPatNo(), p.getTimes());
  489. setlinfoDao.insertPreSettleInfo(setlEntity);
  490. log.info("插入预结算临时信息成功:{}_{}", p.getPatNo(), p.getTimes());
  491. return ResultVoUtil.success(fundDetail);
  492. }
  493. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, result.getString(ERROR_MESSAGE));
  494. }
  495. private ResultVo<FundDetail> getFundDetailByPatientInfo(String patNo, int times, boolean realSettle) {
  496. SiSetlinfo sisetlinfo = mzDao.selectSettledInfo(patNo, times, 0);
  497. if (!realSettle && null == sisetlinfo) {
  498. sisetlinfo = setlinfoDao.selectPresettleInfo(patNo, times);
  499. }
  500. if (null != sisetlinfo) {
  501. return getFundDetailFromSetlinfo(sisetlinfo);
  502. }
  503. return null;
  504. }
  505. private ResultVo<FundDetail> getFundDetailFromSetlinfo(SiSetlinfo setlinfo) {
  506. FundDetail fundDetail = new FundDetail();
  507. fundDetail.setCardType(getCardType(setlinfo.getInsuplcAdmdvs()));
  508. fundDetail.setTotalCost(String.valueOf(setlinfo.getMedfeeSumamt()));
  509. fundDetail.setFundPay(String.valueOf(setlinfo.getFundPaySumamt()));
  510. fundDetail.setAcctPay(String.valueOf(setlinfo.getAcctPay()));
  511. fundDetail.setCashPay(String.valueOf(setlinfo.getPsnCashPay()));
  512. fundDetail.setSelfPay(String.valueOf(setlinfo.getPsnCashPay()));
  513. if (setlinfo.getRevoked() == 1) {
  514. fundDetail.reverseAll();
  515. }
  516. fundDetail.setSetlinfo(setlinfo);
  517. return ResultVoUtil.success(fundDetail);
  518. }
  519. private Integer getCardType(String insplc) {
  520. if (insplc.startsWith("3213")) {
  521. return 1;
  522. } else if (insplc.equals("329900")) {
  523. return 2;
  524. }
  525. return 3;
  526. }
  527. public ResultVo<FundDetail> outpatientSettlement(MzPatientInfo p) {
  528. ResultVo<FundDetail> setlfund = getFundDetailByPatientInfo(p.getPatNo(), p.getTimes(), true);
  529. if (setlfund != null) {
  530. return setlfund;
  531. }
  532. Setlmt setlmt = mzDao.selectSetlmt(p.getPatNo(), p.getTimes());
  533. if (null == setlmt) {
  534. return ResultVoUtil.fail(ExceptionEnum.NULL_POINTER, "没有此患者的医保就诊信息。");
  535. }
  536. p.setInsuplcAdmdvs(setlmt.getInsuplcAdmdvs());
  537. p.setPsnNo(setlmt.getPsnNo());
  538. p.setMdtrtId(setlmt.getMdtrtId());
  539. JSONObject input = exec.makeTradeHeaderWithInsureArea(SiFunction.OUTPATIENT_SETTLEMENT,
  540. setlmt.getInsuplcAdmdvs(), p.getStaffId());
  541. ReadCardBizType readCardBizType = ReadCardBizType.get(p.getReadCardBizType());
  542. if (readCardBizType != null) {
  543. MdtrtCertType mdtrtCertType = MdtrtCertType.getByLabel(p.getMdtrtCertType());
  544. setlmt.setMdtrtCertType(mdtrtCertType.getCode());
  545. if (mdtrtCertType.getCode().equals(MdtrtCertType.SOCIAL_SECURITY_CARD.getCode())) {
  546. String[] out = p.getReadCardResult().split("\\|");
  547. setlmt.setMdtrtCertNo(out[2] + "|" + p.getBusCardInfo());
  548. setlmt.setCardSn(out[3]);
  549. } else if (mdtrtCertType.getCode().equals(MdtrtCertType.ELECTRONIC_VOUCHER.getCode())) {
  550. String socialNo = mzDao.selectSocialNo(p.getPatNo());
  551. JSONObject qrinfo = JSONObject.parseObject(p.getReadCardResult());
  552. if (!Objects.equals(socialNo, qrinfo.getString("idNo").trim())) {
  553. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "电子医保凭证身份证与HIS身份证不一致,请确认是否人证相符。");
  554. }
  555. setlmt.setMdtrtCertNo(qrinfo.getString("ecToken"));
  556. }
  557. }
  558. setlmt.setMedfeeSumamt(setlmt.getMedfeeSumamt().setScale(2, RoundingMode.HALF_UP));
  559. setlmt.setPsnSetlway(PsnSetlWay.SETTLE_BY_ITEMS.getCode());
  560. setlmt.setChrgBchno(p.getPatNo() + "_" + p.getTimes());
  561. Integer acctUsedFlag = p.getRealAcctUsedFlag();
  562. if (null == acctUsedFlag) {
  563. Double acctPay = mzDao.selectAcctPayInPreSettle(setlmt.getMdtrtId());
  564. if (null != acctPay && acctPay > 0) {
  565. acctUsedFlag = 1;
  566. } else {
  567. acctUsedFlag = 0;
  568. }
  569. }
  570. setlmt.setAcctUsedFlag(String.valueOf(acctUsedFlag));
  571. setlmt.setInvono(SnowFlakeId.getInstance().nextId());
  572. setlmt.setExpContent(p.getExpContent());
  573. String ref = JSONObject.toJSONString(setlmt);
  574. input.getJSONObject("input").put("data", JSONObject.parseObject(ref));
  575. JSONObject result = exec.executeTrade(input, SiFunction.OUTPATIENT_SETTLEMENT);
  576. log.info("【操作员:{}】门诊结算:\n参数:{},\n结果:{}", p.getStaffId(), input, result);
  577. Integer infcode = result.getInteger(RESULT_CODE);
  578. logDao.insert(new SiLog(input, result, p.getPatNo(), p.getTimes(), infcode, setlmt.getPsnNo()));
  579. if (infcode == 0) {
  580. JSONObject setlinfo = result.getJSONObject(OUTPUT).getJSONObject("setlinfo");
  581. SiSetlinfo setlEntity = JSONObject.parseObject(setlinfo.toJSONString(), SiSetlinfo.class);
  582. List<SiSetldetail> fundList = new ArrayList<>();
  583. JSONArray setldetail = result.getJSONObject(OUTPUT).getJSONArray("setldetail");
  584. for (int i = 0; i < setldetail.size(); i++) {
  585. SiSetldetail setldetailEntity = JSONObject.parseObject(setldetail.getJSONObject(i).toJSONString(),
  586. SiSetldetail.class);
  587. fundList.add(setldetailEntity);
  588. }
  589. setlEntity.setSetldetail(fundList);
  590. return dealSetlEntity(p, setlEntity);
  591. }
  592. String errMsg = result.getString(ERROR_MESSAGE);
  593. if (errMsg.contains("服务提供者后端服务响应超时")) {
  594. return timeoutSetl(p);
  595. }
  596. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, errMsg);
  597. }
  598. public ResultVo<FundDetail> timeoutSetl(MzPatientInfo p) {
  599. if (StringUtil.isBlank(p.getMdtrtId())) {
  600. p.setMdtrtId(mzDao.getMdtrtId(p.getPatNo(), p.getTimes()));
  601. }
  602. if (StringUtil.isBlank(p.getMdtrtId())) {
  603. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "没有找到患者的医保就诊信息!");
  604. }
  605. ResultVo<FundDetail> setlfund = getFundDetailByPatientInfo(p.getPatNo(), p.getTimes(), true);
  606. if (setlfund != null) {
  607. return setlfund;
  608. }
  609. SiSetlinfo setlEntity = querySettlementInfo(p);
  610. if (null != setlEntity) {
  611. return dealSetlEntity(p, setlEntity);
  612. }
  613. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "超时结算失败。");
  614. }
  615. private ResultVo<FundDetail> dealSetlEntity(MzPatientInfo p, SiSetlinfo setlEntity) {
  616. saveSetlinfoToDatabase(setlEntity, p);
  617. setlinfoDao.deletePreSettleInfo(p.getPatNo(), p.getTimes());
  618. return getFundDetailFromSetlinfo(setlEntity);
  619. }
  620. private SiSetlinfo querySettlementInfo(MzPatientInfo p) {
  621. String url = "http://130.150.161.72:8706/siQuery/querySettlementInfo";
  622. JSONObject params = new JSONObject();
  623. params.put("psnNo", p.getPsnNo());
  624. params.put("mdtrtId", p.getMdtrtId());
  625. ResultVo<LinkedHashMap> vo = new RestTemplate().postForObject(url, params, ResultVo.class);
  626. if (null == vo || vo.getCode() != ExceptionEnum.SUCCESS.getCode()) {
  627. return null;
  628. }
  629. LinkedHashMap resMap = vo.getData();
  630. SiSetlinfo entity = JSONObject.parseObject(JSON.toJSONString(resMap), SiSetlinfo.class);
  631. entity.setInsuplcAdmdvs(resMap.get("insuOptins").toString());
  632. if (null == entity.getPsnPartAmt()) {
  633. entity.setPsnPartAmt(new BigDecimal(resMap.get("psnPay").toString()));
  634. }
  635. if (null == entity.getPsnCashPay()) {
  636. entity.setPsnCashPay(new BigDecimal(resMap.get("cashPayamt").toString()));
  637. }
  638. return entity;
  639. }
  640. private void saveSetlinfoToDatabase(SiSetlinfo setlEntity, MzPatientInfo p) {
  641. setlEntity.setPatNo(p.getPatNo());
  642. setlEntity.setTimes(p.getTimes());
  643. setlEntity.setLedgerSn(0);
  644. setlEntity.setStaffId(p.getStaffId());
  645. setlEntity.setRevoked(YesOrNo.NO.getCode());
  646. setlEntity.setInsuplcAdmdvsName(mzDao.getInsuplcAdmdvsName(setlEntity.getMdtrtId()));
  647. setlEntity.setSetlType(ClrType.OUTPATIENT.getCode());
  648. if (StringUtil.isBlank(setlEntity.getInsuplcAdmdvs())) {
  649. setlEntity.setInsuplcAdmdvs(p.getInsuplcAdmdvs());
  650. }
  651. setlEntity.setBegntime(mzDao.selectBegntime(p.getPatNo(), p.getTimes()));
  652. setlEntity.setEndtime(setlEntity.getSetlTime());
  653. setlEntity.setMzSaved(p.getSaved());
  654. BigDecimal hospitalPart = BigDecimal.ZERO;
  655. List<SiSetldetail> fundList = setlEntity.getSetldetail();
  656. fundList = null == fundList ? new ArrayList<>() : fundList;
  657. for (int i = 0; i < fundList.size(); i++) {
  658. SiSetldetail detail = fundList.get(i);
  659. detail.setPatNo(p.getPatNo());
  660. detail.setTimes(p.getTimes());
  661. detail.setSetlId(setlEntity.getSetlId());
  662. detail.setSortNo(i + 1);
  663. detail.setLedgerSn(0);
  664. if (Objects.equals(detail.getFundPayType(),"999996")) {
  665. hospitalPart = hospitalPart.add(BigDecimal.valueOf(detail.getFundPayamt()));
  666. }
  667. setldetailDao.insert(detail);
  668. }
  669. setlEntity.setHospPartAmt(hospitalPart);
  670. setlinfoDao.insert(setlEntity);
  671. setlinfoDao.updateSiZyInfoSetlId(p.getPatNo(), p.getTimes(), 0, setlEntity.getSetlId(),
  672. setlEntity.getMedinsSetlId(), setlEntity.getMedinsSetlId());
  673. webHisService.saveCumInfo(hisApi.getZy(), setlEntity);
  674. }
  675. public ResultVo<FundDetail> revokeOutpatientSettlement(MzPatientInfo p) {
  676. log.info("请求撤销门诊医保结算:{}", JSONObject.toJSON(p));
  677. if (null == p.getTimes()) {
  678. p.setTimes(mzDao.selectMaxTimes(p.getPatNo()));
  679. }
  680. SiSetlinfo setlinfo = mzDao.selectSettledInfo(p.getPatNo(), p.getTimes(), 0);
  681. if (null == setlinfo) {
  682. if (p.needRevokeRegistration()) {
  683. deletePresettleInfoAndRevokeYb(p);
  684. }
  685. setlinfo = mzDao.selectSettledInfo(p.getPatNo(), p.getTimes(), 1);
  686. if (null == setlinfo) {
  687. return ResultVoUtil.fail(ExceptionEnum.NULL_POINTER, "没有此患者的已结算数据。");
  688. }
  689. return getFundDetailFromSetlinfo(setlinfo);
  690. }
  691. JSONObject input = exec.makeTradeHeaderWithInsureArea(SiFunction.REVOKE_OUTPATIENT_SETTLEMENT,
  692. mzDao.selectAdmdvs(setlinfo.getPatNo(), setlinfo.getTimes(), setlinfo.getLedgerSn()), p.getStaffId());
  693. JSONObject data = new JSONObject();
  694. data.put("setl_id", setlinfo.getSetlId());
  695. data.put("mdtrt_id", setlinfo.getMdtrtId());
  696. data.put("psn_no", setlinfo.getPsnNo());
  697. input.getJSONObject("input").put("data", data);
  698. JSONObject result = exec.executeTrade(input, SiFunction.REVOKE_OUTPATIENT_SETTLEMENT);
  699. log.info("【操作员:{}】门诊结算撤销:\n参数:{},\n结果:{}", p.getStaffId(), input, result);
  700. Integer infcode = result.getInteger(RESULT_CODE);
  701. logDao.insert(new SiLog(input, result, p.getPatNo(), p.getTimes(), infcode, setlinfo.getPsnNo()));
  702. if (p.needRevokeRegistration()) {
  703. deletePresettleInfoAndRevokeYb(p);
  704. }
  705. if (infcode == 0) {
  706. afterRevokeSetl(p.getPatNo(), p.getTimes(), input.getString("msgid"));
  707. return getFundDetailFromSetlinfo(setlinfo);
  708. }
  709. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, result.getString(ERROR_MESSAGE));
  710. }
  711. public void revokeOutpatientSettlementForTask(SiSetlinfo setlinfo) {
  712. JSONObject input = exec.makeTradeHeaderWithInsureArea(SiFunction.REVOKE_OUTPATIENT_SETTLEMENT,
  713. mzDao.selectAdmdvs(setlinfo.getPatNo(), setlinfo.getTimes(), setlinfo.getLedgerSn()), "99999");
  714. JSONObject data = new JSONObject();
  715. data.put("setl_id", setlinfo.getSetlId());
  716. data.put("mdtrt_id", setlinfo.getMdtrtId());
  717. data.put("psn_no", setlinfo.getPsnNo());
  718. input.getJSONObject("input").put("data", data);
  719. JSONObject result = exec.executeTrade(input, SiFunction.REVOKE_OUTPATIENT_SETTLEMENT);
  720. log.info("【操作员:99999】门诊结算撤销:\n参数:{},\n结果:{}", input, result);
  721. Integer infcode = result.getInteger(RESULT_CODE);
  722. logDao.insert(new SiLog(input, result, setlinfo.getPatNo(), setlinfo.getTimes(), infcode, setlinfo.getPsnNo()));
  723. if (null != infcode && infcode == 0) {
  724. afterRevokeSetl(setlinfo.getPatNo(), setlinfo.getTimes(), input.getString("msgid"));
  725. MzPatientInfo mzPatientInfo = new MzPatientInfo();
  726. mzPatientInfo.setPatNo(setlinfo.getPatNo());
  727. mzPatientInfo.setTimes(setlinfo.getTimes());
  728. mzPatientInfo.setStaffId("99999");
  729. revokeOutpatientFeeDetails(mzPatientInfo);
  730. revokeOutpatientRegistration(mzPatientInfo);
  731. }
  732. }
  733. public void afterRevokeSetl(String patNo, int times, String msgId) {
  734. MzgjUtil.finishProcessing(patNo);
  735. try {
  736. mzDao.deleteSetlInfo(patNo, times);
  737. mzDao.deleteSetlDetail(patNo, times);
  738. mzDao.updateRvkSetlMsgid(patNo, times, msgId);
  739. setlinfoDao.deletePreSettleInfo(patNo, times);
  740. } catch (Exception e) {
  741. String sql1 = String.format("update t_si_setlinfo set revoked=1,mz_saved=0 where pat_no='%s' and times=%d;\n", patNo, times);
  742. String sql2 = String.format("delete from t_si_setldetail where pat_no='%s' and times=%d;\n", patNo, times);
  743. String sql3 = String.format("update t_si_pat_info set rvk_setl_msgid='%s' where pat_no='%s' and times=%d;",
  744. msgId, patNo, times);
  745. String sql = sql1 + sql2 + sql3;
  746. log.info("执行失败的sql: \n{}", sql);
  747. }
  748. }
  749. public ResultVo<FundDetail> directRegistration(DirectionRegParam param) {
  750. log.info("门诊共济:{}", param);
  751. if (MzgjUtil.inProcessing(param.getPatientId())) {
  752. log.info("【{}】此患者上一次的共济流程尚未结束,请稍后再试。", param.getPatientId());
  753. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "此患者上一次的共济流程尚未结束,请稍后再试。");
  754. }
  755. ResultVo<FundDetail> setlfund = getFundDetailByPatientInfo(param.getPatientId(), param.getTimes(), false);
  756. if (setlfund != null) {
  757. return setlfund;
  758. }
  759. MzgjUtil.addProcess(param.getPatientId());
  760. ResultVo<FundDetail> response;
  761. try {
  762. response = executeMzgj(param);
  763. } catch (Exception e) {
  764. response = ResultVoUtil.fail(ExceptionEnum.INTERNAL_SERVER_ERROR, e.getMessage());
  765. } finally {
  766. MzgjUtil.finishProcessing(param.getPatientId());
  767. }
  768. return response;
  769. }
  770. private ResultVo<FundDetail> executeMzgj(DirectionRegParam param) {
  771. if (mzDao.selectExistCount(param.getPatientId(), param.getTimes()) == 0) {
  772. if (mzDao.updateMzTimes(param.getPatientId(), param.getTimes()) == 0) {
  773. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR,
  774. "[t_si_pat_info]不存在患者[" + param.getPatientId()
  775. + "]第[" + param.getTimes() + "]次的就诊信息,请重新查询。");
  776. }
  777. }
  778. mzDao.deleteTempPatinfo(param.getPatientId(), param.getTimes());
  779. MzPatientInfo mzptnt = new MzPatientInfo();
  780. mzptnt.setStaffId(param.getStaffId());
  781. mzptnt.setPatNo(param.getPatientId());
  782. mzptnt.setTimes(param.getTimes());
  783. mzptnt.setMedType(param.getMedType());
  784. mzptnt.setAcctUsedFlag(param.getAcctUsedFlag());
  785. if (mzptnt.getAcctUsedFlag() == 2) {
  786. mzptnt.setAcctUsedFlag(1);
  787. }
  788. mzptnt.setStraitSettle(param.getStraitSettle());
  789. mzptnt.setAbortBeforeUploadFees(param.abortBeforeUploadFees());
  790. mzptnt.setVisitDate(param.getVisitDate());
  791. mzptnt.setDeptCode(param.getVisitDeptCode());
  792. mzptnt.setDoctorCode(param.getDoctorCode());
  793. mzptnt.setIcdCodeNew(param.getIcdCodeNew());
  794. mzptnt.setIcdTextNew(param.getIcdTextNew());
  795. if (!param.abortBeforeUploadFees()) {
  796. // 生成医保费用
  797. String mzReceipts = generateSiMzFees(mzptnt);
  798. if (!mzReceipts.equals("SUCCESS")) {
  799. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, mzReceipts);
  800. }
  801. }
  802. // 填充医保基本信息
  803. SiPatInfo siPatInfo = mzDao.selectSiPatInfoForMz(mzptnt.getPatNo(), mzptnt.getTimes());
  804. mzptnt.setInsuplcAdmdvs(siPatInfo.getInsuplcAdmdvs());
  805. mzptnt.setInsutype(siPatInfo.getInsutype());
  806. mzptnt.setPsnType(siPatInfo.getPsnType());
  807. mzptnt.setName(siPatInfo.getPsnName());
  808. mzptnt.setSocialNo(siPatInfo.getCertno());
  809. // 解析读卡信息
  810. if (StringUtil.notBlank(param.getReadCardResult())) {
  811. MdtrtCertType mdtrtCertType = MdtrtCertType.get(param.getReadCardType());
  812. mzptnt.setMdtrtCertType(mdtrtCertType.getLabel());
  813. mzptnt.setReadCardBizType(ReadCardBizType.REGISTRATION.getCode());
  814. mzptnt.setReadCardResult(param.getReadCardResult());
  815. mzptnt.setBusCardInfo(param.getBusCardInfo());
  816. if (mdtrtCertType.getCode().equals(MdtrtCertType.ELECTRONIC_VOUCHER.getCode())) {
  817. JSONObject obj = JSONObject.parseObject(param.getReadCardResult());
  818. JSONObject qrdata = obj.getJSONObject("data");
  819. if (null != qrdata) {
  820. obj = qrdata;
  821. }
  822. String admdvs = obj.getString("insuOrg");
  823. if (StringUtil.isBlank(mzptnt.getInsuplcAdmdvs())) {
  824. mzptnt.setInsuplcAdmdvs(admdvs);
  825. }
  826. }
  827. }
  828. // 挂号登记
  829. ResultVo<String> regres = outpatientRegistration(mzptnt);
  830. if (regres.getCode() != ExceptionEnum.SUCCESS.getCode()) {
  831. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, regres.getMessage());
  832. }
  833. // 上传就诊信息
  834. siPatInfo = mzDao.selectSiPatInfoForMz(mzptnt.getPatNo(), mzptnt.getTimes());
  835. siPatInfo.setFromDirectReg(true);
  836. SpcChrDiseAcct spcChrDiseAcct = new SpcChrDiseAcct();
  837. spcChrDiseAcct.setStaffId(param.getStaffId());
  838. spcChrDiseAcct.setOpspDiseCode(param.getOpspDiseCode());
  839. spcChrDiseAcct.setOpspDiseName(param.getOpspDiseName());
  840. spcChrDiseAcct.setExpContent(param.getExpContent());
  841. ResultVo<String> upldMdtrtRes = uploadOutpatientInfo(mzptnt, spcChrDiseAcct, siPatInfo);
  842. if (upldMdtrtRes.getCode() != ExceptionEnum.SUCCESS.getCode()) {
  843. revokeOutpatientRegistration(mzptnt);
  844. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, upldMdtrtRes.getMessage());
  845. }
  846. if (param.abortBeforeUploadFees()) {
  847. return ResultVoUtil.success();
  848. }
  849. // 上传费用明细
  850. spcChrDiseAcct.setStaffId(param.getStaffId());
  851. spcChrDiseAcct.setPatNo(mzptnt.getPatNo());
  852. spcChrDiseAcct.setTimes(mzptnt.getTimes());
  853. spcChrDiseAcct.setFromDirectReg(true);
  854. ResultVo<SiPatInfo> upldFeeRes = uploadOutpatientFeeDetails(spcChrDiseAcct);
  855. if (upldFeeRes.getCode() != ExceptionEnum.SUCCESS.getCode()) {
  856. revokeOutpatientRegistration(mzptnt);
  857. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, upldFeeRes.getMessage());
  858. }
  859. // 如果是退费重收,直接结算
  860. if (param.getStraitSettle()) {
  861. return outpatientSettlement(mzptnt);
  862. }
  863. mzptnt.setReadCardBizType(ReadCardBizType.SETTLEMENT.getCode());
  864. return outpatientPreSettlement(mzptnt);
  865. }
  866. public String generateSiMzFees(MzPatientInfo mzptnt) {
  867. int setlCount = mzDao.getSetlCount(mzptnt.getPatNo(), mzptnt.getTimes());
  868. if (setlCount > 0) {
  869. return "患者已办理医保结算,不可重复操作。";
  870. }
  871. ResultVo<List<Map<String, Object>>> getMzRcptRes
  872. = webHisService.getMzReceipts(hisApi.getZy(), mzptnt);
  873. if (null == getMzRcptRes) {
  874. return ExceptionEnum.NETWORK_ERROR.getMessage();
  875. }
  876. if (getMzRcptRes.getCode() != ExceptionEnum.SUCCESS.getCode()) {
  877. return getMzRcptRes.getMessage();
  878. }
  879. List<MzReceipt> mzReceipts = new ArrayList<>();
  880. for (Map<String, Object> item : getMzRcptRes.getData()) {
  881. int times = (int) item.get("times");
  882. if (times != mzptnt.getTimes()) {
  883. continue;
  884. }
  885. mzDao.deleteAllReceipts(mzptnt.getPatNo(), times);
  886. Map<Integer, List<MzReceipt>> orderReceiptsMap = FilterUtil.cast(item.get("mzReceipts"));
  887. for (Map.Entry<Integer, List<MzReceipt>> entry : orderReceiptsMap.entrySet()) {
  888. mzReceipts.addAll(entry.getValue());
  889. }
  890. }
  891. if (mzReceipts.isEmpty()) {
  892. return "没有可以上传到医保的费用。";
  893. }
  894. ResultVo<String> insertSiMzFeeRes = webHisService.insertSiMzFees(hisApi.getZy(), mzReceipts);
  895. if (insertSiMzFeeRes.getCode() != ExceptionEnum.SUCCESS.getCode()) {
  896. return insertSiMzFeeRes.getMessage();
  897. }
  898. return "SUCCESS";
  899. }
  900. private String queryDiscount(String patNo, int times, List<String> mzReceipts) {
  901. JSONObject params = new JSONObject();
  902. params.put("patientId", patNo);
  903. params.put("times", times);
  904. params.put("chargeCodes", mzReceipts);
  905. JSONObject response = webHisService.checkDiscount(hisApi.getMz(), params);
  906. int code = response.getIntValue("code");
  907. if (code == 0) {
  908. return "OK";
  909. }
  910. if (code == -2) {
  911. return "患者本次就诊有折扣优惠,无法进行医保统筹。";
  912. }
  913. return response.getString("message");
  914. }
  915. public ResultVo<Integer> isPatientDuringSiSettle(String patientId) {
  916. int result = MzgjUtil.inProcessing(patientId) ? 1 : 0;
  917. return ResultVoUtil.success(result);
  918. }
  919. public void deletePresettleInfoAndRevokeYb(MzPatientInfo p) {
  920. int res = setlinfoDao.deletePreSettleInfo(p.getPatNo(), p.getTimes());
  921. if (res == 1) {
  922. revokeOutpatientFeeDetails(p);
  923. revokeOutpatientRegistration(p);
  924. }
  925. }
  926. private boolean existSettledButNotPay(String patNo, int times) {
  927. List<SiSetlinfo> setlinfos = scheduledDao.selectSettleInfosByPatient(patNo, times);
  928. for (SiSetlinfo item : setlinfos) {
  929. if (null != item.getPayCount() && item.getPayCount() > 0) {
  930. scheduledDao.updateMzSaved(item.getSetlId());
  931. } else {
  932. return true;
  933. }
  934. }
  935. return false;
  936. }
  937. }