feat(ops): OrderLifecycleManager 支持 forceComplete 强制完成工单
新增 forced 字段到 OrderTransitionRequest,StateTransitionHandler 根据 该字段选择 transition 或 forceTransition,确保强制状态转换也走完整 责任链(队列同步 + 事件发布),避免绕过 QueueSyncHandler 产生脏数据。 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -166,6 +166,25 @@ public interface OrderLifecycleManager {
|
||||
*/
|
||||
void cancelOrder(Long orderId, Long operatorId, OperatorTypeEnum operatorType, String reason);
|
||||
|
||||
/**
|
||||
* 强制完成工单(跳过状态规则校验,走完整责任链)
|
||||
* <p>
|
||||
* 适用于系统自动结单等场景:告警自动解除时工单可能处于任何非终态
|
||||
* (QUEUED / DISPATCHED / CONFIRMED / ARRIVED / PAUSED),
|
||||
* 需要直接跳转到 COMPLETED,同时确保队列清理和事件发布。
|
||||
* <p>
|
||||
* 与直接调用 {@code OrderStateMachine.forceTransition()} 的区别:
|
||||
* 本方法走完整责任链(状态转换 → 队列同步 → 事件发布),
|
||||
* 避免队列脏数据和 Redis 状态不一致。
|
||||
*
|
||||
* @param orderId 工单ID
|
||||
* @param operatorId 操作人ID
|
||||
* @param operatorType 操作人类型
|
||||
* @param remark 完成备注
|
||||
* @return 转换结果
|
||||
*/
|
||||
OrderTransitionResult forceComplete(Long orderId, Long operatorId, OperatorTypeEnum operatorType, String remark);
|
||||
|
||||
// ==================== 查询方法 ====================
|
||||
|
||||
/**
|
||||
|
||||
@@ -346,6 +346,32 @@ public class OrderLifecycleManagerImpl implements OrderLifecycleManager {
|
||||
.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public OrderTransitionResult forceComplete(Long orderId, Long operatorId,
|
||||
OperatorTypeEnum operatorType, String remark) {
|
||||
log.info("强制完成工单: orderId={}, operatorId={}, operatorType={}, remark={}",
|
||||
orderId, operatorId, operatorType, remark);
|
||||
|
||||
OpsOrderDO order = opsOrderMapper.selectById(orderId);
|
||||
if (order == null) {
|
||||
log.warn("强制完成工单失败,工单不存在: orderId={}", orderId);
|
||||
return OrderTransitionResult.fail(orderId, "工单不存在");
|
||||
}
|
||||
|
||||
OrderTransitionRequest request = OrderTransitionRequest.builder()
|
||||
.orderId(orderId)
|
||||
.targetStatus(WorkOrderStatusEnum.COMPLETED)
|
||||
.operatorType(operatorType != null ? operatorType : OperatorTypeEnum.SYSTEM)
|
||||
.operatorId(operatorId)
|
||||
.reason(remark)
|
||||
.assigneeId(order.getAssigneeId())
|
||||
.forced(true)
|
||||
.build();
|
||||
|
||||
return transition(request);
|
||||
}
|
||||
|
||||
// ==================== 查询方法 ====================
|
||||
|
||||
@Override
|
||||
|
||||
@@ -38,13 +38,19 @@ public class StateTransitionHandler extends TransitionHandler {
|
||||
|
||||
// 通过状态机执行状态转换
|
||||
try {
|
||||
orderStateMachine.transition(
|
||||
order,
|
||||
targetStatus,
|
||||
request.getOperatorType() != null ? request.getOperatorType() : OperatorTypeEnum.SYSTEM,
|
||||
request.getOperatorId(),
|
||||
request.getReason()
|
||||
);
|
||||
OperatorTypeEnum operatorType = request.getOperatorType() != null
|
||||
? request.getOperatorType() : OperatorTypeEnum.SYSTEM;
|
||||
|
||||
if (Boolean.TRUE.equals(request.getForced())) {
|
||||
// 强制转换:跳过状态规则校验(用于系统自动结单等场景)
|
||||
orderStateMachine.forceTransition(
|
||||
order, targetStatus, operatorType,
|
||||
request.getOperatorId(), request.getReason());
|
||||
} else {
|
||||
orderStateMachine.transition(
|
||||
order, targetStatus, operatorType,
|
||||
request.getOperatorId(), request.getReason());
|
||||
}
|
||||
|
||||
// 更新上下文中的状态
|
||||
context.setNewStatus(targetStatus);
|
||||
|
||||
@@ -91,6 +91,14 @@ public class OrderTransitionRequest {
|
||||
*/
|
||||
private PriorityEnum priority;
|
||||
|
||||
/**
|
||||
* 是否强制转换(跳过状态规则校验)
|
||||
* <p>
|
||||
* 适用于系统自动结单等场景:告警自动解除时工单可能处于任何非终态,
|
||||
* 需要直接跳转到 COMPLETED / CANCELLED,不经过中间状态。
|
||||
*/
|
||||
private Boolean forced;
|
||||
|
||||
/**
|
||||
* 扩展信息(可选)
|
||||
* <p>
|
||||
|
||||
Reference in New Issue
Block a user