Эх сурвалжийг харах

fix:完善时段配置管理

puhui999 1 жил өмнө
parent
commit
331be53b8b
10 өөрчлөгдсөн 105 нэмэгдсэн , 115 устгасан
  1. 2 0
      yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java
  2. 8 4
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillConfigController.java
  3. 29 0
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/config/SeckillConfigSimpleRespVO.java
  4. 3 0
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckillconfig/SeckillConfigConvert.java
  5. 1 1
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckillactivity/SeckillActivityDO.java
  6. 0 23
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillconfig/SeckillConfigMapper.java
  7. 0 25
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillactivity/SeckillActivityServiceImpl.java
  8. 6 14
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillconfig/SeckillConfigService.java
  9. 41 33
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillconfig/SeckillConfigServiceImpl.java
  10. 15 15
      yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/seckillactivity/SeckillActivityServiceImplTest.java

+ 2 - 0
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java

@@ -56,5 +56,7 @@ public interface ErrorCodeConstants {
     // ========== 秒杀时段 1013009000 ==========
     ErrorCode SECKILL_TIME_NOT_EXISTS = new ErrorCode(1013009000, "秒杀时段不存在");
     ErrorCode SECKILL_TIME_CONFLICTS = new ErrorCode(1013009001, "秒杀时段冲突");
+    ErrorCode SECKILL_TIME_EQUAL = new ErrorCode(1013009002, "秒杀时段开始时间和结束时间不能相等");
+    ErrorCode SECKILL_START_TIME_BEFORE_END_TIME = new ErrorCode(1013009003, "秒杀时段开始时间不能在结束时间之后");
 
 }

+ 8 - 4
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillConfigController.java

@@ -2,10 +2,7 @@ package cn.iocoder.yudao.module.promotion.controller.admin.seckill;
 
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigCreateReqVO;
-import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigPageReqVO;
-import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigRespVO;
-import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigUpdateReqVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.*;
 import cn.iocoder.yudao.module.promotion.convert.seckill.seckillconfig.SeckillConfigConvert;
 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillconfig.SeckillConfigDO;
 import cn.iocoder.yudao.module.promotion.service.seckill.seckillconfig.SeckillConfigService;
@@ -77,6 +74,13 @@ public class SeckillConfigController {
         return success(SeckillConfigConvert.INSTANCE.convertList(list));
     }
 
+    @GetMapping("/list-all-simple")
+    @Operation(summary = "获得所有开启状态的秒杀时段精简列表", description = "主要用于前端的下拉选项")
+    public CommonResult<List<SeckillConfigSimpleRespVO>> getListAllSimple() {
+        List<SeckillConfigDO> list = seckillConfigService.getListAllSimple();
+        return success(SeckillConfigConvert.INSTANCE.convertList1(list));
+    }
+
     @GetMapping("/page")
     @Operation(summary = "获得秒杀活动分页")
     @PreAuthorize("@ss.hasPermission('promotion:seckill-config:query')")

+ 29 - 0
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/config/SeckillConfigSimpleRespVO.java

@@ -0,0 +1,29 @@
+package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.validation.constraints.NotNull;
+
+/**
+ * 管理后台 - 秒杀时段配置精简信息 Response VO
+ *
+ * @author HUIHUI
+ */
+@Schema(description = "管理后台 - 秒杀时段配置精简信息 Response VO")
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class SeckillConfigSimpleRespVO {
+
+    @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @NotNull(message = "编号不能为空")
+    private Long id;
+
+    @Schema(description = "秒杀时段名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "早上场")
+    @NotNull(message = "秒杀时段名称不能为空")
+    private String name;
+
+}

+ 3 - 0
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckillconfig/SeckillConfigConvert.java

@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.promotion.convert.seckill.seckillconfig;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigCreateReqVO;
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigRespVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigSimpleRespVO;
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigUpdateReqVO;
 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillconfig.SeckillConfigDO;
 import org.mapstruct.Mapper;
@@ -28,6 +29,8 @@ public interface SeckillConfigConvert {
 
     List<SeckillConfigRespVO> convertList(List<SeckillConfigDO> list);
 
+    List<SeckillConfigSimpleRespVO> convertList1(List<SeckillConfigDO> list);
+
     PageResult<SeckillConfigRespVO> convertPage(PageResult<SeckillConfigDO> page);
 
 }

+ 1 - 1
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckillactivity/SeckillActivityDO.java

@@ -41,7 +41,7 @@ public class SeckillActivityDO extends BaseDO {
     private String name;
     /**
      * 活动状态
-     * <p>
+     *
      * 枚举 {@link PromotionActivityStatusEnum 对应的类}
      */
     private Integer status;

+ 0 - 23
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillconfig/SeckillConfigMapper.java

@@ -5,34 +5,11 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigPageReqVO;
 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillconfig.SeckillConfigDO;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
 import org.apache.ibatis.annotations.Mapper;
 
-import java.time.LocalTime;
-import java.util.Collection;
-import java.util.List;
-
 @Mapper
 public interface SeckillConfigMapper extends BaseMapperX<SeckillConfigDO> {
 
-    default List<SeckillConfigDO> selectListByTime(LocalTime time) {
-        return selectList(SeckillConfigDO::getStartTime, SeckillConfigDO::getEndTime, time);
-    }
-
-    default List<SeckillConfigDO> selectListByTime(LocalTime startTime, LocalTime endTime) {
-        return selectList(new LambdaQueryWrapper<SeckillConfigDO>()
-                .ge(SeckillConfigDO::getStartTime, startTime)
-                .le(SeckillConfigDO::getEndTime, endTime));
-    }
-
-    default void updateActivityCount(Collection<Long> ids, String type, Integer count) {
-        new LambdaUpdateChainWrapper<>(this)
-                .in(SeckillConfigDO::getId, ids)
-                .setSql("`seckill_activity_count` = `seckill_activity_count` " + type + count)
-                .update();
-    }
-
     default PageResult<SeckillConfigDO> selectPage(SeckillConfigPageReqVO reqVO) {
         return selectPage(reqVO, new LambdaQueryWrapperX<SeckillConfigDO>()
                 .likeIfPresent(SeckillConfigDO::getName, reqVO.getName())

+ 0 - 25
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillactivity/SeckillActivityServiceImpl.java

@@ -56,8 +56,6 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
         // 插入商品
         List<SeckillProductDO> productDOs = SeckillActivityConvert.INSTANCE.convertList(createReqVO.getProducts(), seckillActivity);
         seckillProductMapper.insertBatch(productDOs);
-        // 更新秒杀时段的秒杀活动数量
-        seckillConfigService.seckillActivityCountIncr(createReqVO.getConfigIds());
         return seckillActivity.getId();
     }
 
@@ -77,31 +75,8 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
         seckillActivityMapper.updateById(updateObj);
         // 更新商品
         updateSeckillProduct(updateReqVO);
-        // 更新秒杀时段的秒杀活动数量
-        updateSeckillConfigActivityCount(seckillActivity, updateReqVO.getConfigIds());
     }
 
-    /**
-     * 更新秒杀时段的秒杀活动数量
-     *
-     * @param seckillActivity 查询出的秒杀活动
-     * @param updateTimeIds   更新后的秒杀时段id列表
-     */
-    private void updateSeckillConfigActivityCount(SeckillActivityDO seckillActivity, List<Long> updateTimeIds) {
-        // 查询出 timeIds
-        List<Long> existsTimeIds = seckillActivity.getConfigIds();
-        // 需要减少的时间段
-        Collection<Long> reduceIds = CollUtil.filterNew(existsTimeIds, existsTimeId -> !updateTimeIds.contains(existsTimeId));
-        // 需要添加的时间段
-        updateTimeIds.removeIf(existsTimeIds::contains);
-        // 更新减少时间段和增加时间段
-        if (CollUtil.isNotEmpty(updateTimeIds)) {
-            seckillConfigService.seckillActivityCountIncr(updateTimeIds);
-        }
-        if (CollUtil.isNotEmpty(reduceIds)) {
-            seckillConfigService.seckillActivityCountDecr(reduceIds);
-        }
-    }
 
     /**
      * 更新秒杀商品

+ 6 - 14
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillconfig/SeckillConfigService.java

@@ -61,20 +61,6 @@ public interface SeckillConfigService {
      */
     void validateSeckillConfigExists(Collection<Long> timeIds);
 
-    /**
-     * 秒杀时段列表的秒杀活动数量加 1
-     *
-     * @param ids 秒杀时段id列表
-     */
-    void seckillActivityCountIncr(Collection<Long> ids);
-
-
-    /**
-     * 秒杀时段列表的秒杀活动数量减 1
-     *
-     * @param ids 秒杀时段id列表
-     */
-    void seckillActivityCountDecr(Collection<Long> ids);
 
     /**
      * 获得秒杀时间段配置分页数据
@@ -84,4 +70,10 @@ public interface SeckillConfigService {
      */
     PageResult<SeckillConfigDO> getSeckillConfigPage(SeckillConfigPageReqVO pageVO);
 
+    /**
+     * 获得所有正常状态的时段配置列表
+     *
+     * @return 秒杀时段列表
+     */
+    List<SeckillConfigDO> getListAllSimple();
 }

+ 41 - 33
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillconfig/SeckillConfigServiceImpl.java

@@ -1,6 +1,7 @@
 package cn.iocoder.yudao.module.promotion.service.seckill.seckillconfig;
 
 import cn.hutool.core.collection.CollUtil;
+import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigCreateReqVO;
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigPageReqVO;
@@ -15,11 +16,11 @@ import javax.annotation.Resource;
 import java.time.LocalTime;
 import java.util.Collection;
 import java.util.List;
-import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
-import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.SECKILL_TIME_CONFLICTS;
-import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.SECKILL_TIME_NOT_EXISTS;
+import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
 
 /**
  * 秒杀时段 Service 实现类
@@ -36,7 +37,7 @@ public class SeckillConfigServiceImpl implements SeckillConfigService {
     @Override
     public Long createSeckillConfig(SeckillConfigCreateReqVO createReqVO) {
         // 校验时间段是否冲突
-        //validateSeckillConfigConflict(null, createReqVO.getStartTime(), createReqVO.getEndTime());
+        validateSeckillConfigConflict(createReqVO.getStartTime(), createReqVO.getEndTime());
 
         // 插入
         SeckillConfigDO seckillConfig = SeckillConfigConvert.INSTANCE.convert(createReqVO);
@@ -48,9 +49,9 @@ public class SeckillConfigServiceImpl implements SeckillConfigService {
     @Override
     public void updateSeckillConfig(SeckillConfigUpdateReqVO updateReqVO) {
         // 校验存在
-        this.validateSeckillConfigExists(updateReqVO.getId());
+        validateSeckillConfigExists(updateReqVO.getId());
         // 校验时间段是否冲突
-        //validateSeckillConfigConflict(updateReqVO.getId(), updateReqVO.getStartTime(), updateReqVO.getEndTime());
+        validateSeckillConfigConflict(updateReqVO.getStartTime(), updateReqVO.getEndTime());
 
         // 更新
         SeckillConfigDO updateObj = SeckillConfigConvert.INSTANCE.convert(updateReqVO);
@@ -60,7 +61,8 @@ public class SeckillConfigServiceImpl implements SeckillConfigService {
     @Override
     public void deleteSeckillConfig(Long id) {
         // 校验存在
-        this.validateSeckillConfigExists(id);
+        validateSeckillConfigExists(id);
+
         // 删除
         seckillConfigMapper.deleteById(id);
     }
@@ -77,21 +79,32 @@ public class SeckillConfigServiceImpl implements SeckillConfigService {
      * @param startTime 开始时间
      * @param endTime   结束时间
      */
-    private void validateSeckillConfigConflict(Long id, LocalTime startTime, LocalTime endTime) {
-        //查询开始时间,结束时间,是否在别人的时间段内
-        // TODO 为什么要检查这个时间段是否冲突 比如早上 09:00:00 - 10:00:00 我再添加一个 09:00:00 - 09:30:00 不可以这样吗?
-        List<SeckillConfigDO> startTimeList = seckillConfigMapper.selectListByTime(startTime);
-        List<SeckillConfigDO> endTimeList = seckillConfigMapper.selectListByTime(endTime);
-        //查询自己时间段内是否有时间段
-        List<SeckillConfigDO> startEndTimeList = seckillConfigMapper.selectListByTime(startTime, endTime);
-        if (id != null) {
-            //移除自己
-            startTimeList.removeIf(seckillConfig -> Objects.equals(seckillConfig.getId(), id));
-            endTimeList.removeIf(seckillConfig -> Objects.equals(seckillConfig.getId(), id));
-            startEndTimeList.removeIf(seckillConfig -> Objects.equals(seckillConfig.getId(), id));
+    private void validateSeckillConfigConflict(String startTime, String endTime) {
+        LocalTime startTime1 = LocalTime.parse(startTime);
+        LocalTime endTime1 = LocalTime.parse(endTime);
+        // 检查选择的时间是否相等
+        if (startTime1.equals(endTime1)) {
+            throw exception(SECKILL_TIME_EQUAL);
+        }
+        // 检查开始时间是否在结束时间之前
+        if (startTime1.isAfter(endTime1)) {
+            throw exception(SECKILL_START_TIME_BEFORE_END_TIME);
         }
-        if (CollUtil.isNotEmpty(startTimeList) || CollUtil.isNotEmpty(endTimeList)
-                || CollUtil.isNotEmpty(startEndTimeList)) {
+        // 查询出所有的时段配置
+        List<SeckillConfigDO> configDOs = seckillConfigMapper.selectList();
+        // 过滤出重叠的时段 ids
+        Set<Long> ids = configDOs.stream().filter((config) -> {
+            LocalTime startTime2 = LocalTime.parse(config.getStartTime());
+            LocalTime endTime2 = LocalTime.parse(config.getEndTime());
+            // 判断时间是否重叠
+            // 开始时间在已配置时段的结束时间之前 且 结束时间在已配置时段的开始时间之后 []
+            return startTime1.isBefore(endTime2) && endTime1.isAfter(startTime2)
+                    // 开始时间在已配置时段的开始时间之前 且 结束时间在已配置时段的开始时间之后 (] 或 ()
+                    || startTime1.isBefore(startTime2) && endTime1.isAfter(startTime2)
+                    // 开始时间在已配置时段的结束时间之前 且 结束时间在已配值时段的结束时间之后 [) 或 ()
+                    || startTime1.isBefore(endTime2) && endTime1.isAfter(endTime2);
+        }).map(SeckillConfigDO::getId).collect(Collectors.toSet());
+        if (CollUtil.isNotEmpty(ids)) {
             throw exception(SECKILL_TIME_CONFLICTS);
         }
     }
@@ -107,28 +120,23 @@ public class SeckillConfigServiceImpl implements SeckillConfigService {
     }
 
     @Override
-    public void validateSeckillConfigExists(Collection<Long> timeIds) {
-        if (CollUtil.isEmpty(timeIds)) {
+    public void validateSeckillConfigExists(Collection<Long> configIds) {
+        if (CollUtil.isEmpty(configIds)) {
             throw exception(SECKILL_TIME_NOT_EXISTS);
         }
-        if (seckillConfigMapper.selectBatchIds(timeIds).size() != timeIds.size()) {
+        if (seckillConfigMapper.selectBatchIds(configIds).size() != configIds.size()) {
             throw exception(SECKILL_TIME_NOT_EXISTS);
         }
     }
 
     @Override
-    public void seckillActivityCountIncr(Collection<Long> ids) {
-        seckillConfigMapper.updateActivityCount(ids, "+", 1);
-    }
-
-    @Override
-    public void seckillActivityCountDecr(Collection<Long> ids) {
-        seckillConfigMapper.updateActivityCount(ids, "-", 1);
+    public PageResult<SeckillConfigDO> getSeckillConfigPage(SeckillConfigPageReqVO pageVO) {
+        return seckillConfigMapper.selectPage(pageVO);
     }
 
     @Override
-    public PageResult<SeckillConfigDO> getSeckillConfigPage(SeckillConfigPageReqVO pageVO) {
-        return seckillConfigMapper.selectPage(pageVO);
+    public List<SeckillConfigDO> getListAllSimple() {
+        return seckillConfigMapper.selectList(SeckillConfigDO::getStatus, CommonStatusEnum.ENABLE.getStatus());
     }
 
 }

+ 15 - 15
yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/seckillactivity/SeckillActivityServiceImplTest.java

@@ -113,26 +113,26 @@ public class SeckillActivityServiceImplTest extends BaseDbUnitTest {
        });
        seckillActivityMapper.insert(dbSeckillActivity);
        // 测试 name 不匹配
-       seckillActivityMapper.insert(cloneIgnoreId(dbSeckillActivity, o -> o.setName(null)));
-       // 测试 status 不匹配
-       seckillActivityMapper.insert(cloneIgnoreId(dbSeckillActivity, o -> o.setStatus(null)));
-       // 测试 timeId 不匹配
+        seckillActivityMapper.insert(cloneIgnoreId(dbSeckillActivity, o -> o.setName(null)));
+        // 测试 status 不匹配
+        seckillActivityMapper.insert(cloneIgnoreId(dbSeckillActivity, o -> o.setStatus(null)));
+        // 测试 timeId 不匹配
         seckillActivityMapper.insert(cloneIgnoreId(dbSeckillActivity, o -> o.setConfigIds(null)));
-       // 测试 createTime 不匹配
-       seckillActivityMapper.insert(cloneIgnoreId(dbSeckillActivity, o -> o.setCreateTime(null)));
-       // 准备参数
-       SeckillActivityPageReqVO reqVO = new SeckillActivityPageReqVO();
-       reqVO.setName(null);
+        // 测试 createTime 不匹配
+        seckillActivityMapper.insert(cloneIgnoreId(dbSeckillActivity, o -> o.setCreateTime(null)));
+        // 准备参数
+        SeckillActivityPageReqVO reqVO = new SeckillActivityPageReqVO();
+        reqVO.setName(null);
         reqVO.setStatus(null);
         reqVO.setConfigId(null);
         reqVO.setCreateTime((new LocalDateTime[]{}));
 
-       // 调用
-       PageResult<SeckillActivityDO> pageResult = seckillActivityService.getSeckillActivityPage(reqVO);
-       // 断言
-       assertEquals(1, pageResult.getTotal());
-       assertEquals(1, pageResult.getList().size());
-       assertPojoEquals(dbSeckillActivity, pageResult.getList().get(0));
+        // 调用
+        PageResult<SeckillActivityDO> pageResult = seckillActivityService.getSeckillActivityPage(reqVO);
+        // 断言
+        assertEquals(1, pageResult.getTotal());
+        assertEquals(1, pageResult.getList().size());
+        assertPojoEquals(dbSeckillActivity, pageResult.getList().get(0));
     }
 
     @Test