OrderScheduleTask.java 5.64 KB
package com.diligrp.rider.task;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.diligrp.rider.entity.Orders;
import com.diligrp.rider.mapper.OrdersMapper;
import com.diligrp.rider.service.WebhookService;
import com.diligrp.rider.service.AdminMessageService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 订单定时任务
 * OrderhandleCron(每3秒执行)
 */
@Slf4j
@Component
@EnableScheduling
@RequiredArgsConstructor
public class OrderScheduleTask {

    private final OrdersMapper ordersMapper;
    private final WebhookService webhookService;
    private final ObjectMapper objectMapper;
    private final AdminMessageService adminMessageService;

    /**
     * 超时未接单订单自动取消(30分钟)
     * Orders::cancel()
     * 每分钟执行一次
     */
    @Scheduled(fixedDelay = 60_000)
    public void autoCancelTimeout() {
        try {
            long expireTime = System.currentTimeMillis() / 1000 - 30 * 60;
            List<Orders> timeoutOrders = ordersMapper.selectList(
                    new LambdaQueryWrapper<Orders>()
                            .eq(Orders::getStatus, 2)
                            .le(Orders::getAddTime, expireTime));

            for (Orders order : timeoutOrders) {
                int updated = ordersMapper.update(null, new LambdaUpdateWrapper<Orders>()
                        .eq(Orders::getId, order.getId())
                        .eq(Orders::getStatus, 2)
                        .set(Orders::getStatus, 10));
                if (updated > 0) {
                    log.info("订单超时自动取消 orderId={}", order.getId());
                    // 通知接入方
                    notifyCancel(order);
                    // 发送消息:订单取消(如果已分配骑手)
                    if (order.getRiderId() != null && order.getRiderId() > 0) {
                        try {
                            Map<String, Object> params = new HashMap<>();
                            params.put("orderNo", order.getOrderNo());
                            params.put("bizId", order.getId());
                            adminMessageService.sendByTemplate(order.getCityId(), order.getRiderId(), "order_cancelled", params);
                        } catch (Exception e) {
                            log.error("发送订单取消消息失败,orderId={} riderId={}", order.getId(), order.getRiderId(), e);
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error("超时取消任务异常", e);
        }
    }

    /**
     * 订单超时提醒(配送中的订单,距离预计送达时间还有5分钟)
     * 每分钟执行一次
     */
    @Scheduled(fixedDelay = 60_000)
    public void timeoutReminder() {
        try {
            long now = System.currentTimeMillis() / 1000;
            // 查询配送中的订单(状态=4)
            List<Orders> deliveringOrders = ordersMapper.selectList(
                    new LambdaQueryWrapper<Orders>()
                            .eq(Orders::getStatus, 4)
                            .isNotNull(Orders::getRiderId)
                            .gt(Orders::getRiderId, 0));

            for (Orders order : deliveringOrders) {
                // 简单逻辑:取件后超过30分钟提醒
                if (order.getPickTime() != null && order.getPickTime() > 0) {
                    long elapsedMinutes = (now - order.getPickTime()) / 60;
                    if (elapsedMinutes >= 30 && elapsedMinutes < 31) {
                        // 发送超时提醒消息
                        try {
                            Map<String, Object> params = new HashMap<>();
                            params.put("orderNo", order.getOrderNo());
                            params.put("bizId", order.getId());
                            adminMessageService.sendByTemplate(order.getCityId(), order.getRiderId(), "order_timeout", params);
                            log.info("发送订单超时提醒,orderId={} riderId={}", order.getId(), order.getRiderId());
                        } catch (Exception e) {
                            log.error("发送订单超时提醒失败,orderId={} riderId={}", order.getId(), order.getRiderId(), e);
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error("超时取消任务异常", e);
        }
    }


    private void notifyCancel(Orders order) {
        try {
            if (order.getAppKey() == null || order.getAppKey().isBlank()) return;
            Map<String, Object> payload = new HashMap<>();
            payload.put("event", "order.cancelled");
            payload.put("outOrderNo", order.getOutOrderNo());
            payload.put("deliveryOrderId", order.getId());
            payload.put("orderNo", order.getOrderNo());
            payload.put("status", 10);
            payload.put("reason", "超时无人接单,系统自动取消");
            payload.put("timestamp", System.currentTimeMillis() / 1000);
            webhookService.send("order.cancelled", order.getId(),
                    objectMapper.writeValueAsString(payload));
        } catch (Exception e) {
            log.warn("取消通知失败 orderId={}", order.getId(), e);
        }
    }
}