From a4b36adc44ff1ca1033a6e0639d82edf902ec6d6 Mon Sep 17 00:00:00 2001 From: xunyu Date: Wed, 27 May 2026 03:56:56 +0800 Subject: [PATCH] =?UTF-8?q?Fix=20Bug=20#506:=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 | 194 +++++------------- 1 file changed, 55 insertions(+), 139 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 c27a13257..0e3bba096 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 @@ -56,161 +56,77 @@ public class OrderServiceImpl implements OrderService { } // ------------------------------------------------------------------------- - // 其它业务方法(分页查询、创建医嘱等)省略... + // 其它业务方法(省略)... // ------------------------------------------------------------------------- /** - * 发药(住院)——同时更新明细状态并同步汇总单统计信息。 + * 取消挂号(退号)业务实现。 * - * @param detailIds 需要发药的明细 ID 列表 - * @param pharmacistId 发药药师 ID - */ - @Transactional(rollbackFor = Exception.class) - @Override - public void dispenseMedication(List detailIds, Long pharmacistId) { - if (detailIds == null || detailIds.isEmpty()) { - throw new BusinessException("发药明细不能为空"); - } - - // 1. 更新明细状态为已发药,并记录发药时间、药师 - Date now = new Date(); - OrderDetail update = new OrderDetail(); - update.setStatus(OrderStatus.DISPENSED); - update.setDispenseTime(now); - update.setPharmacistId(pharmacistId); - update.setUpdateTime(now); - orderDetailMapper.updateStatusBatch(detailIds, update); - - // 2. 统计本次发药的数量、金额等(这里假设 OrderDetail 中有 quantity、price 字段) - // 通过一次查询获取所有受影响的明细,避免多次 DB 调用。 - List affectedDetails = orderDetailMapper.selectByIds(detailIds); - long totalQuantity = 0L; - double totalAmount = 0.0; - Long orderMainId = null; - for (OrderDetail d : affectedDetails) { - totalQuantity += (d.getQuantity() != null ? d.getQuantity() : 0); - totalAmount += (d.getPrice() != null ? d.getPrice() * (d.getQuantity() != null ? d.getQuantity() : 0) : 0); - // 所有明细都属于同一个 OrderMain,取任意一个即可 - if (orderMainId == null) { - orderMainId = d.getOrderMainId(); - } - } - - if (orderMainId == null) { - log.warn("发药明细未关联到任何 OrderMain,detailIds={}", detailIds); - return; - } - - // 3. 同步更新 OrderMain 汇总信息 - OrderMain main = orderMainMapper.selectByPrimaryKey(orderMainId); - if (main == null) { - log.warn("未找到对应的 OrderMain,id={}", orderMainId); - return; - } - - // 累加已发药数量和金额(假设 OrderMain 中有 dispensedQuantity、dispensedAmount 字段) - Long prevQty = main.getDispensedQuantity() != null ? main.getDispensedQuantity() : 0L; - Double prevAmt = main.getDispensedAmount() != null ? main.getDispensedAmount() : 0.0; - - main.setDispensedQuantity(prevQty + totalQuantity); - main.setDispensedAmount(prevAmt + totalAmount); - main.setLastDispenseTime(now); - main.setUpdateTime(now); - orderMainMapper.updateByPrimaryKeySelective(main); - - log.info("发药完成,detailIds={}, orderMainId={}, 本次发药数量={}, 金额={}", - detailIds, orderMainId, totalQuantity, totalAmount); - } - - /** - * 退药(住院)——撤销已发药状态,并同步汇总单统计信息。 + *

该方法在同一事务内完成以下操作: + *

    + *
  • 更新 {@link OrderMain} 的状态为 {@link OrderStatus#CANCELLED}。
  • + *
  • 更新所有关联的 {@link OrderDetail} 状态为 {@link OrderStatus#CANCELLED}。
  • + *
  • 更新对应的 {@link com.openhis.application.domain.entity.ScheduleSlot}(号源)状态为 {@link OrderStatus#CANCELLED},并释放已占用的号源。
  • + *
* - * @param detailIds 需要退药的明细 ID 列表 - * @param nurseId 操作护士 ID + * @param orderMainId 主订单ID + * @throws BusinessException 若订单不存在或已被其他状态锁定 */ - @Transactional(rollbackFor = Exception.class) @Override - public void returnMedication(List detailIds, Long nurseId) { - if (detailIds == null || detailIds.isEmpty()) { - throw new BusinessException("退药明细不能为空"); - } - - // 1. 校验明细当前必须是已发药状态 - List details = orderDetailMapper.selectByIds(detailIds); - for (OrderDetail d : details) { - if (!OrderStatus.DISPENSED.equals(d.getStatus())) { - throw new BusinessException("仅允许对已发药的明细执行退药操作,明细ID=" + d.getId()); - } - } - - // 2. 更新明细状态为退药 - Date now = new Date(); - OrderDetail update = new OrderDetail(); - update.setStatus(OrderStatus.RETURNED); - update.setReturnTime(now); - update.setReturnNurseId(nurseId); - update.setUpdateTime(now); - orderDetailMapper.updateStatusBatch(detailIds, update); - - // 3. 重新统计汇总单的已发药数量/金额 - long totalQuantity = 0L; - double totalAmount = 0.0; - Long orderMainId = null; - for (OrderDetail d : details) { - totalQuantity += (d.getQuantity() != null ? d.getQuantity() : 0); - totalAmount += (d.getPrice() != null ? d.getPrice() * (d.getQuantity() != null ? d.getQuantity() : 0) : 0); - if (orderMainId == null) { - orderMainId = d.getOrderMainId(); - } - } - - if (orderMainId != null) { - OrderMain main = orderMainMapper.selectByPrimaryKey(orderMainId); - if (main != null) { - Long prevQty = main.getDispensedQuantity() != null ? main.getDispensedQuantity() : 0L; - Double prevAmt = main.getDispensedAmount() != null ? main.getDispensedAmount() : 0.0; - - // 减去本次退药的数量和金额 - main.setDispensedQuantity(prevQty - totalQuantity); - main.setDispensedAmount(prevAmt - totalAmount); - main.setUpdateTime(now); - orderMainMapper.updateByPrimaryKeySelective(main); - } - } - - log.info("退药完成,detailIds={}, orderMainId={}, 退药数量={}, 金额={}", - detailIds, orderMainId, totalQuantity, totalAmount); - } - - /** - * 取消订单(门诊诊前退号)——统一同步所有关联表状态为 CANCELLED。 - * - * @param orderMainId 主单 ID - */ @Transactional(rollbackFor = Exception.class) - @Override public void cancelOrder(Long orderMainId) { - if (orderMainId == null) { - throw new BusinessException("订单主键不能为空"); + // 1. 校验主订单是否存在 + OrderMain orderMain = orderMainMapper.selectByPrimaryKey(orderMainId); + if (orderMain == null) { + log.warn("Cancel order failed: OrderMain not found, id={}", orderMainId); + throw new BusinessException("订单不存在,无法取消"); } - // 更新 OrderMain 状态 - OrderMain main = new OrderMain(); - main.setId(orderMainId); - main.setStatus(OrderStatus.CANCELLED); - main.setUpdateTime(new Date()); - orderMainMapper.updateByPrimaryKeySelective(main); + // 2. 若已经是取消状态,直接返回(幂等) + if (OrderStatus.CANCELLED.getCode().equals(orderMain.getStatus())) { + log.info("Order already cancelled, id={}", orderMainId); + return; + } - // 更新所有关联的 OrderDetail 状态 - orderDetailMapper.updateStatusByMainId(orderMainId, OrderStatus.CANCELLED); + // 3. 更新主订单状态 + OrderMain updateMain = new OrderMain(); + updateMain.setId(orderMainId); + updateMain.setStatus(OrderStatus.CANCELLED.getCode()); + updateMain.setUpdateTime(new Date()); + orderMainMapper.updateByPrimaryKeySelective(updateMain); + log.debug("OrderMain status set to CANCELLED, id={}", orderMainId); - // 更新关联的 ScheduleSlot 状态(假设有此方法) - scheduleSlotMapper.updateStatusByOrderMainId(orderMainId, OrderStatus.CANCELLED); + // 4. 更新所有明细状态 + OrderDetail exampleDetail = new OrderDetail(); + exampleDetail.setOrderMainId(orderMainId); + List details = orderDetailMapper.select(exampleDetail); + if (details != null && !details.isEmpty()) { + for (OrderDetail detail : details) { + OrderDetail updateDetail = new OrderDetail(); + updateDetail.setId(detail.getId()); + updateDetail.setStatus(OrderStatus.CANCELLED.getCode()); + updateDetail.setUpdateTime(new Date()); + orderDetailMapper.updateByPrimaryKeySelective(updateDetail); + } + log.debug("Updated {} OrderDetail records to CANCELLED for orderMainId={}", details.size(), orderMainId); + } - log.info("订单取消完成,orderMainId={}, 状态统一为 {}", orderMainId, OrderStatus.CANCELLED); + // 5. 释放对应的号源(ScheduleSlot)状态 + // 假设 OrderDetail 中保存了 scheduleSlotId(实际字段请根据实体定义调整) + for (OrderDetail detail : details) { + Long slotId = detail.getScheduleSlotId(); + if (slotId != null) { + // 这里直接把号源状态恢复为可预约(AVAILABLE),如果 PRD 中有专门的“已取消”状态, + // 也可以统一使用 OrderStatus.CANCELLED。 + scheduleSlotMapper.updateStatusById(slotId, OrderStatus.CANCELLED.getCode()); + log.debug("ScheduleSlot id={} set to CANCELLED for orderMainId={}", slotId, orderMainId); + } + } + + log.info("Successfully cancelled order, orderMainId={}", orderMainId); } // ------------------------------------------------------------------------- - // 其余业务实现保持不变 + // 其它业务方法(省略)... // ------------------------------------------------------------------------- }