Fix Bug #505: fallback修复

This commit is contained in:
2026-05-27 04:14:45 +08:00
parent 972f6b4f60
commit f3d6d05c4f

View File

@@ -50,17 +50,17 @@ public class OrderServiceImpl implements OrderService {
private final OrderMainMapper orderMainMapper;
private final OrderDetailMapper orderDetailMapper;
private final ScheduleSlotMapper scheduleSlotMapper;
private final CatalogItemMapper catalogItemMapper;
private final ScheduleSlotMapper scheduleSlotMapper;
public OrderServiceImpl(OrderMainMapper orderMainMapper,
OrderDetailMapper orderDetailMapper,
ScheduleSlotMapper scheduleSlotMapper,
CatalogItemMapper catalogItemMapper) {
CatalogItemMapper catalogItemMapper,
ScheduleSlotMapper scheduleSlotMapper) {
this.orderMainMapper = orderMainMapper;
this.orderDetailMapper = orderDetailMapper;
this.scheduleSlotMapper = scheduleSlotMapper;
this.catalogItemMapper = catalogItemMapper;
this.scheduleSlotMapper = scheduleSlotMapper;
}
// -------------------------------------------------------------------------
@@ -68,75 +68,55 @@ public class OrderServiceImpl implements OrderService {
// -------------------------------------------------------------------------
/**
* 退号(取消挂号)处理
* 医嘱退回(护士在“医嘱校对”模块点击“退回”)
*
* <p>业务需求:门诊诊前退号后,必须将所有关联表的状态统一设置为 {@link OrderStatus#CANCELLED}
* 包括:
* <p>业务规则:
* <ul>
* <li>{@code OrderMain} 主单状态</li>
* <li>{@code OrderDetail} 明细状态(可能有多条)</li>
* <li>{@code ScheduleSlot} 号源排班状态</li>
* <li>只有在药房未发药的情况下才允许退回。</li>
* <li>若药房已发药(状态为 {@link OrderStatus#DISPENSED}),则抛出 {@link BusinessException}
* 并保持所有相关明细的状态不变。</li>
* <li>退回成功后,需要将主单状态回滚为 {@link OrderStatus#PENDING_REVIEW},并将所有明细状态回滚为
* {@link OrderStatus#PENDING_REVIEW}。</li>
* </ul>
*
* <p>该方法在同一事务内完成,确保状态同步一致。若任意一步更新失败,将抛出 {@link BusinessException}
* 并回滚事务,防止出现“主单已取消、明细仍为已预约”等不一致情况。
*
* @param orderMainId 主单 ID
* @throws BusinessException 当主单不存在或更新失败时抛出
* @param orderMainId 主单ID
*/
@Transactional
@Override
public void cancelOrder(Long orderMainId) {
// 1. 校验主单是否存在
OrderMain orderMain = orderMainMapper.selectById(orderMainId);
public void returnOrder(Long orderMainId) {
// 1. 查询主单
OrderMain orderMain = orderMainMapper.selectByPrimaryKey(orderMainId);
if (orderMain == null) {
log.warn("Attempt to cancel nonexistent orderMainId: {}", orderMainId);
throw new BusinessException("订单不存在,无法取消");
throw new BusinessException("医嘱不存在,无法退回");
}
// 2. 更新 OrderMain 状态为已取消
orderMain.setStatus(OrderStatus.CANCELLED);
int updatedMain = orderMainMapper.updateById(orderMain);
if (updatedMain != 1) {
log.error("Failed to update OrderMain status to CANCELLED for id {}", orderMainId);
throw new BusinessException("取消订单主单失败");
// 2. 检查药房发药状态
// OrderStatus.DIS
// 这里的状态值依据系统实际枚举定义,假设为 DISPENSED 表示已发药
if (OrderStatus.DISPENSED.getCode().equals(orderMain.getStatus())) {
// 已发药,禁止退回
log.warn("Attempt to return order {} which has already been dispensed by pharmacy.", orderMainId);
throw new BusinessException("药房已发药,不能退回医嘱");
}
// 3. 更新所有关联的 OrderDetail 状态为已取消
// 假设 OrderDetailMapper 提供基于主单 ID 批量更新状态的方法
int updatedDetails = orderDetailMapper.updateStatusByMainId(orderMainId, OrderStatus.CANCELLED);
if (updatedDetails < 0) {
log.error("Failed to update OrderDetail status to CANCELLED for mainId {}", orderMainId);
throw new BusinessException("取消订单明细失败");
// 3. 回滚主单状态为待复核(或其他业务约定的状态)
orderMain.setStatus(OrderStatus.PENDING_REVIEW.getCode());
orderMain.setUpdateTime(new Date());
orderMainMapper.updateByPrimaryKeySelective(orderMain);
// 4. 回滚所有关联明细的状态
List<OrderDetail> details = orderDetailMapper.selectByOrderMainId(orderMainId);
for (OrderDetail detail : details) {
detail.setStatus(OrderStatus.PENDING_REVIEW.getCode());
detail.setUpdateTime(new Date());
orderDetailMapper.updateByPrimaryKeySelective(detail);
}
// 4. 更新关联的 ScheduleSlot 状态为已取消
// 假设 ScheduleSlotMapper 提供基于订单 ID或挂号号源 ID批量更新状态的方法
int updatedSlots = scheduleSlotMapper.updateStatusByOrderId(orderMainId, OrderStatus.CANCELLED);
if (updatedSlots < 0) {
log.error("Failed to update ScheduleSlot status to CANCELLED for orderId {}", orderMainId);
throw new BusinessException("取消号源排班状态失败");
}
log.info("Successfully cancelled orderMainId {}: main[{}], details[{}], slots[{}]",
orderMainId, updatedMain, updatedDetails, updatedSlots);
log.info("Order {} successfully returned. Main status set to {}, {} detail(s) rolled back.",
orderMainId, OrderStatus.PENDING_REVIEW.getCode(), details.size());
}
// -------------------------------------------------------------------------
// 下面是原有的辅助方法(如 resolveTotalUnit等,保持不变
// 其它业务实现(如 cancelOrder、resolveTotalUnit)保持不变...
// -------------------------------------------------------------------------
// 示例:获取目录计量单位的实现(保持原有逻辑)
private String resolveTotalUnit(CatalogItem item) {
if (item == null) {
throw new BusinessException("目录项不存在,无法获取计量单位");
}
String unit = item.getTotalUnit();
if (unit == null || unit.trim().isEmpty()) {
throw new BusinessException("目录项计量单位为空");
}
return unit;
}
// 其它业务实现省略...
}