ソースを参照

预约服务 信息设置

qinxuyang 2 ヶ月 前
コミット
f5883f575a

+ 82 - 0
alien-entity/src/main/java/shop/alien/entity/store/StoreBookingSettings.java

@@ -0,0 +1,82 @@
+package shop.alien.entity.store;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * 预订服务信息设置表
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+@Data
+@JsonInclude
+@TableName("store_booking_settings")
+@ApiModel(value = "StoreBookingSettings对象", description = "预订服务信息设置表")
+public class StoreBookingSettings {
+
+    @ApiModelProperty(value = "主键ID")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    @ApiModelProperty(value = "门店ID")
+    @TableField("store_id")
+    private Integer storeId;
+
+    @ApiModelProperty(value = "未按时到店是否保留位置(0:不保留位置, 1:保留位置)")
+    @TableField("retain_position_flag")
+    private Integer retainPositionFlag;
+
+    @ApiModelProperty(value = "保留时长(分钟)")
+    @TableField("retention_duration")
+    private Integer retentionDuration;
+
+    @ApiModelProperty(value = "预订日期显示(天)")
+    @TableField("booking_date_display_days")
+    private Integer bookingDateDisplayDays;
+
+    @ApiModelProperty(value = "预订时间类型(0:非全天, 1:全天)")
+    @TableField("booking_time_type")
+    private Integer bookingTimeType;
+
+    @ApiModelProperty(value = "预订开始时间(HH:mm格式,非全天时必填)")
+    @TableField("booking_start_time")
+    private String bookingStartTime;
+
+    @ApiModelProperty(value = "预订结束时间(HH:mm格式,非全天时必填)")
+    @TableField("booking_end_time")
+    private String bookingEndTime;
+
+    @ApiModelProperty(value = "单时段最大容纳人数")
+    @TableField("max_capacity_per_slot")
+    private Integer maxCapacityPerSlot;
+
+    @ApiModelProperty(value = "删除标记, 0:未删除, 1:已删除")
+    @TableField("delete_flag")
+    @TableLogic
+    private Integer deleteFlag;
+
+    @ApiModelProperty(value = "创建时间")
+    @TableField(value = "created_time", fill = FieldFill.INSERT)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date createdTime;
+
+    @ApiModelProperty(value = "创建人ID")
+    @TableField("created_user_id")
+    private Integer createdUserId;
+
+    @ApiModelProperty(value = "修改时间")
+    @TableField(value = "updated_time", fill = FieldFill.INSERT_UPDATE)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date updatedTime;
+
+    @ApiModelProperty(value = "修改人ID")
+    @TableField("updated_user_id")
+    private Integer updatedUserId;
+}

+ 43 - 0
alien-entity/src/main/java/shop/alien/entity/store/dto/StoreBookingSettingsDTO.java

@@ -0,0 +1,43 @@
+package shop.alien.entity.store.dto;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * 预订服务信息设置DTO
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+@Data
+@ApiModel(value = "StoreBookingSettingsDTO", description = "预订服务信息设置DTO")
+public class StoreBookingSettingsDTO {
+
+    @ApiModelProperty(value = "设置ID(编辑时必填)")
+    private Integer id;
+
+    @ApiModelProperty(value = "门店ID", required = true)
+    private Integer storeId;
+
+    @ApiModelProperty(value = "未按时到店是否保留位置(0:不保留位置, 1:保留位置)", required = true)
+    private Integer retainPositionFlag;
+
+    @ApiModelProperty(value = "保留时长(分钟)", required = true)
+    private Integer retentionDuration;
+
+    @ApiModelProperty(value = "预订日期显示(天)", required = true)
+    private Integer bookingDateDisplayDays;
+
+    @ApiModelProperty(value = "预订时间类型(0:非全天, 1:全天)", required = true)
+    private Integer bookingTimeType;
+
+    @ApiModelProperty(value = "预订开始时间(HH:mm格式,非全天时必填)")
+    private String bookingStartTime;
+
+    @ApiModelProperty(value = "预订结束时间(HH:mm格式,非全天时必填)")
+    private String bookingEndTime;
+
+    @ApiModelProperty(value = "单时段最大容纳人数", required = true)
+    private Integer maxCapacityPerSlot;
+}

+ 13 - 0
alien-entity/src/main/java/shop/alien/mapper/StoreBookingSettingsMapper.java

@@ -0,0 +1,13 @@
+package shop.alien.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import shop.alien.entity.store.StoreBookingSettings;
+
+/**
+ * 预订服务信息设置表 Mapper 接口
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+public interface StoreBookingSettingsMapper extends BaseMapper<StoreBookingSettings> {
+}

+ 30 - 0
alien-entity/src/main/resources/mapper/StoreBookingSettingsMapper.xml

@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="shop.alien.mapper.StoreBookingSettingsMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="shop.alien.entity.store.StoreBookingSettings">
+        <id column="id" property="id" />
+        <result column="store_id" property="storeId" />
+        <result column="retain_position_flag" property="retainPositionFlag" />
+        <result column="retention_duration" property="retentionDuration" />
+        <result column="booking_date_display_days" property="bookingDateDisplayDays" />
+        <result column="booking_time_type" property="bookingTimeType" />
+        <result column="booking_start_time" property="bookingStartTime" />
+        <result column="booking_end_time" property="bookingEndTime" />
+        <result column="max_capacity_per_slot" property="maxCapacityPerSlot" />
+        <result column="delete_flag" property="deleteFlag" />
+        <result column="created_time" property="createdTime" />
+        <result column="created_user_id" property="createdUserId" />
+        <result column="updated_time" property="updatedTime" />
+        <result column="updated_user_id" property="updatedUserId" />
+    </resultMap>
+
+    <!-- 通用查询结果列 -->
+    <sql id="Base_Column_List">
+        id, store_id, retain_position_flag, retention_duration, booking_date_display_days, 
+        booking_time_type, booking_start_time, booking_end_time, max_capacity_per_slot, 
+        delete_flag, created_time, created_user_id, updated_time, updated_user_id
+    </sql>
+
+</mapper>

+ 113 - 0
alien-store/src/main/java/shop/alien/store/controller/StoreBookingSettingsController.java

@@ -0,0 +1,113 @@
+package shop.alien.store.controller;
+
+import io.swagger.annotations.*;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.util.StringUtils;
+import org.springframework.web.bind.annotation.*;
+import shop.alien.entity.result.R;
+import shop.alien.entity.store.StoreBookingSettings;
+import shop.alien.entity.store.dto.StoreBookingSettingsDTO;
+import shop.alien.store.service.StoreBookingSettingsService;
+
+/**
+ * 预订服务信息设置 前端控制器
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+@Slf4j
+@Api(tags = {"预订服务-信息设置"})
+@ApiSort(17)
+@CrossOrigin
+@RestController
+@RequestMapping("/store/booking/settings")
+@RequiredArgsConstructor
+public class StoreBookingSettingsController {
+
+    private final StoreBookingSettingsService storeBookingSettingsService;
+
+    @ApiOperationSupport(order = 1)
+    @ApiOperation("查询预订服务信息设置")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "storeId", value = "门店ID", dataType = "Integer", paramType = "query", required = true)
+    })
+    @GetMapping("/detail")
+    public R<StoreBookingSettings> getSettings(@RequestParam Integer storeId) {
+        log.info("StoreBookingSettingsController.getSettings?storeId={}", storeId);
+        
+        if (storeId == null) {
+            return R.fail("门店ID不能为空");
+        }
+        
+        try {
+            StoreBookingSettings settings = storeBookingSettingsService.getByStoreId(storeId);
+            if (settings == null) {
+                return R.fail("未找到该门店的预订服务信息设置");
+            }
+            return R.data(settings);
+        } catch (Exception e) {
+            log.error("查询预订服务信息设置失败", e);
+            return R.fail("查询失败:" + e.getMessage());
+        }
+    }
+
+    @ApiOperationSupport(order = 2)
+    @ApiOperation("保存预订服务信息设置(新增或更新)")
+    @PostMapping("/save")
+    public R<String> saveSettings(@RequestBody StoreBookingSettingsDTO dto) {
+        log.info("StoreBookingSettingsController.saveSettings?dto={}", dto);
+        
+        // 参数验证
+        if (dto.getStoreId() == null) {
+            return R.fail("门店ID不能为空");
+        }
+        if (dto.getRetainPositionFlag() == null) {
+            return R.fail("未按时到店是否保留位置不能为空");
+        }
+        if (dto.getRetentionDuration() == null || dto.getRetentionDuration() <= 0) {
+            return R.fail("保留时长必须大于0");
+        }
+        if (dto.getBookingDateDisplayDays() == null || dto.getBookingDateDisplayDays() <= 0) {
+            return R.fail("预订日期显示天数必须大于0");
+        }
+        if (dto.getBookingTimeType() == null) {
+            return R.fail("预订时间类型不能为空");
+        }
+        if (dto.getMaxCapacityPerSlot() == null || dto.getMaxCapacityPerSlot() <= 0) {
+            return R.fail("单时段最大容纳人数必须大于0");
+        }
+        
+        // 如果选择非全天,必须填写开始时间和结束时间
+        if (dto.getBookingTimeType() != null && dto.getBookingTimeType() == 0) {
+            if (!StringUtils.hasText(dto.getBookingStartTime())) {
+                return R.fail("非全天时必须填写开始时间");
+            }
+            if (!StringUtils.hasText(dto.getBookingEndTime())) {
+                return R.fail("非全天时必须填写结束时间");
+            }
+        }
+        
+        try {
+            StoreBookingSettings settings = new StoreBookingSettings();
+            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());
+            
+            boolean result = storeBookingSettingsService.saveOrUpdateSettings(settings);
+            if (result) {
+                return R.success("保存成功");
+            } else {
+                return R.fail("保存失败");
+            }
+        } catch (Exception e) {
+            log.error("保存预订服务信息设置失败", e);
+            return R.fail("保存失败:" + e.getMessage());
+        }
+    }
+}

+ 29 - 0
alien-store/src/main/java/shop/alien/store/service/StoreBookingSettingsService.java

@@ -0,0 +1,29 @@
+package shop.alien.store.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import shop.alien.entity.store.StoreBookingSettings;
+
+/**
+ * 预订服务信息设置表 服务类
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+public interface StoreBookingSettingsService extends IService<StoreBookingSettings> {
+
+    /**
+     * 根据门店ID查询预订服务信息设置
+     *
+     * @param storeId 门店ID
+     * @return StoreBookingSettings
+     */
+    StoreBookingSettings getByStoreId(Integer storeId);
+
+    /**
+     * 新增或更新预订服务信息设置
+     *
+     * @param settings 设置对象
+     * @return boolean
+     */
+    boolean saveOrUpdateSettings(StoreBookingSettings settings);
+}

+ 158 - 0
alien-store/src/main/java/shop/alien/store/service/impl/StoreBookingSettingsServiceImpl.java

@@ -0,0 +1,158 @@
+package shop.alien.store.service.impl;
+
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+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.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.StringUtils;
+import shop.alien.entity.store.StoreBookingSettings;
+import shop.alien.mapper.StoreBookingSettingsMapper;
+import shop.alien.store.service.StoreBookingSettingsService;
+import shop.alien.util.common.JwtUtil;
+
+import java.util.regex.Pattern;
+
+/**
+ * 预订服务信息设置表 服务实现类
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+@Slf4j
+@Service
+@Transactional
+@RequiredArgsConstructor
+public class StoreBookingSettingsServiceImpl extends ServiceImpl<StoreBookingSettingsMapper, StoreBookingSettings> implements StoreBookingSettingsService {
+
+    // 时间格式正则:HH:mm
+    private static final Pattern TIME_PATTERN = Pattern.compile("^([0-1][0-9]|2[0-3]):[0-5][0-9]$");
+
+    @Override
+    public StoreBookingSettings getByStoreId(Integer storeId) {
+        log.info("StoreBookingSettingsServiceImpl.getByStoreId?storeId={}", storeId);
+        
+        if (storeId == null) {
+            log.warn("查询预订服务信息设置失败:门店ID不能为空");
+            return null;
+        }
+        
+        LambdaQueryWrapper<StoreBookingSettings> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(StoreBookingSettings::getStoreId, storeId);
+        // @TableLogic 会自动过滤已删除的记录(delete_flag=0)
+        
+        return this.getOne(wrapper);
+    }
+
+    @Override
+    public boolean saveOrUpdateSettings(StoreBookingSettings settings) {
+        log.info("StoreBookingSettingsServiceImpl.saveOrUpdateSettings?settings={}", settings);
+        
+        // 从JWT获取当前登录用户ID
+        Integer userId = getCurrentUserId();
+        
+        // 参数验证
+        if (settings.getStoreId() == null) {
+            log.warn("保存预订服务信息设置失败:门店ID不能为空");
+            throw new RuntimeException("门店ID不能为空");
+        }
+        if (settings.getRetainPositionFlag() == null) {
+            log.warn("保存预订服务信息设置失败:未按时到店是否保留位置不能为空");
+            throw new RuntimeException("未按时到店是否保留位置不能为空");
+        }
+        if (settings.getRetentionDuration() == null || settings.getRetentionDuration() <= 0) {
+            log.warn("保存预订服务信息设置失败:保留时长必须大于0");
+            throw new RuntimeException("保留时长必须大于0");
+        }
+        if (settings.getBookingDateDisplayDays() == null || settings.getBookingDateDisplayDays() <= 0) {
+            log.warn("保存预订服务信息设置失败:预订日期显示天数必须大于0");
+            throw new RuntimeException("预订日期显示天数必须大于0");
+        }
+        if (settings.getBookingTimeType() == null) {
+            log.warn("保存预订服务信息设置失败:预订时间类型不能为空");
+            throw new RuntimeException("预订时间类型不能为空");
+        }
+        if (settings.getMaxCapacityPerSlot() == null || settings.getMaxCapacityPerSlot() <= 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());
+        
+        if (existingSettings != null) {
+            // 更新
+            settings.setId(existingSettings.getId());
+            LambdaUpdateWrapper<StoreBookingSettings> updateWrapper = new LambdaUpdateWrapper<>();
+            updateWrapper.eq(StoreBookingSettings::getId, existingSettings.getId());
+            
+            updateWrapper.set(StoreBookingSettings::getRetainPositionFlag, settings.getRetainPositionFlag());
+            updateWrapper.set(StoreBookingSettings::getRetentionDuration, settings.getRetentionDuration());
+            updateWrapper.set(StoreBookingSettings::getBookingDateDisplayDays, settings.getBookingDateDisplayDays());
+            updateWrapper.set(StoreBookingSettings::getBookingTimeType, settings.getBookingTimeType());
+            updateWrapper.set(StoreBookingSettings::getBookingStartTime, settings.getBookingStartTime());
+            updateWrapper.set(StoreBookingSettings::getBookingEndTime, settings.getBookingEndTime());
+            updateWrapper.set(StoreBookingSettings::getMaxCapacityPerSlot, settings.getMaxCapacityPerSlot());
+            
+            if (userId != null) {
+                updateWrapper.set(StoreBookingSettings::getUpdatedUserId, userId);
+            }
+            
+            return this.update(updateWrapper);
+        } else {
+            // 新增
+            settings.setCreatedUserId(userId);
+            return this.save(settings);
+        }
+    }
+
+    /**
+     * 从JWT获取当前登录用户ID
+     *
+     * @return 用户ID,如果未登录返回null
+     */
+    private Integer getCurrentUserId() {
+        try {
+            JSONObject userInfo = JwtUtil.getCurrentUserInfo();
+            if (userInfo != null) {
+                return userInfo.getInteger("userId");
+            }
+        } catch (Exception e) {
+            log.warn("获取当前登录用户ID失败: {}", e.getMessage());
+        }
+        return null;
+    }
+}