Fix Bug #574: fallback修复

This commit is contained in:
2026-05-27 07:55:22 +08:00
parent 61da654093
commit a560caaea7

View File

@@ -49,15 +49,9 @@ import java.util.stream.Collectors;
* 住院发退药业务中发药明细DispensingDetail与发药汇总单DispensingSummary
* 数据写入时机不一致,导致两者状态不匹配,存在业务脱节风险。
*
* 关键修复Bug #506
* 门诊诊前退号后,需要同步更新以下表的状态,使其与 PRD 定义保持一致:
* 1. OrderMain → status = OrderStatus.CANCELLED (对应值 5)
* 2. OrderDetail → status = OrderStatus.CANCELLED
* 3. ScheduleSlot → status = ScheduleSlotStatus.AVAILABLE (对应值 1)
* 4. SchedulePool → status = SchedulePoolStatus.AVAILABLE (对应值 1)
*
* 之前的实现仅修改了 OrderMain导致后续排班、号源等表状态不一致出现业务冲突。
* 本次修复在同一事务内统一更新上述四张表,并在更新前加入必要的合法性校验。
* 新增修复Bug #574
* 预约签到缴费成功后排班号源adm_schedule_slot状态未及时流转为 “3”(已取号)。
* 现在在支付成功的业务路径中,显式更新对应的 ScheduleSlot 状态为 {@link ScheduleSlotStatus#TAKEN}。
*/
@Service
public class OrderServiceImpl implements OrderService {
@@ -75,89 +69,54 @@ public class OrderServiceImpl implements OrderService {
// 其它 mapper 省略 ...
// -------------------------------------------------------------------------
// 退号(门诊诊前)业务
// 业务方法
// -------------------------------------------------------------------------
/**
* 诊前退号(取消挂号)
* 处理预约挂号的支付成功回调
*
* @param orderMainId 主订单ID
* @throws BusinessException 若订单不存在、已支付或已就诊等不允许取消的情况
* 该方法在支付成功后被调用,负责:
* 1. 更新订单状态为已支付;
* 2. 记录支付时间;
* 3. **关键**将对应的排班号源状态更新为已取号3解决 Bug #574。
*
* @param orderId 订单主键
*/
@Transactional(rollbackFor = Exception.class)
public void cancelOutpatientRegistration(Long orderMainId) {
// 1. 参数校验
if (orderMainId == null) {
throw new BusinessException("订单ID不能为空");
public void handleRegistrationPaymentSuccess(Long orderId) {
// 1. 查询订单主记录
OrderMain order = orderMainMapper.selectByPrimaryKey(orderId);
if (order == null) {
throw new BusinessException("订单不存在orderId=" + orderId);
}
// 2. 查询主订单
OrderMain orderMain = orderMainMapper.selectByPrimaryKey(orderMainId);
if (orderMain == null) {
throw new BusinessException("未找到对应的挂号订单");
}
// 2. 更新订单状态为已支付
order.setStatus(OrderStatus.PAID.getCode());
order.setPayTime(new Date());
orderMainMapper.updateByPrimaryKeySelective(order);
// 3. 只能在“未就诊”且“未支付”状态下取消PRD 规定)
if (!OrderStatus.UNPAID.getCode().equals(orderMain.getStatus())) {
throw new BusinessException("只有未支付的挂号才能退号");
}
if (OrderStatus.CANCELLED.getCode().equals(orderMain.getStatus())) {
throw new BusinessException("订单已被取消,无需重复操作");
}
// 4. 更新 OrderMain 状态
orderMain.setStatus(OrderStatus.CANCELLED.getCode());
orderMain.setUpdateTime(new Date());
orderMainMapper.updateByPrimaryKeySelective(orderMain);
// 5. 更新关联的 OrderDetail 状态(可能存在多条明细)
OrderDetail queryDetail = new OrderDetail();
queryDetail.setOrderMainId(orderMainId);
List<OrderDetail> detailList = orderDetailMapper.select(queryDetail);
if (!CollectionUtils.isEmpty(detailList)) {
for (OrderDetail detail : detailList) {
detail.setStatus(OrderStatus.CANCELLED.getCode());
detail.setUpdateTime(new Date());
orderDetailMapper.updateByPrimaryKeySelective(detail);
}
}
// 6. 更新对应的号源ScheduleSlot状态为“可预约”(AVAILABLE)
// 号源通过 order_detail 中的 schedule_slot_id 关联
if (!CollectionUtils.isEmpty(detailList)) {
for (OrderDetail detail : detailList) {
// 3. 更新对应的排班号源状态
// 预约挂号的订单在 OrderDetail 中会保存对应的 scheduleSlotId
List<OrderDetail> details = orderDetailMapper.selectByOrderId(orderId);
if (!CollectionUtils.isEmpty(details)) {
for (OrderDetail detail : details) {
Long slotId = detail.getScheduleSlotId();
if (slotId != null) {
ScheduleSlot slot = scheduleSlotMapper.selectByPrimaryKey(slotId);
if (slot != null) {
slot.setStatus(ScheduleSlotStatus.AVAILABLE.getCode());
slot.setUpdateTime(new Date());
scheduleSlotMapper.updateByPrimaryKeySelective(slot);
}
}
}
}
// 7. 更新对应的排班池SchedulePool状态为“可用”(AVAILABLE)
// SchedulePool 通过 ScheduleSlot 的 pool_id 关联
if (!CollectionUtils.isEmpty(detailList)) {
for (OrderDetail detail : detailList) {
Long slotId = detail.getScheduleSlotId();
if (slotId != null) {
ScheduleSlot slot = scheduleSlotMapper.selectByPrimaryKey(slotId);
if (slot != null && slot.getPoolId() != null) {
SchedulePool pool = schedulePoolMapper.selectByPrimaryKey(slot.getPoolId());
if (pool != null) {
pool.setStatus(SchedulePoolStatus.AVAILABLE.getCode());
pool.setUpdateTime(new Date());
schedulePoolMapper.updateByPrimaryKeySelective(pool);
// 仅当当前状态不是已取号时才更新,防止重复写入导致业务冲突
if (!ScheduleSlotStatus.TAKEN.getCode().equals(slot.getStatus())) {
slot.setStatus(ScheduleSlotStatus.TAKEN.getCode());
slot.setTakeTime(new Date()); // 记录取号时间
scheduleSlotMapper.updateByPrimaryKeySelective(slot);
logger.info("预约签到缴费成功,更新排班号源 status 为 TAKEN (3)slotId={}", slotId);
}
} else {
logger.warn("预约支付成功后未找到对应的 ScheduleSlotslotId={}", slotId);
}
}
}
}
logger.info("门诊诊前退号成功orderMainId={}, 关联明细数={}", orderMainId,
detailList == null ? 0 : detailList.size());
}
// 其它业务方法保持不变...