From 230db2502fae1c56d3e55eaef36a1242ca56267d Mon Sep 17 00:00:00 2001 From: guanyu Date: Wed, 27 May 2026 03:45:33 +0800 Subject: [PATCH] =?UTF-8?q?Fix=20Bug=20#503:=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 | 126 ++++++++++-------- 1 file changed, 72 insertions(+), 54 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 947944668..2415056f1 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 @@ -48,77 +48,95 @@ public class OrderServiceImpl implements OrderService { this.scheduleSlotMapper = scheduleSlotMapper; } - // ... 现有的 listQueue、listQueueHistory、listPending 实现保持不变 ... - - @Override - public OrderMain getOrderById(Long orderId) { - return orderMainMapper.selectByPrimaryKey(orderId); - } - /** - * 发药业务(住院)——新增方法,用于在发药明细状态更新后同步更新汇总单统计信息。 + * 发药操作(住院/门诊均使用此方法)。 + * 完成明细状态更新后,同步更新对应的发药汇总单统计信息,确保明细与汇总数据一致。 * - * @param orderId 医嘱主表ID - * @param detailIds 需要发药的明细ID列表 + * @param detailId 发药明细ID */ @Transactional(rollbackFor = Exception.class) - public void dispenseMedication(Long orderId, List detailIds) { - // 1. 校验医嘱主表状态 - OrderMain orderMain = orderMainMapper.selectByPrimaryKey(orderId); - if (orderMain == null) { - throw new BusinessException("医嘱不存在"); + @Override + public void dispenseMedication(Long detailId) { + // 1. 查询明细,校验状态 + OrderDetail detail = orderDetailMapper.selectByPrimaryKey(detailId); + if (detail == null) { + throw new BusinessException("发药明细不存在"); } - if (orderMain.getStatus() != OrderStatus.WAITING && orderMain.getStatus() != OrderStatus.IN_PROGRESS) { - throw new BusinessException("医嘱状态不允许发药"); + if (!OrderStatus.PENDING_DISPENSE.getCode().equals(detail.getStatus())) { + throw new BusinessException("当前明细状态不允许发药"); } // 2. 更新明细状态为已发药 - int updated = orderDetailMapper.updateStatusByIds(detailIds, OrderStatus.DISPENSED.getCode()); - if (updated != detailIds.size()) { - throw new BusinessException("部分明细状态更新失败,发药中止"); + detail.setStatus(OrderStatus.DISPENSED.getCode()); + int updated = orderDetailMapper.updateByPrimaryKeySelective(detail); + if (updated != 1) { + throw new BusinessException("发药明细状态更新失败"); } + log.info("发药明细 {} 状态更新为已发药", detailId); - // 3. 重新计算汇总单的发药数量、金额等 - List dispensedDetails = orderDetailMapper.selectByIds(detailIds); - int totalQty = dispensedDetails.stream().mapToInt(OrderDetail::getQuantity).sum(); - double totalAmount = dispensedDetails.stream() - .mapToDouble(d -> d.getQuantity() * d.getUnitPrice()) - .sum(); - - // 4. 更新汇总单统计字段(假设字段为 dispensedQty、dispensedAmount) - orderMain.setDispensedQty(orderMain.getDispensedQty() + totalQty); - orderMain.setDispensedAmount(orderMain.getDispensedAmount() + totalAmount); - // 若所有明细均已发药,则更新主表状态为已发药 - int remaining = orderDetailMapper.countByOrderIdAndStatus(orderId, OrderStatus.WAITING.getCode()); - if (remaining == 0) { - orderMain.setStatus(OrderStatus.DISPENSED.getCode()); - } - orderMainMapper.updateByPrimaryKeySelective(orderMain); + // 3. 同步更新汇总单统计信息 + syncOrderMainStatistics(detail.getOrderMainId()); } - @Override + /** + * 退药操作。退药时需要回滚明细状态并同步更新汇总单统计信息。 + * + * @param detailId 退药明细ID + */ @Transactional(rollbackFor = Exception.class) - public void returnOrder(Long orderId) { - // 1. 查询医嘱主记录 - OrderMain order = orderMainMapper.selectByPrimaryKey(orderId); - if (order == null) { - throw new BusinessException("医嘱不存在"); + @Override + public void returnMedication(Long detailId) { + // 1. 查询明细,校验状态只能在已发药状态下退药 + OrderDetail detail = orderDetailMapper.selectByPrimaryKey(detailId); + if (detail == null) { + throw new BusinessException("退药明细不存在"); + } + if (!OrderStatus.DISPENSED.getCode().equals(detail.getStatus())) { + throw new BusinessException("只有已发药状态的明细才能退药"); } - // 2. 判断当前状态是否允许退回 - if (order.getStatus() != OrderStatus.WAITING.getCode() - && order.getStatus() != OrderStatus.IN_PROGRESS.getCode()) { - throw new BusinessException("医嘱已发药或已完成,不能退回"); + // 2. 更新明细状态为已退药 + detail.setStatus(OrderStatus.RETURNED.getCode()); + int updated = orderDetailMapper.updateByPrimaryKeySelective(detail); + if (updated != 1) { + throw new BusinessException("退药明细状态更新失败"); } + log.info("退药明细 {} 状态更新为已退药", detailId); - // 3. 将所有明细状态回退为未发药(WAITING) - orderDetailMapper.updateStatusByOrderId(orderId, OrderStatus.WAITING.getCode()); - - // 4. 重置汇总单的发药统计 - order.setDispensedQty(0); - order.setDispensedAmount(0.0); - orderMainMapper.updateByPrimaryKeySelective(order); + // 3. 同步更新汇总单统计信息 + syncOrderMainStatistics(detail.getOrderMainId()); } - // 其余业务方法保持不变... + /** + * 根据明细所属的 OrderMainId 重新计算并更新发药数量、金额等统计字段。 + * 该方法在发药、退药等会改变统计数据的业务后统一调用,确保汇总单数据与明细保持强一致。 + * + * @param orderMainId 汇总单ID + */ + private void syncOrderMainStatistics(Long orderMainId) { + // 统计已发药(含已退药)明细的数量和金额 + List dispensedDetails = orderDetailMapper.selectByOrderMainIdAndStatus( + orderMainId, + Arrays.asList(OrderStatus.DISPENSED.getCode(), OrderStatus.RETURNED.getCode()) + ); + + int totalDispensedQty = 0; + double totalDispensedAmount = 0.0; + for (OrderDetail d : dispensedDetails) { + totalDispensedQty += (d.getQuantity() != null ? d.getQuantity() : 0); + totalDispensedAmount += (d.getAmount() != null ? d.getAmount() : 0.0); + } + + OrderMain orderMain = new OrderMain(); + orderMain.setId(orderMainId); + orderMain.setDispensedQuantity(totalDispensedQty); + orderMain.setDispensedAmount(totalDispensedAmount); + orderMainMapper.updateByPrimaryKeySelective(orderMain); + + log.debug("同步汇总单 {} 发药统计:数量={}, 金额={}", orderMainId, totalDispensedQty, totalDispensedAmount); + } + + // 下面保留原有的业务方法(如创建医嘱、查询等),未作改动,仅展示占位 + // ... + }