liujie
2026-08-21 77649c76ec1c3afcb93e9963243d637665b3a307
backend/src/main/java/com/tourguide/modules/order/service/OrderLifecycleScheduler.java
@@ -1,11 +1,13 @@
package com.tourguide.modules.order.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.tourguide.config.properties.UniPushProperties;
import com.tourguide.modules.operation.entity.OperationScenicSpot;
import com.tourguide.modules.operation.mapper.OperationScenicSpotMapper;
import com.tourguide.modules.order.domain.OrderStatus;
import com.tourguide.modules.order.entity.TourOrder;
import com.tourguide.modules.order.mapper.TourOrderMapper;
import com.tourguide.modules.system.service.GuideNotificationService;
import com.tourguide.modules.user.entity.GuideReceivingSession;
import com.tourguide.modules.user.mapper.GuideRealtimeStatusMapper;
import com.tourguide.modules.user.mapper.GuideReceivingSessionMapper;
@@ -23,22 +25,29 @@
    private final GuideOrderMatchingService matchingService;
    private final GuideReceivingSessionMapper sessionMapper;
    private final GuideSessionTransitionService sessionTransitionService;
    private final GuideNotificationService notificationService;
    private final UniPushProperties uniPushProperties;
    public OrderLifecycleScheduler(TourOrderMapper orderMapper, OperationScenicSpotMapper scenicMapper,
                                   GuideOrderMatchingService matchingService,
                                   GuideReceivingSessionMapper sessionMapper,
                                   GuideSessionTransitionService sessionTransitionService) {
                                   GuideSessionTransitionService sessionTransitionService,
                                   GuideNotificationService notificationService,
                                   UniPushProperties uniPushProperties) {
        this.orderMapper = orderMapper;
        this.scenicMapper = scenicMapper;
        this.matchingService = matchingService;
        this.sessionMapper = sessionMapper;
        this.sessionTransitionService = sessionTransitionService;
        this.notificationService = notificationService;
        this.uniPushProperties = uniPushProperties;
    }
    @Scheduled(fixedDelayString = "${tourguide.order.lifecycle-scan-delay-millis:10000}")
    public void process() {
        cancelExpiredUnpaidOrders();
        retryPendingOrders();
        sendServiceReminders();
        startDueGroupSessions();
    }
@@ -73,4 +82,32 @@
            sessionTransitionService.startIfDue(session);
        }
    }
    void sendServiceReminders() {
        int reminderMinutes = Math.max(1, uniPushProperties.getServiceReminderMinutes());
        LocalDateTime now = LocalDateTime.now();
        List<GuideReceivingSession> sessions = sessionMapper.selectList(
                new LambdaQueryWrapper<GuideReceivingSession>()
                        .eq(GuideReceivingSession::getStatus, "RECEIVING")
                        .isNull(GuideReceivingSession::getReminderPushedAt)
                        .isNotNull(GuideReceivingSession::getServiceStartAt)
                        .gt(GuideReceivingSession::getServiceStartAt, now)
                        .le(GuideReceivingSession::getServiceStartAt, now.plusMinutes(reminderMinutes))
                        .orderByAsc(GuideReceivingSession::getServiceStartAt)
                        .last("LIMIT " + BATCH_SIZE));
        for (GuideReceivingSession session : sessions) {
            TourOrder order = orderMapper.selectOne(new LambdaQueryWrapper<TourOrder>()
                    .eq(TourOrder::getReceivingSessionId, session.getId())
                    .eq(TourOrder::getGuideId, session.getGuideId())
                    .eq(TourOrder::getStatus, OrderStatus.PENDING_MEETING.getCode())
                    .orderByAsc(TourOrder::getId)
                    .last("LIMIT 1"));
            if (order == null) continue;
            LocalDateTime claimedAt = LocalDateTime.now();
            if (sessionMapper.claimServiceReminder(session.getId(), claimedAt) != 1) continue;
            if (!notificationService.pushServiceReminder(order)) {
                sessionMapper.releaseServiceReminder(session.getId(), claimedAt);
            }
        }
    }
}