|
@@ -13,10 +13,12 @@ import org.springframework.util.StringUtils;
|
|
|
import shop.alien.entity.store.EssentialHolidayComparison;
|
|
import shop.alien.entity.store.EssentialHolidayComparison;
|
|
|
import shop.alien.entity.store.StoreBookingBusinessHours;
|
|
import shop.alien.entity.store.StoreBookingBusinessHours;
|
|
|
import shop.alien.entity.store.StoreBookingSettings;
|
|
import shop.alien.entity.store.StoreBookingSettings;
|
|
|
|
|
+import shop.alien.entity.store.StoreBusinessInfo;
|
|
|
import shop.alien.entity.store.dto.StoreBookingBusinessHoursDTO;
|
|
import shop.alien.entity.store.dto.StoreBookingBusinessHoursDTO;
|
|
|
import shop.alien.entity.store.dto.StoreBookingSettingsDTO;
|
|
import shop.alien.entity.store.dto.StoreBookingSettingsDTO;
|
|
|
import shop.alien.mapper.EssentialHolidayComparisonMapper;
|
|
import shop.alien.mapper.EssentialHolidayComparisonMapper;
|
|
|
import shop.alien.mapper.StoreBookingSettingsMapper;
|
|
import shop.alien.mapper.StoreBookingSettingsMapper;
|
|
|
|
|
+import shop.alien.mapper.StoreBusinessInfoMapper;
|
|
|
import shop.alien.store.service.StoreBookingBusinessHoursService;
|
|
import shop.alien.store.service.StoreBookingBusinessHoursService;
|
|
|
import shop.alien.store.service.StoreBookingSettingsService;
|
|
import shop.alien.store.service.StoreBookingSettingsService;
|
|
|
import shop.alien.util.common.JwtUtil;
|
|
import shop.alien.util.common.JwtUtil;
|
|
@@ -40,6 +42,7 @@ public class StoreBookingSettingsServiceImpl extends ServiceImpl<StoreBookingSet
|
|
|
|
|
|
|
|
private final StoreBookingBusinessHoursService storeBookingBusinessHoursService;
|
|
private final StoreBookingBusinessHoursService storeBookingBusinessHoursService;
|
|
|
private final EssentialHolidayComparisonMapper essentialHolidayComparisonMapper;
|
|
private final EssentialHolidayComparisonMapper essentialHolidayComparisonMapper;
|
|
|
|
|
+ private final StoreBusinessInfoMapper storeBusinessInfoMapper;
|
|
|
|
|
|
|
|
// 时间格式正则:HH:mm
|
|
// 时间格式正则:HH:mm
|
|
|
private static final Pattern TIME_PATTERN = Pattern.compile("^([0-1][0-9]|2[0-3]):[0-5][0-9]$");
|
|
private static final Pattern TIME_PATTERN = Pattern.compile("^([0-1][0-9]|2[0-3]):[0-5][0-9]$");
|
|
@@ -225,12 +228,18 @@ public class StoreBookingSettingsServiceImpl extends ServiceImpl<StoreBookingSet
|
|
|
|
|
|
|
|
// 3.1 处理正常营业时间(business_type=1)
|
|
// 3.1 处理正常营业时间(business_type=1)
|
|
|
if (dto.getNormalBusinessHours() != null) {
|
|
if (dto.getNormalBusinessHours() != null) {
|
|
|
|
|
+ // 校验正常营业时间:预约时间的正常时间不能大于门店营业时间的正常时间
|
|
|
|
|
+ validateNormalBusinessHours(dto.getStoreId(), dto.getNormalBusinessHours());
|
|
|
|
|
+
|
|
|
StoreBookingBusinessHours normalHours = convertToBusinessHours(dto.getNormalBusinessHours(), settingsId, 1);
|
|
StoreBookingBusinessHours normalHours = convertToBusinessHours(dto.getNormalBusinessHours(), settingsId, 1);
|
|
|
businessHoursList.add(normalHours);
|
|
businessHoursList.add(normalHours);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 3.2 处理特殊营业时间列表(business_type=2)
|
|
// 3.2 处理特殊营业时间列表(business_type=2)
|
|
|
if (dto.getSpecialBusinessHoursList() != null && !dto.getSpecialBusinessHoursList().isEmpty()) {
|
|
if (dto.getSpecialBusinessHoursList() != null && !dto.getSpecialBusinessHoursList().isEmpty()) {
|
|
|
|
|
+ // 校验特殊营业时间:预约时间的特殊时间不能大于门店营业时间的特殊时间
|
|
|
|
|
+ validateSpecialBusinessHours(dto.getStoreId(), dto.getSpecialBusinessHoursList());
|
|
|
|
|
+
|
|
|
int sort = 1;
|
|
int sort = 1;
|
|
|
for (StoreBookingBusinessHoursDTO specialDto : dto.getSpecialBusinessHoursList()) {
|
|
for (StoreBookingBusinessHoursDTO specialDto : dto.getSpecialBusinessHoursList()) {
|
|
|
StoreBookingBusinessHours specialHours = convertToBusinessHours(specialDto, settingsId, 2);
|
|
StoreBookingBusinessHours specialHours = convertToBusinessHours(specialDto, settingsId, 2);
|
|
@@ -361,6 +370,227 @@ public class StoreBookingSettingsServiceImpl extends ServiceImpl<StoreBookingSet
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
|
|
+ * 校验正常营业时间:预约时间的正常时间不能大于门店营业时间的正常时间
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param storeId 门店ID
|
|
|
|
|
+ * @param normalBusinessHours 预约时间的正常营业时间
|
|
|
|
|
+ */
|
|
|
|
|
+ private void validateNormalBusinessHours(Integer storeId, StoreBookingBusinessHoursDTO normalBusinessHours) {
|
|
|
|
|
+ log.info("开始校验正常营业时间,storeId={}", storeId);
|
|
|
|
|
+
|
|
|
|
|
+ if (storeId == null || normalBusinessHours == null) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 如果是全天营业,跳过校验
|
|
|
|
|
+ if (normalBusinessHours.getBookingTimeType() != null && normalBusinessHours.getBookingTimeType() == 1) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 如果没有开始时间和结束时间,跳过校验
|
|
|
|
|
+ if (!StringUtils.hasText(normalBusinessHours.getStartTime()) ||
|
|
|
|
|
+ !StringUtils.hasText(normalBusinessHours.getEndTime())) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 查询门店的正常营业时间(store_business_info,business_type=1)
|
|
|
|
|
+ List<StoreBusinessInfo> storeNormalBusinessHours = storeBusinessInfoMapper.selectList(
|
|
|
|
|
+ new LambdaQueryWrapper<StoreBusinessInfo>()
|
|
|
|
|
+ .eq(StoreBusinessInfo::getStoreId, storeId)
|
|
|
|
|
+ .eq(StoreBusinessInfo::getBusinessType, 1) // 正常营业时间
|
|
|
|
|
+ .eq(StoreBusinessInfo::getDeleteFlag, 0)
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ if (storeNormalBusinessHours == null || storeNormalBusinessHours.isEmpty()) {
|
|
|
|
|
+ log.warn("门店未配置正常营业时间,无法校验,storeId={}", storeId);
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 查找匹配的门店正常营业时间(正常营业时间通常只有一条,或者按 business_date 匹配)
|
|
|
|
|
+ StoreBusinessInfo matchedStoreHours = null;
|
|
|
|
|
+
|
|
|
|
|
+ // 如果有 holiday_date,尝试通过 business_date 匹配
|
|
|
|
|
+ if (StringUtils.hasText(normalBusinessHours.getHolidayDate())) {
|
|
|
|
|
+ matchedStoreHours = storeNormalBusinessHours.stream()
|
|
|
|
|
+ .filter(h -> normalBusinessHours.getHolidayDate().equals(h.getBusinessDate()))
|
|
|
|
|
+ .findFirst()
|
|
|
|
|
+ .orElse(null);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 如果没有匹配到,使用第一条正常营业时间(通常正常营业时间只有一条)
|
|
|
|
|
+ if (matchedStoreHours == null && !storeNormalBusinessHours.isEmpty()) {
|
|
|
|
|
+ matchedStoreHours = storeNormalBusinessHours.get(0);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 如果没有匹配到门店正常营业时间,跳过校验
|
|
|
|
|
+ if (matchedStoreHours == null) {
|
|
|
|
|
+ log.warn("未找到匹配的门店正常营业时间,跳过校验");
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 如果门店正常营业时间没有开始时间和结束时间,跳过校验
|
|
|
|
|
+ if (!StringUtils.hasText(matchedStoreHours.getStartTime()) ||
|
|
|
|
|
+ !StringUtils.hasText(matchedStoreHours.getEndTime())) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 比较时间范围
|
|
|
|
|
+ String bookingStartTime = normalBusinessHours.getStartTime().trim();
|
|
|
|
|
+ String bookingEndTime = normalBusinessHours.getEndTime().trim();
|
|
|
|
|
+ String storeStartTime = matchedStoreHours.getStartTime().trim();
|
|
|
|
|
+ String storeEndTime = matchedStoreHours.getEndTime().trim();
|
|
|
|
|
+
|
|
|
|
|
+ // 比较开始时间:预约时间的开始时间不能早于门店营业时间的开始时间
|
|
|
|
|
+ if (compareTime(bookingStartTime, storeStartTime) < 0) {
|
|
|
|
|
+ log.error("预约时间的正常时间开始时间早于门店营业时间的正常时间,storeId={}, bookingStartTime={}, storeStartTime={}",
|
|
|
|
|
+ storeId, bookingStartTime, storeStartTime);
|
|
|
|
|
+ throw new RuntimeException("预订时间与营业时间冲突,请重新设置");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 比较结束时间:预约时间的结束时间不能晚于门店营业时间的结束时间
|
|
|
|
|
+ if (compareTime(bookingEndTime, storeEndTime) > 0) {
|
|
|
|
|
+ log.error("预约时间的正常时间结束时间晚于门店营业时间的正常时间,storeId={}, bookingEndTime={}, storeEndTime={}",
|
|
|
|
|
+ storeId, bookingEndTime, storeEndTime);
|
|
|
|
|
+ throw new RuntimeException("预订时间与营业时间冲突,请重新设置");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ log.info("正常营业时间校验通过,storeId={}", storeId);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 校验特殊营业时间:预约时间的特殊时间不能大于门店营业时间的特殊时间
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param storeId 门店ID
|
|
|
|
|
+ * @param specialBusinessHoursList 预约时间的特殊营业时间列表
|
|
|
|
|
+ */
|
|
|
|
|
+ private void validateSpecialBusinessHours(Integer storeId, List<StoreBookingBusinessHoursDTO> specialBusinessHoursList) {
|
|
|
|
|
+ log.info("开始校验特殊营业时间,storeId={}, specialBusinessHoursList.size={}",
|
|
|
|
|
+ storeId, specialBusinessHoursList != null ? specialBusinessHoursList.size() : 0);
|
|
|
|
|
+
|
|
|
|
|
+ if (storeId == null || specialBusinessHoursList == null || specialBusinessHoursList.isEmpty()) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 查询门店的特殊营业时间(store_business_info,business_type=2)
|
|
|
|
|
+ List<StoreBusinessInfo> storeSpecialBusinessHours = storeBusinessInfoMapper.selectList(
|
|
|
|
|
+ new LambdaQueryWrapper<StoreBusinessInfo>()
|
|
|
|
|
+ .eq(StoreBusinessInfo::getStoreId, storeId)
|
|
|
|
|
+ .eq(StoreBusinessInfo::getBusinessType, 2) // 特殊营业时间
|
|
|
|
|
+ .eq(StoreBusinessInfo::getDeleteFlag, 0)
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ if (storeSpecialBusinessHours == null || storeSpecialBusinessHours.isEmpty()) {
|
|
|
|
|
+ log.warn("门店未配置特殊营业时间,无法校验,storeId={}", storeId);
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 遍历预约时间的特殊营业时间,与门店特殊营业时间进行匹配和比较
|
|
|
|
|
+ for (StoreBookingBusinessHoursDTO bookingSpecialHours : specialBusinessHoursList) {
|
|
|
|
|
+ // 如果是全天营业,跳过校验
|
|
|
|
|
+ if (bookingSpecialHours.getBookingTimeType() != null && bookingSpecialHours.getBookingTimeType() == 1) {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 如果没有开始时间和结束时间,跳过校验
|
|
|
|
|
+ if (!StringUtils.hasText(bookingSpecialHours.getStartTime()) ||
|
|
|
|
|
+ !StringUtils.hasText(bookingSpecialHours.getEndTime())) {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 查找匹配的门店特殊营业时间
|
|
|
|
|
+ StoreBusinessInfo matchedStoreHours = null;
|
|
|
|
|
+
|
|
|
|
|
+ // 优先通过 essential_id 匹配
|
|
|
|
|
+ if (bookingSpecialHours.getEssentialId() != null) {
|
|
|
|
|
+ matchedStoreHours = storeSpecialBusinessHours.stream()
|
|
|
|
|
+ .filter(h -> {
|
|
|
|
|
+ if (h.getEssentialId() == null || h.getEssentialId().trim().isEmpty()) {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ try {
|
|
|
|
|
+ Integer essentialId = Integer.parseInt(h.getEssentialId().trim());
|
|
|
|
|
+ return essentialId.equals(bookingSpecialHours.getEssentialId());
|
|
|
|
|
+ } catch (NumberFormatException e) {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ .findFirst()
|
|
|
|
|
+ .orElse(null);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 如果没有通过 essential_id 匹配到,尝试通过 holiday_date 匹配
|
|
|
|
|
+ if (matchedStoreHours == null && StringUtils.hasText(bookingSpecialHours.getHolidayDate())) {
|
|
|
|
|
+ matchedStoreHours = storeSpecialBusinessHours.stream()
|
|
|
|
|
+ .filter(h -> bookingSpecialHours.getHolidayDate().equals(h.getBusinessDate()))
|
|
|
|
|
+ .findFirst()
|
|
|
|
|
+ .orElse(null);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 如果没有匹配到门店特殊营业时间,跳过校验(可能是新增的特殊时间)
|
|
|
|
|
+ if (matchedStoreHours == null) {
|
|
|
|
|
+ log.warn("未找到匹配的门店特殊营业时间,跳过校验,essentialId={}, holidayDate={}",
|
|
|
|
|
+ bookingSpecialHours.getEssentialId(), bookingSpecialHours.getHolidayDate());
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 如果门店特殊营业时间没有开始时间和结束时间,跳过校验
|
|
|
|
|
+ if (!StringUtils.hasText(matchedStoreHours.getStartTime()) ||
|
|
|
|
|
+ !StringUtils.hasText(matchedStoreHours.getEndTime())) {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 比较时间范围
|
|
|
|
|
+ String bookingStartTime = bookingSpecialHours.getStartTime().trim();
|
|
|
|
|
+ String bookingEndTime = bookingSpecialHours.getEndTime().trim();
|
|
|
|
|
+ String storeStartTime = matchedStoreHours.getStartTime().trim();
|
|
|
|
|
+ String storeEndTime = matchedStoreHours.getEndTime().trim();
|
|
|
|
|
+
|
|
|
|
|
+ // 比较开始时间:预约时间的开始时间不能早于门店营业时间的开始时间
|
|
|
|
|
+ if (compareTime(bookingStartTime, storeStartTime) < 0) {
|
|
|
|
|
+ log.error("预约时间的特殊时间开始时间早于门店营业时间的特殊时间,storeId={}, bookingStartTime={}, storeStartTime={}",
|
|
|
|
|
+ storeId, bookingStartTime, storeStartTime);
|
|
|
|
|
+ throw new RuntimeException("预订时间与营业时间冲突,请重新设置");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 比较结束时间:预约时间的结束时间不能晚于门店营业时间的结束时间
|
|
|
|
|
+ if (compareTime(bookingEndTime, storeEndTime) > 0) {
|
|
|
|
|
+ log.error("预约时间的特殊时间结束时间晚于门店营业时间的特殊时间,storeId={}, bookingEndTime={}, storeEndTime={}",
|
|
|
|
|
+ storeId, bookingEndTime, storeEndTime);
|
|
|
|
|
+ throw new RuntimeException("预订时间与营业时间冲突,请重新设置");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ log.info("特殊营业时间校验通过,storeId={}", storeId);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 比较两个时间(HH:mm格式)
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param time1 时间1
|
|
|
|
|
+ * @param time2 时间2
|
|
|
|
|
+ * @return 负数表示time1 < time2,0表示相等,正数表示time1 > time2
|
|
|
|
|
+ */
|
|
|
|
|
+ private int compareTime(String time1, String time2) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ String[] parts1 = time1.split(":");
|
|
|
|
|
+ String[] parts2 = time2.split(":");
|
|
|
|
|
+
|
|
|
|
|
+ int hour1 = Integer.parseInt(parts1[0]);
|
|
|
|
|
+ int minute1 = Integer.parseInt(parts1[1]);
|
|
|
|
|
+ int hour2 = Integer.parseInt(parts2[0]);
|
|
|
|
|
+ int minute2 = Integer.parseInt(parts2[1]);
|
|
|
|
|
+
|
|
|
|
|
+ int totalMinutes1 = hour1 * 60 + minute1;
|
|
|
|
|
+ int totalMinutes2 = hour2 * 60 + minute2;
|
|
|
|
|
+
|
|
|
|
|
+ return totalMinutes1 - totalMinutes2;
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.error("比较时间失败,time1={}, time2={}", time1, time2, e);
|
|
|
|
|
+ throw new RuntimeException("时间格式错误");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
* 从JWT获取当前登录用户ID
|
|
* 从JWT获取当前登录用户ID
|
|
|
*
|
|
*
|
|
|
* @return 用户ID,如果未登录返回null
|
|
* @return 用户ID,如果未登录返回null
|