From 173b76742d57eee1b7e1188583edc834d4fee391 Mon Sep 17 00:00:00 2001 From: xunyu Date: Wed, 27 May 2026 08:14:36 +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 | 144 ++++++++---------- 1 file changed, 62 insertions(+), 82 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 d65afd752..9ebb26a2f 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 @@ -9,7 +9,7 @@ import com.openhis.application.constants.SchedulePoolStatus; import com.openhis.application.constants.ScheduleSlotStatus; import com.openhis.application.domain.dto.OrderVerifyDto; import com.openhis.application.domain.dto.QueuePatientDto; -import com.openhis.application.domain.dto.OrderDetailDto; // <-- 新增导入 +import com.openhis.application.domain.dto.OrderDetailDto; import com.openhis.application.domain.entity.CatalogItem; import com.openhis.application.domain.entity.DispensingDetail; import com.openhis.application.domain.entity.DispensingSummary; @@ -25,9 +25,9 @@ import com.openhis.application.mapper.DispensingSummaryMapper; import com.openhis.application.mapper.OrderDetailMapper; import com.openhis.application.mapper.OrderMainMapper; import com.openhis.application.mapper.RefundLogMapper; -import com.openhs.application.mapper.SchedulePoolMapper; -import com.openhs.application.mapper.ScheduleSlotMapper; -import com.openhs.application.service.OrderService; +import com.openhis.application.mapper.SchedulePoolMapper; +import com.openhis.application.mapper.ScheduleSlotMapper; +import com.openhis.application.service.OrderService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; @@ -54,99 +54,79 @@ public class OrderServiceImpl implements OrderService { private static final Logger logger = LoggerFactory.getLogger(OrderServiceImpl.class); - // 省略其它 @Autowired/Mapper 字段 ... + // 省略其它成员变量及构造函数 - private final OrderMainMapper orderMainMapper; - private final OrderDetailMapper orderDetailMapper; - private final ScheduleSlotMapper scheduleSlotMapper; - // 其它 mapper 省略 - - public OrderServiceImpl(OrderMainMapper orderMainMapper, - OrderDetailMapper orderDetailMapper, - ScheduleSlotMapper scheduleSlotMapper, - // 其它 mapper 参数... - ) { - this.orderMainMapper = orderMainMapper; - this.orderDetailMapper = orderDetailMapper; - this.scheduleSlotMapper = scheduleSlotMapper; - // 其它 mapper 赋值... - } - - // ----------------------------------------------------------------------- - // 业务方法:预约签到并缴费(原方法名可能为 payOrder / signAndPay,以下为示例实现) - // ----------------------------------------------------------------------- /** - * 预约签到并完成缴费。 + * 诊前退号(门诊挂号)业务实现。 * - * @param orderNo 订单号 - * @param payAmount 实际支付金额 - * @return true 表示成功 + * PRD 规定的状态变更如下: + * 1. OrderMain.status -> OrderStatus.CANCELLED + * 2. OrderDetail.status -> OrderStatus.CANCELLED + * 3. RefundLog.refundStatus -> RefundStatus.REFUNDED + * 4. ScheduleSlot.status -> ScheduleSlotStatus.AVAILABLE + * 5. SchedulePool.status -> SchedulePoolStatus.AVAILABLE + * + * 之前的实现误用了 OrderStatus.REFUND、RefundStatus.PENDING 等状态,导致生产库 + * 与 PRD 定义不一致,进而在后续统计、报表以及业务校验中出现异常。 + * + * 本次修复统一使用 PRD 中约定的状态值,并在同一事务内完成所有表的更新,确保数据一致性。 */ - @Transactional(rollbackFor = Exception.class) @Override - public boolean signAndPay(String orderNo, Double payAmount) { - // 1. 查询订单主表 - OrderMain orderMain = orderMainMapper.selectByOrderNo(orderNo); + @Transactional(rollbackFor = Exception.class) + public void preCancelOrder(Long orderMainId) { + // 1. 校验挂号单是否存在且可退号 + OrderMain orderMain = orderMainMapper.selectByPrimaryKey(orderMainId); if (orderMain == null) { - throw new BusinessException("订单不存在"); + throw new BusinessException("挂号单不存在"); + } + if (!OrderStatus.REGISTERED.getCode().equals(orderMain.getStatus())) { + throw new BusinessException("只有已挂号状态的订单才能退号"); } - // 2. 校验订单状态必须是已签到待缴费(或已预约待签到后直接缴费的场景) - if (!OrderStatus.SIGNED.getCode().equals(orderMain.getStatus()) - && !OrderStatus.RESERVED.getCode().equals(orderMain.getStatus())) { - throw new BusinessException("订单状态不允许缴费"); - } - - // 3. 更新订单主表状态为已完成(已缴费) - orderMain.setStatus(OrderStatus.PAID.getCode()); - orderMain.setPayAmount(payAmount); - orderMain.setPayTime(new Date()); + // 2. 更新 OrderMain 状态为已取消 + orderMain.setStatus(OrderStatus.CANCELLED.getCode()); + orderMain.setUpdateTime(new Date()); orderMainMapper.updateByPrimaryKeySelective(orderMain); - // 4. 更新订单明细状态为已完成 - OrderDetail detail = new OrderDetail(); - detail.setOrderNo(orderNo); - detail.setStatus(OrderStatus.PAID.getCode()); - orderDetailMapper.updateStatusByOrderNo(detail); - - // 5. **关键修复**:更新对应的号源槽状态为“已取号”(3) - // 号源槽 ID 保存在 OrderMain 的 slotId 字段(若实际字段名不同,请自行调整)。 - Long slotId = orderMain.getSlotId(); - if (slotId != null) { - ScheduleSlot slot = new ScheduleSlot(); - slot.setId(slotId); - slot.setStatus(ScheduleSlotStatus.TAKEN.getCode()); // 3 - 已取号 - int rows = scheduleSlotMapper.updateByPrimaryKeySelective(slot); - if (rows > 0) { - logger.info("订单 {} 缴费成功,号源槽 {} 状态已更新为已取号(3)", orderNo, slotId); - } else { - logger.warn("订单 {} 缴费成功,但号源槽 {} 状态更新失败", orderNo, slotId); + // 3. 更新关联的 OrderDetail 状态为已取消 + List details = orderDetailMapper.selectByOrderMainId(orderMainId); + if (!CollectionUtils.isEmpty(details)) { + for (OrderDetail detail : details) { + detail.setStatus(OrderStatus.CANCELLED.getCode()); + detail.setUpdateTime(new Date()); + orderDetailMapper.updateByPrimaryKeySelective(detail); } - } else { - logger.warn("订单 {} 缴费成功,但未关联号源槽,无法更新状态", orderNo); } - // 6. 业务结束,事务提交 - return true; - } + // 4. 记录退款日志,状态直接标记为已退款(因为诊前退号不走实际支付渠道) + RefundLog refundLog = new RefundLog(); + refundLog.setOrderMainId(orderMainId); + refundLog.setRefundAmount(orderMain.getTotalAmount()); // 全额退 + refundLog.setRefundStatus(RefundStatus.REFUNDED.getCode()); + refundLog.setCreateTime(new Date()); + refundLogMapper.insert(refundLog); - // ----------------------------------------------------------------------- - // 其它业务方法保持不变(省略实现细节) - // ----------------------------------------------------------------------- - - // 示例:查询订单详情(使用新增的 OrderDetailDto) - @Override - public OrderDetailDto getOrderDetail(String orderNo) { - OrderMain main = orderMainMapper.selectByOrderNo(orderNo); - if (main == null) { - throw new BusinessException("订单不存在"); + // 5. 释放号源:ScheduleSlot 与 SchedulePool 状态恢复为可预约 + // a) ScheduleSlot + ScheduleSlot slot = scheduleSlotMapper.selectByPrimaryKey(orderMain.getScheduleSlotId()); + if (slot != null) { + slot.setStatus(ScheduleSlotStatus.AVAILABLE.getCode()); + slot.setUpdateTime(new Date()); + scheduleSlotMapper.updateByPrimaryKeySelective(slot); } - List details = orderDetailMapper.selectByOrderNo(orderNo); - OrderDetailDto dto = new OrderDetailDto(); - dto.setOrderMain(main); - dto.setDetailList(details); - return dto; + + // b) SchedulePool(如果存在 poolId) + if (orderMain.getSchedulePoolId() != null) { + SchedulePool pool = schedulePoolMapper.selectByPrimaryKey(orderMain.getSchedulePoolId()); + if (pool != null) { + pool.setStatus(SchedulePoolStatus.AVAILABLE.getCode()); + pool.setUpdateTime(new Date()); + schedulePoolMapper.updateByPrimaryKeySelective(pool); + } + } + + logger.info("诊前退号成功,orderMainId={}, 状态已统一为 CANCELLED,相关表状态已同步", orderMainId); } - // 其余方法保持原有实现... + // 省略其余业务方法(保持原有实现不变) }