砍价活动 时间槽 修正新需求。 增加必要的字段
This commit is contained in:
parent
0c15b2c034
commit
38b674e05a
@ -56,6 +56,9 @@ public class ShopActivityCutprice implements Serializable {
|
|||||||
@ApiModelProperty(value = "砍价人数")
|
@ApiModelProperty(value = "砍价人数")
|
||||||
private Integer ac_num;
|
private Integer ac_num;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "砍价过期时间戳")
|
||||||
|
private Long expired_at;
|
||||||
|
|
||||||
@Version
|
@Version
|
||||||
@ApiModelProperty(value = "乐观锁")
|
@ApiModelProperty(value = "乐观锁")
|
||||||
private Integer version;
|
private Integer version;
|
||||||
|
|||||||
@ -127,4 +127,12 @@ public class ShopStoreActivityBase implements Serializable {
|
|||||||
@TableField(updateStrategy = NOT_EMPTY)
|
@TableField(updateStrategy = NOT_EMPTY)
|
||||||
private String flow_no;
|
private String flow_no;
|
||||||
|
|
||||||
|
@Version
|
||||||
|
@ApiModelProperty(value = "在活动时间范围内,用户砍价允许的天数")
|
||||||
|
private Integer cut_days;
|
||||||
|
|
||||||
|
@Version
|
||||||
|
@ApiModelProperty(value = "活动商品的总数量")
|
||||||
|
private Integer product_cont;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -439,15 +439,15 @@ public class DateTimeUtils {
|
|||||||
* @param startTimeStr 开始时间字符串,支持格式如 HH:mm, HH:mm:ss, HH:mm:ss.SSS 等
|
* @param startTimeStr 开始时间字符串,支持格式如 HH:mm, HH:mm:ss, HH:mm:ss.SSS 等
|
||||||
* @param endTimeStr 结束时间字符串,支持格式如 HH:mm, HH:mm:ss, HH:mm:ss.SSS 等
|
* @param endTimeStr 结束时间字符串,支持格式如 HH:mm, HH:mm:ss, HH:mm:ss.SSS 等
|
||||||
* @param currentTime 要判断的时间点
|
* @param currentTime 要判断的时间点
|
||||||
* @return 如果在时间段内返回true,否则返回false。出现异常时返回false,不影响主流程
|
* @return 返回值: -1-在时间段之前 0-时间段内,1-在时间段之后
|
||||||
*/
|
*/
|
||||||
public static boolean isTimeInRange(String startTimeStr, String endTimeStr, LocalDateTime currentTime) {
|
public static int isTimeInRange(String startTimeStr, String endTimeStr, LocalDateTime currentTime) {
|
||||||
try {
|
try {
|
||||||
// 参数校验
|
// 参数校验
|
||||||
if (startTimeStr == null || endTimeStr == null || currentTime == null) {
|
if (startTimeStr == null || endTimeStr == null || currentTime == null) {
|
||||||
log.warn("时间参数不能为空,startTimeStr: {}, endTimeStr: {}, currentTime: {}",
|
log.warn("时间参数不能为空,startTimeStr: {}, endTimeStr: {}, currentTime: {}",
|
||||||
startTimeStr, endTimeStr, currentTime);
|
startTimeStr, endTimeStr, currentTime);
|
||||||
return false;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 解析开始时间 - 支持多种时间格式
|
// 解析开始时间 - 支持多种时间格式
|
||||||
@ -459,37 +459,53 @@ public class DateTimeUtils {
|
|||||||
// 获取当前时间的时间部分
|
// 获取当前时间的时间部分
|
||||||
LocalTime nowTime = currentTime.toLocalTime();
|
LocalTime nowTime = currentTime.toLocalTime();
|
||||||
|
|
||||||
|
// 处理开始时间等于结束时间的情况
|
||||||
|
if (startTime.equals(endTime)) {
|
||||||
|
return nowTime.equals(startTime) ? 0 : -1; // 精确匹配为时间段内,否则为时间段前
|
||||||
|
}
|
||||||
|
|
||||||
// 处理跨天情况,例如 22:00 - 06:00
|
// 处理跨天情况,例如 22:00 - 06:00
|
||||||
if (endTime.isBefore(startTime)) {
|
if (endTime.isBefore(startTime)) {
|
||||||
// 如果结束时间小于开始时间,说明跨越了午夜
|
// 如果结束时间小于开始时间,说明跨越了午夜
|
||||||
// 当前时间需要满足:大于等于开始时间 或者 小于等于结束时间
|
// 跨天时间段: [startTime, 24:00) ∪ [00:00, endTime]
|
||||||
return !nowTime.isBefore(startTime) || !nowTime.isAfter(endTime);
|
if (!nowTime.isBefore(startTime) || !nowTime.isAfter(endTime)) {
|
||||||
|
return 0; // 时间段内
|
||||||
|
} else {
|
||||||
|
// 对于跨天情况,不在时间段内的唯一可能就是"时间段前"
|
||||||
|
// 因为跨天时间段覆盖了从startTime到endTime经过午夜的整个区间
|
||||||
|
return -1; // 时间段前
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// 正常情况(不跨天),当前时间需要在开始时间和结束时间之间(包含边界)
|
// 正常情况(不跨天),当前时间需要在开始时间和结束时间之间(包含边界)
|
||||||
return !nowTime.isBefore(startTime) && !nowTime.isAfter(endTime);
|
if (nowTime.isBefore(startTime)) {
|
||||||
|
return -1; // 时间段前
|
||||||
|
} else if (nowTime.isAfter(endTime)) {
|
||||||
|
return 1; // 时间段后
|
||||||
|
} else {
|
||||||
|
return 0; // 时间段内
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// 捕获解析异常,记录日志并返回false,避免影响主流程
|
// 捕获解析异常,记录日志并返回false,避免影响主流程
|
||||||
log.error("判断时间是否在范围内时发生异常,startTimeStr: {}, endTimeStr: {}, currentTime: {}",
|
log.error("判断时间是否在范围内时发生异常,startTimeStr: {}, endTimeStr: {}, currentTime: {}",
|
||||||
startTimeStr, endTimeStr, currentTime, e);
|
startTimeStr, endTimeStr, currentTime, e);
|
||||||
return false;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 判断指定时间是否在两个时间点之间(包含边界)
|
* 判断指定时间是否在两个时间点之间(包含边界)
|
||||||
*
|
*
|
||||||
* @param startTimeStr 开始时间字符串,支持格式如 HH:mm, HH:mm:ss, HH:mm:ss.SSS 等
|
* @param startTimeStr 开始时间字符串,支持格式如 HH:mm, HH:mm:ss, HH:mm:ss.SSS 等
|
||||||
* @param endTimeStr 结束时间字符串,支持格式如 HH:mm, HH:mm:ss, HH:mm:ss.SSS 等
|
* @param endTimeStr 结束时间字符串,支持格式如 HH:mm, HH:mm:ss, HH:mm:ss.SSS 等
|
||||||
* @param currentTime 要判断的时间点
|
* @param currentTime 要判断的时间点
|
||||||
* @return 如果在时间段内返回true,否则返回false。出现异常时返回false,不影响主流程
|
* @return 返回值: -1-在时间段之前 0-时间段内,1-在时间段之后
|
||||||
*/
|
*/
|
||||||
public static boolean isTimeInRange(String startTimeStr, String endTimeStr, Date currentTime) {
|
public static int isTimeInRange(String startTimeStr, String endTimeStr, Date currentTime) {
|
||||||
if (currentTime == null) {
|
if (currentTime == null) {
|
||||||
log.warn("时间参数不能为空,startTimeStr: {}, endTimeStr: {}, currentTime: null",
|
log.warn("时间参数不能为空,startTimeStr: {}, endTimeStr: {}, currentTime: null",
|
||||||
startTimeStr, endTimeStr);
|
startTimeStr, endTimeStr);
|
||||||
return false;
|
return -1;
|
||||||
}
|
}
|
||||||
// 将Date转换为LocalDateTime并调用已有的方法
|
// 将Date转换为LocalDateTime并调用已有的方法
|
||||||
LocalDateTime localDateTime = currentTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
|
LocalDateTime localDateTime = currentTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
|
||||||
@ -501,9 +517,9 @@ public class DateTimeUtils {
|
|||||||
*
|
*
|
||||||
* @param startTimeStr 开始时间字符串,支持格式如 HH:mm, HH:mm:ss, HH:mm:ss.SSS 等
|
* @param startTimeStr 开始时间字符串,支持格式如 HH:mm, HH:mm:ss, HH:mm:ss.SSS 等
|
||||||
* @param endTimeStr 结束时间字符串,支持格式如 HH:mm, HH:mm:ss, HH:mm:ss.SSS 等
|
* @param endTimeStr 结束时间字符串,支持格式如 HH:mm, HH:mm:ss, HH:mm:ss.SSS 等
|
||||||
* @return 如果在时间段内返回true,否则返回false
|
* @return 返回值: -1-在时间段之前 0-时间段内,1-在时间段之后
|
||||||
*/
|
*/
|
||||||
public static boolean isCurrentTimeInRange(String startTimeStr, String endTimeStr) {
|
public static int isCurrentTimeInRange(String startTimeStr, String endTimeStr) {
|
||||||
return isTimeInRange(startTimeStr, endTimeStr, LocalDateTime.now());
|
return isTimeInRange(startTimeStr, endTimeStr, LocalDateTime.now());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -902,7 +902,7 @@ public class ShopOrderInfoServiceImpl extends BaseServiceImpl<ShopOrderInfoMappe
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 6. 店铺营业时间检查
|
// 6. 店铺营业时间检查
|
||||||
if (!DateTimeUtils.isTimeInRange(shopStoreInfo.getStore_opening_hours(), shopStoreInfo.getStore_close_hours(), bookingBeginTime)) {
|
if (DateTimeUtils.isTimeInRange(shopStoreInfo.getStore_opening_hours(), shopStoreInfo.getStore_close_hours(), bookingBeginTime) != 0) {
|
||||||
String message = StrUtil.format("[预约单校验] 请在 {}-{} 店铺营业时间内预约下单", shopStoreInfo.getStore_opening_hours(), shopStoreInfo.getStore_close_hours());
|
String message = StrUtil.format("[预约单校验] 请在 {}-{} 店铺营业时间内预约下单", shopStoreInfo.getStore_opening_hours(), shopStoreInfo.getStore_close_hours());
|
||||||
return Pair.of(false, message);
|
return Pair.of(false, message);
|
||||||
}
|
}
|
||||||
@ -1035,79 +1035,149 @@ public class ShopOrderInfoServiceImpl extends BaseServiceImpl<ShopOrderInfoMappe
|
|||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 显示几天的时间槽,默认7天
|
// 显示几天的时间槽,默认7天
|
||||||
int daysCnt = 7;
|
int daysCnt = 7;
|
||||||
|
|
||||||
List<BookingArgDTO> result = new ArrayList<>();
|
List<BookingArgDTO> result = new ArrayList<>();
|
||||||
|
|
||||||
// 判断今天还能不能立即下单和预约下单?能:就有今天的时间槽;不能:就没有今天的时间槽
|
// 判断今天还能不能立即下单和预约下单?能:就有今天的时间槽;不能:就没有今天的时间槽
|
||||||
boolean canBookingToday = DateTimeUtils.isTimeInRange(timesPair.getFirst(), timesPair.getSecond(), new Date());
|
//-1-在时间段之前 0-时间段内,1-在时间段之后
|
||||||
|
int inRangeVal = DateTimeUtils.isCurrentTimeInRange(timesPair.getFirst(), timesPair.getSecond());
|
||||||
|
|
||||||
// 生成7天的可预约时间槽数据
|
// 确定起始日期
|
||||||
Date startDate = new Date();
|
Date startDate = inRangeVal == 1 ? DateUtil.offsetDay(new Date(), 1) : new Date();
|
||||||
if (!canBookingToday) {
|
boolean isTodayAvailable = inRangeVal <= 0; // 今天是否可预约(在营业时间之前或之中)
|
||||||
// 如果今天不能下单和预约,则从明天开始生成时间槽
|
|
||||||
startDate = DateUtil.offsetDay(new Date(), 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < daysCnt; i++) {
|
for (int i = 0; i < daysCnt; i++) {
|
||||||
startDate = DateUtil.offsetDay(startDate, i);
|
Date currentDate = DateUtil.offsetDay(startDate, i);
|
||||||
BookingArgDTO bookingArgDTO = new BookingArgDTO();
|
BookingArgDTO bookingArgDTO = new BookingArgDTO();
|
||||||
|
|
||||||
// 设置日期相关信息
|
// 设置日期相关信息
|
||||||
String dateStr = DateUtil.format(startDate, "yyyy-MM-dd");
|
String dateStr = DateUtil.format(currentDate, "yyyy-MM-dd");
|
||||||
String displayDateStr = DateUtil.format(startDate, "MM月dd日");
|
String displayDateStr = DateUtil.format(currentDate, "MM月dd日");
|
||||||
|
|
||||||
// 安全获取星期信息
|
// 安全获取星期信息
|
||||||
String weekStr = "星期";
|
String weekStr = "星期";
|
||||||
try {
|
try {
|
||||||
weekStr = DateTimeUtils.getWeekOfDate(startDate);
|
weekStr = DateTimeUtils.getWeekOfDate(currentDate);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.warn("[生成预约参数] 获取星期信息异常,使用默认值,date: {}", dateStr);
|
logger.warn("[生成预约参数] 获取星期信息异常,使用默认值,date: {}", dateStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 设置date_title - 优化后的代码
|
// 设置date_title
|
||||||
String dateTitle;
|
String dateTitle;
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
dateTitle = canBookingToday ? "今天" : "明天";
|
dateTitle = isTodayAvailable ? "今天" : "明天";
|
||||||
} else if (i == 1) {
|
} else if (i == 1) {
|
||||||
dateTitle = canBookingToday ? "明天" : "后天";
|
dateTitle = isTodayAvailable ? "后天" : "明天";
|
||||||
} else {
|
} else {
|
||||||
dateTitle = displayDateStr;
|
dateTitle = displayDateStr;
|
||||||
}
|
}
|
||||||
bookingArgDTO.setDate_title(dateTitle + "(" + weekStr + ")");
|
|
||||||
|
|
||||||
|
bookingArgDTO.setDate_title(dateTitle + "(" + weekStr + ")");
|
||||||
bookingArgDTO.setDate_str(displayDateStr);
|
bookingArgDTO.setDate_str(displayDateStr);
|
||||||
bookingArgDTO.setDate(dateStr);
|
bookingArgDTO.setDate(dateStr);
|
||||||
|
|
||||||
// 生成时间项
|
|
||||||
// List<BookingArgDTO.BookingArgItem> items = new ArrayList<>();
|
|
||||||
|
|
||||||
// 如果是今天且在配送时间内,添加"立即送出"选项
|
|
||||||
// if (i == 0 && canBookingToday) {
|
|
||||||
// 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);
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
String startTimeStr = timesPair.getFirst();
|
String startTimeStr = timesPair.getFirst();
|
||||||
String endTimeStr = timesPair.getSecond();
|
String endTimeStr = timesPair.getSecond();
|
||||||
boolean isToday = i == 0 && canBookingToday;
|
|
||||||
// 生成时间项
|
|
||||||
List<BookingArgDTO.BookingArgItem> items = generateTimeSlots(dateStr, startTimeStr, endTimeStr, isToday);
|
|
||||||
// if (i == 0 && canBookingToday) {
|
|
||||||
// items.addAll(timeSlots.stream().filter(item -> item.getBooking_state() != 1).collect(Collectors.toList()));
|
|
||||||
// } else {
|
|
||||||
// items.addAll(timeSlots);
|
|
||||||
// }
|
|
||||||
|
|
||||||
bookingArgDTO.setWorking_hours(String.format("%s-%s", startTimeStr, endTimeStr));
|
bookingArgDTO.setWorking_hours(String.format("%s-%s", startTimeStr, endTimeStr));
|
||||||
|
|
||||||
|
// 生成时间槽
|
||||||
|
List<BookingArgDTO.BookingArgItem> items = new ArrayList<>();
|
||||||
|
|
||||||
|
// 参数校验
|
||||||
|
if (StrUtil.isNotBlank(dateStr) && StrUtil.isNotBlank(startTimeStr) && StrUtil.isNotBlank(endTimeStr)) {
|
||||||
|
try {
|
||||||
|
// 解析营业时间
|
||||||
|
Date openTime = DateUtil.parse(dateStr + " " + startTimeStr + ":00", "yyyy-MM-dd HH:mm:ss");
|
||||||
|
Date closeTime = DateUtil.parse(dateStr + " " + endTimeStr + ":00", "yyyy-MM-dd HH:mm:ss");
|
||||||
|
|
||||||
|
// 验证营业时间有效性
|
||||||
|
if (!openTime.after(closeTime)) {
|
||||||
|
// 在营业时间段内,且是今天,添加"立即送出"选项
|
||||||
|
if (i == 0 && isTodayAvailable && inRangeVal == 0) {
|
||||||
|
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 startTime = openTime;
|
||||||
|
if (i == 0 && isTodayAvailable && inRangeVal <= 0) {
|
||||||
|
// 当前时间+50分钟作为时间槽的开始时间
|
||||||
|
Date nowPlusFifty = DateUtil.offsetMinute(new Date(), CommonConstant.MIN_DELAY_MINUTES_FOR_BOOKING_ORDER);
|
||||||
|
|
||||||
|
// 确保开始时间在营业时间范围内
|
||||||
|
if (nowPlusFifty.after(openTime)) {
|
||||||
|
if (nowPlusFifty.before(closeTime)) {
|
||||||
|
// 如果当前时间+50分钟在营业时间范围内,则从该时间开始
|
||||||
|
startTime = nowPlusFifty;
|
||||||
|
logger.debug("[生成时间槽] 当前时间+50分钟在营业时间范围内,则从该时间开始");
|
||||||
|
} else {
|
||||||
|
// 如果当前时间+50分钟已经超过营业结束时间,则不生成后续时间槽
|
||||||
|
logger.debug("[生成时间槽] 当前时间+50分钟已超过营业结束时间,不生成后续时间槽");
|
||||||
|
startTime = null; // 标记为不生成时间槽
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成时间槽
|
||||||
|
if (startTime != null) {
|
||||||
|
Date currentTimeSlot = startTime;
|
||||||
|
int slotCount = 0;
|
||||||
|
final int MAX_SLOTS = 96; // 最多生成96个时间段,防止异常循环
|
||||||
|
|
||||||
|
while (currentTimeSlot.before(closeTime) && slotCount < MAX_SLOTS) {
|
||||||
|
Date endTimeSlot = DateUtil.offsetMinute(currentTimeSlot, 15);
|
||||||
|
|
||||||
|
// 如果结束时间超过了营业结束时间,则使用营业结束时间
|
||||||
|
if (endTimeSlot.after(closeTime)) {
|
||||||
|
endTimeSlot = closeTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建时间段项
|
||||||
|
BookingArgDTO.BookingArgItem timeItem = new BookingArgDTO.BookingArgItem();
|
||||||
|
String beginTimeStr = DateUtil.format(currentTimeSlot, "HH:mm");
|
||||||
|
String endTimeStrItem = DateUtil.format(endTimeSlot, "HH:mm");
|
||||||
|
|
||||||
|
timeItem.setTime_title(beginTimeStr + "-" + endTimeStrItem);
|
||||||
|
|
||||||
|
// 时间戳计算(秒)
|
||||||
|
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(endTimeSlot, "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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logger.warn("[生成时间槽] 营业时间无效,openTime: {}, closeTime: {}", openTime, closeTime);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("[生成时间槽] 生成时间槽异常,date: {}, openingHours: {}, closeHours: {}", dateStr, startTimeStr, endTimeStr, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bookingArgDTO.setItems(items);
|
bookingArgDTO.setItems(items);
|
||||||
result.add(bookingArgDTO);
|
result.add(bookingArgDTO);
|
||||||
}
|
}
|
||||||
@ -1118,119 +1188,6 @@ public class ShopOrderInfoServiceImpl extends BaseServiceImpl<ShopOrderInfoMappe
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 生成时间槽列表
|
|
||||||
*
|
|
||||||
* @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 (openTime.after(closeTime)) {
|
|
||||||
logger.warn("[生成时间槽] 营业时间无效,openTime: {}, closeTime: {}", openTime, closeTime);
|
|
||||||
return items;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 时间槽间隔(分钟)
|
|
||||||
int slotInterval = 15;
|
|
||||||
|
|
||||||
// 对于今天,需要特殊处理:第二个时间槽从当前时间+50分钟开始
|
|
||||||
Date startTime = openTime;
|
|
||||||
if (isToday) {
|
|
||||||
// 当前时间+50分钟作为第二个时间槽的开始时间
|
|
||||||
Date nowPlusFifty = DateUtil.offsetMinute(new Date(), CommonConstant.MIN_DELAY_MINUTES_FOR_BOOKING_ORDER);
|
|
||||||
|
|
||||||
// 如果当前时间+50分钟在营业时间范围内,则从该时间开始
|
|
||||||
if (nowPlusFifty.after(openTime) && nowPlusFifty.before(closeTime)) {
|
|
||||||
startTime = nowPlusFifty;
|
|
||||||
}
|
|
||||||
// 如果当前时间+50分钟已经超过营业结束时间,则不生成后续时间槽
|
|
||||||
else if (nowPlusFifty.after(closeTime)) {
|
|
||||||
logger.debug("[生成时间槽] 当前时间+50分钟已超过营业结束时间,不生成后续时间槽");
|
|
||||||
return items;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 生成时间槽
|
|
||||||
Date currentTimeSlot = startTime;
|
|
||||||
int slotCount = 0;
|
|
||||||
final int MAX_SLOTS = 48; // 最多生成48个时间段,防止异常循环
|
|
||||||
|
|
||||||
while (currentTimeSlot.before(closeTime) && slotCount < MAX_SLOTS) {
|
|
||||||
Date endTimeSlot = DateUtil.offsetMinute(currentTimeSlot, slotInterval);
|
|
||||||
|
|
||||||
// 如果结束时间超过了营业结束时间,则使用营业结束时间
|
|
||||||
if (endTimeSlot.after(closeTime)) {
|
|
||||||
endTimeSlot = closeTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建时间段项
|
|
||||||
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(endTimeSlot, "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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据 storeIds(一个或多个 storeid,如 34,23,43,23,),先对id去重,
|
* 根据 storeIds(一个或多个 storeid,如 34,23,43,23,),先对id去重,
|
||||||
* 再获取多个店铺的营业时间 List<map{startTimeStr, endTimeStr}> 列表list
|
* 再获取多个店铺的营业时间 List<map{startTimeStr, endTimeStr}> 列表list
|
||||||
|
|||||||
@ -4217,7 +4217,7 @@ public class ShopStoreBaseServiceImpl extends BaseServiceImpl<ShopStoreBaseMappe
|
|||||||
// 检查店铺是否营业中且营业时间已设置
|
// 检查店铺是否营业中且营业时间已设置
|
||||||
if (CommonConstant.Enable.equals(storeBizState) && !StrUtil.hasBlank(openingHours, closingHours)) {
|
if (CommonConstant.Enable.equals(storeBizState) && !StrUtil.hasBlank(openingHours, closingHours)) {
|
||||||
// 检查当前时间是否在营业时间内
|
// 检查当前时间是否在营业时间内
|
||||||
if (!DateTimeUtils.isCurrentTimeInRange(openingHours, closingHours)) {
|
if (DateTimeUtils.isCurrentTimeInRange(openingHours, closingHours) != 0) {
|
||||||
// 不在营业时间内,返回已打烊状态
|
// 不在营业时间内,返回已打烊状态
|
||||||
return CommonConstant.Disable2;
|
return CommonConstant.Disable2;
|
||||||
}
|
}
|
||||||
@ -4265,7 +4265,7 @@ public class ShopStoreBaseServiceImpl extends BaseServiceImpl<ShopStoreBaseMappe
|
|||||||
&& StrUtil.isNotBlank(openingHours)
|
&& StrUtil.isNotBlank(openingHours)
|
||||||
&& StrUtil.isNotBlank(closingHours)) {
|
&& StrUtil.isNotBlank(closingHours)) {
|
||||||
// 检查当前时间是否在营业时间内
|
// 检查当前时间是否在营业时间内
|
||||||
if (!DateTimeUtils.isCurrentTimeInRange(openingHours, closingHours)) {
|
if (DateTimeUtils.isCurrentTimeInRange(openingHours, closingHours) != 0) {
|
||||||
// 不在营业时间内,返回已打烊状态
|
// 不在营业时间内,返回已打烊状态
|
||||||
log.debug("店铺当前不在营业时间内,storeId: {}, openingHours: {}, closingHours: {}",
|
log.debug("店铺当前不在营业时间内,storeId: {}, openingHours: {}, closingHours: {}",
|
||||||
storeId, openingHours, closingHours);
|
storeId, openingHours, closingHours);
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
<!-- 通用查询结果列 -->
|
<!-- 通用查询结果列 -->
|
||||||
<sql id="Base_Column_List">
|
<sql id="Base_Column_List">
|
||||||
ac_id, activity_id, user_id, ac_sale_price, ac_datetime, order_id, ac_mix_limit_price, ac_num
|
ac_id, activity_id, user_id, ac_sale_price, ac_datetime, order_id, ac_mix_limit_price, ac_num, expired_at, version
|
||||||
</sql>
|
</sql>
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|||||||
@ -6,7 +6,8 @@
|
|||||||
<sql id="Base_Column_List">
|
<sql id="Base_Column_List">
|
||||||
activity_id, store_id, user_id, activity_name, activity_title, activity_remark, activity_combo_id,
|
activity_id, store_id, user_id, activity_name, activity_title, activity_remark, activity_combo_id,
|
||||||
activity_type_id, activity_starttime, activity_endtime, activity_state, activity_rule, activity_type,
|
activity_type_id, activity_starttime, activity_endtime, activity_state, activity_rule, activity_type,
|
||||||
activity_order, activity_is_finish, item_id, subsite_id
|
activity_order, activity_is_finish, item_id, subsite_id,activity_use_level, activity_releasetime,
|
||||||
|
activity_on_is_off, activity_share_num, version, flow_no, cut_days, product_cont
|
||||||
</sql>
|
</sql>
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user