Fix Bug #506: fallback修复
This commit is contained in:
@@ -5,14 +5,15 @@ 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 定义保持一致。
|
||||
* 之前的退号实现仅调用 {@link RegistrationMapper#updateRegStatus}
|
||||
* 导致费用表、排队表状态未同步,数据库状态与 PRD 定义不符。
|
||||
*
|
||||
* 现在改为使用 {@link RegistrationMapper#cancelRegistration},并在
|
||||
* 方法上加上 {@code @Transactional},确保在同一事务内完成三表更新。
|
||||
*/
|
||||
@Service
|
||||
public class RegistrationService {
|
||||
@@ -21,36 +22,35 @@ public class RegistrationService {
|
||||
private RegistrationMapper registrationMapper;
|
||||
|
||||
/**
|
||||
* 诊前退号业务
|
||||
* 诊前退号(统一更新挂号、费用、排队三张表的状态)。
|
||||
*
|
||||
* @param registrationId 挂号主键 ID
|
||||
* @throws IllegalStateException 当挂号状态不允许退号时抛出
|
||||
* @return true 表示全部三表均成功更新,false 表示更新失败(受影响行数 < 3)
|
||||
*/
|
||||
@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);
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean preCancel(Long registrationId) {
|
||||
// 调用统一的多表更新 SQL
|
||||
int affected = registrationMapper.cancelRegistration(registrationId);
|
||||
// 期望受影响行数为 3(每张表各 1 行),否则视为失败
|
||||
return affected == 3;
|
||||
}
|
||||
|
||||
// 其它业务方法省略...
|
||||
/**
|
||||
* 旧接口保留(兼容旧前端),内部已转为调用统一退号方法。
|
||||
*
|
||||
* @param registrationId 挂号主键 ID
|
||||
* @return 是否成功
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean cancelLegacy(Long registrationId) {
|
||||
// 直接使用统一方法,保持业务一致性
|
||||
return preCancel(registrationId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询挂号详情(供前端展示)。
|
||||
*/
|
||||
public Map<String, Object> getDetail(Long registrationId) {
|
||||
return registrationMapper.selectRegistrationDetail(registrationId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
package com.openhis.web.outpatient.mapper;
|
||||
|
||||
import org.apache.ibatis.annotations.*;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 门诊挂号数据访问层
|
||||
*
|
||||
* 修复 Bug #506:
|
||||
* 门诊诊前退号后,系统只更新了挂号表的状态,而未同步更新
|
||||
* 关联的费用表(his_registration_fee)以及患者排队表(his_registration_queue)的状态,
|
||||
* 导致数据库中多表状态与 PRD(“退号后挂号状态=3、费用状态=2、排队状态=0”)不一致。
|
||||
*
|
||||
* 解决方案:
|
||||
* 1. 在退号操作中统一使用 {@link #cancelRegistration(Long)} 方法,
|
||||
* 该方法一次性完成三张表的状态更新,确保事务一致性。
|
||||
* 2. 采用 MySQL 多表 UPDATE 语法,一次提交完成所有状态变更,避免因分散
|
||||
* 多次调用导致的中间状态不一致。
|
||||
* 3. 为兼容历史代码,保留原来的单表更新方法 {@code updateRegStatus},但
|
||||
* 在业务层已改为调用新的统一方法。
|
||||
*/
|
||||
@Mapper
|
||||
public interface RegistrationMapper {
|
||||
|
||||
/**
|
||||
* 旧版:仅更新挂号表状态(已废弃,仅为兼容历史调用)。
|
||||
*/
|
||||
@Update("UPDATE his_registration SET status = #{status} WHERE id = #{regId}")
|
||||
int updateRegStatus(@Param("regId") Long regId, @Param("status") Integer status);
|
||||
|
||||
/**
|
||||
* 统一退号:一次性更新挂号表、费用表、排队表的状态。
|
||||
*
|
||||
* PRD 约定的状态值:
|
||||
* - 挂号表 status = 3 (已退号)
|
||||
* - 费用表 fee_status = 2 (已退款)
|
||||
* - 排队表 queue_status = 0 (未排队/已移除)
|
||||
*
|
||||
* @param regId 挂号主键 ID
|
||||
* @return 受影响的行数(3 表均成功更新返回 3,否则返回 <3)
|
||||
*/
|
||||
@Update({
|
||||
"<script>",
|
||||
"UPDATE his_registration r",
|
||||
"JOIN his_registration_fee f ON f.registration_id = r.id",
|
||||
"JOIN his_registration_queue q ON q.registration_id = r.id",
|
||||
"SET r.status = 3,",
|
||||
" f.fee_status = 2,",
|
||||
" q.queue_status = 0",
|
||||
"WHERE r.id = #{regId}",
|
||||
"</script>"
|
||||
})
|
||||
int cancelRegistration(@Param("regId") Long regId);
|
||||
|
||||
/**
|
||||
* 查询挂号详情(用于前端展示)。
|
||||
*/
|
||||
@Select("SELECT r.id, r.patient_id, r.doctor_id, r.status, r.register_time, " +
|
||||
"f.amount, f.fee_status, q.queue_status " +
|
||||
"FROM his_registration r " +
|
||||
"LEFT JOIN his_registration_fee f ON f.registration_id = r.id " +
|
||||
"LEFT JOIN his_registration_queue q ON q.registration_id = r.id " +
|
||||
"WHERE r.id = #{regId}")
|
||||
Map<String, Object> selectRegistrationDetail(@Param("regId") Long regId);
|
||||
}
|
||||
Reference in New Issue
Block a user