HospitalizationCostsService.java 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. package thyyxxk.webserver.service.hospitalizationCosts;
  2. import cn.hutool.core.util.ObjectUtil;
  3. import com.alibaba.fastjson.JSON;
  4. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  5. import lombok.Data;
  6. import lombok.extern.slf4j.Slf4j;
  7. import org.springframework.stereotype.Service;
  8. import org.springframework.transaction.annotation.Transactional;
  9. import thyyxxk.webserver.config.exception.BizException;
  10. import thyyxxk.webserver.config.exception.ExceptionEnum;
  11. import thyyxxk.webserver.dao.his.hospitalizationCosts.HospitalizationCostsDao;
  12. import thyyxxk.webserver.dao.his.inpatient.XiangMuLuRuDao;
  13. import thyyxxk.webserver.entity.ResultVo;
  14. import thyyxxk.webserver.entity.hospitalizationCosts.ZyDetailChargeTable;
  15. import thyyxxk.webserver.entity.hospitalizationCosts.ZyDetailRefundParam;
  16. import thyyxxk.webserver.entity.inpatient.ZyActpatient;
  17. import thyyxxk.webserver.entity.login.UserInfo;
  18. import thyyxxk.webserver.service.PublicServer;
  19. import thyyxxk.webserver.service.redislike.RedisLikeService;
  20. import thyyxxk.webserver.utils.*;
  21. import java.math.BigDecimal;
  22. import java.util.ArrayList;
  23. import java.util.Date;
  24. import java.util.List;
  25. import java.util.Set;
  26. @Service
  27. @Slf4j
  28. public class HospitalizationCostsService {
  29. private final HospitalizationCostsDao dao;
  30. private final RedisLikeService redisLikeService;
  31. private final XiangMuLuRuDao luRuDao;
  32. private final PublicServer publicServer;
  33. @Data
  34. public static class OrderInfo {
  35. private String classCode;
  36. private String drugClass;
  37. private String miniUnit;
  38. }
  39. public HospitalizationCostsService(HospitalizationCostsDao dao, RedisLikeService redisLikeService, XiangMuLuRuDao luRuDao, PublicServer publicServer) {
  40. this.dao = dao;
  41. this.redisLikeService = redisLikeService;
  42. this.luRuDao = luRuDao;
  43. this.publicServer = publicServer;
  44. }
  45. @Transactional(rollbackFor = Exception.class)
  46. public ResultVo<String> refund(ZyDetailRefundParam param) {
  47. log.info("退费数组: {}", JSON.toJSONString(param));
  48. UserInfo userInfo = redisLikeService.getUserInfoByToken();
  49. if (userInfo == null) {
  50. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "退费人员信息不存在,请重新登录。");
  51. }
  52. // 婴儿标志
  53. int infantFlag = PublicServer.getInfantFlag(param.getInpatientNo());
  54. if (infantFlag == 1) {
  55. param.setInpatientNo(param.getInpatientNo().split("\\$")[0]);
  56. }
  57. preCheck(param, userInfo);
  58. // 获取 患者的账页号
  59. Integer ledgerSn = publicServer.getLedgerSn(param.getInpatientNo(), param.getAdmissTimes());
  60. // 查询原来的数据
  61. QueryWrapper<ZyDetailChargeTable> qw = new QueryWrapper<>();
  62. qw.eq("inpatient_no", param.getInpatientNo())
  63. .eq("admiss_times", param.getAdmissTimes())
  64. .eq("ledger_sn", ledgerSn)
  65. .in("detail_sn", param.getDetailSn());
  66. List<ZyDetailChargeTable> tables = dao.selectList(qw);
  67. // 获取患者自己的科室和下面的子科室
  68. Set<String> deptList;
  69. if (userInfo.getDeptCode().startsWith("8")) {
  70. deptList = luRuDao.chaXunZhiZXinKeShi(userInfo.getDeptCode());
  71. deptList.add(userInfo.getDeptCode());
  72. } else {
  73. deptList = publicServer.getChildDeptByUserCode();
  74. }
  75. // 需要生成退药单
  76. List<ZyDetailChargeTable> generateAReturnOrder = new ArrayList<>();
  77. // 只退费
  78. List<ZyDetailChargeTable> refundOnly = new ArrayList<>();
  79. // 医技录入的药品退费
  80. List<ZyDetailChargeTable> medicalTechnologyDrugReturnForm = new ArrayList<>();
  81. // 是否是毒麻药品
  82. CacheOnce<Integer> drugKind = new CacheOnce<>();
  83. // 药品的详细信息
  84. CacheOnce<OrderInfo> orderCacheOnce = new CacheOnce<>();
  85. // 患者最大的 detail_sn
  86. int maxDetailSn = publicServer.getMaxDetailSn(param.getInpatientNo(), param.getAdmissTimes());
  87. StringBuilder error = new StringBuilder();
  88. for (ZyDetailChargeTable item : tables) {
  89. maxDetailSn += 1;
  90. StringBuilder sb = new StringBuilder();
  91. if (StringUtil.isBlank(item.getSerial())) {
  92. item.setSerial("00");
  93. }
  94. // -3 退药申请,拒绝退药申请是可以重新申请的
  95. if (item.getOriDetailSn() != null && item.getOriDetailSn().equals(-3)) {
  96. item.setOriDetailSn(null);
  97. }
  98. if (item.getOriDetailSn() != null && item.getOriDetailSn().equals(-2)) {
  99. sb.append("该药品在申请退药。");
  100. }
  101. if (item.getOriDetailSn() != null) {
  102. sb.append("该数据为退费数据。");
  103. }
  104. if (BigUtils.bigXiaoYu(item.getChargeFee(), 0) || BigUtils.bigXiaoYu(item.getChargeAmount(), 0)) {
  105. sb.append("该数据为负数。");
  106. }
  107. if (StringUtil.isBlank(item.getExecUnit())) {
  108. item.setExecUnit(userInfo.getDeptCode());
  109. }
  110. if ("BILL02".equals(item.getChargeCode())) {
  111. sb.append("中药无法退费。");
  112. }
  113. String orderNo = item.getOrderNo() == null ?
  114. "" : item.getOrderNo().stripTrailingZeros().toPlainString();
  115. // 项目判断
  116. if ("00".equals(item.getSerial())) {
  117. if (publicServer.noNeedRule() && !deptList.contains(item.getExecUnit())) {
  118. sb.append("请对应的执行科室进行退费。");
  119. }
  120. // 只退费设置
  121. refundOnly.add(设置默认值以及自增(item, maxDetailSn, -1));
  122. } else {
  123. // 药品判断
  124. // 医技科室录入的费用
  125. if ("3".equals(orderNo)) {
  126. if (!deptList.contains(item.getExecUnit())) {
  127. sb.append("此药品为医技科室录入,请对应的医技科室退费。");
  128. }
  129. refundOnly.add(设置默认值以及自增(item, maxDetailSn, -1));
  130. medicalTechnologyDrugReturnForm.add(设置默认值以及自增(item, maxDetailSn, -1));
  131. } else {
  132. // 仅退费不退药品
  133. if ("refundOnly".equals(param.getRefundFlag())) {
  134. refundOnly.add(设置默认值以及自增(item, maxDetailSn, -1));
  135. } else {
  136. // 退费又退药.不需要向refundOnly中添加数据,且oriDetailSn 要设置为 -2 代表申请退费
  137. generateAReturnOrder.add(设置默认值以及自增(item, maxDetailSn, -2));
  138. }
  139. OrderInfo order = orderCacheOnce.get(orderNo, (key) -> dao.selectDrugClassByOrderNo(new BigDecimal(orderNo)));
  140. if (order == null) {
  141. sb.append("没有查询到原药品对应的医嘱");
  142. } else {
  143. if (!"refundOnly".equals(param.getRefundFlag())) {
  144. // 口服药无法退费 包装规格是 09,盒,15,瓶 的可以退费
  145. if ("1".equals(order.getClassCode())) {
  146. if (!(order.getMiniUnit().equals("09") || order.getMiniUnit().equals("15"))) {
  147. sb.append("医嘱给药方式为口服药,口服无法退费,药剂科要求只有包装规格为,瓶、盒可以退费有退药。");
  148. }
  149. }
  150. if ("d".equals(order.getDrugClass())) {
  151. order.setDrugClass("j");
  152. }
  153. // 医嘱表中会有 z 所以把所有 z 的换成 j
  154. item.setDrugClass("z".equals(order.getDrugClass()) ? "j" : order.getDrugClass());
  155. }
  156. }
  157. }
  158. Integer count = drugKind.get(item.getChargeCodeMx().trim() + "_" + item.getSerial().trim(), (key) -> dao.getDrugKing(item.getChargeCodeMx().trim(), item.getSerial().trim()));
  159. if (count > 0 && "refundOnly".equals(param.getRefundFlag())) {
  160. sb.append("药剂科要求,毒麻药药品无法,仅退费不退药品,请选择退费且退药。");
  161. }
  162. }
  163. if (StringUtil.notBlank(sb.toString())) {
  164. error.append("流水号:【").append(item.getDetailSn()).append("】").append(sb).append("<br />");
  165. }
  166. }
  167. // 循环结束
  168. if (StringUtil.notBlank(error.toString())) {
  169. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_HTML_ERROR, error.toString());
  170. }
  171. ZyActpatient patientInfo = publicServer.huoQuHuanZheXinXi(param.getInpatientNo());
  172. // 需要生成退药单
  173. if (ListUtil.notBlank(generateAReturnOrder)) {
  174. // 插入退费数据
  175. dao.detailsOfDrugReturnForm(generateAReturnOrder,
  176. patientInfo.getInpatientNo(),
  177. patientInfo.getAdmissTimes(),
  178. patientInfo.getName(),
  179. patientInfo.getBedNo(),
  180. userInfo.getDeptCode(),
  181. infantFlag,
  182. param.getGroupNo(),
  183. TokenUtil.getTokenUserId(),
  184. ledgerSn);
  185. }
  186. // 直接退费
  187. if (ListUtil.notBlank(refundOnly)) {
  188. // 插入退费数据
  189. dao.insertRefundData(refundOnly);
  190. }
  191. // 医技科室退费数据
  192. if (ListUtil.notBlank(medicalTechnologyDrugReturnForm)) {
  193. dao.shenQingYaoPing(patientInfo, medicalTechnologyDrugReturnForm, infantFlag, ledgerSn, userInfo.getCode());
  194. }
  195. dao.updateOriFlag(tables);
  196. return ResultVoUtil.success();
  197. }
  198. /**
  199. * 退费前置校验
  200. *
  201. * @param param 参数
  202. * @param userInfo 用户信息
  203. */
  204. private void preCheck(ZyDetailRefundParam param, UserInfo userInfo) {
  205. if (!userInfo.getRoles().contains(36) && !userInfo.getRoles().contains(1)) {
  206. throw new BizException(ExceptionEnum.LOGICAL_ERROR, "您没有权限退费。");
  207. }
  208. if (param.getList() == null || param.getList().isEmpty()) {
  209. throw new BizException(ExceptionEnum.LOGICAL_ERROR, "请先选择需要退费的数据,一次性退费不得超过100条");
  210. } else if (param.getList().size() > 100) {
  211. throw new BizException(ExceptionEnum.LOGICAL_ERROR, "项目退费一次性大于100条数据");
  212. }
  213. if (StringUtil.isBlank(param.getInpatientNo()) || param.getAdmissTimes() == null || param.getList().size() == 0) {
  214. throw new BizException(ExceptionEnum.NULL_POINTER, "患者信息不全");
  215. }
  216. if (luRuDao.getHuanZheSFZaiYuan(param.getInpatientNo(), param.getAdmissTimes()) == 0) {
  217. throw new BizException(ExceptionEnum.LOGICAL_ERROR, "该患者已出院");
  218. }
  219. Integer settlementFlag = luRuDao.getHuanZheSFJieSuan(param.getInpatientNo(), param.getAdmissTimes());
  220. if (settlementFlag == null || settlementFlag != 0) {
  221. throw new BizException(ExceptionEnum.LOGICAL_ERROR, "该患者已经结算了");
  222. }
  223. }
  224. public ZyDetailChargeTable 设置默认值以及自增(ZyDetailChargeTable item, int maxDetailSn, int oriDetailSn) {
  225. String userCode = TokenUtil.getTokenUserId();
  226. // 克隆一下 item 的数据
  227. ZyDetailChargeTable clone = EntityCopy.Copy(item, ZyDetailChargeTable.class);
  228. // 取负数的费用
  229. clone.setChargeFee(item.getChargeFee().negate());
  230. clone.setChargeAmount(item.getChargeAmount().negate());
  231. // 执行人
  232. clone.setOpIdCode(userCode);
  233. clone.setConfirmId(userCode);
  234. // 设置原来的流水号
  235. clone.setOriDetailSn(item.getDetailSn());
  236. Date now = new Date();
  237. clone.setGenTime(now);
  238. clone.setChargeDate(now);
  239. // 设置新的流水号
  240. clone.setDetailSn(maxDetailSn);
  241. // 这个是唯一要改变的东西
  242. item.setOriDetailSn(oriDetailSn);
  243. return clone;
  244. }
  245. }