package com.tourguide.modules.order.service;
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.tourguide.modules.operation.service.PlatformSettingsService;
|
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 org.springframework.scheduling.annotation.Scheduled;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
|
import java.time.LocalDateTime;
|
import java.util.List;
|
|
@Service
|
public class OrderAutoRefundService {
|
private static final int BATCH_SIZE = 100;
|
|
private final TourOrderMapper orderMapper;
|
private final PlatformSettingsService platformSettingsService;
|
private final OrderRefundService orderRefundService;
|
|
public OrderAutoRefundService(TourOrderMapper orderMapper,
|
PlatformSettingsService platformSettingsService,
|
OrderRefundService orderRefundService) {
|
this.orderMapper = orderMapper;
|
this.platformSettingsService = platformSettingsService;
|
this.orderRefundService = orderRefundService;
|
}
|
|
@Scheduled(fixedDelayString = "${tourguide.order.auto-refund-scan-delay-millis:10000}")
|
@Transactional
|
public void refundExpiredUnacceptedOrders() {
|
Integer configuredMinutes = platformSettingsService.getSettings().getUnacceptedAutoRefundMinutes();
|
int timeoutMinutes = configuredMinutes == null || configuredMinutes < 1 ? 5 : configuredMinutes;
|
LocalDateTime expiredBefore = LocalDateTime.now().minusMinutes(timeoutMinutes);
|
List<TourOrder> orders = orderMapper.selectList(
|
new LambdaQueryWrapper<TourOrder>()
|
.eq(TourOrder::getStatus, OrderStatus.PENDING_ACCEPT.getCode())
|
.isNotNull(TourOrder::getPaymentTime)
|
.le(TourOrder::getPaymentTime, expiredBefore)
|
.and(wrapper -> wrapper.isNull(TourOrder::getRefundStatus)
|
.or().eq(TourOrder::getRefundStatus, RefundStatus.NONE.getCode()))
|
.orderByAsc(TourOrder::getPaymentTime)
|
.last("LIMIT " + BATCH_SIZE));
|
for (TourOrder order : orders) {
|
refundIfStillUnaccepted(order.getId());
|
}
|
}
|
|
void refundIfStillUnaccepted(Long orderId) {
|
if (orderMapper.claimUnacceptedOrderForRefund(orderId) != 1) {
|
return;
|
}
|
TourOrder order = orderMapper.selectById(orderId);
|
orderRefundService.requestRefund(order);
|
}
|
}
|