feat(ops): add CleanOrderConfirmEventHandler
This commit is contained in:
@@ -0,0 +1,161 @@
|
||||
package com.viewsh.module.ops.environment.integration.consumer;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.viewsh.module.iot.api.device.IotDeviceControlApi;
|
||||
import com.viewsh.module.iot.api.device.dto.IotDeviceServiceInvokeReqDTO;
|
||||
import com.viewsh.module.ops.core.lifecycle.OrderLifecycleManager;
|
||||
import com.viewsh.module.ops.core.lifecycle.model.OrderTransitionRequest;
|
||||
import com.viewsh.module.ops.dal.dataobject.workorder.OpsOrderDO;
|
||||
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.integration.dto.CleanOrderConfirmEventDTO;
|
||||
import com.viewsh.module.ops.infrastructure.log.context.BusinessLogContext;
|
||||
import com.viewsh.module.ops.infrastructure.log.enumeration.LogType;
|
||||
import com.viewsh.module.ops.infrastructure.log.publisher.BusinessLogPublisher;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.rocketmq.spring.annotation.ConsumeMode;
|
||||
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
|
||||
import org.apache.rocketmq.spring.core.RocketMQListener;
|
||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 保洁工单确认事件消费者
|
||||
* <p>
|
||||
* 订阅 IoT 模块发布的工单确认事件(如:工牌按键确认)
|
||||
*
|
||||
* @author AI
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@RocketMQMessageListener(
|
||||
topic = "ops.order.confirm",
|
||||
consumerGroup = "ops-clean-order-confirm-group",
|
||||
consumeMode = ConsumeMode.CONCURRENTLY
|
||||
)
|
||||
public class CleanOrderConfirmEventHandler implements RocketMQListener<String> {
|
||||
|
||||
private static final String DEDUP_KEY_PATTERN = "ops:clean:dedup:confirm:%s";
|
||||
private static final int DEDUP_TTL_SECONDS = 300;
|
||||
|
||||
@Resource
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
@Resource
|
||||
private StringRedisTemplate stringRedisTemplate;
|
||||
|
||||
@Resource
|
||||
private OpsOrderMapper opsOrderMapper;
|
||||
|
||||
@Resource
|
||||
private OrderLifecycleManager orderLifecycleManager;
|
||||
|
||||
@Resource
|
||||
private BusinessLogPublisher businessLogPublisher;
|
||||
|
||||
@Resource
|
||||
private IotDeviceControlApi iotDeviceControlApi;
|
||||
|
||||
@Override
|
||||
public void onMessage(String message) {
|
||||
try {
|
||||
// 1. JSON 反序列化
|
||||
CleanOrderConfirmEventDTO event = objectMapper.readValue(message, CleanOrderConfirmEventDTO.class);
|
||||
String eventId = event.getEventId();
|
||||
|
||||
// 2. 幂等性检查
|
||||
String dedupKey = String.format(DEDUP_KEY_PATTERN, eventId);
|
||||
Boolean firstTime = stringRedisTemplate.opsForValue()
|
||||
.setIfAbsent(dedupKey, "1", DEDUP_TTL_SECONDS, TimeUnit.SECONDS);
|
||||
|
||||
if (!Boolean.TRUE.equals(firstTime)) {
|
||||
log.debug("[CleanOrderConfirmEventHandler] 重复事件,跳过处理: eventId={}", eventId);
|
||||
return;
|
||||
}
|
||||
|
||||
// 3. 加载工单
|
||||
Long orderId = event.getOrderId();
|
||||
OpsOrderDO order = opsOrderMapper.selectById(orderId);
|
||||
if (order == null) {
|
||||
log.warn("[CleanOrderConfirmEventHandler] 工单不存在: orderId={}", orderId);
|
||||
return;
|
||||
}
|
||||
|
||||
WorkOrderStatusEnum currentStatus = WorkOrderStatusEnum.fromStatus(order.getStatus());
|
||||
log.info("[CleanOrderConfirmEventHandler] 收到确认事件: eventId={}, orderId={}, currentStatus={}",
|
||||
eventId, orderId, currentStatus);
|
||||
|
||||
// 4. 状态检查
|
||||
// 如果已在进行中 (CONFIRMED or ARRIVED),提示"工单已在进行中"
|
||||
if (currentStatus == WorkOrderStatusEnum.CONFIRMED || currentStatus == WorkOrderStatusEnum.ARRIVED) {
|
||||
sendTTS(event.getDeviceId(), "工单已在进行中");
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查是否可以确认
|
||||
if (!currentStatus.canConfirm()) {
|
||||
log.warn("[CleanOrderConfirmEventHandler] 当前状态无法确认工单: orderId={}, status={}", orderId, currentStatus);
|
||||
sendTTS(event.getDeviceId(), "当前状态无法确认工单");
|
||||
return;
|
||||
}
|
||||
|
||||
// 5. 状态流转 -> CONFIRMED
|
||||
OrderTransitionRequest request = OrderTransitionRequest.builder()
|
||||
.orderId(orderId)
|
||||
.targetStatus(WorkOrderStatusEnum.CONFIRMED)
|
||||
.reason("工牌按键确认")
|
||||
.operatorType(OperatorTypeEnum.CLEANER)
|
||||
.operatorId(order.getAssigneeId())
|
||||
.build();
|
||||
|
||||
orderLifecycleManager.transition(request);
|
||||
|
||||
// 6. 记录业务日志
|
||||
BusinessLogContext logContext = BusinessLogContext.forOrder(
|
||||
LogType.TRANSITION,
|
||||
"工单已确认 (工牌按键)",
|
||||
orderId
|
||||
);
|
||||
businessLogPublisher.publishSuccess(logContext);
|
||||
|
||||
// 7. 发送 TTS 通知
|
||||
// "工单已确认,请前往{AreaName}开始作业"
|
||||
String ttsText = "工单已确认,请前往作业区域开始作业";
|
||||
sendTTS(event.getDeviceId(), ttsText);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("[CleanOrderConfirmEventHandler] 消息处理失败: message={}", message, e);
|
||||
throw new RuntimeException("保洁工单确认事件处理失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送 TTS 语音播报
|
||||
*/
|
||||
private void sendTTS(Long deviceId, String text) {
|
||||
if (deviceId == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("text", text);
|
||||
|
||||
IotDeviceServiceInvokeReqDTO req = IotDeviceServiceInvokeReqDTO.builder()
|
||||
.deviceId(deviceId)
|
||||
.identifier("TTS")
|
||||
.params(params)
|
||||
.timeoutSeconds(10)
|
||||
.build();
|
||||
|
||||
iotDeviceControlApi.invokeService(req);
|
||||
} catch (Exception e) {
|
||||
log.error("[CleanOrderConfirmEventHandler] TTS 发送失败: deviceId={}", deviceId, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user