refactor(ops): 服务层调整,统一使用设备ID
Some checks failed
Java CI with Maven / build (11) (push) Has been cancelled
Java CI with Maven / build (17) (push) Has been cancelled
Java CI with Maven / build (8) (push) Has been cancelled

- CleanOrderService: 将所有 cleanerId 参数改为 deviceId
- CleanOrderAutoCreateReqDTO: 新增 triggerData 字段
- EventPublishHandler: 添加 assigneeId/urgentOrderId 到 payload
- OrderQueueService: 修正注释说明 userId 实际为 deviceId
- EventDomain: 新增 AUDIT 域
- 更新测试用例适配接口变更

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
lzh
2026-01-25 18:23:37 +08:00
parent 373f379b01
commit a8d3fc84d2
7 changed files with 108 additions and 77 deletions

View File

@@ -8,6 +8,8 @@ import lombok.EqualsAndHashCode;
import jakarta.validation.constraints.Min; import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import java.util.Map;
/** /**
* 保洁自动工单创建请求 DTO * 保洁自动工单创建请求 DTO
* *
@@ -44,4 +46,7 @@ public class CleanOrderAutoCreateReqDTO extends OpsOrderCreateReqDTO {
@Schema(description = "触发设备Key冗余便于查询") @Schema(description = "触发设备Key冗余便于查询")
private String triggerDeviceKey; private String triggerDeviceKey;
@Schema(description = "触发数据(如客流值、阈值等,用于后续处理)")
private Map<String, Object> triggerData;
} }

View File

@@ -59,24 +59,24 @@ public interface CleanOrderService {
// ========== 保洁特有的状态转换 ========== // ========== 保洁特有的状态转换 ==========
/** /**
* 保洁员按键确认工单 * 设备按键确认工单
* 状态转换DISPATCHED → CONFIRMED * 状态转换DISPATCHED → CONFIRMED
* 同时更新保洁员状态IDLE → BUSY关键确认后才变为忙碌 * 设备状态保持 BUSY在 DISPATCHED 时已设置
* *
* @param orderId 工单ID * @param orderId 工单ID
* @param cleanerId 保洁员ID * @param deviceId 工牌设备ID
*/ */
void confirmOrder(Long orderId, Long cleanerId); void confirmOrder(Long orderId, Long deviceId);
/** /**
* 感知信标,开始作业 * 感知信标,开始作业
* 状态转换CONFIRMED → ARRIVED * 状态转换CONFIRMED → ARRIVED
* *
* @param orderId 工单ID * @param orderId 工单ID
* @param cleanerId 保洁员ID * @param deviceId 工牌设备ID
* @param beaconId 信标ID * @param beaconId 信标ID
*/ */
void startWorkingOnBeacon(Long orderId, Long cleanerId, Long beaconId); void startWorkingOnBeacon(Long orderId, Long deviceId, Long beaconId);
/** /**
* 丢失信号,自动完成 * 丢失信号,自动完成
@@ -84,11 +84,11 @@ public interface CleanOrderService {
* 完成后自动推送队列中的下一个任务 * 完成后自动推送队列中的下一个任务
* *
* @param orderId 工单ID * @param orderId 工单ID
* @param cleanerId 保洁员ID * @param deviceId 工牌设备ID
* @param beaconId 信标ID * @param beaconId 信标ID
* @param lostSeconds 丢失信号时长(秒) * @param lostSeconds 丢失信号时长(秒)
*/ */
void autoCompleteOnSignalLost(Long orderId, Long cleanerId, Long beaconId, Integer lostSeconds); void autoCompleteOnSignalLost(Long orderId, Long deviceId, Long beaconId, Integer lostSeconds);
// ========== 任务自动切换 ========== // ========== 任务自动切换 ==========
@@ -96,37 +96,38 @@ public interface CleanOrderService {
* 任务完成后,自动推送队列中的下一个任务 * 任务完成后,自动推送队列中的下一个任务
* *
* @param completedOrderId 已完成的工单ID * @param completedOrderId 已完成的工单ID
* @param cleanerId 保洁员ID * @param deviceId 工牌设备ID
*/ */
void autoDispatchNextOrder(Long completedOrderId, Long cleanerId); void autoDispatchNextOrder(Long completedOrderId, Long deviceId);
// ========== 语音播报(支持去重合并) ========== // ========== 语音播报(支持去重合并) ==========
/** /**
* 语音播报:空闲保洁员收到新工单 * 语音播报:空闲设备收到新工单
* *
* @param cleanerId 保洁员ID * @param deviceId 工牌设备ID
*/ */
void playVoiceForNewOrder(Long cleanerId); void playVoiceForNewOrder(Long deviceId);
/** /**
* 语音播报:忙碌保洁员收到待办(支持去重合并) * 语音播报:忙碌设备收到待办(支持去重合并)
* 例如:"新增3项待办您共有5个待办工单" * 例如:"新增3项待办您共有5个待办工单"
* *
* @param cleanerId 保洁员ID * @param deviceId 工牌设备ID
* @param queueCount 当前待办数量 * @param queueCount 当前待办数量
*/ */
void playVoiceForQueuedOrder(Long cleanerId, int queueCount); void playVoiceForQueuedOrder(Long deviceId, int queueCount);
/** /**
* 语音播报:任务完成后自动推送下一个 * 语音播报:任务完成后自动推送下一个
* 例如:"待办工单总数2个第一位待办工单xxx" * 例如:"待办工单总数2个第一位待办工单xxx"
* *
* @param cleanerId 保洁员ID * @param deviceId 工牌设备ID
* @param queueCount 待办数量 * @param queueCount 待办数量
* @param nextTaskTitle 下一个任务标题 * @param nextTaskTitle 下一个任务标题
*/ */
void playVoiceForNextTask(Long cleanerId, int queueCount, String nextTaskTitle); void playVoiceForNextTask(Long deviceId, int queueCount, String nextTaskTitle);
// ========== 优先级管理 ========== // ========== 优先级管理 ==========

View File

@@ -4,7 +4,6 @@ import com.viewsh.module.ops.api.queue.OrderQueueDTO;
import com.viewsh.module.ops.api.queue.OrderQueueService; import com.viewsh.module.ops.api.queue.OrderQueueService;
import com.viewsh.module.ops.core.dispatch.DispatchEngine; import com.viewsh.module.ops.core.dispatch.DispatchEngine;
import com.viewsh.module.ops.core.dispatch.model.DispatchResult; import com.viewsh.module.ops.core.dispatch.model.DispatchResult;
import com.viewsh.module.ops.core.dispatch.model.OrderDispatchContext;
import com.viewsh.module.ops.core.event.OrderCreatedEvent; import com.viewsh.module.ops.core.event.OrderCreatedEvent;
import com.viewsh.module.ops.core.event.OrderEventPublisher; import com.viewsh.module.ops.core.event.OrderEventPublisher;
import com.viewsh.module.ops.core.lifecycle.OrderLifecycleManager; import com.viewsh.module.ops.core.lifecycle.OrderLifecycleManager;
@@ -120,7 +119,7 @@ public class CleanOrderServiceImpl implements CleanOrderService {
log.info("创建自动保洁工单成功: orderId={}, orderCode={}, expectedDuration={}分钟, triggerSource={}", log.info("创建自动保洁工单成功: orderId={}, orderCode={}, expectedDuration={}分钟, triggerSource={}",
orderId, orderCode, createReq.getExpectedDuration(), createReq.getTriggerSource()); orderId, orderCode, createReq.getExpectedDuration(), createReq.getTriggerSource());
// 5. 发布工单创建事件,由 CleanOrderEventListener 触发调度 // 5. 发布工单创建事件
OrderCreatedEvent event = OrderCreatedEvent.builder() OrderCreatedEvent event = OrderCreatedEvent.builder()
.orderId(orderId) .orderId(orderId)
.orderType("CLEAN") .orderType("CLEAN")
@@ -132,7 +131,14 @@ public class CleanOrderServiceImpl implements CleanOrderService {
.build() .build()
.addPayload("isAuto", true) .addPayload("isAuto", true)
.addPayload("expectedDuration", createReq.getExpectedDuration()) .addPayload("expectedDuration", createReq.getExpectedDuration())
.addPayload("triggerSource", createReq.getTriggerSource()); .addPayload("triggerSource", createReq.getTriggerSource())
.addPayload("triggerDeviceId", createReq.getTriggerDeviceId())
.addPayload("triggerDeviceKey", createReq.getTriggerDeviceKey());
// 添加触发数据(用于客流计数器重置等后续处理)
if (createReq.getTriggerData() != null && !createReq.getTriggerData().isEmpty()) {
event.getPayload().put("triggerData", createReq.getTriggerData());
}
orderEventPublisher.publishOrderCreated(event); orderEventPublisher.publishOrderCreated(event);
@@ -143,28 +149,28 @@ public class CleanOrderServiceImpl implements CleanOrderService {
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void enqueueOrderOnly(Long orderId, Long cleanerId) { public void enqueueOrderOnly(Long orderId, Long deviceId) {
// 使用生命周期管理器入队 // 使用生命周期管理器入队
OrderTransitionRequest request = OrderTransitionRequest.builder() OrderTransitionRequest request = OrderTransitionRequest.builder()
.orderId(orderId) .orderId(orderId)
.assigneeId(cleanerId) .assigneeId(deviceId)
.operatorType(OperatorTypeEnum.SYSTEM) .operatorType(OperatorTypeEnum.SYSTEM)
.operatorId(cleanerId) .operatorId(deviceId)
.reason("执行人忙碌,任务入队") .reason("执行人忙碌,任务入队")
.build(); .build();
orderLifecycleManager.enqueue(request); orderLifecycleManager.enqueue(request);
log.info("工单已入队: orderId={}, cleanerId={}", orderId, cleanerId); log.info("工单已入队: orderId={}, deviceId={}", orderId, deviceId);
} }
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void enqueueAndDispatch(Long orderId, Long cleanerId) { public void enqueueAndDispatch(Long orderId, Long deviceId) {
enqueueAndDispatch(orderId, cleanerId, false); enqueueAndDispatch(orderId, deviceId, false);
} }
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void enqueueAndDispatch(Long orderId, Long cleanerId, boolean isUrgent) { public void enqueueAndDispatch(Long orderId, Long deviceId, boolean isUrgent) {
// 查询工单 // 查询工单
OpsOrderDO order = opsOrderMapper.selectById(orderId); OpsOrderDO order = opsOrderMapper.selectById(orderId);
if (order == null) { if (order == null) {
@@ -174,25 +180,25 @@ public class CleanOrderServiceImpl implements CleanOrderService {
if (isUrgent) { if (isUrgent) {
// P0紧急任务使用紧急插队 // P0紧急任务使用紧急插队
DispatchResult result = dispatchEngine.urgentInterrupt(orderId, cleanerId); DispatchResult result = dispatchEngine.urgentInterrupt(orderId, deviceId);
log.warn("P0紧急派单结果: orderId={}, success={}", orderId, result.isSuccess()); log.warn("P0紧急派单结果: orderId={}, success={}", orderId, result.isSuccess());
} else { } else {
// 普通任务:正常派单 // 普通任务:正常派单
OrderTransitionRequest request = OrderTransitionRequest.builder() OrderTransitionRequest request = OrderTransitionRequest.builder()
.orderId(orderId) .orderId(orderId)
.targetStatus(WorkOrderStatusEnum.DISPATCHED) .targetStatus(WorkOrderStatusEnum.DISPATCHED)
.assigneeId(cleanerId) .assigneeId(deviceId)
.operatorType(OperatorTypeEnum.SYSTEM) .operatorType(OperatorTypeEnum.SYSTEM)
.operatorId(cleanerId) .operatorId(deviceId)
.reason("自动派单") .reason("自动派单")
.build(); .build();
orderLifecycleManager.dispatch(request); orderLifecycleManager.dispatch(request);
log.info("工单已派发: orderId={}, cleanerId={}", orderId, cleanerId); log.info("工单已派发: orderId={}, deviceId={}", orderId, deviceId);
} }
// 语音播报 // 语音播报
cleanOrderEventListener.sendNewOrderNotification(cleanerId, orderId); cleanOrderEventListener.sendNewOrderNotification(deviceId, orderId);
} }
@Override @Override
@@ -266,35 +272,35 @@ public class CleanOrderServiceImpl implements CleanOrderService {
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void confirmOrder(Long orderId, Long cleanerId) { public void confirmOrder(Long orderId, Long deviceId) {
log.info("保洁员确认工单: orderId={}, cleanerId={}", orderId, cleanerId); log.info("设备确认工单: orderId={}, deviceId={}", orderId, deviceId);
// 使用生命周期管理器转换状态 // 使用生命周期管理器转换状态
OrderTransitionRequest request = OrderTransitionRequest.builder() OrderTransitionRequest request = OrderTransitionRequest.builder()
.orderId(orderId) .orderId(orderId)
.targetStatus(WorkOrderStatusEnum.CONFIRMED) .targetStatus(WorkOrderStatusEnum.CONFIRMED)
.assigneeId(cleanerId) .assigneeId(deviceId)
.operatorType(OperatorTypeEnum.CLEANER) .operatorType(OperatorTypeEnum.CLEANER)
.operatorId(cleanerId) .operatorId(deviceId)
.reason("确认工单") .reason("确认工单")
.build(); .build();
orderLifecycleManager.transition(request); orderLifecycleManager.transition(request);
// 注意:保洁员状态更新由 CleanOrderEventListener 处理 // 注意:设备状态更新由 BadgeDeviceStatusServiceImpl 处理
} }
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void startWorkingOnBeacon(Long orderId, Long cleanerId, Long beaconId) { public void startWorkingOnBeacon(Long orderId, Long deviceId, Long beaconId) {
log.info("感知信标,开始作业: orderId={}, cleanerId={}, beaconId={}", orderId, cleanerId, beaconId); log.info("感知信标,开始作业: orderId={}, deviceId={}, beaconId={}", orderId, deviceId, beaconId);
// 使用生命周期管理器转换状态 // 使用生命周期管理器转换状态
OrderTransitionRequest request = OrderTransitionRequest.builder() OrderTransitionRequest request = OrderTransitionRequest.builder()
.orderId(orderId) .orderId(orderId)
.targetStatus(WorkOrderStatusEnum.ARRIVED) .targetStatus(WorkOrderStatusEnum.ARRIVED)
.assigneeId(cleanerId) .assigneeId(deviceId)
.operatorType(OperatorTypeEnum.SYSTEM) .operatorType(OperatorTypeEnum.SYSTEM)
.operatorId(cleanerId) .operatorId(deviceId)
.reason("感知信标,开始作业") .reason("感知信标,开始作业")
.build(); .build();
request.putPayload("beaconId", beaconId); request.putPayload("beaconId", beaconId);
@@ -307,17 +313,17 @@ public class CleanOrderServiceImpl implements CleanOrderService {
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void autoCompleteOnSignalLost(Long orderId, Long cleanerId, Long beaconId, Integer lostSeconds) { public void autoCompleteOnSignalLost(Long orderId, Long deviceId, Long beaconId, Integer lostSeconds) {
log.info("丢失信号,自动完成工单: orderId={}, cleanerId={}, lostSeconds={}秒", log.info("丢失信号,自动完成工单: orderId={}, deviceId={}, lostSeconds={}秒",
orderId, cleanerId, lostSeconds); orderId, deviceId, lostSeconds);
// 使用生命周期管理器转换状态 // 使用生命周期管理器转换状态
OrderTransitionRequest request = OrderTransitionRequest.builder() OrderTransitionRequest request = OrderTransitionRequest.builder()
.orderId(orderId) .orderId(orderId)
.targetStatus(WorkOrderStatusEnum.COMPLETED) .targetStatus(WorkOrderStatusEnum.COMPLETED)
.assigneeId(cleanerId) .assigneeId(deviceId)
.operatorType(OperatorTypeEnum.SYSTEM) .operatorType(OperatorTypeEnum.SYSTEM)
.operatorId(cleanerId) .operatorId(deviceId)
.reason("丢失信号,自动完成") .reason("丢失信号,自动完成")
.build(); .build();
request.putPayload("lostSeconds", lostSeconds); request.putPayload("lostSeconds", lostSeconds);
@@ -329,40 +335,39 @@ public class CleanOrderServiceImpl implements CleanOrderService {
recordCompletedTime(orderId); recordCompletedTime(orderId);
// 自动推送下一个任务 // 自动推送下一个任务
dispatchEngine.autoDispatchNext(orderId, cleanerId); dispatchEngine.autoDispatchNext(orderId, deviceId);
} }
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void autoDispatchNextOrder(Long completedOrderId, Long cleanerId) { public void autoDispatchNextOrder(Long completedOrderId, Long deviceId) {
log.info("任务完成后自动调度下一个: completedOrderId={}, cleanerId={}", completedOrderId, cleanerId); log.info("任务完成后自动调度下一个: completedOrderId={}, deviceId={}", completedOrderId, deviceId);
// 使用新的调度引擎自动推送下一个 // 使用调度引擎自动推送下一个
DispatchResult result = dispatchEngine.autoDispatchNext(completedOrderId, cleanerId); DispatchResult result = dispatchEngine.autoDispatchNext(completedOrderId, deviceId);
if (result.isSuccess()) { if (result.isSuccess()) {
log.info("已自动推送下一个任务: cleanerId={}", cleanerId); log.info("已自动推送下一个任务: deviceId={}", deviceId);
} else { } else {
log.info("无等待任务,保洁员变空闲: cleanerId={}", cleanerId); log.info("无等待任务,设备变空闲: deviceId={}", deviceId);
// 状态更新由 CleanOrderEventListener 处理
} }
} }
// ==================== 语音播报(委托给 EventHandler==================== // ==================== 语音播报(委托给 EventHandler====================
@Override @Override
public void playVoiceForNewOrder(Long cleanerId) { public void playVoiceForNewOrder(Long deviceId) {
cleanOrderEventListener.sendNewOrderNotification(cleanerId, null); cleanOrderEventListener.sendNewOrderNotification(deviceId, null);
} }
@Override @Override
public void playVoiceForQueuedOrder(Long cleanerId, int queueCount) { public void playVoiceForQueuedOrder(Long deviceId, int queueCount) {
cleanOrderEventListener.sendQueuedOrderNotification(cleanerId, queueCount); cleanOrderEventListener.sendQueuedOrderNotification(deviceId, queueCount);
} }
@Override @Override
public void playVoiceForNextTask(Long cleanerId, int queueCount, String nextTaskTitle) { public void playVoiceForNextTask(Long deviceId, int queueCount, String nextTaskTitle) {
cleanOrderEventListener.sendNextTaskNotification(cleanerId, queueCount, nextTaskTitle); cleanOrderEventListener.sendNextTaskNotification(deviceId, queueCount, nextTaskTitle);
} }
// ==================== 作业时长计算 ==================== // ==================== 作业时长计算 ====================

View File

@@ -18,6 +18,7 @@ import com.viewsh.framework.common.pojo.CommonResult;
import com.viewsh.module.ops.environment.integration.listener.CleanOrderEventListener; import com.viewsh.module.ops.environment.integration.listener.CleanOrderEventListener;
import com.viewsh.module.ops.environment.service.cleanorder.CleanOrderServiceImpl; import com.viewsh.module.ops.environment.service.cleanorder.CleanOrderServiceImpl;
import com.viewsh.module.ops.environment.service.voice.VoiceBroadcastService; import com.viewsh.module.ops.environment.service.voice.VoiceBroadcastService;
import com.viewsh.module.ops.environment.service.badge.BadgeDeviceStatusService;
import com.viewsh.module.ops.infrastructure.code.OrderCodeGenerator; import com.viewsh.module.ops.infrastructure.code.OrderCodeGenerator;
import com.viewsh.module.ops.infrastructure.id.OrderIdGenerator; import com.viewsh.module.ops.infrastructure.id.OrderIdGenerator;
import com.viewsh.module.ops.infrastructure.log.recorder.EventLogRecorder; import com.viewsh.module.ops.infrastructure.log.recorder.EventLogRecorder;
@@ -89,6 +90,10 @@ public class CleanOrderEndToEndTest {
private ValueOperations<String, String> valueOperations; private ValueOperations<String, String> valueOperations;
@Mock @Mock
private VoiceBroadcastService voiceBroadcastService; private VoiceBroadcastService voiceBroadcastService;
@Mock
private BadgeDeviceStatusService badgeDeviceStatusService;
@Mock @Mock
private EventLogRecorder eventLogRecorder; private EventLogRecorder eventLogRecorder;
@@ -245,7 +250,8 @@ public class CleanOrderEndToEndTest {
@Test @Test
void testAV01_BeaconAutoArrive() throws Exception { void testAV01_BeaconAutoArrive() throws Exception {
injectField(arriveEventHandler, "orderLifecycleManager", orderLifecycleManager); injectField(arriveEventHandler, "orderLifecycleManager", orderLifecycleManager);
injectField(arriveEventHandler, "badgeDeviceStatusService", badgeDeviceStatusService);
// 准备工单:状态 DISPATCHED // 准备工单:状态 DISPATCHED
Long orderId = 1001L; Long orderId = 1001L;
OpsOrderDO order = OpsOrderDO.builder() OpsOrderDO order = OpsOrderDO.builder()
@@ -283,9 +289,10 @@ public class CleanOrderEndToEndTest {
assertEquals(orderId, req.getOrderId()); assertEquals(orderId, req.getOrderId());
assertEquals(WorkOrderStatusEnum.ARRIVED, req.getTargetStatus()); assertEquals(WorkOrderStatusEnum.ARRIVED, req.getTargetStatus());
assertTrue(req.getReason().contains("自动到岗确认")); assertTrue(req.getReason().contains("自动到岗确认"));
// 3. 验证 Redis 缓存更新 // 3. 验证设备状态服务更新工单信息
verify(valueOperations).set(contains("ops:clean:device:order:5001"), anyString(), anyLong(), any(TimeUnit.class)); verify(badgeDeviceStatusService).setCurrentOrderInfo(eq(5001L), eq(1001L),
eq(WorkOrderStatusEnum.ARRIVED.getStatus()), eq(101L), eq("F0:C8:60:1D:10:BB"));
} }
@Test @Test
@@ -315,6 +322,7 @@ public class CleanOrderEndToEndTest {
void testCP01_SignalLossAutoComplete() throws Exception { void testCP01_SignalLossAutoComplete() throws Exception {
injectField(completeEventHandler, "orderLifecycleManager", orderLifecycleManager); injectField(completeEventHandler, "orderLifecycleManager", orderLifecycleManager);
injectField(completeEventHandler, "cleanOrderService", cleanOrderService); injectField(completeEventHandler, "cleanOrderService", cleanOrderService);
injectField(completeEventHandler, "badgeDeviceStatusService", badgeDeviceStatusService);
injectField(cleanOrderService, "dispatchEngine", dispatchEngine); injectField(cleanOrderService, "dispatchEngine", dispatchEngine);
// 准备工单:状态 ARRIVED // 准备工单:状态 ARRIVED
@@ -333,7 +341,7 @@ public class CleanOrderEndToEndTest {
"\"triggerSource\":\"IOT_SIGNAL_LOSS\"," + "\"triggerSource\":\"IOT_SIGNAL_LOSS\"," +
"\"triggerData\":{\"durationMs\":1800000}" + "\"triggerData\":{\"durationMs\":1800000}" +
"}"; "}";
// 模拟 autoDispatchNext 调用成功 // 模拟 autoDispatchNext 调用成功
when(dispatchEngine.autoDispatchNext(eq(orderId), eq(2001L))) when(dispatchEngine.autoDispatchNext(eq(orderId), eq(2001L)))
.thenReturn(DispatchResult.success("Success", 2001L)); .thenReturn(DispatchResult.success("Success", 2001L));
@@ -345,8 +353,8 @@ public class CleanOrderEndToEndTest {
// 1. 验证调用了 completeOrder // 1. 验证调用了 completeOrder
verify(orderLifecycleManager).completeOrder(eq(orderId), eq(null), contains("信号丢失超时")); verify(orderLifecycleManager).completeOrder(eq(orderId), eq(null), contains("信号丢失超时"));
// 2. 验证清理了 Redis 缓存 // 2. 验证清理了设备工单缓存
verify(stringRedisTemplate).delete(contains("ops:clean:device:order:5001")); verify(badgeDeviceStatusService).clearCurrentOrder(5001L);
// 3. 验证触发了自动调度下一单 // 3. 验证触发了自动调度下一单
verify(dispatchEngine).autoDispatchNext(eq(orderId), eq(2001L)); verify(dispatchEngine).autoDispatchNext(eq(orderId), eq(2001L));

View File

@@ -8,7 +8,7 @@ import java.util.List;
/** /**
* 工单队列管理服务接口 * 工单队列管理服务接口
* 提供工单队列的核心管理功能,包括入队、出队、状态变更、优先级调整等 * 提供工单队列的核心管理功能,包括入队、出队、状态变更、优先级调整等
* * @deprecated userId 参数实际存储的是工牌设备ID
* @author lzh * @author lzh
*/ */
public interface OrderQueueService { public interface OrderQueueService {
@@ -18,7 +18,7 @@ public interface OrderQueueService {
* 将工单加入派单队列,等待派单 * 将工单加入派单队列,等待派单
* *
* @param opsOrderId 工单ID * @param opsOrderId 工单ID
* @param userId 执行人员ID保洁员 * @param userId 执行人员ID保洁员/工牌设备ID
* @param priority 优先级 * @param priority 优先级
* @param queueIndex 队列顺序(可选,用于同优先级排序) * @param queueIndex 队列顺序(可选,用于同优先级排序)
* @return 队列记录ID * @return 队列记录ID

View File

@@ -33,6 +33,18 @@ public class EventPublishHandler extends TransitionHandler {
log.debug("事件发布处理器: orderId={}, {} -> {}", context.getOrder().getId(), oldStatus, targetStatus); log.debug("事件发布处理器: orderId={}, {} -> {}", context.getOrder().getId(), oldStatus, targetStatus);
try { try {
// 构建事件 payload包含 assigneeId
java.util.Map<String, Object> payload = request.getPayload() != null
? new java.util.HashMap<>(request.getPayload())
: new java.util.HashMap<>();
if (request.getAssigneeId() != null) {
payload.put("assigneeId", request.getAssigneeId());
}
// 添加 urgentOrderIdP0打断场景
if (request.getUrgentOrderId() != null) {
payload.put("urgentOrderId", request.getUrgentOrderId());
}
// 发布状态变更事件 // 发布状态变更事件
OrderStateChangedEvent event = OrderStateChangedEvent.builder() OrderStateChangedEvent event = OrderStateChangedEvent.builder()
.orderId(context.getOrder().getId()) .orderId(context.getOrder().getId())
@@ -44,7 +56,7 @@ public class EventPublishHandler extends TransitionHandler {
.operatorType(request.getOperatorType()) .operatorType(request.getOperatorType())
.eventTime(java.time.LocalDateTime.now()) .eventTime(java.time.LocalDateTime.now())
.remark(request.getReason()) .remark(request.getReason())
.payload(request.getPayload()) .payload(payload)
.build(); .build();
orderEventPublisher.publishStateChanged(event); orderEventPublisher.publishStateChanged(event);

View File

@@ -25,7 +25,7 @@ public enum EventDomain {
TRAFFIC("traffic", "客流"), TRAFFIC("traffic", "客流"),
/** /**
* 设备域 - 设备控制、TTS<EFBFBD><EFBFBD>震动等 * 设备域 - 设备控制、TTS震动等
*/ */
DEVICE("device", "设备"), DEVICE("device", "设备"),