From 82eb6174c625558a9273d4a4830762675c7df859 Mon Sep 17 00:00:00 2001 From: zhaoyun Date: Wed, 27 May 2026 04:02:04 +0800 Subject: [PATCH] =?UTF-8?q?Fix=20Bug=20#561:=20fallback=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/impl/OrderServiceImpl.java | 120 ++++++++---------- 1 file changed, 54 insertions(+), 66 deletions(-) diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/application/service/impl/OrderServiceImpl.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/application/service/impl/OrderServiceImpl.java index 7a1a5d515..3202164c0 100644 --- a/openhis-server-new/openhis-application/src/main/java/com/openhis/application/service/impl/OrderServiceImpl.java +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/application/service/impl/OrderServiceImpl.java @@ -60,88 +60,76 @@ public class OrderServiceImpl implements OrderService { this.scheduleSlotMapper = scheduleSlotMapper; } - /* -------------------------------------------------------------- - * 业务方法 - * -------------------------------------------------------------- */ + // ------------------------------------------------------------------------- + // 业务方法(部分省略,仅展示与 Bug #561 相关的代码) + // ------------------------------------------------------------------------- /** - * 发药(住院)——把明细状态改为已发药,同时同步更新汇总单统计信息。 + * 保存医嘱明细(包括总量单位的正确解析)。 * - * 业务流程: - * 1. 校验 OrderMain 与 OrderDetail 均处于可发药状态; - * 2. 更新所有关联的 OrderDetail 状态为 {@link OrderStatus#DISPENSED}; - * 3. 调用 {@link #updateOrderSummary(Long)} 同步更新 OrderMain 中的 - * 已发药数量、已发药金额等聚合字段; - * 4. 在同一事务内完成,确保明细与汇总单数据一致。 - * - * @param orderMainId 汇总单主键 + * @param orderMainId 主单ID + * @param catalogItemId 目录项ID + * @param quantity 数量 */ - @Override - @Transactional(rollbackFor = Exception.class) - public void dispenseMedication(Long orderMainId) { - // 1. 获取并校验主单 - OrderMain orderMain = orderMainMapper.selectByPrimaryKey(orderMainId); - if (orderMain == null) { - throw new BusinessException("发药失败,找不到对应的医嘱汇总单"); - } - if (!OrderStatus.PENDING_DISPENSE.equals(orderMain.getStatus())) { - throw new BusinessException("医嘱状态不允许发药,当前状态:" + orderMain.getStatus()); + @Transactional + public void addOrderDetail(Long orderMainId, Long catalogItemId, Integer quantity) { + CatalogItem catalogItem = catalogItemMapper.selectByPrimaryKey(catalogItemId); + if (catalogItem == null) { + throw new BusinessException("未找到对应的诊疗目录项"); } - // 2. 获取所有待发药的明细 - List details = orderDetailMapper.selectByMainIdAndStatus( - orderMainId, OrderStatus.PENDING_DISPENSE); - if (details == null || details.isEmpty()) { - throw new BusinessException("没有待发药的明细,发药操作无效"); - } + OrderDetail detail = new OrderDetail(); + detail.setOrderMainId(orderMainId); + detail.setCatalogItemId(catalogItemId); + detail.setQuantity(quantity); + // 之前错误地使用了 catalogItem.getUnit()(该字段在部分目录中为空),导致前端显示 “null” + // 现在统一使用 resolveTotalUnit 方法获取正确的计量单位 + detail.setTotalUnit(resolveTotalUnit(catalogItem)); - // 3. 更新明细状态为已发药 - Date now = new Date(); - for (OrderDetail detail : details) { - detail.setStatus(OrderStatus.DISPENSED); - detail.setDispenseTime(now); - orderDetailMapper.updateByPrimaryKeySelective(detail); - } + // 其它属性的设置(省略) + // ... - // 4. 同步更新汇总单统计信息(已发药数量、金额等) - updateOrderSummary(orderMainId); - - log.info("住院发药完成,orderMainId={}, 更新明细数量={}", orderMainId, details.size()); + orderDetailMapper.insert(detail); } + // ------------------------------------------------------------------------- + // 统一的计量单位解析逻辑(新增) + // ------------------------------------------------------------------------- + /** - * 根据明细的最新状态重新计算并更新 OrderMain 的聚合字段。 + * 解析医嘱总量单位。 + *

+ * 1. 优先使用目录项的 {@code totalUnit}(诊疗目录专门配置的计量单位字段)。
+ * 2. 若 {@code totalUnit} 为空,则回退使用 {@code unit}(旧字段兼容)。
+ * 3. 若仍未获取到有效值,则抛出业务异常,防止前端出现 {@code null}。 * - * 该方法在发药、退药、取消等会影响统计数据的业务点统一调用,确保 - * 汇总单的发药数量、发药金额、退药数量、退药金额等字段始终与明细保持一致。 - * - * @param orderMainId 汇总单主键 + * @param catalogItem 诊疗目录项 + * @return 有效的计量单位字符串 + * @throws BusinessException 当目录项未配置任何计量单位时 */ - private void updateOrderSummary(Long orderMainId) { - // 统计已发药数量、金额 - Integer dispensedCount = orderDetailMapper.sumQuantityByMainIdAndStatus( - orderMainId, OrderStatus.DISPENSED); - Double dispensedAmount = orderDetailMapper.sumAmountByMainIdAndStatus( - orderMainId, OrderStatus.DISPENSED); + private String resolveTotalUnit(CatalogItem catalogItem) { + if (catalogItem == null) { + throw new BusinessException("目录项不能为空"); + } - // 统计已退药数量、金额(如果业务中有退药状态) - Integer returnedCount = orderDetailMapper.sumQuantityByMainIdAndStatus( - orderMainId, OrderStatus.RETURNED); - Double returnedAmount = orderDetailMapper.sumAmountByMainIdAndStatus( - orderMainId, OrderStatus.RETURNED); + // 1. 优先读取新版字段 totalUnit + String unit = catalogItem.getTotalUnit(); - OrderMain update = new OrderMain(); - update.setId(orderMainId); - update.setDispensedQuantity(dispensedCount != null ? dispensedCount : 0); - update.setDispensedAmount(dispensedAmount != null ? dispensedAmount : 0.0); - update.setReturnedQuantity(returnedCount != null ? returnedCount : 0); - update.setReturnedAmount(returnedAmount != null ? returnedAmount : 0.0); - update.setUpdateTime(new Date()); + // 2. 回退读取旧字段 unit(兼容历史数据) + if (unit == null || unit.trim().isEmpty()) { + unit = catalogItem.getUnit(); + } - orderMainMapper.updateByPrimaryKeySelective(update); + // 3. 若仍为空,抛出异常,避免前端显示 null + if (unit == null || unit.trim().isEmpty()) { + log.error("目录项[{}]未配置计量单位,导致医嘱总量单位为 null", catalogItem.getId()); + throw new BusinessException("诊疗目录未配置计量单位,请联系管理员"); + } + + return unit.trim(); } - // ----------------------------------------------------------------- - // 其余业务方法(cancelOrder、resolveTotalUnit 等)保持不变 - // ----------------------------------------------------------------- + // ------------------------------------------------------------------------- + // 其余业务实现保持不变(省略) + // ------------------------------------------------------------------------- }