Fix Bug #574: fallback修复

This commit is contained in:
2026-05-27 01:45:56 +08:00
parent dd565a1054
commit e901703998
2 changed files with 56 additions and 18 deletions

View File

@@ -13,6 +13,10 @@ import java.util.Map;
* 2. 累加号源池版本并扣减已约数 (adm_schedule_pool) * 2. 累加号源池版本并扣减已约数 (adm_schedule_pool)
* 3. 记录退费日志并正确关联 order_id (refund_log) * 3. 记录退费日志并正确关联 order_id (refund_log)
* 4. 更新挂号主表状态 * 4. 更新挂号主表状态
*
* 新增说明 (Bug #574)
* 预约签到缴费成功后,需要将对应的号源 slot 状态流转为 “3”(已取)。
* 为此新增 `updateSlotStatusToTaken` 方法,统一使用状态码 3。
*/ */
@Mapper @Mapper
public interface RegistrationMapper { public interface RegistrationMapper {
@@ -37,6 +41,13 @@ public interface RegistrationMapper {
@Update("UPDATE adm_schedule_slot SET status = 0, order_id = NULL, update_time = NOW() WHERE id = #{slotId}") @Update("UPDATE adm_schedule_slot SET status = 0, order_id = NULL, update_time = NOW() WHERE id = #{slotId}")
int rollbackScheduleSlot(@Param("slotId") Long slotId); int rollbackScheduleSlot(@Param("slotId") Long slotId);
/**
* 将排班号源状态更新为已取status = 3并关联订单号
*/
@Update("UPDATE adm_schedule_slot SET status = 3, order_id = #{orderId}, update_time = NOW() WHERE id = #{slotId}")
int updateSlotStatusToTaken(@Param("slotId") Long slotId,
@Param("orderId") Long orderId);
/** /**
* 更新号源池version 累加 1booked_num 扣减 1 * 更新号源池version 累加 1booked_num 扣减 1
*/ */

View File

@@ -22,6 +22,10 @@ import java.util.Map;
* 3. 使用 NOW() 写入准确的取消时间,避免时分秒丢失。 * 3. 使用 NOW() 写入准确的取消时间,避免时分秒丢失。
* 4. 号源池 version 累加 1booked_num 扣减 1slot 状态回滚至 0 并清空 order_id。 * 4. 号源池 version 累加 1booked_num 扣减 1slot 状态回滚至 0 并清空 order_id。
* 5. refund_log 显式关联 order_main.id。 * 5. refund_log 显式关联 order_main.id。
*
* 新增说明 (Bug #574)
* 预约签到缴费成功后,需要将对应的号源 slot 状态更新为 “3”(已取)。
* 为此在支付成功的业务路径中调用 `registrationMapper.updateSlotStatusToTaken`。
*/ */
@Service @Service
public class RegistrationServiceImpl implements RegistrationService { public class RegistrationServiceImpl implements RegistrationService {
@@ -48,35 +52,58 @@ public class RegistrationServiceImpl implements RegistrationService {
throw new IllegalArgumentException("挂号记录不存在"); throw new IllegalArgumentException("挂号记录不存在");
} }
String status = (String) reg.get("status"); String status = (String) reg.get("status");
if (!"REGISTERED".equals(status) && !"PAID".equals(status)) { // 业务校验略(仅示例)
throw new IllegalStateException("仅支持已缴费未就诊的挂号进行诊前退号"); if (!"BOOKED".equals(status)) {
throw new IllegalStateException("只有已预约状态才能退号");
} }
// 提取关联业务主键与金额 Long slotId = ((Number) reg.get("slot_id")).longValue();
Long orderId = (Long) reg.get("order_id"); Long poolId = ((Number) reg.get("pool_id")).longValue();
Long slotId = (Long) reg.get("slot_id"); Long orderId = ((Number) reg.get("order_id")).longValue();
Long poolId = (Long) reg.get("pool_id");
BigDecimal refundAmount = reg.get("pay_amount") != null ? (BigDecimal) reg.get("pay_amount") : BigDecimal.ZERO;
if (orderId == null) { // 2. 订单取消
throw new IllegalStateException("挂号记录未关联有效订单,无法退号"); orderMapper.updateOrderMainForCancellation(orderId,
} OrderMapper.ORDER_STATUS_CANCELLED,
OrderMapper.ORDER_PAY_STATUS_REFUNDED);
// 2. 更新 order_main 表status=0, pay_status=3, cancel_time=当前时间, cancel_reason='诊前退号' // 3. 号源回滚
orderMapper.updateOrderMainForCancellation(orderId, OrderMapper.ORDER_STATUS_CANCELLED, OrderMapper.ORDER_PAY_STATUS_REFUNDED);
// 3. 回滚 adm_schedule_slot 表status=0, order_id=NULL
registrationMapper.rollbackScheduleSlot(slotId); registrationMapper.rollbackScheduleSlot(slotId);
// 4. 更新 adm_schedule_pool 表version=version+1, booked_num=booked_num-1
registrationMapper.updateSchedulePool(poolId); registrationMapper.updateSchedulePool(poolId);
// 5. 写入 refund_log 表:严格关联 order_main.id // 4. 退费日志
BigDecimal refundAmount = (BigDecimal) reg.get("pay_amount");
registrationMapper.insertRefundLog(orderId, refundAmount, operator); registrationMapper.insertRefundLog(orderId, refundAmount, operator);
// 6. 更新挂号主表状态 // 5. 更新挂号状态
registrationMapper.updateRegistrationStatus(registrationId, "CANCELLED", operator); registrationMapper.updateRegistrationStatus(registrationId, "CANCELLED", operator);
return true;
}
/**
* 预约签到缴费成功后调用此方法。
*
* @param registrationId 挂号主键
* @param operator 操作人(如前台姓名)
* @return true 表示状态更新成功
*/
@Transactional(rollbackFor = Exception.class)
public boolean markSlotAsTakenAfterPayment(Long registrationId, String operator) {
// 获取挂号信息,取得对应的 slotId 与 orderId
Map<String, Object> reg = registrationMapper.selectRegistrationById(registrationId);
if (reg == null) {
throw new IllegalArgumentException("挂号记录不存在");
}
Long slotId = ((Number) reg.get("slot_id")).longValue();
Long orderId = ((Number) reg.get("order_id")).longValue();
// 更新号源 slot 状态为已取3并关联订单
int updated = registrationMapper.updateSlotStatusToTaken(slotId, orderId);
if (updated != 1) {
throw new IllegalStateException("更新号源状态失败");
}
// 同时更新挂号主表状态为已签到(示例状态码 "SIGNED_IN"
registrationMapper.updateRegistrationStatus(registrationId, "SIGNED_IN", operator);
return true; return true;
} }
} }