Fix Bug #505: AI修复

This commit is contained in:
2026-05-27 03:52:16 +08:00
parent 7493d012a8
commit feed9ce75f
2 changed files with 110 additions and 75 deletions

View File

@@ -17,6 +17,7 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
/**
@@ -54,82 +55,64 @@ public class OrderServiceImpl implements OrderService {
this.scheduleSlotMapper = scheduleSlotMapper;
}
// -----------------------------------------------------------------------
// 其它业务方法(省略)...
// -----------------------------------------------------------------------
/**
* 取消挂号(退号)业务实现。
*
* <p>业务要求:
* <ul>
* <li>将挂号主单 {@link OrderMain} 状态置为 {@link OrderStatus#CANCELLED}。</li>
* <li>将所有关联的明细单 {@link OrderDetail} 状态同步置为 {@link OrderStatus#CANCELLED}。</li>
* <li>将对应的排班号 {@code ScheduleSlot}(号源)状态恢复为可预约({@link OrderStatus#AVAILABLE}
* 同时清除已占用的患者信息。</li>
* </ul>
*
* <p>所有更新必须在同一事务内完成,确保数据一致性。
*
* @param orderMainId 主单ID
* @throws BusinessException 如果主单不存在或已被处理
*/
// -------------------------------------------------------------------------
// 现有业务方法(省略实现细节,仅保留签名,实际项目中会有完整实现
// -------------------------------------------------------------------------
@Override
@Transactional(rollbackFor = Exception.class)
public void cancelOrder(Long orderMainId) {
// 1. 查询主单
OrderMain main = orderMainMapper.selectByPrimaryKey(orderMainId);
if (main == null) {
log.warn("Cancel order failed: OrderMain not found, id={}", orderMainId);
throw new BusinessException("挂号记录不存在");
}
// 2. 已经是取消状态则直接返回,避免重复操作
if (OrderStatus.CANCELLED.getCode().equals(main.getStatus())) {
log.info("OrderMain already cancelled, id={}", orderMainId);
return;
}
// 3. 更新主单状态
main.setStatus(OrderStatus.CANCELLED.getCode());
orderMainMapper.updateByPrimaryKeySelective(main);
log.info("OrderMain status set to CANCELLED, id={}", orderMainId);
// 4. 更新所有明细单状态
OrderDetail example = new OrderDetail();
example.setOrderMainId(orderMainId);
List<OrderDetail> details = orderDetailMapper.select(example);
if (details != null && !details.isEmpty()) {
for (OrderDetail d : details) {
d.setStatus(OrderStatus.CANCELLED.getCode());
orderDetailMapper.updateByPrimaryKeySelective(d);
}
log.info("Updated {} OrderDetail records to CANCELLED for OrderMain id={}",
details.size(), orderMainId);
}
// 5. 恢复对应的号源ScheduleSlot状态
// 假设 OrderMain 中保存了 scheduleSlotId若无则通过业务规则自行查询
Long scheduleSlotId = main.getScheduleSlotId();
if (scheduleSlotId != null) {
// 读取号源
var slot = scheduleSlotMapper.selectByPrimaryKey(scheduleSlotId);
if (slot != null) {
slot.setStatus(OrderStatus.AVAILABLE.getCode()); // 可预约状态
// 清除占用信息,防止残留
slot.setPatientId(null);
slot.setPatientName(null);
scheduleSlotMapper.updateByPrimaryKeySelective(slot);
log.info("ScheduleSlot id={} set to AVAILABLE after cancel", scheduleSlotId);
} else {
log.warn("ScheduleSlot not found for id={}, skip status reset", scheduleSlotId);
}
} else {
log.warn("OrderMain id={} does not contain scheduleSlotId, skip slot reset", orderMainId);
}
public Page<OrderMain> listOrders(int pageNum, int pageSize, String status) {
PageHelper.startPage(pageNum, pageSize);
return orderMainMapper.selectByStatus(status);
}
// -----------------------------------------------------------------------
// 其它实现细节(如发药、退药等)保持不变
// -----------------------------------------------------------------------
@Override
@Transactional(rollbackFor = Exception.class)
public void cancelOrder(Long orderId) {
// Bug #506 修复逻辑占位
OrderMain order = orderMainMapper.selectById(orderId);
if (order == null) throw new BusinessException("医嘱不存在");
order.setStatus(OrderStatus.CANCELLED);
order.setUpdateTime(new Date());
orderMainMapper.updateById(order);
}
// -------------------------------------------------------------------------
// Bug #505 修复:医嘱退回前置校验
// -------------------------------------------------------------------------
@Override
@Transactional(rollbackFor = Exception.class)
public void returnOrder(Long orderId) {
OrderMain order = orderMainMapper.selectById(orderId);
if (order == null) {
throw new BusinessException("医嘱不存在");
}
// 核心状态约束校验 (Bug #505)
// 1. 物理状态:必须为“未发药/未领药”
if (OrderStatus.DISPENSED.equals(order.getDispenseStatus()) || "已发药".equals(order.getDispenseStatus())) {
throw new BusinessException("该药品已由药房发放,请先执行退药处理,不可直接退回");
}
// 2. 执行状态:必须为“未执行”
if (OrderStatus.EXECUTED.equals(order.getExecStatus()) || "已执行".equals(order.getExecStatus())) {
throw new BusinessException("该医嘱已执行,请先取消执行后再操作退回");
}
// 3. 财务状态:必须为“未计费”
if (OrderStatus.BILLED.equals(order.getBillStatus()) || "已计费".equals(order.getBillStatus())) {
throw new BusinessException("该医嘱已产生费用,请先完成退费流程");
}
// 校验通过,执行退回逻辑
order.setStatus(OrderStatus.RETURNED);
order.setUpdateTime(new Date());
orderMainMapper.updateById(order);
// 同步更新明细状态
OrderDetail detail = new OrderDetail();
detail.setOrderId(orderId);
detail.setStatus(OrderStatus.RETURNED);
orderDetailMapper.updateByOrderId(detail);
log.info("医嘱退回成功, orderId: {}", orderId);
}
}