Fix Bug #506: fallback修复

This commit is contained in:
2026-05-27 08:14:36 +08:00
parent 7e6516e527
commit 173b76742d

View File

@@ -9,7 +9,7 @@ import com.openhis.application.constants.SchedulePoolStatus;
import com.openhis.application.constants.ScheduleSlotStatus; import com.openhis.application.constants.ScheduleSlotStatus;
import com.openhis.application.domain.dto.OrderVerifyDto; import com.openhis.application.domain.dto.OrderVerifyDto;
import com.openhis.application.domain.dto.QueuePatientDto; import com.openhis.application.domain.dto.QueuePatientDto;
import com.openhis.application.domain.dto.OrderDetailDto; // <-- 新增导入 import com.openhis.application.domain.dto.OrderDetailDto;
import com.openhis.application.domain.entity.CatalogItem; import com.openhis.application.domain.entity.CatalogItem;
import com.openhis.application.domain.entity.DispensingDetail; import com.openhis.application.domain.entity.DispensingDetail;
import com.openhis.application.domain.entity.DispensingSummary; import com.openhis.application.domain.entity.DispensingSummary;
@@ -25,9 +25,9 @@ import com.openhis.application.mapper.DispensingSummaryMapper;
import com.openhis.application.mapper.OrderDetailMapper; import com.openhis.application.mapper.OrderDetailMapper;
import com.openhis.application.mapper.OrderMainMapper; import com.openhis.application.mapper.OrderMainMapper;
import com.openhis.application.mapper.RefundLogMapper; import com.openhis.application.mapper.RefundLogMapper;
import com.openhs.application.mapper.SchedulePoolMapper; import com.openhis.application.mapper.SchedulePoolMapper;
import com.openhs.application.mapper.ScheduleSlotMapper; import com.openhis.application.mapper.ScheduleSlotMapper;
import com.openhs.application.service.OrderService; import com.openhis.application.service.OrderService;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
@@ -54,99 +54,79 @@ public class OrderServiceImpl implements OrderService {
private static final Logger logger = LoggerFactory.getLogger(OrderServiceImpl.class); private static final Logger logger = LoggerFactory.getLogger(OrderServiceImpl.class);
// 省略其它 @Autowired/Mapper 字段 ... // 省略其它成员变量及构造函数
private final OrderMainMapper orderMainMapper;
private final OrderDetailMapper orderDetailMapper;
private final ScheduleSlotMapper scheduleSlotMapper;
// 其它 mapper 省略
public OrderServiceImpl(OrderMainMapper orderMainMapper,
OrderDetailMapper orderDetailMapper,
ScheduleSlotMapper scheduleSlotMapper,
// 其它 mapper 参数...
) {
this.orderMainMapper = orderMainMapper;
this.orderDetailMapper = orderDetailMapper;
this.scheduleSlotMapper = scheduleSlotMapper;
// 其它 mapper 赋值...
}
// -----------------------------------------------------------------------
// 业务方法:预约签到并缴费(原方法名可能为 payOrder / signAndPay以下为示例实现
// -----------------------------------------------------------------------
/** /**
* 预约签到并完成缴费 * 诊前退号(门诊挂号)业务实现
* *
* @param orderNo 订单号 * PRD 规定的状态变更如下:
* @param payAmount 实际支付金额 * 1. OrderMain.status -> OrderStatus.CANCELLED
* @return true 表示成功 * 2. OrderDetail.status -> OrderStatus.CANCELLED
* 3. RefundLog.refundStatus -> RefundStatus.REFUNDED
* 4. ScheduleSlot.status -> ScheduleSlotStatus.AVAILABLE
* 5. SchedulePool.status -> SchedulePoolStatus.AVAILABLE
*
* 之前的实现误用了 OrderStatus.REFUND、RefundStatus.PENDING 等状态,导致生产库
* 与 PRD 定义不一致,进而在后续统计、报表以及业务校验中出现异常。
*
* 本次修复统一使用 PRD 中约定的状态值,并在同一事务内完成所有表的更新,确保数据一致性。
*/ */
@Transactional(rollbackFor = Exception.class)
@Override @Override
public boolean signAndPay(String orderNo, Double payAmount) { @Transactional(rollbackFor = Exception.class)
// 1. 查询订单主表 public void preCancelOrder(Long orderMainId) {
OrderMain orderMain = orderMainMapper.selectByOrderNo(orderNo); // 1. 校验挂号单是否存在且可退号
OrderMain orderMain = orderMainMapper.selectByPrimaryKey(orderMainId);
if (orderMain == null) { if (orderMain == null) {
throw new BusinessException("单不存在"); throw new BusinessException("挂号单不存在");
}
if (!OrderStatus.REGISTERED.getCode().equals(orderMain.getStatus())) {
throw new BusinessException("只有已挂号状态的订单才能退号");
} }
// 2. 校验订单状态必须是已签到待缴费(或已预约待签到后直接缴费的场景) // 2. 更新 OrderMain 状态为已取消
if (!OrderStatus.SIGNED.getCode().equals(orderMain.getStatus()) orderMain.setStatus(OrderStatus.CANCELLED.getCode());
&& !OrderStatus.RESERVED.getCode().equals(orderMain.getStatus())) { orderMain.setUpdateTime(new Date());
throw new BusinessException("订单状态不允许缴费");
}
// 3. 更新订单主表状态为已完成(已缴费)
orderMain.setStatus(OrderStatus.PAID.getCode());
orderMain.setPayAmount(payAmount);
orderMain.setPayTime(new Date());
orderMainMapper.updateByPrimaryKeySelective(orderMain); orderMainMapper.updateByPrimaryKeySelective(orderMain);
// 4. 更新订单明细状态为已完成 // 3. 更新关联的 OrderDetail 状态为已取消
OrderDetail detail = new OrderDetail(); List<OrderDetail> details = orderDetailMapper.selectByOrderMainId(orderMainId);
detail.setOrderNo(orderNo); if (!CollectionUtils.isEmpty(details)) {
detail.setStatus(OrderStatus.PAID.getCode()); for (OrderDetail detail : details) {
orderDetailMapper.updateStatusByOrderNo(detail); detail.setStatus(OrderStatus.CANCELLED.getCode());
detail.setUpdateTime(new Date());
// 5. **关键修复**:更新对应的号源槽状态为“已取号”(3) orderDetailMapper.updateByPrimaryKeySelective(detail);
// 号源槽 ID 保存在 OrderMain 的 slotId 字段(若实际字段名不同,请自行调整)。
Long slotId = orderMain.getSlotId();
if (slotId != null) {
ScheduleSlot slot = new ScheduleSlot();
slot.setId(slotId);
slot.setStatus(ScheduleSlotStatus.TAKEN.getCode()); // 3 - 已取号
int rows = scheduleSlotMapper.updateByPrimaryKeySelective(slot);
if (rows > 0) {
logger.info("订单 {} 缴费成功,号源槽 {} 状态已更新为已取号(3)", orderNo, slotId);
} else {
logger.warn("订单 {} 缴费成功,但号源槽 {} 状态更新失败", orderNo, slotId);
} }
} else {
logger.warn("订单 {} 缴费成功,但未关联号源槽,无法更新状态", orderNo);
} }
// 6. 业务结束,事务提交 // 4. 记录退款日志,状态直接标记为已退款(因为诊前退号不走实际支付渠道)
return true; RefundLog refundLog = new RefundLog();
} refundLog.setOrderMainId(orderMainId);
refundLog.setRefundAmount(orderMain.getTotalAmount()); // 全额退
refundLog.setRefundStatus(RefundStatus.REFUNDED.getCode());
refundLog.setCreateTime(new Date());
refundLogMapper.insert(refundLog);
// ----------------------------------------------------------------------- // 5. 释放号源ScheduleSlot 与 SchedulePool 状态恢复为可预约
// 其它业务方法保持不变(省略实现细节) // a) ScheduleSlot
// ----------------------------------------------------------------------- ScheduleSlot slot = scheduleSlotMapper.selectByPrimaryKey(orderMain.getScheduleSlotId());
if (slot != null) {
// 示例:查询订单详情(使用新增的 OrderDetailDto slot.setStatus(ScheduleSlotStatus.AVAILABLE.getCode());
@Override slot.setUpdateTime(new Date());
public OrderDetailDto getOrderDetail(String orderNo) { scheduleSlotMapper.updateByPrimaryKeySelective(slot);
OrderMain main = orderMainMapper.selectByOrderNo(orderNo);
if (main == null) {
throw new BusinessException("订单不存在");
} }
List<OrderDetail> details = orderDetailMapper.selectByOrderNo(orderNo);
OrderDetailDto dto = new OrderDetailDto(); // b) SchedulePool如果存在 poolId
dto.setOrderMain(main); if (orderMain.getSchedulePoolId() != null) {
dto.setDetailList(details); SchedulePool pool = schedulePoolMapper.selectByPrimaryKey(orderMain.getSchedulePoolId());
return dto; if (pool != null) {
pool.setStatus(SchedulePoolStatus.AVAILABLE.getCode());
pool.setUpdateTime(new Date());
schedulePoolMapper.updateByPrimaryKeySelective(pool);
}
}
logger.info("诊前退号成功orderMainId={}, 状态已统一为 CANCELLED相关表状态已同步", orderMainId);
} }
// 其余方法保持原有实现... // 省略其余业务方法保持原有实现不变)
} }