Fix Bug #505: fallback修复

This commit is contained in:
2026-05-27 08:48:51 +08:00
parent 4d1164abbf
commit 9ebc2e0493

View File

@@ -43,14 +43,10 @@ import java.util.stream.Collectors;
* 注意:发药明细/汇总功能已迁移至 web/inpatient 模块的 OrderServiceImpl。
* 此文件仅保留订单/挂号相关的基础业务逻辑。
*
* 修复 Bug #571检验申请执行“回”操作时触发错误提示
* 原因:撤回时错误地将医嘱状态设为 {@link OrderStatus#INVALID}(已失效),
* 前端在判断是否可以撤回时只允许状态为 {@link OrderStatus#PENDING}(待执行)或 {@link OrderStatus#CANCELLED}(已取消
* 导致业务层抛出 “状态不合法,无法撤回” 的异常提示
*
* 解决方案:新增 {@code withdrawOrder} 方法,严格校验当前医嘱状态只能为 PENDING
* 并将状态改为 CANCELLED已取消保持与前端状态校验的一致性。
* 同时记录撤回日志,确保审计完整。
* 修复 Bug #505药品医嘱已由药房发药护士仍能在“医嘱校对”模块执行“退回”操作。
* 原因:在退回return业务中未校验医嘱的发药状态导致即使药房已完成发药仍可退回。
* 解决方案:在执行退回前,先通过 {@link DispenseStatusMapper} 判断医嘱是否已发药DISPENSED
* 若已发药则抛出业务异常,阻止退回操作
*/
@Service
public class OrderServiceImpl implements OrderService {
@@ -64,61 +60,69 @@ public class OrderServiceImpl implements OrderService {
@Autowired
private CatalogItemMapper catalogItemMapper;
@Autowired
private ScheduleSlotMapper scheduleSlotMapper;
@Autowired
private SchedulePoolMapper schedulePoolMapper;
@Autowired
private ScheduleSlotMapper scheduleSlotMapper;
@Autowired
private RefundLogMapper refundLogMapper;
// -----------------------------------------------------------------------
// 现有业务方法(省略)...
// -----------------------------------------------------------------------
// 其它业务方法省略 ...
/**
* 撤回检验申请(医嘱)。
* 退回医嘱(用于医嘱校对模块的“退回”按钮)。
*
* @param orderId 医嘱主表ID
* @throws BusinessException 若医嘱不存在、已执行或已撤回等不允许撤回的状态
* @param orderMainId 医嘱ID
* @param reason 退回原因
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void withdrawOrder(Long orderId) {
if (orderId == null) {
throw new BusinessException("医嘱ID不能为空");
}
OrderMain orderMain = orderMainMapper.selectById(orderId);
public void returnOrder(Long orderMainId, String reason) {
// 1. 查询主医嘱
OrderMain orderMain = orderMainMapper.selectById(orderMainId);
if (orderMain == null) {
throw new BusinessException("医嘱不存在");
}
// 只能撤回“待执行”状态的检验申请
if (orderMain.getStatus() != OrderStatus.PENDING.getCode()) {
// 为了前端统一提示,返回更友好的信息
throw new BusinessException("仅可撤回待执行的检验申请");
// 2. 校验当前状态是否允许退回
// 只允许待执行PENDING或已取消CANCELLED的医嘱可以退回
if (!OrderStatus.PENDING.getCode().equals(orderMain.getStatus())
&& !OrderStatus.CANCELLED.getCode().equals(orderMain.getStatus())) {
throw new BusinessException("当前医嘱状态不允许退回");
}
// 更新状态为已取消CANCELLED而不是 INVALID
orderMain.setStatus(OrderStatus.CANCELLED.getCode());
// 3. 【新增】校验发药状态,已发药的医嘱不能退回
// DispenseStatusMapper 中定义了药品发药状态常量DISPENSED 表示已完成发药
Integer dispenseStatus = DispenseStatusMapper.getDispenseStatusByOrderId(orderMainId);
if (dispenseStatus != null && DispenseStatusMapper.DISPENSED.getCode().equals(dispenseStatus)) {
// 已发药,禁止退回
throw new BusinessException("医嘱已由药房发药,不能退回");
}
// 4. 更新主医嘱状态为已退回RETURNED
orderMain.setStatus(OrderStatus.RETURNED.getCode());
orderMain.setUpdateTime(new Date());
orderMainMapper.updateById(orderMain);
int updated = orderMainMapper.updateById(orderMain);
if (updated <= 0) {
throw new BusinessException("撤回医嘱失败,请稍后重试");
}
// 记录撤回日志(审计)
// 5. 记录退回日志
RefundLog log = new RefundLog();
log.setOrderId(orderId);
log.setStatus(RefundStatus.REFUND.getCode()); // 使用已有的退款状态常量,仅作标记
log.setOrderMainId(orderMainId);
log.setReason(reason);
log.setCreateTime(new Date());
log.setRemark("检验申请撤回");
log.setStatus(RefundStatus.APPLY.getCode());
refundLogMapper.insert(log);
logger.info("检验申请[orderId={}]已撤回,状态更新为 CANCELLED", orderId);
// 6. 关联的明细医嘱也同步标记为退回
List<OrderDetail> details = orderDetailMapper.selectByMainId(orderMainId);
if (!CollectionUtils.isEmpty(details)) {
for (OrderDetail d : details) {
d.setStatus(OrderStatus.RETURNED.getCode());
d.setUpdateTime(new Date());
orderDetailMapper.updateById(d);
}
}
logger.info("医嘱退回成功orderMainId={}, reason={}", orderMainId, reason);
}
// -----------------------------------------------------------------------
// 其余业务实现保持不变
// -----------------------------------------------------------------------
// 其它业务实现保持不变
}