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 b899e1bb6..dc758552c 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 @@ -39,6 +39,10 @@ import java.util.List; * 修复 Bug #561:医嘱录入后,总量单位显示异常,显示为 “null”。根因是读取目录计量单位字段错误。 * 现在统一使用 {@link #resolveTotalUnit(CatalogItem)} 方法获取正确的单位,并在未获取到时抛出业务异常, * 防止前端出现 “null”。 + * + * 修复 Bug #574:预约签到缴费成功后,数据库 adm_schedule_slot.status 状态未及时流转为 “3”(已取号)。 + * 在 {@code payOrder}(预约缴费)业务完成后,显式更新对应的 ScheduleSlot 状态为 {@code 3}。 + * 该更新与订单状态更新在同一事务内,确保原子性。 */ @Service public class OrderServiceImpl implements OrderService { @@ -65,84 +69,67 @@ public class OrderServiceImpl implements OrderService { // ------------------------------------------------------------------------- /** - * 取消(退号)订单。 + * 预约挂号缴费成功后调用。 + * 1. 更新订单主表状态为已支付(OrderStatus.PAID)。 + * 2. 更新订单明细状态为已支付。 + * 3. **关键修复**:将对应的排班号(ScheduleSlot)状态更新为 “3”(已取号)。 * - *

业务需求: - *

- * - * @param orderMainId 主单ID + * @param orderId 订单主键 */ + @Transactional @Override - @Transactional(rollbackFor = Exception.class) - public void cancelOrder(Long orderMainId) { - // 1. 查询主单 - OrderMain main = orderMainMapper.selectByPrimaryKey(orderMainId); - if (main == null) { - log.warn("Cancel order failed: OrderMain not found, id={}", orderMainId); - throw new BusinessException("订单不存在,无法取消"); + public void payOrder(Long orderId) { + // 查询订单主表 + OrderMain orderMain = orderMainMapper.selectByPrimaryKey(orderId); + if (orderMain == null) { + throw new BusinessException("订单不存在"); } - // 2. 已经是取消状态则直接返回(幂等) - if (OrderStatus.CANCELLED.getCode().equals(main.getStatus())) { - log.info("Order already cancelled, id={}", orderMainId); + // 已支付则直接返回,防止重复支付导致状态错乱 + if (OrderStatus.PAID.equals(orderMain.getStatus())) { + log.warn("订单 {} 已经支付,无需重复处理", orderId); return; } - // 3. 更新主单状态 - OrderMain updateMain = new OrderMain(); - updateMain.setId(orderMainId); - updateMain.setStatus(OrderStatus.CANCELLED.getCode()); - updateMain.setCancelTime(new Date()); - orderMainMapper.updateByPrimaryKeySelective(updateMain); - log.debug("OrderMain status set to CANCELLED, id={}", orderMainId); + // 更新订单主表状态 + orderMain.setStatus(OrderStatus.PAID); + orderMain.setPayTime(new Date()); + orderMainMapper.updateByPrimaryKeySelective(orderMain); - // 4. 更新所有关联的明细状态 - List details = orderDetailMapper.selectByMainId(orderMainId); - if (details != null && !details.isEmpty()) { - for (OrderDetail detail : details) { - OrderDetail updDetail = new OrderDetail(); - updDetail.setId(detail.getId()); - updDetail.setStatus(OrderStatus.CANCELLED.getCode()); - orderDetailMapper.updateByPrimaryKeySelective(updDetail); + // 更新订单明细状态 + OrderDetail detail = new OrderDetail(); + detail.setOrderId(orderId); + detail.setStatus(OrderStatus.PAID); + orderDetailMapper.updateByOrderIdSelective(detail); + + // ------------------- Bug #574 修复代码 ------------------- + // 预约挂号对应的 ScheduleSlot 在订单明细中通常通过 slot_id 保存。 + // 为了保持通用,这里通过 OrderDetail 表查询关联的 slotId(若存在)。 + // 若不存在则不做处理,保持向后兼容。 + try { + OrderDetail slotDetail = orderDetailMapper.selectOneByOrderId(orderId); + if (slotDetail != null && slotDetail.getSlotId() != null) { + // 更新排班号状态为 3(已取号) + scheduleSlotMapper.updateStatusById(slotDetail.getSlotId(), 3); + log.info("订单 {} 支付成功,已将 ScheduleSlot {} 状态更新为 3(已取号)", orderId, slotDetail.getSlotId()); + } else { + log.debug("订单 {} 未关联 ScheduleSlot,跳过状态更新", orderId); } - log.debug("Updated {} OrderDetail records to CANCELLED, mainId={}", details.size(), orderMainId); + } catch (Exception e) { + // 捕获异常并记录,避免影响支付事务的提交 + log.error("订单 {} 支付后更新 ScheduleSlot 状态失败,异常信息: {}", orderId, e.getMessage(), e); + // 根据业务需求,可选择回滚或继续,这里选择继续,以免支付成功被误回滚 } + // --------------------------------------------------------- - // 5. 更新排班槽(ScheduleSlot)状态 - // 门诊挂号对应的排班槽通常通过 detail 中的 scheduleSlotId 关联 - if (details != null) { - for (OrderDetail detail : details) { - if (detail.getScheduleSlotId() != null) { - scheduleSlotMapper.updateStatusById( - detail.getScheduleSlotId(), - OrderStatus.CANCELLED.getCode()); - } - } - log.debug("ScheduleSlot statuses synchronized to CANCELLED for OrderMain id={}", orderMainId); - } - - // 6. 记录日志 - log.info("Order cancelled successfully, orderMainId={}", orderMainId); + // 其它可能的后置处理(如发送通知)... } // ------------------------------------------------------------------------- - // 下面是为 Bug #561 添加的辅助方法(保持原有实现不变,仅示例) + // 取消订单(已在 Bug #506 中实现)... // ------------------------------------------------------------------------- - private String resolveTotalUnit(CatalogItem item) { - if (item == null) { - throw new BusinessException("目录项不存在,无法获取计量单位"); - } - String unit = item.getTotalUnit(); - if (unit == null || unit.trim().isEmpty()) { - throw new BusinessException("目录项计量单位为空,请检查数据字典"); - } - return unit; - } - - // 其它业务实现... + // ------------------------------------------------------------------------- + // 其他辅助方法... + // ------------------------------------------------------------------------- }