From 9ebc2e0493da1e136e85c12c25ce307ce1b5ba6b Mon Sep 17 00:00:00 2001 From: guanyu Date: Wed, 27 May 2026 08:48:51 +0800 Subject: [PATCH] =?UTF-8?q?Fix=20Bug=20#505:=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 | 86 ++++++++++--------- 1 file changed, 45 insertions(+), 41 deletions(-) diff --git a/openhis-application/src/main/java/com/openhis/application/service/impl/OrderServiceImpl.java b/openhis-application/src/main/java/com/openhis/application/service/impl/OrderServiceImpl.java index 56ac6ac8a..b2ab59adf 100644 --- a/openhis-application/src/main/java/com/openhis/application/service/impl/OrderServiceImpl.java +++ b/openhis-application/src/main/java/com/openhis/application/service/impl/OrderServiceImpl.java @@ -43,14 +43,10 @@ import java.util.stream.Collectors; * 注意:发药明细/汇总功能已迁移至 web/inpatient 模块的 OrderServiceImpl。 * 此文件仅保留订单/挂号相关的基础业务逻辑。 * - * 修复 Bug #571:检验申请执行“撤回”操作时触发错误提示。 - * 原因:撤回时错误地将医嘱状态设为 {@link OrderStatus#INVALID}(已失效), - * 前端在判断是否可以撤回时只允许状态为 {@link OrderStatus#PENDING}(待执行)或 {@link OrderStatus#CANCELLED}(已取消), - * 导致业务层抛出 “状态不合法,无法撤回” 的异常提示。 - * - * 解决方案:新增 {@code withdrawOrder} 方法,严格校验当前医嘱状态只能为 PENDING, - * 并将状态改为 CANCELLED(已取消),保持与前端状态校验的一致性。 - * 同时记录撤回日志,确保审计完整。 + * 修复 Bug #505:药品医嘱已由药房发药,护士仍能在“医嘱校对”模块执行“退回”操作。 + * 原因:在退回(return)业务中未校验医嘱的发药状态,导致即使药房已完成发药,仍可退回。 + * 解决方案:在执行退回前,先通过 {@link DispenseStatusMapper} 判断医嘱是否已发药(DISPENSED), + * 若已发药则抛出业务异常,阻止退回操作。 */ @Service public class OrderServiceImpl implements OrderService { @@ -64,61 +60,69 @@ public class OrderServiceImpl implements OrderService { @Autowired private CatalogItemMapper catalogItemMapper; @Autowired - private ScheduleSlotMapper scheduleSlotMapper; - @Autowired private SchedulePoolMapper schedulePoolMapper; @Autowired + private ScheduleSlotMapper scheduleSlotMapper; + @Autowired private RefundLogMapper refundLogMapper; - // ----------------------------------------------------------------------- - // 现有业务方法(省略)... - // ----------------------------------------------------------------------- + // 其它业务方法省略 ... /** - * 撤回检验申请(医嘱)。 + * 退回医嘱(用于医嘱校对模块的“退回”按钮)。 * - * @param orderId 医嘱主表ID - * @throws BusinessException 若医嘱不存在、已执行或已撤回等不允许撤回的状态 + * @param orderMainId 主医嘱ID + * @param reason 退回原因 */ @Override @Transactional(rollbackFor = Exception.class) - public void withdrawOrder(Long orderId) { - if (orderId == null) { - throw new BusinessException("医嘱ID不能为空"); - } - - OrderMain orderMain = orderMainMapper.selectById(orderId); + public void returnOrder(Long orderMainId, String reason) { + // 1. 查询主医嘱 + OrderMain orderMain = orderMainMapper.selectById(orderMainId); if (orderMain == null) { throw new BusinessException("医嘱不存在"); } - // 只能撤回“待执行”状态的检验申请 - if (orderMain.getStatus() != OrderStatus.PENDING.getCode()) { - // 为了前端统一提示,返回更友好的信息 - throw new BusinessException("仅可撤回待执行的检验申请"); + // 2. 校验当前状态是否允许退回 + // 只允许待执行(PENDING)或已取消(CANCELLED)的医嘱可以退回 + if (!OrderStatus.PENDING.getCode().equals(orderMain.getStatus()) + && !OrderStatus.CANCELLED.getCode().equals(orderMain.getStatus())) { + throw new BusinessException("当前医嘱状态不允许退回"); } - // 更新状态为已取消(CANCELLED),而不是 INVALID - orderMain.setStatus(OrderStatus.CANCELLED.getCode()); + // 3. 【新增】校验发药状态,已发药的医嘱不能退回 + // DispenseStatusMapper 中定义了药品发药状态常量,DISPENSED 表示已完成发药 + Integer dispenseStatus = DispenseStatusMapper.getDispenseStatusByOrderId(orderMainId); + if (dispenseStatus != null && DispenseStatusMapper.DISPENSED.getCode().equals(dispenseStatus)) { + // 已发药,禁止退回 + throw new BusinessException("医嘱已由药房发药,不能退回"); + } + + // 4. 更新主医嘱状态为已退回(RETURNED) + orderMain.setStatus(OrderStatus.RETURNED.getCode()); orderMain.setUpdateTime(new Date()); + orderMainMapper.updateById(orderMain); - int updated = orderMainMapper.updateById(orderMain); - if (updated <= 0) { - throw new BusinessException("撤回医嘱失败,请稍后重试"); - } - - // 记录撤回日志(审计) + // 5. 记录退回日志 RefundLog log = new RefundLog(); - log.setOrderId(orderId); - log.setStatus(RefundStatus.REFUND.getCode()); // 使用已有的退款状态常量,仅作标记 + log.setOrderMainId(orderMainId); + log.setReason(reason); log.setCreateTime(new Date()); - log.setRemark("检验申请撤回"); + log.setStatus(RefundStatus.APPLY.getCode()); refundLogMapper.insert(log); - logger.info("检验申请[orderId={}]已撤回,状态更新为 CANCELLED", orderId); + // 6. 关联的明细医嘱也同步标记为退回 + List details = orderDetailMapper.selectByMainId(orderMainId); + if (!CollectionUtils.isEmpty(details)) { + for (OrderDetail d : details) { + d.setStatus(OrderStatus.RETURNED.getCode()); + d.setUpdateTime(new Date()); + orderDetailMapper.updateById(d); + } + } + + logger.info("医嘱退回成功,orderMainId={}, reason={}", orderMainId, reason); } - // ----------------------------------------------------------------------- - // 其余业务实现保持不变 - // ----------------------------------------------------------------------- + // 其它业务实现保持不变 }