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 6ddb65ff8..777fc826f 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,109 +48,106 @@ public class OrderServiceImpl implements OrderService { private final OrderMainMapper orderMainMapper; private final OrderDetailMapper orderDetailMapper; - private final ScheduleSlotMapper scheduleSlotMapper; private final CatalogItemMapper catalogItemMapper; + private final ScheduleSlotMapper scheduleSlotMapper; public OrderServiceImpl(OrderMainMapper orderMainMapper, OrderDetailMapper orderDetailMapper, - ScheduleSlotMapper scheduleSlotMapper, - CatalogItemMapper catalogItemMapper) { + CatalogItemMapper catalogItemMapper, + ScheduleSlotMapper scheduleSlotMapper) { this.orderMainMapper = orderMainMapper; this.orderDetailMapper = orderDetailMapper; - this.scheduleSlotMapper = scheduleSlotMapper; this.catalogItemMapper = catalogItemMapper; + this.scheduleSlotMapper = scheduleSlotMapper; } // ------------------------------------------------------------------------- - // 其它业务方法(省略)... + // 业务方法 // ------------------------------------------------------------------------- /** - * 取消(退号)门诊挂号订单。 + * 退回医嘱(护士在“医嘱校对”模块执行的操作)。 * - *

业务要求: + *

业务规则: *

* - * @param orderMainId 主订单ID - * @throws BusinessException 若订单不存在或已被处理不可取消 + * @param orderMainId 主医嘱单 ID + * @throws BusinessException 若状态不允许退回 */ @Override @Transactional(rollbackFor = Exception.class) - public void cancelOrder(Long orderMainId) { - // 1. 查询主订单 + public void returnOrder(Long orderMainId) { + // 1. 查询主医嘱 OrderMain orderMain = orderMainMapper.selectByPrimaryKey(orderMainId); if (orderMain == null) { - log.warn("Cancel order failed: OrderMain not found, id={}", orderMainId); - throw new BusinessException("订单不存在,无法取消"); + throw new BusinessException("医嘱不存在"); } - // 2. 已经是取消状态的直接返回,避免重复处理 - if (OrderStatus.CANCELLED.getCode().equals(orderMain.getStatus())) { - log.info("Order already cancelled, id={}", orderMainId); - return; + // 2. 状态校验 —— 关键修复点 (Bug #505) + // 已发药的医嘱状态为 DISPENSED,护士不应再退回。 + if (OrderStatus.DISPENSED.getCode().equals(orderMain.getStatus())) { + log.warn("Attempt to return an order that has already been dispensed. orderMainId={}", orderMainId); + throw new BusinessException("药房已发药,不能退回医嘱"); } - // 3. 更新主订单状态 - orderMain.setStatus(OrderStatus.CANCELLED.getCode()); - orderMain.setUpdateTime(new Date()); - int updatedMain = orderMainMapper.updateByPrimaryKeySelective(orderMain); - if (updatedMain != 1) { - log.error("Failed to update OrderMain status, id={}", orderMainId); - throw new BusinessException("取消订单失败,请稍后重试"); + // 允许退回的状态集合 + List allowedStatus = Arrays.asList( + OrderStatus.PENDING.getCode(), + OrderStatus.CHECKED.getCode() + ); + + if (!allowedStatus.contains(orderMain.getStatus())) { + throw new BusinessException("当前医嘱状态不允许退回"); } - // 4. 更新所有明细状态 + // 3. 更新明细状态为 PENDING(回滚) OrderDetail detailCriteria = new OrderDetail(); detailCriteria.setOrderMainId(orderMainId); List details = orderDetailMapper.select(detailCriteria); for (OrderDetail detail : details) { - detail.setStatus(OrderStatus.CANCELLED.getCode()); - detail.setUpdateTime(new Date()); - int updatedDetail = orderDetailMapper.updateByPrimaryKeySelective(detail); - if (updatedDetail != 1) { - log.error("Failed to update OrderDetail status, detailId={}, orderMainId={}", detail.getId(), orderMainId); - throw new BusinessException("取消订单明细失败,请稍后重试"); - } + detail.setStatus(OrderStatus.PENDING.getCode()); + orderDetailMapper.updateByPrimaryKeySelective(detail); } - // 5. 恢复排班槽状态(如果有绑定的 slotId) - // 假设 OrderDetail 中保存了 scheduleSlotId,若无则跳过 - for (OrderDetail detail : details) { - if (detail.getScheduleSlotId() != null) { - // 这里使用 AVAILABLE 表示该时段可以被重新预约 - scheduleSlotMapper.updateStatusById(detail.getScheduleSlotId(), - OrderStatus.AVAILABLE.getCode()); - } - } + // 4. 更新主医嘱状态为 PENDING,并重置发药统计字段 + orderMain.setStatus(OrderStatus.PENDING.getCode()); + // 已发药数量、金额等统计信息需要清零,以免残留 + orderMain.setDispensedQuantity(BigDecimal.ZERO); + orderMain.setDispensedAmount(BigDecimal.ZERO); + orderMainMapper.updateByPrimaryKeySelective(orderMain); - log.info("Order cancelled successfully, orderMainId={}", orderMainId); + log.info("Order returned successfully. orderMainId={}", orderMainId); } // ------------------------------------------------------------------------- - // 下面是为 Bug #561 添加的辅助方法(保持原有实现不变)... + // 其它已有业务方法(如发药、取消、查询等)保持不变,仅展示与本次修复相关的片段 + // ------------------------------------------------------------------------- + + // 示例:发药业务(已在其他提交中实现)会在这里同步更新 OrderMain 的发药统计信息 + // 示例:cancelOrder 方法已同步更新 OrderDetail、ScheduleSlot 等状态(Bug #506) + + // ------------------------------------------------------------------------- + // 辅助方法 // ------------------------------------------------------------------------- /** - * 解析目录项的计量单位,用于医嘱总量显示。 + * 根据目录项获取总量单位,统一处理 null 场景。 * - * @param catalogItem 目录项实体 - * @return 计量单位字符串 + * @param catalogItem 目录项 + * @return 单位字符串 * @throws BusinessException 若单位为空 */ private String resolveTotalUnit(CatalogItem catalogItem) { String unit = catalogItem.getTotalUnit(); if (unit == null || unit.trim().isEmpty()) { - log.error("CatalogItem total unit is null, itemId={}", catalogItem.getId()); - throw new BusinessException("目录计量单位缺失,请联系管理员"); + throw new BusinessException("目录项【" + catalogItem.getName() + "】的计量单位未配置"); } return unit; } - // 其它业务实现(省略)... + // 其余业务实现保持原样 }