UploadFeeService.java 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. package hnthyyxxk.cssybuploadfees.service;
  2. import com.alibaba.fastjson.JSON;
  3. import com.alibaba.fastjson.JSONObject;
  4. import hnthyyxxk.cssybuploadfees.dao.Dao;
  5. import hnthyyxxk.cssybuploadfees.pojo.Fee;
  6. import hnthyyxxk.cssybuploadfees.pojo.DJRet;
  7. import hnthyyxxk.cssybuploadfees.pojo.SimpleResponse;
  8. import hnthyyxxk.cssybuploadfees.pojo.UploadFeeParam;
  9. import hnthyyxxk.cssybuploadfees.utils.DTool;
  10. import hnthyyxxk.cssybuploadfees.utils.ExceptionEnum;
  11. import hnthyyxxk.cssybuploadfees.utils.MsgProducer;
  12. import hnthyyxxk.cssybuploadfees.utils.SnowFlakeId;
  13. import lombok.extern.slf4j.Slf4j;
  14. import org.springframework.beans.factory.annotation.Autowired;
  15. import org.springframework.stereotype.Service;
  16. import java.text.DateFormat;
  17. import java.text.SimpleDateFormat;
  18. import java.util.*;
  19. import static hnthyyxxk.cssybuploadfees.utils.DTool.betweenAutoUpload;
  20. /**
  21. * @author dj
  22. */
  23. @Slf4j
  24. @Service
  25. public class UploadFeeService {
  26. private final Dao dao;
  27. private final MsgProducer producer;
  28. @Autowired
  29. public UploadFeeService(Dao dao, MsgProducer producer) {
  30. this.dao = dao;
  31. this.producer = producer;
  32. }
  33. public DJRet multipleUpload(List<UploadFeeParam> list) {
  34. if (betweenAutoUpload()) {
  35. return DJRet.fail(ExceptionEnum.LOGICAL_ERROR, "01:55:00 至 08:00:00 为自动上传时间,请勿在此时间段内做上传操作!");
  36. }
  37. JSONObject obj = new JSONObject();
  38. DJRet djRet = DJRet.success();
  39. for (int i = 0; i < list.size(); i ++) {
  40. obj.put("name", "updatePatientIndex");
  41. obj.put("val", i + 1);
  42. producer.sendTopicQueue(list.get(0).getSid(), obj.toJSONString());
  43. UploadFeeParam item = list.get(i);
  44. djRet = uploadFees(item);
  45. if (djRet.getCode() != ExceptionEnum.SUCCESS.getCode()) {
  46. log.warn("[ 操作员:{} ] - 上传出错>>> {}", item.getStaffId(), obj);
  47. sendUploadFeeResponse(item.getInpatientNo(), item.getName(),
  48. -1, djRet.getMessage(), item.getSid());
  49. }
  50. }
  51. return djRet;
  52. }
  53. public DJRet uploadFees(UploadFeeParam param) {
  54. UploadFeeParam temp = dao.getPatientInfo(param.getInpatientNo());
  55. param.merge(temp);
  56. log.info("上传费用:{}", param);
  57. return startUpload(param);
  58. }
  59. private DJRet startUpload(UploadFeeParam param) {
  60. if (null == param.getSid()) {
  61. return DJRet.fail(ExceptionEnum.LOGICAL_ERROR, "未检测到连接id,请刷新页面。");
  62. }
  63. if (!"autoUpload".equals(param.getSid()) && DTool.betweenAutoUpload()) {
  64. return DJRet.fail(ExceptionEnum.LOGICAL_ERROR, "01:55:00 至 08:00:00 为自动上传时间,请勿在此时间段内做上传操作!");
  65. }
  66. param.setFeeSize(dao.queryFeeSize(param.getInpatientNo(), param.getAdmissTimes()));
  67. if (param.getFeeSize() == 0) {
  68. return DJRet.fail(ExceptionEnum.LOGICAL_ERROR, "此患者没有需要上传的费用。");
  69. }
  70. SimpleResponse response = makeUploadStmt(param, 1, 0);
  71. int code = response.getCode();
  72. if (code == -9) {
  73. return DJRet.fail(ExceptionEnum.LOGICAL_ERROR, response.getMessage());
  74. }
  75. response = makeUploadStmt(param, 2, code);
  76. if (response.getCode() == -9) {
  77. return DJRet.fail(ExceptionEnum.LOGICAL_ERROR, response.getMessage());
  78. }
  79. return preCalculateCost(param);
  80. }
  81. private SimpleResponse makeUploadStmt(UploadFeeParam param, int flag, int index) {
  82. Queue<Fee> fees = flag == 1 ?
  83. dao.getCssybProjectFee(param.getInpatientNo(), param.getAdmissTimes()) :
  84. dao.getCssybMedicineFee(param.getInpatientNo(), param.getAdmissTimes());
  85. SimpleResponse response = new SimpleResponse();
  86. if (null == fees || fees.isEmpty()) {
  87. response.setCode(0);
  88. return response;
  89. }
  90. List<Integer> refundDetailSn = new ArrayList<>();
  91. JSONObject socketMsg = new JSONObject();
  92. while (!fees.isEmpty()) {
  93. Fee fee = fees.poll();
  94. if (null == fee.getYbCode() || "".equals(fee.getYbCode().trim())) {
  95. String message = "项目/药品【" + fee.getName() + "】未匹配,请联系物价科进行匹配,内线电话:2104";
  96. sendUploadFeeResponse(param.getInpatientNo(), param.getName(),
  97. fee.getDetailSn(), message, param.getSid());
  98. }
  99. String amount = fee.getAmount();
  100. if (null == amount || "".equals(amount.trim())) {
  101. amount = fee.getChargeAmount();
  102. }
  103. if (null == amount || "".equals(amount.trim())) {
  104. log.info("项目/药品数量不正确:{}", fee);
  105. continue;
  106. }
  107. if (amount.startsWith("-") && !refundDetailSn.contains(fee.getDetailSn())) {
  108. refundDetailSn.add(fee.getDetailSn());
  109. fees.offer(fee);
  110. log.info("退费项目,安排到末尾 >>> {}", fee);
  111. continue;
  112. }
  113. fee.setPrice(DTool.mathDivide(fee.getChargeFee(), amount));
  114. log.info("[ 操作员:{} ] - [ 患者{} ] - 费用上传>>> {}", param.getStaffId(),
  115. param.getMainInfo(), JSON.toJSONString(fee));
  116. String stmt = getUploadFuncId(param.getYbType().trim()) + "^43010150145^" + param.getStaffId() + "^^" +
  117. SnowFlakeId.getInstance().nextId() + "^0000^" + param.getYbJlh() + "|" + fee.getYbClass() + "|" +
  118. fee.getYbBillCode() + "|" + fee.getDetailSn() + "|" + formatChargeDate(fee.getChargeDate()) + "|"
  119. + fee.getChargeCode() + "|" + fee.getYbCode() + "|" + fee.getName() + "|" +
  120. fee.getPrice() + "|" + amount + "|||||||||||||" + fee.getStatusFlag() + "|^";
  121. response = executeSybTrade(param.getStaffId(), stmt);
  122. log.info("[ 操作员:{} ] - [ 患者{} ] - 费用上传回执>>> {}", param.getStaffId(), param.getMainInfo(), response);
  123. if ((response.getCode() == 0) || (response.getMessage().contains("主键重复"))) {
  124. if (response.getCode() == 0) {
  125. String retPrice = response.getMessage().split("\\|")[1].trim();
  126. int offset = DTool.mathCompare(retPrice.trim(), fee.getChargeFee().trim());
  127. if (offset != 0) {
  128. log.warn("[ 操作员:{} ] - [ 患者{} ] - 本条上传HIS费用和医保接收到的不一致。医保返回为 {}," +
  129. "本条费用HIS详细为 {} ", param.getStaffId(), param.getMainInfo(), response, fee);
  130. }
  131. }
  132. dao.updateTransFlagYbBySingle(param.getInpatientNo(), param.getAdmissTimes(), fee.getDetailSn());
  133. } else {
  134. if (response.getMessage().contains("没有找到此人的登记信息")) {
  135. response.setCode(-9);
  136. response.setMessage(response.getMessage());
  137. return response;
  138. }
  139. if (response.getMessage().contains("费用金额大于目前系统中有效的金额")) {
  140. response.setMessage(response.getMessage() + "(意思就是退费金额比收费金额大,退多了。)");
  141. }
  142. String message = "项目/药品 - " + fee.getName() + ":" + response.getMessage();
  143. sendUploadFeeResponse(param.getInpatientNo(), param.getName(),
  144. fee.getDetailSn(), message, param.getSid());
  145. }
  146. if (response.getCode() == 9) {
  147. return response;
  148. }
  149. index ++;
  150. socketMsg.put("name", "updateProgress");
  151. socketMsg.put("percentage", makePercentage(index, param.getFeeSize()));
  152. producer.sendTopicQueue(param.getSid(), socketMsg.toJSONString());
  153. }
  154. if (flag == 1) {
  155. response.setCode(index);
  156. } else {
  157. log.info("[ 操作员:{} ] - 上传结束>>> {}", param.getStaffId(), param.getMainInfo());
  158. }
  159. return response;
  160. }
  161. public DJRet preCalculateCost(UploadFeeParam param) {
  162. log.info("[ 操作员:{} ] - 预结算>>> {}", param.getStaffId(), param.getMainInfo());
  163. final String serialNo = SnowFlakeId.getInstance().nextId();
  164. final String staff = dao.getStaffNameByCode(param.getStaffId());
  165. String dismissDate = dao.getDismissDate(param.getInpatientNo(), param.getAdmissTimes());
  166. if (null == dismissDate) {
  167. dismissDate = formatDateWithoutDash();
  168. } else {
  169. dismissDate = dismissDate.replaceAll("-", "");
  170. }
  171. final String stmt = String.format("2420^43010150145^%s^^%s^0000^" +
  172. "%s|%s|%s|%s|%s||%s|||||0|0||%s|^", param.getStaffId(), serialNo,
  173. param.getYbJlh(), serialNo, param.getYbType(),
  174. formatDateWithoutDash(), dismissDate, param.getIcdCode(), staff);
  175. final SimpleResponse response = executeSybTrade(param.getStaffId(), stmt);
  176. log.info("预结算结果:{}", response);
  177. if (response.getCode() == 0) {
  178. Map<String, String> feeMap = makeFeeMap(response.getMessage());
  179. final String hisCharge = getHisChargeFee(param.getInpatientNo(), param.getAdmissTimes());
  180. if (DTool.mathCompare(feeMap.get("fundPay"), hisCharge) == 1) {
  181. feeMap.replace("fundPay", hisCharge);
  182. }
  183. dao.preCalculateCost(feeMap.get("fundPay"), feeMap.get("fullSelfPay"), feeMap.get("partSelfPay"),
  184. param.getInpatientNo(), param.getAdmissTimes());
  185. if (DTool.feeDiffsOverOneRmb(hisCharge, feeMap.get("totalCost"))) {
  186. String message = "患者:" + param.getName() + ",住院号:" +
  187. param.getInpatientNo() + " HIS总费用:" + hisCharge + "与医保上传总费用:" +
  188. feeMap.get("totalCost") + "不一致!";
  189. return DJRet.fail(ExceptionEnum.NEED_PROOFREAD, message, feeMap);
  190. } else {
  191. return DJRet.success(feeMap);
  192. }
  193. } else {
  194. return DJRet.fail(ExceptionEnum.LOGICAL_ERROR, response.getMessage());
  195. }
  196. }
  197. private String getUploadFuncId(String ybType) {
  198. final boolean isGs = "42".equals(ybType) || "44".equals(ybType);
  199. return isGs ? "2330" : "2310";
  200. }
  201. private int makePercentage(int index, int size) {
  202. float per = (float)index / (float)size;
  203. return (int) (per * 100);
  204. }
  205. private String formatChargeDate(String target) {
  206. return target.replaceAll("-", "")
  207. .replaceAll("/", "")
  208. .replaceAll(":", "")
  209. .replaceAll(" ", "");
  210. }
  211. private String formatDateWithoutDash() {
  212. DateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
  213. return df.format(new Date());
  214. }
  215. private String getHisChargeFee(String inpatientNo, Integer admissTimes) {
  216. int hasInfant = dao.hasInfant(inpatientNo, admissTimes);
  217. return hasInfant == 0 ? dao.getTotalCharge(inpatientNo, admissTimes) :
  218. dao.getMomFee(inpatientNo, admissTimes);
  219. }
  220. private Map<String, String> makeFeeMap(String feeMsg) {
  221. String[] arr = feeMsg.split("\\|");
  222. Map<String, String> map = new HashMap<>();
  223. map.put("totalCost", arr[10]);
  224. map.put("fundPay", DTool.mathMinus(arr[10], arr[14]));
  225. map.put("cashPay", arr[14]);
  226. try {
  227. map.put("fullSelfPay", arr[46]);
  228. map.put("partSelfPay", arr[47]);
  229. } catch (Exception e) {
  230. map.put("fullSelfPay", "");
  231. map.put("partSelfPay", "");
  232. }
  233. return map;
  234. }
  235. private SimpleResponse executeSybTrade(String codeRs, String statement) {
  236. CssybCore core = CssybCore.getInstance();
  237. core.setStaffId(codeRs);
  238. core.setStmt(statement);
  239. return core.call();
  240. }
  241. private void sendUploadFeeResponse(String zyh, String patName, Integer detailSn, String message, String sid) {
  242. JSONObject socketMsg = new JSONObject();
  243. socketMsg.put("name", "uploadFeeResponse");
  244. socketMsg.put("inpatientNo", zyh);
  245. socketMsg.put("patientName", patName);
  246. socketMsg.put("detailSn", detailSn);
  247. socketMsg.put("msg", message);
  248. producer.sendTopicQueue(sid, socketMsg.toJSONString());
  249. }
  250. }