fix(ops): 手动完单走完整责任链,补全队列同步、设备状态、事件发布等缺失环节

原手动完单逻辑直接更新 DB 状态,绕过了 OrderLifecycleManager 责任链,
导致队列未清理、工牌设备状态未恢复 IDLE、自动派发下一任务未触发、
事件表缺少操作人信息等问题。

改动:
- CleanWorkOrderServiceImpl.manualCompleteOrder 改为委托 OrderLifecycleManager
- OrderLifecycleManager 新增 completeOrder(orderId, operatorId, operatorType, remark) 重载
- Controller 注入 SecurityFrameworkUtils.getLoginUserId() 填充操作人
- EventPublishHandler 修复 OrderCompletedEvent.assigneeId 兜底逻辑
- 新增已完成幂等返回和已取消拒绝校验

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
lzh
2026-02-25 17:12:01 +08:00
parent 3e54094c3d
commit 161f55007b
6 changed files with 64 additions and 39 deletions

View File

@@ -21,4 +21,7 @@ public class ManualCompleteOrderReqDTO {
@Schema(description = "备注", example = "管理员手动完成")
private String remark;
@Schema(description = "操作人ID由后端自动填充", hidden = true)
private Long operatorId;
}

View File

@@ -2,10 +2,13 @@ package com.viewsh.module.ops.environment.service.cleanorder;
import com.viewsh.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.viewsh.module.ops.api.clean.OrderTimelineRespDTO;
import com.viewsh.module.ops.core.lifecycle.OrderLifecycleManager;
import com.viewsh.module.ops.dal.dataobject.workorder.OpsOrderDO;
import com.viewsh.module.ops.dal.dataobject.workorder.OpsOrderEventDO;
import com.viewsh.module.ops.dal.mysql.workorder.OpsOrderEventMapper;
import com.viewsh.module.ops.dal.mysql.workorder.OpsOrderMapper;
import com.viewsh.module.ops.enums.OperatorTypeEnum;
import com.viewsh.module.ops.enums.WorkOrderStatusEnum;
import com.viewsh.module.ops.environment.dal.dataobject.ManualCompleteOrderReqDTO;
import com.viewsh.module.ops.environment.dal.dataobject.UpgradePriorityReqDTO;
import com.viewsh.module.ops.service.event.OpsOrderEventService;
@@ -40,6 +43,9 @@ public class CleanWorkOrderServiceImpl implements CleanWorkOrderService {
@Resource
private OpsOrderEventService opsOrderEventService;
@Resource
private OrderLifecycleManager orderLifecycleManager;
/**
* 事件类型名称映射
*/
@@ -120,42 +126,31 @@ public class CleanWorkOrderServiceImpl implements CleanWorkOrderService {
@Override
@Transactional(rollbackFor = Exception.class)
public void manualCompleteOrder(ManualCompleteOrderReqDTO req) {
try {
Long orderId = req.getOrderId();
Long orderId = req.getOrderId();
// 1. 查询工单
OpsOrderDO order = opsOrderMapper.selectById(orderId);
if (order == null) {
log.warn("[manualCompleteOrder] 工单不存在: orderId={}", orderId);
return;
}
String fromStatus = order.getStatus();
// 2. 更新工单状态为已完成
OpsOrderDO updateDO = new OpsOrderDO();
updateDO.setId(orderId);
updateDO.setStatus("COMPLETED");
updateDO.setEndTime(LocalDateTime.now());
opsOrderMapper.updateById(updateDO);
// 3. 记录事件
opsOrderEventService.recordEvent(
orderId,
fromStatus,
"COMPLETED",
"COMPLETE",
"ADMIN",
null, // 管理员操作当前未传递具体ID
req.getRemark() != null ? req.getRemark() : "管理员手动完成"
);
log.info("[manualCompleteOrder] 手动完成工单成功: orderId={}, remark={}", orderId, req.getRemark());
} catch (Exception e) {
log.error("[manualCompleteOrder] 手动完成工单失败: orderId={}", req.getOrderId(), e);
throw e;
// 1. 查询工单
OpsOrderDO order = opsOrderMapper.selectById(orderId);
if (order == null) {
throw new IllegalArgumentException("工单不存在: orderId=" + orderId);
}
// 2. 校验:已完成的工单幂等返回
if (WorkOrderStatusEnum.COMPLETED.getStatus().equals(order.getStatus())) {
log.info("[manualCompleteOrder] 工单已处于完成状态,幂等返回: orderId={}", orderId);
return;
}
// 3. 校验:已取消的工单不能完成
if (WorkOrderStatusEnum.CANCELLED.getStatus().equals(order.getStatus())) {
throw new IllegalStateException("已取消的工单不能完成: orderId=" + orderId);
}
// 4. 通过 OrderLifecycleManager 走完整责任链(状态校验→队列同步→事件发布)
String remark = req.getRemark() != null ? req.getRemark() : "管理员手动完成";
orderLifecycleManager.completeOrder(orderId, req.getOperatorId(), OperatorTypeEnum.ADMIN, remark);
log.info("[manualCompleteOrder] 手动完成工单成功: orderId={}, operatorId={}, remark={}",
orderId, req.getOperatorId(), remark);
}
@Override