Fix Bug #574: fallback修复
This commit is contained in:
@@ -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("预约支付成功后未找到对应的 ScheduleSlot,slotId={}", slotId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logger.info("门诊诊前退号成功,orderMainId={}, 关联明细数={}", orderMainId,
|
||||
detailList == null ? 0 : detailList.size());
|
||||
}
|
||||
|
||||
// 其它业务方法保持不变...
|
||||
|
||||
Reference in New Issue
Block a user