fix(ops): 完善手动取消工单接口的状态机、校验和事件处理

- 状态机允许 ARRIVED→CANCELLED,与业务枚举 canCancel() 保持一致
- cancelOrder 增加已取消幂等返回,已完成改用 ServiceException
- cancelOrder 构建请求时传递 assigneeId 确保事件链路完整
- CleanOrderEventListener 新增 handleCancelled:记录扩展表取消时间、
  自动调度下一个等待任务;业务日志由 LifecycleManager 统一记录

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
lzh
2026-02-14 12:26:47 +08:00
parent a68ce9a28a
commit 8ab7e7cc05
4 changed files with 58 additions and 7 deletions

View File

@@ -309,6 +309,7 @@ public class OrderLifecycleManagerImpl implements OrderLifecycleManager {
.operatorType(operatorType)
.operatorId(operatorId)
.reason(reason)
.assigneeId(order != null ? order.getAssigneeId() : null)
.build();
// 执行状态转换

View File

@@ -78,7 +78,8 @@ public class OrderStateMachine {
// 作业中
WorkOrderStatusEnum.ARRIVED, Set.of(
WorkOrderStatusEnum.PAUSED, // 暂停作业
WorkOrderStatusEnum.COMPLETED // 完成作业
WorkOrderStatusEnum.COMPLETED, // 完成作业
WorkOrderStatusEnum.CANCELLED // 取消作业
),
// 暂停状态

View File

@@ -1,5 +1,6 @@
package com.viewsh.module.ops.service.order;
import com.viewsh.framework.common.exception.ServiceException;
import com.viewsh.framework.common.pojo.PageResult;
import com.viewsh.framework.common.util.object.BeanUtils;
import com.viewsh.module.ops.core.lifecycle.OrderLifecycleManager;
@@ -274,12 +275,18 @@ public class OpsOrderServiceImpl implements OpsOrderService {
throw new RuntimeException("工单不存在: " + orderId);
}
// 2. 校验:已完成的工单不能取消
if (WorkOrderStatusEnum.COMPLETED.getStatus().equals(order.getStatus())) {
throw new RuntimeException("已完成的工单不能取消");
// 2. 校验:已取消的工单幂等返回
if (WorkOrderStatusEnum.CANCELLED.getStatus().equals(order.getStatus())) {
log.info("工单已处于取消状态,幂等返回: orderId={}", orderId);
return;
}
// 3. 委托给 OrderLifecycleManager 处理(确保工单和队列状态同步)
// 3. 校验:已完成的工单不能取消
if (WorkOrderStatusEnum.COMPLETED.getStatus().equals(order.getStatus())) {
throw new ServiceException(400, "已完成的工单不能取消");
}
// 4. 委托给 OrderLifecycleManager 处理(确保工单和队列状态同步)
orderLifecycleManager.cancelOrder(orderId, operatorId, operatorType, reason);
log.info("取消工单成功: orderId={}, reason={}", orderId, reason);