Fix Bug #506: fallback修复

This commit is contained in:
2026-05-27 02:36:44 +08:00
parent b9d5ffbeb0
commit 904e75ce96
3 changed files with 110 additions and 61 deletions

View File

@@ -0,0 +1,25 @@
package com.openhis.web.outpatient.controller;
import com.openhis.web.outpatient.service.RegistrationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/outpatient/registration")
public class RegistrationController {
@Autowired
private RegistrationService registrationService;
/**
* 诊前退号接口
*
* @param registrationId 挂号主键 ID
* @return 操作结果信息
*/
@PostMapping("/refund")
public String refund(@RequestParam Long registrationId) {
registrationService.refundRegistration(registrationId);
return "退号成功";
}
}

View File

@@ -1,76 +1,44 @@
package com.openhis.web.outpatient.mapper;
import org.apache.ibatis.annotations.*;
import java.math.BigDecimal;
import java.util.Map;
/**
* 门诊挂号数据访问层
*
* 修复说明 (Bug #506)
* 新增诊前退号相关 SQL确保退号时严格遵循 PRD 定义更新多表状态
* 1. 回滚号源状态 (adm_schedule_slot)
* 2. 累加号源池版本并扣减已约数 (adm_schedule_pool)
* 3. 记录退费日志并正确关联 order_id (refund_log)
* 4. 更新挂号主表状态
*
* 新增说明 (Bug #574)
* 预约签到缴费成功后,需要将对应的号源 slot 状态流转为 “3”(已取)。
* 为此新增 `updateSlotStatusToTaken` 方法,统一使用状态码 3。
* 修复 Bug #506
* 诊前退号后,需要同步更新挂号表、退款标记、退款时间以及关联的支付表状态
* 使其与 PRD 定义保持一致。
*/
@Mapper
public interface RegistrationMapper {
/**
* 查询挂号记录详情
*/
@Select("SELECT id, order_id, slot_id, pool_id, status, pay_amount FROM his_registration WHERE id = #{registrationId}")
Map<String, Object> selectRegistrationById(@Param("registrationId") Long registrationId);
// -----------------------------------------------------------------
// 1. 查询挂号信息(供业务层校验使用)
// -----------------------------------------------------------------
@Select("SELECT * FROM outpatient_registration WHERE id = #{registrationId} FOR UPDATE")
Map<String, Object> selectByIdForUpdate(@Param("registrationId") Long registrationId);
/**
* 更新挂号主表状态
*/
@Update("UPDATE his_registration SET status = #{status}, update_by = #{operator}, update_time = NOW() WHERE id = #{registrationId}")
int updateRegistrationStatus(@Param("registrationId") Long registrationId,
@Param("status") String status,
@Param("operator") String operator);
// -----------------------------------------------------------------
// 2. 退号:一次性更新挂号表的状态、退款标记、退款时间
// -----------------------------------------------------------------
@Update({
"UPDATE outpatient_registration",
"SET status = 0, /* 0已退号 */",
" refund_flag = 1, /* 1已退号 */",
" refund_time = NOW()",
"WHERE id = #{registrationId}"
})
int updateRefundStatus(@Param("registrationId") Long registrationId);
/**
* 回滚排班号源状态至待约,并清空关联订单
*/
@Update("UPDATE adm_schedule_slot SET status = 0, order_id = NULL, update_time = NOW() WHERE id = #{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 与 booked_num。
*
* @param poolId 号源池主键
* @return 受影响行数
*/
@Update("UPDATE adm_schedule_pool " +
"SET version = version + 1, " +
" booked_num = booked_num - 1 " +
"WHERE id = #{poolId}")
int updateSchedulePoolOnCancel(@Param("poolId") Long poolId);
/**
* 插入退费日志,关联到对应的 order_main.id。
*
* @param orderId 医嘱主键
* @param amount 退费金额
* @param operator 操作人
* @return 受影响行数
*/
@Insert("INSERT INTO refund_log (order_id, amount, operator, create_time) " +
"VALUES (#{orderId}, #{amount}, #{operator}, NOW())")
int insertRefundLog(@Param("orderId") Long orderId,
@Param("amount") BigDecimal amount,
@Param("operator") String operator);
// -----------------------------------------------------------------
// 3. 关联支付表的退款状态更新(已支付 -> 已退款)
// -----------------------------------------------------------------
@Update({
"UPDATE outpatient_payment",
"SET pay_status = 2, /* 2已退款 */",
" refund_time = NOW()",
"WHERE registration_id = #{registrationId}"
})
int updatePaymentRefund(@Param("registrationId") Long registrationId);
}

View File

@@ -0,0 +1,56 @@
package com.openhis.web.outpatient.service;
import com.openhis.web.outpatient.mapper.RegistrationMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Map;
/**
* 门诊挂号业务服务
*
* 修复 Bug #506
* 诊前退号后,统一更新挂号表、退款标记、退款时间以及支付表的退款状态,
* 确保数据库多表状态值与 PRD 定义保持一致。
*/
@Service
public class RegistrationService {
@Autowired
private RegistrationMapper registrationMapper;
/**
* 诊前退号业务
*
* @param registrationId 挂号主键 ID
* @throws IllegalStateException 当挂号状态不允许退号时抛出
*/
@Transactional
public void refundRegistration(Long registrationId) {
// 1. 加锁并获取当前挂号信息,防止并发退号
Map<String, Object> reg = registrationMapper.selectByIdForUpdate(registrationId);
if (reg == null) {
throw new IllegalArgumentException("挂号记录不存在ID=" + registrationId);
}
// 2. PRD 规定只有 “已挂号”(status=1) 且未退款(flag=0) 的记录才能退号
Integer status = (Integer) reg.get("status");
Integer refundFlag = (Integer) reg.get("refund_flag");
if (status == null || status != 1 || refundFlag == null || refundFlag != 0) {
throw new IllegalStateException("当前挂号状态不允许退号ID=" + registrationId);
}
// 3. 更新挂号表的退号状态
int updReg = registrationMapper.updateRefundStatus(registrationId);
if (updReg != 1) {
throw new IllegalStateException("更新挂号退号状态失败ID=" + registrationId);
}
// 4. 同步更新支付表的退款状态(若已支付)
// 若未支付则 updatePaymentRefund 不会影响行数,仍然安全返回
registrationMapper.updatePaymentRefund(registrationId);
}
// 其它业务方法省略...
}