|
|
@@ -6,14 +6,22 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
|
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
|
import lombok.RequiredArgsConstructor;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.beans.BeanUtils;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
import org.springframework.util.StringUtils;
|
|
|
+import shop.alien.entity.store.StoreBookingBusinessHours;
|
|
|
import shop.alien.entity.store.StoreBookingSettings;
|
|
|
+import shop.alien.entity.store.dto.StoreBookingBusinessHoursDTO;
|
|
|
+import shop.alien.entity.store.dto.StoreBookingSettingsDTO;
|
|
|
import shop.alien.mapper.StoreBookingSettingsMapper;
|
|
|
+import shop.alien.store.service.StoreBookingBusinessHoursService;
|
|
|
import shop.alien.store.service.StoreBookingSettingsService;
|
|
|
import shop.alien.util.common.JwtUtil;
|
|
|
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.List;
|
|
|
+import java.util.stream.Collectors;
|
|
|
import java.util.regex.Pattern;
|
|
|
|
|
|
/**
|
|
|
@@ -28,6 +36,8 @@ import java.util.regex.Pattern;
|
|
|
@RequiredArgsConstructor
|
|
|
public class StoreBookingSettingsServiceImpl extends ServiceImpl<StoreBookingSettingsMapper, StoreBookingSettings> implements StoreBookingSettingsService {
|
|
|
|
|
|
+ private final StoreBookingBusinessHoursService storeBookingBusinessHoursService;
|
|
|
+
|
|
|
// 时间格式正则:HH:mm
|
|
|
private static final Pattern TIME_PATTERN = Pattern.compile("^([0-1][0-9]|2[0-3]):[0-5][0-9]$");
|
|
|
|
|
|
@@ -80,36 +90,60 @@ public class StoreBookingSettingsServiceImpl extends ServiceImpl<StoreBookingSet
|
|
|
throw new RuntimeException("单时段最大容纳人数必须大于0");
|
|
|
}
|
|
|
|
|
|
- // 如果选择非全天,必须填写开始时间和结束时间
|
|
|
- if (settings.getBookingTimeType() != null && settings.getBookingTimeType() == 0) {
|
|
|
- if (!StringUtils.hasText(settings.getBookingStartTime())) {
|
|
|
- log.warn("保存预订服务信息设置失败:非全天时必须填写开始时间");
|
|
|
- throw new RuntimeException("非全天时必须填写开始时间");
|
|
|
- }
|
|
|
- if (!StringUtils.hasText(settings.getBookingEndTime())) {
|
|
|
- log.warn("保存预订服务信息设置失败:非全天时必须填写结束时间");
|
|
|
- throw new RuntimeException("非全天时必须填写结束时间");
|
|
|
- }
|
|
|
- // 验证时间格式
|
|
|
- if (!TIME_PATTERN.matcher(settings.getBookingStartTime()).matches()) {
|
|
|
- log.warn("保存预订服务信息设置失败:开始时间格式不正确,应为HH:mm格式");
|
|
|
- throw new RuntimeException("开始时间格式不正确,应为HH:mm格式");
|
|
|
+ // 验证预订相关字段
|
|
|
+ // 如果选择付费(reservation=1),必须填写预订金额
|
|
|
+ if (StringUtils.hasText(settings.getReservation()) && "1".equals(settings.getReservation())) {
|
|
|
+ if (settings.getReservationMoney() == null || settings.getReservationMoney() < 0) {
|
|
|
+ log.warn("保存预订服务信息设置失败:选择付费时必须填写预订金额,且金额不能小于0");
|
|
|
+ throw new RuntimeException("选择付费时必须填写预订金额,且金额不能小于0");
|
|
|
}
|
|
|
- if (!TIME_PATTERN.matcher(settings.getBookingEndTime()).matches()) {
|
|
|
- log.warn("保存预订服务信息设置失败:结束时间格式不正确,应为HH:mm格式");
|
|
|
- throw new RuntimeException("结束时间格式不正确,应为HH:mm格式");
|
|
|
- }
|
|
|
- // 验证开始时间必须小于结束时间
|
|
|
- if (settings.getBookingStartTime().compareTo(settings.getBookingEndTime()) >= 0) {
|
|
|
- log.warn("保存预订服务信息设置失败:开始时间必须小于结束时间");
|
|
|
- throw new RuntimeException("开始时间必须小于结束时间");
|
|
|
- }
|
|
|
- } else {
|
|
|
- // 如果是全天,清空开始时间和结束时间
|
|
|
- settings.setBookingStartTime(null);
|
|
|
- settings.setBookingEndTime(null);
|
|
|
+ } else if (StringUtils.hasText(settings.getReservation()) && "0".equals(settings.getReservation())) {
|
|
|
+ // 如果选择免费,清空预订金额
|
|
|
+ settings.setReservationMoney(null);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 验证取消预订退费时长设置
|
|
|
+ if (settings.getOffUnsubscribeHours() == null || settings.getOffUnsubscribeHours() < 0) {
|
|
|
+ log.warn("保存预订服务信息设置失败:取消预订退费时长设置必须大于等于0");
|
|
|
+ throw new RuntimeException("取消预订退费时长设置必须大于等于0");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 验证营业时间结束前不可预订时间
|
|
|
+ if (settings.getBookingNotAvailableTime() == null || settings.getBookingNotAvailableTime() < 0) {
|
|
|
+ log.warn("保存预订服务信息设置失败:营业时间结束前不可预订时间必须大于等于0");
|
|
|
+ throw new RuntimeException("营业时间结束前不可预订时间必须大于等于0");
|
|
|
}
|
|
|
|
|
|
+ // 如果选择非全天,必须填写开始时间和结束时间
|
|
|
+// if (settings.getBookingTimeType() != null && settings.getBookingTimeType() == 0) {
|
|
|
+// if (!StringUtils.hasText(settings.getBookingStartTime())) {
|
|
|
+// log.warn("保存预订服务信息设置失败:非全天时必须填写开始时间");
|
|
|
+// throw new RuntimeException("非全天时必须填写开始时间");
|
|
|
+// }
|
|
|
+// if (!StringUtils.hasText(settings.getBookingEndTime())) {
|
|
|
+// log.warn("保存预订服务信息设置失败:非全天时必须填写结束时间");
|
|
|
+// throw new RuntimeException("非全天时必须填写结束时间");
|
|
|
+// }
|
|
|
+// // 验证时间格式
|
|
|
+// if (!TIME_PATTERN.matcher(settings.getBookingStartTime()).matches()) {
|
|
|
+// log.warn("保存预订服务信息设置失败:开始时间格式不正确,应为HH:mm格式");
|
|
|
+// throw new RuntimeException("开始时间格式不正确,应为HH:mm格式");
|
|
|
+// }
|
|
|
+// if (!TIME_PATTERN.matcher(settings.getBookingEndTime()).matches()) {
|
|
|
+// log.warn("保存预订服务信息设置失败:结束时间格式不正确,应为HH:mm格式");
|
|
|
+// throw new RuntimeException("结束时间格式不正确,应为HH:mm格式");
|
|
|
+// }
|
|
|
+// // 验证开始时间必须小于结束时间
|
|
|
+// if (settings.getBookingStartTime().compareTo(settings.getBookingEndTime()) >= 0) {
|
|
|
+// log.warn("保存预订服务信息设置失败:开始时间必须小于结束时间");
|
|
|
+// throw new RuntimeException("开始时间必须小于结束时间");
|
|
|
+// }
|
|
|
+// } else {
|
|
|
+// // 如果是全天,清空开始时间和结束时间
|
|
|
+// settings.setBookingStartTime(null);
|
|
|
+// settings.setBookingEndTime(null);
|
|
|
+// }
|
|
|
+
|
|
|
// 查询是否已存在该门店的设置
|
|
|
StoreBookingSettings existingSettings = getByStoreId(settings.getStoreId());
|
|
|
|
|
|
@@ -126,6 +160,10 @@ public class StoreBookingSettingsServiceImpl extends ServiceImpl<StoreBookingSet
|
|
|
updateWrapper.set(StoreBookingSettings::getBookingStartTime, settings.getBookingStartTime());
|
|
|
updateWrapper.set(StoreBookingSettings::getBookingEndTime, settings.getBookingEndTime());
|
|
|
updateWrapper.set(StoreBookingSettings::getMaxCapacityPerSlot, settings.getMaxCapacityPerSlot());
|
|
|
+ updateWrapper.set(StoreBookingSettings::getReservation, settings.getReservation());
|
|
|
+ updateWrapper.set(StoreBookingSettings::getReservationMoney, settings.getReservationMoney());
|
|
|
+ updateWrapper.set(StoreBookingSettings::getOffUnsubscribeHours, settings.getOffUnsubscribeHours());
|
|
|
+ updateWrapper.set(StoreBookingSettings::getBookingNotAvailableTime, settings.getBookingNotAvailableTime());
|
|
|
|
|
|
if (userId != null) {
|
|
|
updateWrapper.set(StoreBookingSettings::getUpdatedUserId, userId);
|
|
|
@@ -139,6 +177,164 @@ public class StoreBookingSettingsServiceImpl extends ServiceImpl<StoreBookingSet
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ @Override
|
|
|
+ public boolean saveSettingsWithBusinessHours(StoreBookingSettingsDTO dto) {
|
|
|
+ log.info("StoreBookingSettingsServiceImpl.saveSettingsWithBusinessHours?dto={}", dto);
|
|
|
+
|
|
|
+ // 1. 先保存或更新设置信息
|
|
|
+ StoreBookingSettings settings = new StoreBookingSettings();
|
|
|
+ settings.setId(dto.getId());
|
|
|
+ settings.setStoreId(dto.getStoreId());
|
|
|
+ settings.setRetainPositionFlag(dto.getRetainPositionFlag());
|
|
|
+ settings.setRetentionDuration(dto.getRetentionDuration());
|
|
|
+ settings.setBookingDateDisplayDays(dto.getBookingDateDisplayDays());
|
|
|
+ settings.setBookingTimeType(dto.getBookingTimeType());
|
|
|
+ settings.setBookingStartTime(dto.getBookingStartTime());
|
|
|
+ settings.setBookingEndTime(dto.getBookingEndTime());
|
|
|
+ settings.setMaxCapacityPerSlot(dto.getMaxCapacityPerSlot());
|
|
|
+ settings.setReservation(dto.getReservation());
|
|
|
+ settings.setReservationMoney(dto.getReservationMoney());
|
|
|
+ settings.setOffUnsubscribeHours(dto.getOffUnsubscribeHours());
|
|
|
+ settings.setBookingNotAvailableTime(dto.getBookingNotAvailableTime());
|
|
|
+
|
|
|
+ boolean settingsResult = saveOrUpdateSettings(settings);
|
|
|
+ if (!settingsResult) {
|
|
|
+ log.error("保存预订服务信息设置失败");
|
|
|
+ throw new RuntimeException("保存预订服务信息设置失败");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 2. 获取保存后的设置ID(如果是新增,需要获取新生成的ID)
|
|
|
+ Integer settingsId = settings.getId();
|
|
|
+ if (settingsId == null) {
|
|
|
+ // 如果是新增,重新查询获取ID
|
|
|
+ StoreBookingSettings savedSettings = getByStoreId(dto.getStoreId());
|
|
|
+ if (savedSettings == null) {
|
|
|
+ log.error("保存设置后无法获取设置ID");
|
|
|
+ throw new RuntimeException("保存设置后无法获取设置ID");
|
|
|
+ }
|
|
|
+ settingsId = savedSettings.getId();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 3. 准备营业时间列表
|
|
|
+ List<StoreBookingBusinessHours> businessHoursList = new ArrayList<>();
|
|
|
+
|
|
|
+ // 3.1 处理正常营业时间(business_type=0)
|
|
|
+ if (dto.getNormalBusinessHours() != null) {
|
|
|
+ StoreBookingBusinessHours normalHours = convertToBusinessHours(dto.getNormalBusinessHours(), settingsId, 0);
|
|
|
+ businessHoursList.add(normalHours);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 3.2 处理特殊营业时间列表(business_type=1)
|
|
|
+ if (dto.getSpecialBusinessHoursList() != null && !dto.getSpecialBusinessHoursList().isEmpty()) {
|
|
|
+ int sort = 1;
|
|
|
+ for (StoreBookingBusinessHoursDTO specialDto : dto.getSpecialBusinessHoursList()) {
|
|
|
+ StoreBookingBusinessHours specialHours = convertToBusinessHours(specialDto, settingsId, 1);
|
|
|
+ specialHours.setSort(sort++);
|
|
|
+ businessHoursList.add(specialHours);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 4. 批量保存营业时间(如果列表不为空)
|
|
|
+ if (!businessHoursList.isEmpty()) {
|
|
|
+ boolean businessHoursResult = storeBookingBusinessHoursService.batchSaveBusinessHours(settingsId, businessHoursList);
|
|
|
+ if (!businessHoursResult) {
|
|
|
+ log.error("保存营业时间失败");
|
|
|
+ throw new RuntimeException("保存营业时间失败");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public StoreBookingSettingsDTO getSettingsWithBusinessHoursByStoreId(Integer storeId) {
|
|
|
+ log.info("StoreBookingSettingsServiceImpl.getSettingsWithBusinessHoursByStoreId?storeId={}", storeId);
|
|
|
+
|
|
|
+ if (storeId == null) {
|
|
|
+ log.warn("查询预订服务信息设置失败:门店ID不能为空");
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 1. 查询设置信息
|
|
|
+ StoreBookingSettings settings = getByStoreId(storeId);
|
|
|
+ if (settings == null) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 2. 转换为DTO
|
|
|
+ StoreBookingSettingsDTO dto = new StoreBookingSettingsDTO();
|
|
|
+ BeanUtils.copyProperties(settings, dto);
|
|
|
+
|
|
|
+ // 3. 查询营业时间列表
|
|
|
+ List<StoreBookingBusinessHours> businessHoursList = storeBookingBusinessHoursService.getListBySettingsId(settings.getId());
|
|
|
+
|
|
|
+ // 4. 分离正常营业时间和特殊营业时间
|
|
|
+ StoreBookingBusinessHours normalHours = businessHoursList.stream()
|
|
|
+ .filter(h -> h.getBusinessType() != null && h.getBusinessType() == 0)
|
|
|
+ .findFirst()
|
|
|
+ .orElse(null);
|
|
|
+
|
|
|
+ List<StoreBookingBusinessHours> specialHoursList = businessHoursList.stream()
|
|
|
+ .filter(h -> h.getBusinessType() != null && h.getBusinessType() == 1)
|
|
|
+ .collect(Collectors.toList());
|
|
|
+
|
|
|
+ // 5. 转换为DTO
|
|
|
+ if (normalHours != null) {
|
|
|
+ dto.setNormalBusinessHours(convertToBusinessHoursDTO(normalHours));
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!specialHoursList.isEmpty()) {
|
|
|
+ List<StoreBookingBusinessHoursDTO> specialHoursDTOList = specialHoursList.stream()
|
|
|
+ .map(this::convertToBusinessHoursDTO)
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ dto.setSpecialBusinessHoursList(specialHoursDTOList);
|
|
|
+ }
|
|
|
+
|
|
|
+ return dto;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 将DTO转换为营业时间实体
|
|
|
+ *
|
|
|
+ * @param dto DTO对象
|
|
|
+ * @param settingsId 设置ID
|
|
|
+ * @param businessType 营业类型(0:正常营业, 1:特殊营业/节假日)
|
|
|
+ * @return StoreBookingBusinessHours
|
|
|
+ */
|
|
|
+ private StoreBookingBusinessHours convertToBusinessHours(StoreBookingBusinessHoursDTO dto, Integer settingsId, Integer businessType) {
|
|
|
+ StoreBookingBusinessHours businessHours = new StoreBookingBusinessHours();
|
|
|
+ businessHours.setId(dto.getId());
|
|
|
+ businessHours.setSettingsId(settingsId);
|
|
|
+ businessHours.setBusinessType(businessType);
|
|
|
+ businessHours.setHolidayType(dto.getHolidayType());
|
|
|
+ businessHours.setHolidayDate(dto.getHolidayDate());
|
|
|
+ businessHours.setBookingTimeType(dto.getBookingTimeType());
|
|
|
+ businessHours.setStartTime(dto.getStartTime());
|
|
|
+ businessHours.setEndTime(dto.getEndTime());
|
|
|
+ businessHours.setSort(dto.getSort() != null ? dto.getSort() : 0);
|
|
|
+ return businessHours;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 将营业时间实体转换为DTO
|
|
|
+ *
|
|
|
+ * @param businessHours 营业时间实体
|
|
|
+ * @return StoreBookingBusinessHoursDTO
|
|
|
+ */
|
|
|
+ private StoreBookingBusinessHoursDTO convertToBusinessHoursDTO(StoreBookingBusinessHours businessHours) {
|
|
|
+ StoreBookingBusinessHoursDTO dto = new StoreBookingBusinessHoursDTO();
|
|
|
+ dto.setId(businessHours.getId());
|
|
|
+ dto.setSettingsId(businessHours.getSettingsId());
|
|
|
+ dto.setBusinessType(businessHours.getBusinessType());
|
|
|
+ dto.setHolidayType(businessHours.getHolidayType());
|
|
|
+ dto.setHolidayDate(businessHours.getHolidayDate());
|
|
|
+ dto.setBookingTimeType(businessHours.getBookingTimeType());
|
|
|
+ dto.setStartTime(businessHours.getStartTime());
|
|
|
+ dto.setEndTime(businessHours.getEndTime());
|
|
|
+ dto.setSort(businessHours.getSort());
|
|
|
+ return dto;
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 从JWT获取当前登录用户ID
|
|
|
*
|