预订单逻辑优化
This commit is contained in:
parent
c91fc181c9
commit
eb268d35b3
@ -125,4 +125,11 @@ public class CommonConstant {
|
||||
public static final Integer Order_Booking_State_LJ = 1;
|
||||
public static final Integer Order_Booking_State_YY = 2;
|
||||
|
||||
// 预约下单从当前时间延迟的最小分钟数(单位分钟),不能低于35分钟
|
||||
public final static Integer MIN_DELAY_MINUTES_FOR_BOOKING_ORDER = 46;
|
||||
|
||||
// 预约订单创建提前分钟数(用于提前创建顺丰订单)
|
||||
// public final static Integer MIN_DELAY_MINUTES_FOR_SF_EXPRESS_ORDER = 35;
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -96,6 +96,7 @@ public class RedisKeyExpiredListener implements MessageListener {
|
||||
|
||||
// orderId
|
||||
String orderId = expiredKey.replace(RedisConstant.Order_Booking_Task_Key, "");
|
||||
log.info("[预约订单顺丰同城下单Redis过期监听] 处理预约订单顺丰同城下单超时消息. 订单号: {}", orderId);
|
||||
if (StrUtil.isBlank(orderId)) {
|
||||
log.error("[预约订单顺丰同城下单Redis过期监听] 键: {} 不符合预期格式,无法解析订单号", expiredKey);
|
||||
return;
|
||||
|
||||
@ -607,4 +607,13 @@ public interface ShopOrderBaseService extends IBaseService<ShopOrderBase> {
|
||||
* @return
|
||||
*/
|
||||
Long sameCityOrderExpireSeconds(Long defaultValue);
|
||||
|
||||
/**
|
||||
* 更新订单下单时间
|
||||
*
|
||||
* @param orderId
|
||||
* @param orderTime
|
||||
* @return
|
||||
*/
|
||||
Boolean updateOrderTime(String orderId, Date orderTime);
|
||||
}
|
||||
|
||||
@ -8,7 +8,6 @@
|
||||
|
||||
package com.suisung.mall.shop.order.service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.suisung.mall.common.modules.order.ShopOrderBooking;
|
||||
import com.suisung.mall.core.web.service.IBaseService;
|
||||
@ -40,15 +39,7 @@ public interface ShopOrderBookingService extends IBaseService<ShopOrderBooking>
|
||||
* @return 分页结果
|
||||
*/
|
||||
Page<ShopOrderBooking> findValidBookingList(Integer pageNum, Integer pageSize);
|
||||
|
||||
/**
|
||||
* 更新预约订单任务
|
||||
*
|
||||
* @param updateWrapper 更新条件包装器
|
||||
* @return 是否更新成功
|
||||
*/
|
||||
Boolean update(UpdateWrapper<ShopOrderBooking> updateWrapper);
|
||||
|
||||
|
||||
/**
|
||||
* 更改预约订单任务下单完成状态(同时删除 redis 的定时任务)
|
||||
*
|
||||
|
||||
@ -6675,15 +6675,22 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
|
||||
bookingAt = bookingBeginTime.getTime() / 1000; // 预订单到达时间戳(秒)
|
||||
}
|
||||
|
||||
// 计算订单下单时间:预约开始时间前35分钟
|
||||
Date scheduledOrderTime = DateUtil.offsetSecond(bookingBeginTime, -Convert.toInt(sameCityOrderExpireSeconds(2100L))); // 35分钟超时,60秒*35分钟 = 2100秒
|
||||
|
||||
info_row.setBooking_state(bookingState);
|
||||
info_row.setBooking_at(bookingAt);
|
||||
info_row.setBooking_begin_time(bookingBeginTime);
|
||||
info_row.setBooking_end_time(bookingEndTime);
|
||||
info_row.setOrder_time(scheduledOrderTime.getTime());
|
||||
|
||||
// 重要:预约订单任务创建处理
|
||||
if (!shopOrderBookingService.setupRedisBookingTask(info_row.getOrder_id(), info_row.getBooking_at())) {
|
||||
throw new ApiException(I18nUtil._("保存预约订单任务失败!"));
|
||||
}
|
||||
|
||||
// 更新订单的下单时间
|
||||
updateOrderTime(order_id, scheduledOrderTime);
|
||||
}
|
||||
|
||||
|
||||
@ -8759,7 +8766,7 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
|
||||
// 支付渠道处理
|
||||
m.put("payment_channel_name", m.getOrDefault("payment_channel_name", "线上支付").toString());
|
||||
|
||||
// 配送时间= 支付时间+35分钟
|
||||
// 配送到达时间= 支付时间+35分钟
|
||||
Long mchOrderExpireSeconds = shopOrderBaseService.sameCityOrderExpireSeconds(2100L);
|
||||
// 配送时间
|
||||
Date paymentTime = Convert.toDate(m.get("payment_time"));
|
||||
@ -9271,6 +9278,10 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
|
||||
*/
|
||||
@Override
|
||||
public Long sameCityOrderExpireSeconds(Long defaultValue) {
|
||||
if (CheckUtil.isEmpty(defaultValue)) {
|
||||
defaultValue = 2100L;
|
||||
}
|
||||
|
||||
try {
|
||||
String value = accountService.getAccountBaseConfigValue(CommonConstant.CONF_KEY_SAME_CITY_ORDER_EXPIRE_SECONDS);
|
||||
if (StringUtils.isBlank(value)) {
|
||||
@ -9284,4 +9295,48 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新订单下单时间
|
||||
*
|
||||
* @param orderId 订单ID
|
||||
* @param orderTime 新的订单时间
|
||||
* @return Boolean 更新是否成功
|
||||
*/
|
||||
@Override
|
||||
public Boolean updateOrderTime(String orderId, Date orderTime) {
|
||||
// 1. 参数校验
|
||||
if (StrUtil.isBlank(orderId)) {
|
||||
log.warn("[更新订单时间] 订单ID不能为空");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (orderTime == null) {
|
||||
log.warn("[更新订单时间] 订单时间不能为空, orderId={}", orderId);
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
// 2. 构建更新条件
|
||||
UpdateWrapper<ShopOrderBase> updateWrapper = new UpdateWrapper<>();
|
||||
updateWrapper.eq("order_id", orderId)
|
||||
.set("order_time", orderTime);
|
||||
|
||||
// 3. 执行更新操作
|
||||
boolean result = update(updateWrapper);
|
||||
|
||||
if (result) {
|
||||
log.info("[更新订单时间] 订单时间更新成功, orderId={}, orderTime={}", orderId, orderTime);
|
||||
} else {
|
||||
log.warn("[更新订单时间] 订单时间更新失败, 可能订单不存在, orderId={}", orderId);
|
||||
}
|
||||
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
// 4. 异常处理
|
||||
log.error("[更新订单时间] 更新订单时间时发生异常, orderId={}, orderTime={}", orderId, orderTime, e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -21,6 +21,7 @@ import com.suisung.mall.common.utils.CheckUtil;
|
||||
import com.suisung.mall.core.web.service.RedisService;
|
||||
import com.suisung.mall.core.web.service.impl.BaseServiceImpl;
|
||||
import com.suisung.mall.shop.order.mapper.ShopOrderBookingMapper;
|
||||
import com.suisung.mall.shop.order.service.ShopOrderBaseService;
|
||||
import com.suisung.mall.shop.order.service.ShopOrderBookingService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@ -30,17 +31,18 @@ import org.springframework.util.StringUtils;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class ShopOrderBookingServiceImpl extends BaseServiceImpl<ShopOrderBookingMapper, ShopOrderBooking> implements ShopOrderBookingService {
|
||||
|
||||
private static final Long MINUTES_BEFORE_BOOKING = 35L;
|
||||
|
||||
@Resource
|
||||
private ShopOrderBookingMapper shopOrderBookingMapper;
|
||||
|
||||
@Lazy
|
||||
@Resource
|
||||
private ShopOrderBaseService shopOrderBaseService;
|
||||
|
||||
@Lazy
|
||||
@Autowired
|
||||
private RedisService redisService;
|
||||
@ -64,7 +66,8 @@ public class ShopOrderBookingServiceImpl extends BaseServiceImpl<ShopOrderBookin
|
||||
|
||||
try {
|
||||
// 计算执行时间(预约时间前35分钟)
|
||||
long runAt = bookingAt - TimeUnit.MINUTES.toSeconds(MINUTES_BEFORE_BOOKING);
|
||||
// long runAt = bookingAt - TimeUnit.MINUTES.toSeconds(CommonConstant.MIN_DELAY_MINUTES_FOR_SF_EXPRESS_ORDER);
|
||||
long runAt = bookingAt - shopOrderBaseService.sameCityOrderExpireSeconds(2100L); // 35分钟超时,60秒*35分钟 = 2100秒
|
||||
|
||||
ShopOrderBooking shopOrderBooking = new ShopOrderBooking();
|
||||
shopOrderBooking.setOrder_id(orderId);
|
||||
@ -77,9 +80,10 @@ public class ShopOrderBookingServiceImpl extends BaseServiceImpl<ShopOrderBookin
|
||||
// 如果保存成功,设置Redis过期键
|
||||
if (shopOrderBooking != null) {
|
||||
String redisKey = RedisConstant.Order_Booking_Task_Key + orderId;
|
||||
long remainingSeconds = runAt - System.currentTimeMillis() / 1000;
|
||||
// 设置过期时间为runAt时间点(相对于当前时间的秒数)
|
||||
if (runAt > 0) {
|
||||
redisService.set(redisKey, Convert.toStr(shopOrderBooking.getRun_at()), runAt);
|
||||
if (remainingSeconds > 0) {
|
||||
redisService.set(redisKey, Convert.toStr(shopOrderBooking.getRun_at()), remainingSeconds);
|
||||
log.debug("Redis键设置成功: key={}, bookingAt={}, runAt={}", redisKey, bookingAt, runAt);
|
||||
} else {
|
||||
log.warn("过期时间无效,未设置Redis键: key={}, bookingAt={}, runAt={}", redisKey, bookingAt, runAt);
|
||||
@ -111,7 +115,7 @@ public class ShopOrderBookingServiceImpl extends BaseServiceImpl<ShopOrderBookin
|
||||
|
||||
try {
|
||||
if (CheckUtil.isEmpty(shopOrderBooking.getRun_at())) {
|
||||
long runAt = shopOrderBooking.getBooking_at() - TimeUnit.MINUTES.toSeconds(MINUTES_BEFORE_BOOKING);
|
||||
long runAt = shopOrderBooking.getBooking_at() - shopOrderBaseService.sameCityOrderExpireSeconds(2100L); // 35分钟超时,60秒*35分钟 = 2100秒
|
||||
shopOrderBooking.setRun_at(runAt);
|
||||
}
|
||||
|
||||
@ -166,22 +170,6 @@ public class ShopOrderBookingServiceImpl extends BaseServiceImpl<ShopOrderBookin
|
||||
return this.page(page, queryWrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean update(UpdateWrapper<ShopOrderBooking> updateWrapper) {
|
||||
log.debug("更新预约订单任务");
|
||||
if (updateWrapper == null) {
|
||||
log.warn("更新条件不能为空");
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
return this.update(updateWrapper);
|
||||
} catch (Exception e) {
|
||||
log.error("更新预约订单任务时发生异常", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更改预约订单任务下单完成状态(同时删除 redis 的定时任务)
|
||||
*
|
||||
@ -205,7 +193,7 @@ public class ShopOrderBookingServiceImpl extends BaseServiceImpl<ShopOrderBookin
|
||||
updateWrapper.set("status", CommonConstant.Disable2);
|
||||
|
||||
// 执行更新操作
|
||||
boolean result = this.update(updateWrapper);
|
||||
boolean result = update(updateWrapper);
|
||||
|
||||
if (result) {
|
||||
log.debug("成功完成预约订单任务的同城配送下单: orderId={}", orderId);
|
||||
@ -246,9 +234,16 @@ public class ShopOrderBookingServiceImpl extends BaseServiceImpl<ShopOrderBookin
|
||||
continue;
|
||||
}
|
||||
|
||||
redisService.set(redisKey, Convert.toStr(shopOrderBooking.getRun_at()), shopOrderBooking.getRun_at());
|
||||
if (shopOrderBooking == null || shopOrderBooking.getRun_at() == null) {
|
||||
log.debug("run_at 参数空不能同步到 Redis");
|
||||
continue;
|
||||
}
|
||||
|
||||
count++;
|
||||
long remainingSeconds = shopOrderBooking.getRun_at() - System.currentTimeMillis() / 1000;
|
||||
if (remainingSeconds > 0) {
|
||||
redisService.set(redisKey, Convert.toStr(shopOrderBooking.getRun_at()), remainingSeconds);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
|
||||
@ -119,27 +119,21 @@ public class ShopOrderInfoServiceImpl extends BaseServiceImpl<ShopOrderInfoMappe
|
||||
private ShopStorePrinterService shopStorePrinterService;
|
||||
@Autowired
|
||||
private ShopOrderInfoMapper shopOrderInfoMapper;
|
||||
|
||||
@Lazy
|
||||
@Autowired
|
||||
private ShopStoreSfOrderService shopStoreSfOrderService;
|
||||
|
||||
@Lazy
|
||||
@Autowired
|
||||
private ShopOrderBookingService shopOrderBookingService;
|
||||
|
||||
@Lazy
|
||||
@Autowired
|
||||
private SFExpressApiService sfExpressApiService;
|
||||
|
||||
@Lazy
|
||||
@Autowired
|
||||
private PushMessageService pushMessageService;
|
||||
|
||||
@Autowired
|
||||
private ThreadPoolExecutor executor;
|
||||
|
||||
|
||||
@Override
|
||||
public Map dashboard() {
|
||||
|
||||
@ -914,9 +908,9 @@ public class ShopOrderInfoServiceImpl extends BaseServiceImpl<ShopOrderInfoMappe
|
||||
}
|
||||
|
||||
// 7. 预约时间范围检查 - 仅能预约50分钟后的订单(防止用户在下单页面停留太长,45分钟也是可以通过的)
|
||||
Date fortyFiveMinutesLater = DateUtil.offsetMinute(new Date(), 45);
|
||||
if (!bookingBeginTime.after(fortyFiveMinutesLater)) {
|
||||
return Pair.of(false, "[预约订单校验] 请预约50分后的订单");
|
||||
Date fortyFiveMinutesLater = DateUtil.offsetMinute(new Date(), CommonConstant.MIN_DELAY_MINUTES_FOR_BOOKING_ORDER - 5);
|
||||
if (bookingBeginTime.before(fortyFiveMinutesLater)) {
|
||||
return Pair.of(false, String.format("[预约订单校验] 请预约%d分后的订单", CommonConstant.MIN_DELAY_MINUTES_FOR_BOOKING_ORDER));
|
||||
}
|
||||
|
||||
return Pair.of(true, "[预约订单校验] 成功");
|
||||
@ -975,7 +969,6 @@ public class ShopOrderInfoServiceImpl extends BaseServiceImpl<ShopOrderInfoMappe
|
||||
return Pair.of(false, "预约订单已下过单,请勿重复操作");
|
||||
}
|
||||
|
||||
|
||||
// 调用顺丰接口创建订单
|
||||
Pair<Boolean, String> sfResult = sfExpressApiService.innerCreateSfExpressOrder(orderId, 0L);
|
||||
if (sfResult == null) {
|
||||
@ -1161,7 +1154,7 @@ public class ShopOrderInfoServiceImpl extends BaseServiceImpl<ShopOrderInfoMappe
|
||||
Date startTime = openTime;
|
||||
if (isToday) {
|
||||
// 当前时间+50分钟作为第二个时间槽的开始时间
|
||||
Date nowPlusFifty = DateUtil.offsetMinute(new Date(), 35);
|
||||
Date nowPlusFifty = DateUtil.offsetMinute(new Date(), CommonConstant.MIN_DELAY_MINUTES_FOR_BOOKING_ORDER);
|
||||
|
||||
// 如果当前时间+50分钟在营业时间范围内,则从该时间开始
|
||||
if (nowPlusFifty.after(openTime) && nowPlusFifty.before(closeTime)) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user