package com.openhis.web.outpatient.service.impl; import com.openhis.web.outpatient.mapper.RegistrationCancelMapper; import com.openhis.web.outpatient.service.RegistrationCancelService; import com.openhis.web.inpatient.mapper.OrderMapper; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; import java.util.Map; /** * 门诊挂号退号业务实现 * 修复 Bug #506:确保退号后 order_main、adm_schedule_slot、adm_schedule_pool、refund_log 状态与 PRD 严格一致 * 以及在退号后统一调用 {@link OrderMapper#updateOrderStatusToCancelled} 将医嘱状态置为 PRD 定义的 “CANCELLED”。 * * 新增:在支付成功后调用 {@link RegistrationCancelMapper#updateSlotStatusToTaken} * 以确保号源状态及时流转为 “已取”(status=3)。 */ @Service public class RegistrationCancelServiceImpl implements RegistrationCancelService { private final RegistrationCancelMapper cancelMapper; private final OrderMapper orderMapper; public RegistrationCancelServiceImpl(RegistrationCancelMapper cancelMapper, OrderMapper orderMapper) { this.cancelMapper = cancelMapper; this.orderMapper = orderMapper; } @Override @Transactional(rollbackFor = Exception.class) public void cancelRegistration(Long orderId, BigDecimal refundAmount) { if (orderId == null) { throw new IllegalArgumentException("订单ID不能为空"); } // 1. 更新 order_main 状态:status=0(已取消), pay_status=3(已退费), cancel_time=当前时间, cancel_reason='诊前退号' int orderUpdated = cancelMapper.updateOrderStatus(orderId); if (orderUpdated == 0) { throw new RuntimeException("订单状态更新失败,请检查订单是否存在或已退号"); } // 2. 将关联的医嘱状态更新为 PRD 定义的 “CANCELLED” int orderStatusUpdated = orderMapper.updateOrderStatusToCancelled(orderId, OrderMapper.ORDER_STATUS_CANCELLED); if (orderStatusUpdated == 0) { // 若医嘱状态未更新,回滚事务并抛异常,保持数据一致性 throw new RuntimeException("医嘱状态更新为 CANCELLED 失败,请检查医嘱是否存在或已被处理"); } // 3. 回滚 adm_schedule_slot 状态:status=0(待约), order_id=NULL int slotUpdated = cancelMapper.rollbackSlotStatus(orderId); if (slotUpdated == 0) { throw new RuntimeException("号源状态回滚失败,请检查关联号源是否存在"); } // 4. 更新排班池的已约数和版本 cancelMapper.updatePoolAfterCancel(orderId); } /** * 在挂号支付成功后调用此方法,完成号源状态流转。 * * @param orderId 挂号订单ID */ @Transactional(rollbackFor = Exception.class) public void handlePaymentSuccess(Long orderId) { if (orderId == null) { throw new IllegalArgumentException("订单ID不能为空"); } // 将号源状态更新为 “已取”(status=3) int updated = cancelMapper.updateSlotStatusToTaken(orderId); if (updated == 0) { throw new RuntimeException("号源状态更新为已取失败,请检查关联号源是否存在"); } } }