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

@@ -140,6 +140,18 @@ public interface OrderLifecycleManager {
*/
void completeOrder(Long orderId, Long operatorId, String remark);
/**
* 完成工单(指定操作人类型)
* <p>
* 用于管理员手动完单等场景,允许指定操作人类型
*
* @param orderId 工单ID
* @param operatorId 操作人ID
* @param operatorType 操作人类型
* @param remark 完成备注
*/
void completeOrder(Long orderId, Long operatorId, OperatorTypeEnum operatorType, String remark);
/**
* 取消工单
* <p>

View File

@@ -268,13 +268,20 @@ public class OrderLifecycleManagerImpl implements OrderLifecycleManager {
@Override
@Transactional(rollbackFor = Exception.class)
public void completeOrder(Long orderId, Long operatorId, String remark) {
log.info("开始完成工单: orderId={}, operatorId={}, remark={}", orderId, operatorId, remark);
completeOrder(orderId, operatorId, OperatorTypeEnum.CLEANER, remark);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void completeOrder(Long orderId, Long operatorId, OperatorTypeEnum operatorType, String remark) {
log.info("开始完成工单: orderId={}, operatorId={}, operatorType={}, remark={}",
orderId, operatorId, operatorType, remark);
// 构建请求
OrderTransitionRequest request = OrderTransitionRequest.builder()
.orderId(orderId)
.targetStatus(WorkOrderStatusEnum.COMPLETED)
.operatorType(OperatorTypeEnum.CLEANER)
.operatorType(operatorType)
.operatorId(operatorId)
.reason(remark)
.build();
@@ -287,8 +294,8 @@ public class OrderLifecycleManagerImpl implements OrderLifecycleManager {
}
// 注意IoT 触发的自动完成在 CleanOrderCompleteEventHandler 中记录日志
// 这里只记录手动完成的日志operatorId 不为空的情况)
if (operatorId != null) {
// 管理员手动完成时记录日志
if (operatorType == OperatorTypeEnum.ADMIN) {
recordStatusChangeLog(orderId, result, "ORDER_COMPLETED_MANUAL", "工单手动完成");
}
}

View File

@@ -64,11 +64,16 @@ public class EventPublishHandler extends TransitionHandler {
// 如果是完成状态,额外发布完成事件
if (targetStatus == WorkOrderStatusEnum.COMPLETED) {
// assigneeId 优先从 request 获取,兜底从工单对象获取(手动完单等场景 request 中无 assigneeId
Long assigneeId = request.getAssigneeId() != null
? request.getAssigneeId()
: context.getOrder().getAssigneeId();
OrderCompletedEvent completedEvent = OrderCompletedEvent.builder()
.orderId(context.getOrder().getId())
.orderCode(context.getOrder().getOrderCode())
.orderType(context.getOrder().getOrderType())
.assigneeId(request.getAssigneeId())
.assigneeId(assigneeId)
.workDuration(calculateWorkDuration(context))
.build();