| | |
| | | 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.domain.RefundStatus; |
| | | 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; |
| | |
| | | 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(); |
| | | } |
| | | |
| | |
| | | void retryPendingOrders() { |
| | | List<TourOrder> orders = orderMapper.selectList(new LambdaQueryWrapper<TourOrder>() |
| | | .eq(TourOrder::getStatus, OrderStatus.PENDING_ACCEPT.getCode()) |
| | | .isNotNull(TourOrder::getPaymentTime).orderByAsc(TourOrder::getPaymentTime).last("LIMIT " + BATCH_SIZE)); |
| | | .isNotNull(TourOrder::getPaymentTime) |
| | | .and(wrapper -> wrapper.isNull(TourOrder::getRefundStatus) |
| | | .or().eq(TourOrder::getRefundStatus, RefundStatus.NONE.getCode())) |
| | | .orderByAsc(TourOrder::getPaymentTime).last("LIMIT " + BATCH_SIZE)); |
| | | for (TourOrder order : orders) matchingService.match(order.getId()); |
| | | } |
| | | |
| | |
| | | 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); |
| | | } |
| | | } |
| | | } |
| | | } |