预约订单槽点列表
This commit is contained in:
parent
9b5c618c40
commit
4ff892d09b
@ -0,0 +1,78 @@
|
|||||||
|
package com.suisung.mall.common.pojo.dto;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 预订参数DTO实体类
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
|
@ApiModel(value = "预约订单参数DTO", description = "预约订单参数DTO")
|
||||||
|
public class BookingArgDTO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日期标题(如"今天(周二)")
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "日期标题")
|
||||||
|
private String date_title;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日期字符串(如"01月09日")
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "日期字符串")
|
||||||
|
private String date_str;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日期(如"2025-01-09")
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "日期")
|
||||||
|
private String date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 时间项列表
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "时间项列表")
|
||||||
|
private List<BookingArgItem> items;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 预订时间项实体类
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public static class BookingArgItem {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 时间标题(如"立即送出"或"09:15-09:45")
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "时间标题")
|
||||||
|
private String time_title;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 预订时间戳
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "预订时间戳")
|
||||||
|
private Long booking_at;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 预订状态
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "预订状态:1-立即下单;2-预约下单;")
|
||||||
|
private Integer booking_state;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 预订开始时间
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "预订开始时间")
|
||||||
|
private String booking_begin_time;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 预订结束时间
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "预订结束时间")
|
||||||
|
private String booking_end_time;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -178,6 +178,23 @@ public class DateTimeUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据日期获取星期几
|
||||||
|
*
|
||||||
|
* @param date 日期
|
||||||
|
* @return 星期几
|
||||||
|
*/
|
||||||
|
public static String getWeekOfDate(Date date) {
|
||||||
|
String[] weekDays = {"周日", "周一", "周二", "周三", "周四", "周五", "周六"};
|
||||||
|
Calendar cal = Calendar.getInstance();
|
||||||
|
cal.setTime(date);
|
||||||
|
int w = cal.get(Calendar.DAY_OF_WEEK) - 1;
|
||||||
|
if (w < 0) {
|
||||||
|
w = 0;
|
||||||
|
}
|
||||||
|
return weekDays[w];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将多种日期格式转换为 yyyy-MM-dd
|
* 将多种日期格式转换为 yyyy-MM-dd
|
||||||
@ -473,6 +490,7 @@ public class DateTimeUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 判断时间字符串是否与格式模式匹配
|
* 判断时间字符串是否与格式模式匹配
|
||||||
*
|
*
|
||||||
|
|||||||
@ -12,6 +12,7 @@ import com.suisung.mall.common.api.StateCode;
|
|||||||
import com.suisung.mall.common.domain.UserDto;
|
import com.suisung.mall.common.domain.UserDto;
|
||||||
import com.suisung.mall.common.exception.ApiException;
|
import com.suisung.mall.common.exception.ApiException;
|
||||||
import com.suisung.mall.common.modules.order.*;
|
import com.suisung.mall.common.modules.order.*;
|
||||||
|
import com.suisung.mall.common.pojo.dto.BookingArgDTO;
|
||||||
import com.suisung.mall.common.service.impl.BaseControllerImpl;
|
import com.suisung.mall.common.service.impl.BaseControllerImpl;
|
||||||
import com.suisung.mall.common.utils.CheckUtil;
|
import com.suisung.mall.common.utils.CheckUtil;
|
||||||
import com.suisung.mall.shop.order.service.*;
|
import com.suisung.mall.shop.order.service.*;
|
||||||
@ -321,6 +322,13 @@ public class UserOrderController extends BaseControllerImpl {
|
|||||||
return CommonResult.success(data);
|
return CommonResult.success(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ApiOperation(value = "可预约订单的时间槽", notes = "可预约订单的时间槽")
|
||||||
|
@RequestMapping(value = "/booking_time_args", method = RequestMethod.GET)
|
||||||
|
public CommonResult listInvoice(@RequestParam(name = "store_id", defaultValue = "0") Integer store_id) {
|
||||||
|
List<BookingArgDTO> list = shopOrderInfoService.genBookingOrderArgList(store_id);
|
||||||
|
return CommonResult.success(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package com.suisung.mall.shop.order.service;
|
|||||||
|
|
||||||
import com.suisung.mall.common.api.CommonResult;
|
import com.suisung.mall.common.api.CommonResult;
|
||||||
import com.suisung.mall.common.modules.order.ShopOrderInfo;
|
import com.suisung.mall.common.modules.order.ShopOrderInfo;
|
||||||
|
import com.suisung.mall.common.pojo.dto.BookingArgDTO;
|
||||||
import com.suisung.mall.core.web.service.IBaseService;
|
import com.suisung.mall.core.web.service.IBaseService;
|
||||||
import org.springframework.data.util.Pair;
|
import org.springframework.data.util.Pair;
|
||||||
|
|
||||||
@ -133,4 +134,13 @@ public interface ShopOrderInfoService extends IBaseService<ShopOrderInfo> {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
Pair<Boolean, String> runBookingOrder2SfExpressOrder(String orderId);
|
Pair<Boolean, String> runBookingOrder2SfExpressOrder(String orderId);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据店铺的营业时间范围生成可预约下单的参数
|
||||||
|
*
|
||||||
|
* @param storeId 店铺ID
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
List<BookingArgDTO> genBookingOrderArgList(Integer storeId);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,6 +26,7 @@ import com.suisung.mall.common.modules.pay.PayPlantformResource;
|
|||||||
import com.suisung.mall.common.modules.plantform.ShopPlantformFeedback;
|
import com.suisung.mall.common.modules.plantform.ShopPlantformFeedback;
|
||||||
import com.suisung.mall.common.modules.product.ShopProductComment;
|
import com.suisung.mall.common.modules.product.ShopProductComment;
|
||||||
import com.suisung.mall.common.modules.store.ShopStoreInfo;
|
import com.suisung.mall.common.modules.store.ShopStoreInfo;
|
||||||
|
import com.suisung.mall.common.pojo.dto.BookingArgDTO;
|
||||||
import com.suisung.mall.common.pojo.res.ThirdApiRes;
|
import com.suisung.mall.common.pojo.res.ThirdApiRes;
|
||||||
import com.suisung.mall.common.utils.CheckUtil;
|
import com.suisung.mall.common.utils.CheckUtil;
|
||||||
import com.suisung.mall.common.utils.CommonUtil;
|
import com.suisung.mall.common.utils.CommonUtil;
|
||||||
@ -137,6 +138,7 @@ public class ShopOrderInfoServiceImpl extends BaseServiceImpl<ShopOrderInfoMappe
|
|||||||
@Autowired
|
@Autowired
|
||||||
private ThreadPoolExecutor executor;
|
private ThreadPoolExecutor executor;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map dashboard() {
|
public Map dashboard() {
|
||||||
|
|
||||||
@ -197,7 +199,6 @@ public class ShopOrderInfoServiceImpl extends BaseServiceImpl<ShopOrderInfoMappe
|
|||||||
return Convert.toList(String.class, findKey(queryWrapper));
|
return Convert.toList(String.class, findKey(queryWrapper));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取能自动确认收货的订单号
|
* 获取能自动确认收货的订单号
|
||||||
*
|
*
|
||||||
@ -826,7 +827,6 @@ public class ShopOrderInfoServiceImpl extends BaseServiceImpl<ShopOrderInfoMappe
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getAutoCancelOrderIdByPage(Integer pageNum, Integer pageSize) {
|
public List<String> getAutoCancelOrderIdByPage(Integer pageNum, Integer pageSize) {
|
||||||
QueryWrapper<ShopOrderInfo> queryWrapper = new QueryWrapper<>();
|
QueryWrapper<ShopOrderInfo> queryWrapper = new QueryWrapper<>();
|
||||||
@ -1014,5 +1014,201 @@ public class ShopOrderInfoServiceImpl extends BaseServiceImpl<ShopOrderInfoMappe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据店铺的营业时间范围生成可预约下单的参数
|
||||||
|
*
|
||||||
|
* @param storeId 店铺ID
|
||||||
|
* @return 预约参数列表
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<BookingArgDTO> genBookingOrderArgList(Integer storeId) {
|
||||||
|
// 初始化默认营业时间
|
||||||
|
String openingHours = "09:00";
|
||||||
|
String closeHours = "18:00";
|
||||||
|
|
||||||
|
// 如果storeId不为空,则尝试获取店铺信息
|
||||||
|
if (storeId != null) {
|
||||||
|
try {
|
||||||
|
ShopStoreInfo shopStoreInfo = shopStoreInfoService.getShopStoreInfoByStoreId(storeId);
|
||||||
|
if (shopStoreInfo != null) {
|
||||||
|
// 检查并使用店铺设置的营业时间
|
||||||
|
if (StrUtil.isNotBlank(shopStoreInfo.getStore_opening_hours())) {
|
||||||
|
openingHours = shopStoreInfo.getStore_opening_hours();
|
||||||
|
}
|
||||||
|
if (StrUtil.isNotBlank(shopStoreInfo.getStore_close_hours())) {
|
||||||
|
closeHours = shopStoreInfo.getStore_close_hours();
|
||||||
|
}
|
||||||
|
logger.debug("[生成预约参数] 使用店铺营业时间,storeId: {}, opening: {}, close: {}", storeId, openingHours, closeHours);
|
||||||
|
} else {
|
||||||
|
logger.warn("[生成预约参数] 未找到店铺信息,使用默认营业时间,storeId: {}", storeId);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("[生成预约参数] 获取店铺信息异常,使用默认营业时间,storeId: {}", storeId, e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logger.warn("[生成预约参数] 店铺ID为空,使用默认营业时间");
|
||||||
|
}
|
||||||
|
|
||||||
|
List<BookingArgDTO> result = new ArrayList<>();
|
||||||
|
|
||||||
|
// 生成未来7天的数据
|
||||||
|
Date now = new Date();
|
||||||
|
for (int i = 0; i < 7; i++) {
|
||||||
|
Date currentDate = DateUtil.offsetDay(now, i);
|
||||||
|
BookingArgDTO bookingArgDTO = new BookingArgDTO();
|
||||||
|
|
||||||
|
// 设置日期相关信息
|
||||||
|
String dateStr = DateUtil.format(currentDate, "yyyy-MM-dd");
|
||||||
|
String displayDateStr = DateUtil.format(currentDate, "MM月dd日");
|
||||||
|
|
||||||
|
// 安全获取星期信息
|
||||||
|
String weekStr = "未知";
|
||||||
|
try {
|
||||||
|
weekStr = DateTimeUtils.getWeekOfDate(currentDate);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.warn("[生成预约参数] 获取星期信息异常,使用默认值,date: {}", dateStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置date_title
|
||||||
|
if (i == 0) {
|
||||||
|
bookingArgDTO.setDate_title("今天(" + weekStr + ")");
|
||||||
|
} else if (i == 1) {
|
||||||
|
bookingArgDTO.setDate_title("明天(" + weekStr + ")");
|
||||||
|
} else {
|
||||||
|
bookingArgDTO.setDate_title(displayDateStr + "(" + weekStr + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
bookingArgDTO.setDate_str(displayDateStr);
|
||||||
|
bookingArgDTO.setDate(dateStr);
|
||||||
|
|
||||||
|
// 生成时间项
|
||||||
|
List<BookingArgDTO.BookingArgItem> items = generateTimeSlots(dateStr, openingHours, closeHours, i == 0);
|
||||||
|
bookingArgDTO.setItems(items != null ? items : new ArrayList<>());
|
||||||
|
|
||||||
|
result.add(bookingArgDTO);
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.debug("[生成预约参数] 成功生成预约参数,storeId: {}, opening: {}, close: {}, 参数数量: {}",
|
||||||
|
storeId, openingHours, closeHours, result.size());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成时间槽列表
|
||||||
|
*
|
||||||
|
* @param dateStr 日期字符串 yyyy-MM-dd
|
||||||
|
* @param openingHours 开始营业时间 HH:mm
|
||||||
|
* @param closeHours 结束营业时间 HH:mm
|
||||||
|
* @param isToday 是否是今天
|
||||||
|
* @return 时间槽列表
|
||||||
|
*/
|
||||||
|
private List<BookingArgDTO.BookingArgItem> generateTimeSlots(String dateStr, String openingHours, String closeHours, boolean isToday) {
|
||||||
|
// 参数校验
|
||||||
|
if (StrUtil.isBlank(dateStr) || StrUtil.isBlank(openingHours) || StrUtil.isBlank(closeHours)) {
|
||||||
|
logger.warn("[生成时间槽] 参数为空,dateStr: {}, openingHours: {}, closeHours: {}", dateStr, openingHours, closeHours);
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
List<BookingArgDTO.BookingArgItem> items = new ArrayList<>();
|
||||||
|
|
||||||
|
// 添加"立即送出"选项(仅限今天)
|
||||||
|
if (isToday) {
|
||||||
|
BookingArgDTO.BookingArgItem immediateItem = new BookingArgDTO.BookingArgItem();
|
||||||
|
immediateItem.setTime_title("立即送出");
|
||||||
|
immediateItem.setBooking_at(0L);
|
||||||
|
immediateItem.setBooking_state(1);
|
||||||
|
immediateItem.setBooking_begin_time("");
|
||||||
|
immediateItem.setBooking_end_time("");
|
||||||
|
items.add(immediateItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析营业时间
|
||||||
|
Date openTime = DateUtil.parse(dateStr + " " + openingHours + ":00", "yyyy-MM-dd HH:mm:ss");
|
||||||
|
Date closeTime = DateUtil.parse(dateStr + " " + closeHours + ":00", "yyyy-MM-dd HH:mm:ss");
|
||||||
|
|
||||||
|
// 如果结束时间早于开始时间,说明跨天了,需要调整到第二天
|
||||||
|
if (closeTime.before(openTime)) {
|
||||||
|
closeTime = DateUtil.offsetDay(closeTime, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证营业时间有效性
|
||||||
|
if (openTime.after(closeTime)) {
|
||||||
|
logger.warn("[生成时间槽] 营业时间无效,openTime: {}, closeTime: {}", openTime, closeTime);
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 对于今天,需要特殊处理:从当前时间+5分钟开始生成时间槽
|
||||||
|
Date startTime = openTime;
|
||||||
|
if (isToday) {
|
||||||
|
// 当前时间+5分钟作为第二个时间槽的开始时间
|
||||||
|
Date nowPlusFive = DateUtil.offsetMinute(new Date(), 5);
|
||||||
|
// 如果当前时间+5分钟在营业时间范围内,则从该时间开始
|
||||||
|
if (nowPlusFive.after(openTime) && nowPlusFive.before(closeTime)) {
|
||||||
|
startTime = nowPlusFive;
|
||||||
|
}
|
||||||
|
// 如果当前时间+5分钟已经超过营业结束时间,则不生成后续时间槽
|
||||||
|
else if (nowPlusFive.after(closeTime)) {
|
||||||
|
logger.debug("[生成时间槽] 当前时间+5分钟已超过营业结束时间,不生成后续时间槽");
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成30分钟间隔的时间段
|
||||||
|
Date currentTimeSlot = startTime;
|
||||||
|
int slotCount = 0;
|
||||||
|
final int MAX_SLOTS = 48; // 最多生成48个时间段,防止异常循环
|
||||||
|
|
||||||
|
while (currentTimeSlot.before(closeTime) && slotCount < MAX_SLOTS) {
|
||||||
|
Date endTimeSlot = DateUtil.offsetMinute(currentTimeSlot, 30);
|
||||||
|
|
||||||
|
// 如果结束时间超过了营业结束时间,则使用营业结束时间
|
||||||
|
if (endTimeSlot.after(closeTime)) {
|
||||||
|
endTimeSlot = closeTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建时间段项(跳过"立即送出"项,因为已经添加过了)
|
||||||
|
if (!(isToday && slotCount == 0 && items.size() > 0 && "立即送出".equals(items.get(0).getTime_title()))) {
|
||||||
|
BookingArgDTO.BookingArgItem timeItem = new BookingArgDTO.BookingArgItem();
|
||||||
|
String beginTimeStr = DateUtil.format(currentTimeSlot, "HH:mm");
|
||||||
|
String endTimeStr = DateUtil.format(endTimeSlot, "HH:mm");
|
||||||
|
|
||||||
|
timeItem.setTime_title(beginTimeStr + "-" + endTimeStr);
|
||||||
|
|
||||||
|
// 修正时间戳计算
|
||||||
|
long bookingAt = currentTimeSlot.getTime() / 1000;
|
||||||
|
timeItem.setBooking_at(bookingAt);
|
||||||
|
|
||||||
|
timeItem.setBooking_state(2);
|
||||||
|
timeItem.setBooking_begin_time(DateUtil.format(currentTimeSlot, "yyyy-MM-dd HH:mm:ss"));
|
||||||
|
timeItem.setBooking_end_time(DateUtil.format(DateUtil.offsetMinute(currentTimeSlot, 40), "yyyy-MM-dd HH:mm:ss"));
|
||||||
|
|
||||||
|
items.add(timeItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 移动到下一个时间段
|
||||||
|
currentTimeSlot = endTimeSlot;
|
||||||
|
slotCount++;
|
||||||
|
|
||||||
|
// 防止时间相同导致的死循环
|
||||||
|
if (currentTimeSlot.equals(startTime)) {
|
||||||
|
logger.warn("[生成时间槽] 检测到时间循环,跳出循环");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (slotCount >= MAX_SLOTS) {
|
||||||
|
logger.warn("[生成时间槽] 时间段数量超过最大限制,date: {}", dateStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.debug("[生成时间槽] 成功生成时间槽,date: {}, 时间段数量: {}", dateStr, items.size());
|
||||||
|
return items;
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("[生成时间槽] 生成时间槽异常,date: {}, openingHours: {}, closeHours: {}", dateStr, openingHours, closeHours, e);
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user