Commit 6fdd4da0b3f04d6a096b6a131cc14956679cef77

Authored by YunaiV
1 parent be2ee905

优化秒杀活动的管理后台代码

Showing 20 changed files with 183 additions and 209 deletions
yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/spu/ProductSpuApi.java
@@ -21,4 +21,11 @@ public interface ProductSpuApi { @@ -21,4 +21,11 @@ public interface ProductSpuApi {
21 */ 21 */
22 List<ProductSpuRespDTO> getSpuList(Collection<Long> ids); 22 List<ProductSpuRespDTO> getSpuList(Collection<Long> ids);
23 23
  24 + /**
  25 + * 获得 SPU
  26 + *
  27 + * @return SPU
  28 + */
  29 + ProductSpuRespDTO getSpu(Long id);
  30 +
24 } 31 }
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/spu/ProductSpuApiImpl.java
@@ -5,6 +5,8 @@ import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; @@ -5,6 +5,8 @@ import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
5 import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert; 5 import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert;
6 import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; 6 import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
7 import cn.iocoder.yudao.module.product.dal.mysql.spu.ProductSpuMapper; 7 import cn.iocoder.yudao.module.product.dal.mysql.spu.ProductSpuMapper;
  8 +import cn.iocoder.yudao.module.product.service.sku.ProductSkuService;
  9 +import cn.iocoder.yudao.module.product.service.spu.ProductSpuService;
8 import org.springframework.stereotype.Service; 10 import org.springframework.stereotype.Service;
9 import org.springframework.validation.annotation.Validated; 11 import org.springframework.validation.annotation.Validated;
10 12
@@ -24,15 +26,19 @@ import java.util.List; @@ -24,15 +26,19 @@ import java.util.List;
24 public class ProductSpuApiImpl implements ProductSpuApi { 26 public class ProductSpuApiImpl implements ProductSpuApi {
25 27
26 @Resource 28 @Resource
27 - private ProductSpuMapper productSpuMapper; 29 + private ProductSpuService spuService;
28 30
29 @Override 31 @Override
30 - public List<ProductSpuRespDTO> getSpuList(Collection<Long> spuIds) {  
31 - if (CollectionUtil.isEmpty(spuIds)) { 32 + public List<ProductSpuRespDTO> getSpuList(Collection<Long> ids) {
  33 + if (CollectionUtil.isEmpty(ids)) {
32 return Collections.emptyList(); 34 return Collections.emptyList();
33 } 35 }
34 - List<ProductSpuDO> productSpuDOList = productSpuMapper.selectBatchIds(spuIds);  
35 - return ProductSpuConvert.INSTANCE.convertList2(productSpuDOList); 36 + return ProductSpuConvert.INSTANCE.convertList2(spuService.getSpuList(ids));
  37 + }
  38 +
  39 + @Override
  40 + public ProductSpuRespDTO getSpu(Long id) {
  41 + return ProductSpuConvert.INSTANCE.convert02(spuService.getSpu(id));
36 } 42 }
37 43
38 } 44 }
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java
@@ -64,6 +64,8 @@ public interface ProductSpuConvert { @@ -64,6 +64,8 @@ public interface ProductSpuConvert {
64 64
65 ProductSpuDetailRespVO convert03(ProductSpuDO spu); 65 ProductSpuDetailRespVO convert03(ProductSpuDO spu);
66 66
  67 + ProductSpuRespDTO convert02(ProductSpuDO bean);
  68 +
67 // ========== 用户 App 相关 ========== 69 // ========== 用户 App 相关 ==========
68 70
69 PageResult<AppProductSpuPageRespVO> convertPageForGetSpuPage(PageResult<ProductSpuDO> page); 71 PageResult<AppProductSpuPageRespVO> convertPageForGetSpuPage(PageResult<ProductSpuDO> page);
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java
@@ -50,14 +50,11 @@ public interface ErrorCodeConstants { @@ -50,14 +50,11 @@ public interface ErrorCodeConstants {
50 ErrorCode SECKILL_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED = new ErrorCode(1013008003, "秒杀活动已关闭,不能修改"); 50 ErrorCode SECKILL_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED = new ErrorCode(1013008003, "秒杀活动已关闭,不能修改");
51 ErrorCode SECKILL_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1013008004, "秒杀活动未关闭或未结束,不能删除"); 51 ErrorCode SECKILL_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1013008004, "秒杀活动未关闭或未结束,不能删除");
52 ErrorCode SECKILL_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1013008005, "秒杀活动已关闭,不能重复关闭"); 52 ErrorCode SECKILL_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1013008005, "秒杀活动已关闭,不能重复关闭");
53 - ErrorCode SECKILL_ACTIVITY_CLOSE_FAIL_STATUS_END = new ErrorCode(1013008006, "秒杀活动已结束,不能关闭");  
54 53
55 // ========== 秒杀时段 1013009000 ========== 54 // ========== 秒杀时段 1013009000 ==========
56 - ErrorCode SECKILL_TIME_NOT_EXISTS = new ErrorCode(1013009000, "秒杀时段不存在");  
57 - ErrorCode SECKILL_TIME_CONFLICTS = new ErrorCode(1013009001, "秒杀时段冲突");  
58 - ErrorCode SECKILL_TIME_EQUAL = new ErrorCode(1013009002, "秒杀时段开始时间和结束时间不能相等");  
59 - ErrorCode SECKILL_START_TIME_BEFORE_END_TIME = new ErrorCode(1013009003, "秒杀时段开始时间不能在结束时间之后");  
60 - ErrorCode SECKILL_TIME_DISABLE = new ErrorCode(1013009004, "秒杀时段已关闭"); 55 + ErrorCode SECKILL_CONFIG_NOT_EXISTS = new ErrorCode(1013009000, "秒杀时段不存在");
  56 + ErrorCode SECKILL_CONFIG_TIME_CONFLICTS = new ErrorCode(1013009001, "秒杀时段冲突");
  57 + ErrorCode SECKILL_CONFIG_DISABLE = new ErrorCode(1013009004, "秒杀时段已关闭");
61 58
62 // ========== 拼团活动 1013010000 ========== 59 // ========== 拼团活动 1013010000 ==========
63 ErrorCode COMBINATION_ACTIVITY_NOT_EXISTS = new ErrorCode(1013010000, "拼团活动不存在"); 60 ErrorCode COMBINATION_ACTIVITY_NOT_EXISTS = new ErrorCode(1013010000, "拼团活动不存在");
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillActivityController.java
1 package cn.iocoder.yudao.module.promotion.controller.admin.seckill; 1 package cn.iocoder.yudao.module.promotion.controller.admin.seckill;
2 2
  3 +import cn.hutool.core.collection.CollUtil;
3 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 4 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 import cn.iocoder.yudao.framework.common.pojo.PageResult; 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi; 6 import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
@@ -19,7 +20,6 @@ import org.springframework.web.bind.annotation.*; @@ -19,7 +20,6 @@ import org.springframework.web.bind.annotation.*;
19 import javax.annotation.Resource; 20 import javax.annotation.Resource;
20 import javax.validation.Valid; 21 import javax.validation.Valid;
21 import java.util.List; 22 import java.util.List;
22 -import java.util.Set;  
23 23
24 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 24 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
25 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; 25 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
@@ -33,7 +33,7 @@ public class SeckillActivityController { @@ -33,7 +33,7 @@ public class SeckillActivityController {
33 @Resource 33 @Resource
34 private SeckillActivityService seckillActivityService; 34 private SeckillActivityService seckillActivityService;
35 @Resource 35 @Resource
36 - private ProductSpuApi spuApi; 36 + private ProductSpuApi productSpuApi;
37 37
38 @PostMapping("/create") 38 @PostMapping("/create")
39 @Operation(summary = "创建秒杀活动") 39 @Operation(summary = "创建秒杀活动")
@@ -73,21 +73,27 @@ public class SeckillActivityController { @@ -73,21 +73,27 @@ public class SeckillActivityController {
73 @Parameter(name = "id", description = "编号", required = true, example = "1024") 73 @Parameter(name = "id", description = "编号", required = true, example = "1024")
74 @PreAuthorize("@ss.hasPermission('promotion:seckill-activity:query')") 74 @PreAuthorize("@ss.hasPermission('promotion:seckill-activity:query')")
75 public CommonResult<SeckillActivityDetailRespVO> getSeckillActivity(@RequestParam("id") Long id) { 75 public CommonResult<SeckillActivityDetailRespVO> getSeckillActivity(@RequestParam("id") Long id) {
76 - SeckillActivityDO seckillActivity = seckillActivityService.getSeckillActivity(id);  
77 - List<SeckillProductDO> seckillProducts = seckillActivityService.getSeckillProductListByActivityId(id);  
78 - return success(SeckillActivityConvert.INSTANCE.convert(seckillActivity, seckillProducts)); 76 + SeckillActivityDO activity = seckillActivityService.getSeckillActivity(id);
  77 + List<SeckillProductDO> products = seckillActivityService.getSeckillProductListByActivityId(id);
  78 + return success(SeckillActivityConvert.INSTANCE.convert(activity, products));
79 } 79 }
80 80
81 @GetMapping("/page") 81 @GetMapping("/page")
82 @Operation(summary = "获得秒杀活动分页") 82 @Operation(summary = "获得秒杀活动分页")
83 @PreAuthorize("@ss.hasPermission('promotion:seckill-activity:query')") 83 @PreAuthorize("@ss.hasPermission('promotion:seckill-activity:query')")
84 public CommonResult<PageResult<SeckillActivityRespVO>> getSeckillActivityPage(@Valid SeckillActivityPageReqVO pageVO) { 84 public CommonResult<PageResult<SeckillActivityRespVO>> getSeckillActivityPage(@Valid SeckillActivityPageReqVO pageVO) {
  85 + // 查询活动列表
85 PageResult<SeckillActivityDO> pageResult = seckillActivityService.getSeckillActivityPage(pageVO); 86 PageResult<SeckillActivityDO> pageResult = seckillActivityService.getSeckillActivityPage(pageVO);
86 - Set<Long> aIds = convertSet(pageResult.getList(), SeckillActivityDO::getId);  
87 - List<SeckillProductDO> seckillProducts = seckillActivityService.getSeckillProductListByActivityId(aIds);  
88 - Set<Long> spuIds = convertSet(pageResult.getList(), SeckillActivityDO::getSpuId);  
89 - List<ProductSpuRespDTO> spuList = spuApi.getSpuList(spuIds);  
90 - return success(SeckillActivityConvert.INSTANCE.convertPage(pageResult, seckillProducts, spuList)); 87 + if (CollUtil.isEmpty(pageResult.getList())) {
  88 + return success(PageResult.empty(pageResult.getTotal()));
  89 + }
  90 +
  91 + // 拼接数据
  92 + List<SeckillProductDO> products = seckillActivityService.getSeckillProductListByActivityId(
  93 + convertSet(pageResult.getList(), SeckillActivityDO::getId));
  94 + List<ProductSpuRespDTO> spuList = productSpuApi.getSpuList(
  95 + convertSet(pageResult.getList(), SeckillActivityDO::getSpuId));
  96 + return success(SeckillActivityConvert.INSTANCE.convertPage(pageResult, products, spuList));
91 } 97 }
92 98
93 } 99 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillConfigController.java
@@ -92,4 +92,5 @@ public class SeckillConfigController { @@ -92,4 +92,5 @@ public class SeckillConfigController {
92 PageResult<SeckillConfigDO> pageResult = seckillConfigService.getSeckillConfigPage(pageVO); 92 PageResult<SeckillConfigDO> pageResult = seckillConfigService.getSeckillConfigPage(pageVO);
93 return success(SeckillConfigConvert.INSTANCE.convertPage(pageResult)); 93 return success(SeckillConfigConvert.INSTANCE.convertPage(pageResult));
94 } 94 }
  95 +
95 } 96 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityBaseVO.java
@@ -20,7 +20,7 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ @@ -20,7 +20,7 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
20 @Data 20 @Data
21 public class SeckillActivityBaseVO { 21 public class SeckillActivityBaseVO {
22 22
23 - @Schema(description = "秒杀活动商品id", requiredMode = Schema.RequiredMode.REQUIRED, example = "[121,1212]") 23 + @Schema(description = "秒杀活动商品 id", requiredMode = Schema.RequiredMode.REQUIRED, example = "[121,1212]")
24 @NotNull(message = "秒杀活动商品不能为空") 24 @NotNull(message = "秒杀活动商品不能为空")
25 private Long spuId; 25 private Long spuId;
26 26
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityCreateReqVO.java
1 package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity; 1 package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity;
2 2
3 3
4 -import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductCreateReqVO; 4 +import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductBaseVO;
5 import io.swagger.v3.oas.annotations.media.Schema; 5 import io.swagger.v3.oas.annotations.media.Schema;
6 import lombok.Data; 6 import lombok.Data;
7 import lombok.EqualsAndHashCode; 7 import lombok.EqualsAndHashCode;
@@ -16,6 +16,6 @@ import java.util.List; @@ -16,6 +16,6 @@ import java.util.List;
16 public class SeckillActivityCreateReqVO extends SeckillActivityBaseVO { 16 public class SeckillActivityCreateReqVO extends SeckillActivityBaseVO {
17 17
18 @Schema(description = "秒杀商品", requiredMode = Schema.RequiredMode.REQUIRED) 18 @Schema(description = "秒杀商品", requiredMode = Schema.RequiredMode.REQUIRED)
19 - private List<SeckillProductCreateReqVO> products; 19 + private List<SeckillProductBaseVO> products;
20 20
21 } 21 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityRespVO.java
@@ -21,28 +21,28 @@ public class SeckillActivityRespVO extends SeckillActivityBaseVO { @@ -21,28 +21,28 @@ public class SeckillActivityRespVO extends SeckillActivityBaseVO {
21 @Schema(description = "商品主图", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xx.png") 21 @Schema(description = "商品主图", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xx.png")
22 private String picUrl; 22 private String picUrl;
23 23
24 - @Schema(description = "秒杀活动id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") 24 + @Schema(description = "秒杀活动 id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
25 private Long id; 25 private Long id;
26 26
27 @Schema(description = "秒杀商品", requiredMode = Schema.RequiredMode.REQUIRED) 27 @Schema(description = "秒杀商品", requiredMode = Schema.RequiredMode.REQUIRED)
28 private List<SeckillProductRespVO> products; 28 private List<SeckillProductRespVO> products;
29 29
30 - @Schema(description = "活动状态 开启:0 禁用:1", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") 30 + @Schema(description = "活动状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
31 private Integer status; 31 private Integer status;
32 32
33 @Schema(description = "订单实付金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "22354") 33 @Schema(description = "订单实付金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "22354")
34 private Integer totalPrice; 34 private Integer totalPrice;
35 35
36 - @Schema(description = "秒杀库存", example = "10") 36 + @Schema(description = "秒杀库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
37 private Integer stock; 37 private Integer stock;
38 38
39 - @Schema(description = "秒杀总库存", example = "20") 39 + @Schema(description = "秒杀总库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "20")
40 private Integer totalStock; 40 private Integer totalStock;
41 41
42 - @Schema(description = "新增订单数", example = "20") 42 + @Schema(description = "新增订单数", requiredMode = Schema.RequiredMode.REQUIRED, example = "20")
43 private Integer orderCount; 43 private Integer orderCount;
44 44
45 - @Schema(description = "付款人数", example = "20") 45 + @Schema(description = "付款人数", requiredMode = Schema.RequiredMode.REQUIRED, example = "20")
46 private Integer userCount; 46 private Integer userCount;
47 47
48 @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) 48 @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityUpdateReqVO.java
1 package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity; 1 package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity;
2 2
3 -import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductUpdateReqVO; 3 +import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductBaseVO;
4 import io.swagger.v3.oas.annotations.media.Schema; 4 import io.swagger.v3.oas.annotations.media.Schema;
5 import lombok.Data; 5 import lombok.Data;
6 import lombok.EqualsAndHashCode; 6 import lombok.EqualsAndHashCode;
@@ -18,6 +18,6 @@ public class SeckillActivityUpdateReqVO extends SeckillActivityBaseVO { @@ -18,6 +18,6 @@ public class SeckillActivityUpdateReqVO extends SeckillActivityBaseVO {
18 private Long id; 18 private Long id;
19 19
20 @Schema(description = "秒杀商品", requiredMode = Schema.RequiredMode.REQUIRED) 20 @Schema(description = "秒杀商品", requiredMode = Schema.RequiredMode.REQUIRED)
21 - private List<SeckillProductUpdateReqVO> products; 21 + private List<SeckillProductBaseVO> products;
22 22
23 } 23 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductBaseVO.java
@@ -22,7 +22,7 @@ public class SeckillProductBaseVO { @@ -22,7 +22,7 @@ public class SeckillProductBaseVO {
22 @NotNull(message = "秒杀金额,单位:分不能为空") 22 @NotNull(message = "秒杀金额,单位:分不能为空")
23 private Integer seckillPrice; 23 private Integer seckillPrice;
24 24
25 - @Schema(description = "秒杀库存", requiredMode = Schema.RequiredMode.REQUIRED) 25 + @Schema(description = "秒杀库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
26 @NotNull(message = "秒杀库存不能为空") 26 @NotNull(message = "秒杀库存不能为空")
27 private Integer stock; 27 private Integer stock;
28 28
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductCreateReqVO.java deleted
1 -package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product;  
2 -  
3 -import io.swagger.v3.oas.annotations.media.Schema;  
4 -import lombok.Data;  
5 -import lombok.EqualsAndHashCode;  
6 -import lombok.ToString;  
7 -@Schema(description = "管理后台 - 秒杀参与商品创建 Request VO")  
8 -@Data  
9 -@EqualsAndHashCode(callSuper = true)  
10 -@ToString(callSuper = true)  
11 -public class SeckillProductCreateReqVO extends SeckillProductBaseVO {  
12 -  
13 -}  
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductUpdateReqVO.java deleted
1 -package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product;  
2 -  
3 -import io.swagger.v3.oas.annotations.media.Schema;  
4 -import lombok.Data;  
5 -import lombok.EqualsAndHashCode;  
6 -import lombok.ToString;  
7 -  
8 -@Schema(description = "管理后台 - 秒杀参与商品更新 Request VO")  
9 -@Data  
10 -@EqualsAndHashCode(callSuper = true)  
11 -@ToString(callSuper = true)  
12 -public class SeckillProductUpdateReqVO extends SeckillProductBaseVO {  
13 -  
14 -}  
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckillactivity/SeckillActivityConvert.java
@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.promotion.convert.seckill.seckillactivity; @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.promotion.convert.seckill.seckillactivity;
2 2
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; 4 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
  5 +import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
5 import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; 6 import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
6 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityCreateReqVO; 7 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityCreateReqVO;
7 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityDetailRespVO; 8 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityDetailRespVO;
@@ -19,6 +20,8 @@ import org.mapstruct.factory.Mappers; @@ -19,6 +20,8 @@ import org.mapstruct.factory.Mappers;
19 import java.util.List; 20 import java.util.List;
20 import java.util.Map; 21 import java.util.Map;
21 22
  23 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
  24 +
22 /** 25 /**
23 * 秒杀活动 Convert 26 * 秒杀活动 Convert
24 * 27 *
@@ -37,43 +40,43 @@ public interface SeckillActivityConvert { @@ -37,43 +40,43 @@ public interface SeckillActivityConvert {
37 40
38 List<SeckillActivityRespVO> convertList(List<SeckillActivityDO> list); 41 List<SeckillActivityRespVO> convertList(List<SeckillActivityDO> list);
39 42
40 - PageResult<SeckillActivityRespVO> convertPage(PageResult<SeckillActivityDO> page);  
41 -  
42 - default PageResult<SeckillActivityRespVO> convertPage(PageResult<SeckillActivityDO> page, List<SeckillProductDO> seckillProducts, List<ProductSpuRespDTO> spuList) {  
43 - Map<Long, ProductSpuRespDTO> spuMap = CollectionUtils.convertMap(spuList, ProductSpuRespDTO::getId, c -> c); 43 + default PageResult<SeckillActivityRespVO> convertPage(PageResult<SeckillActivityDO> page,
  44 + List<SeckillProductDO> seckillProducts,
  45 + List<ProductSpuRespDTO> spuList) {
44 PageResult<SeckillActivityRespVO> pageResult = convertPage(page); 46 PageResult<SeckillActivityRespVO> pageResult = convertPage(page);
  47 + // 拼接商品
  48 + Map<Long, ProductSpuRespDTO> spuMap = convertMap(spuList, ProductSpuRespDTO::getId);
45 pageResult.getList().forEach(item -> { 49 pageResult.getList().forEach(item -> {
46 - item.setSpuName(spuMap.get(item.getSpuId()).getName());  
47 - item.setPicUrl(spuMap.get(item.getSpuId()).getPicUrl());  
48 item.setProducts(convertList2(seckillProducts)); 50 item.setProducts(convertList2(seckillProducts));
  51 + MapUtils.findAndThen(spuMap, item.getSpuId(),
  52 + spu -> item.setSpuName(spu.getName()).setPicUrl(spu.getPicUrl()));
49 }); 53 });
50 return pageResult; 54 return pageResult;
51 } 55 }
  56 + PageResult<SeckillActivityRespVO> convertPage(PageResult<SeckillActivityDO> page);
52 57
53 SeckillActivityDetailRespVO convert1(SeckillActivityDO seckillActivity); 58 SeckillActivityDetailRespVO convert1(SeckillActivityDO seckillActivity);
54 59
55 - default SeckillActivityDetailRespVO convert(SeckillActivityDO seckillActivity, List<SeckillProductDO> seckillProducts) {  
56 - return convert1(seckillActivity).setProducts(convertList2(seckillProducts)); 60 + default SeckillActivityDetailRespVO convert(SeckillActivityDO activity,
  61 + List<SeckillProductDO> products) {
  62 + return convert1(activity).setProducts(convertList2(products));
57 } 63 }
58 -  
59 - // TODO @puhui999:参数改成 activity、product 会不会干净一点哈  
60 - @Mappings({  
61 - @Mapping(target = "id", ignore = true),  
62 - @Mapping(target = "activityId", source = "activityDO.id"),  
63 - @Mapping(target = "configIds", source = "activityDO.configIds"),  
64 - @Mapping(target = "spuId", source = "activityDO.spuId"),  
65 - @Mapping(target = "skuId", source = "vo.skuId"),  
66 - @Mapping(target = "seckillPrice", source = "vo.seckillPrice"),  
67 - @Mapping(target = "stock", source = "vo.stock"),  
68 - @Mapping(target = "activityStartTime", source = "activityDO.startTime"),  
69 - @Mapping(target = "activityEndTime", source = "activityDO.endTime")  
70 - })  
71 - SeckillProductDO convert(SeckillActivityDO activityDO, SeckillProductBaseVO vo); 64 + List<SeckillProductRespVO> convertList2(List<SeckillProductDO> productDOs);
72 65
73 default List<SeckillProductDO> convertList(List<? extends SeckillProductBaseVO> products, SeckillActivityDO activityDO) { 66 default List<SeckillProductDO> convertList(List<? extends SeckillProductBaseVO> products, SeckillActivityDO activityDO) {
74 return CollectionUtils.convertList(products, item -> convert(activityDO, item).setActivityStatus(activityDO.getStatus())); 67 return CollectionUtils.convertList(products, item -> convert(activityDO, item).setActivityStatus(activityDO.getStatus()));
75 } 68 }
76 -  
77 - List<SeckillProductRespVO> convertList2(List<SeckillProductDO> productDOs); 69 + @Mappings({
  70 + @Mapping(target = "id", ignore = true),
  71 + @Mapping(target = "activityId", source = "activity.id"),
  72 + @Mapping(target = "configIds", source = "activity.configIds"),
  73 + @Mapping(target = "spuId", source = "activity.spuId"),
  74 + @Mapping(target = "skuId", source = "product.skuId"),
  75 + @Mapping(target = "seckillPrice", source = "product.seckillPrice"),
  76 + @Mapping(target = "stock", source = "product.stock"),
  77 + @Mapping(target = "activityStartTime", source = "activity.startTime"),
  78 + @Mapping(target = "activityEndTime", source = "activity.endTime")
  79 + })
  80 + SeckillProductDO convert(SeckillActivityDO activity, SeckillProductBaseVO product);
78 81
79 } 82 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillProductMapper.java
1 package cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillactivity; 1 package cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillactivity;
2 2
3 -import cn.hutool.core.collection.CollUtil;  
4 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; 3 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
5 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO; 4 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO;
6 -import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;  
7 import org.apache.ibatis.annotations.Mapper; 5 import org.apache.ibatis.annotations.Mapper;
8 6
9 import java.util.Collection; 7 import java.util.Collection;
@@ -25,15 +23,4 @@ public interface SeckillProductMapper extends BaseMapperX&lt;SeckillProductDO&gt; { @@ -25,15 +23,4 @@ public interface SeckillProductMapper extends BaseMapperX&lt;SeckillProductDO&gt; {
25 return selectList(SeckillProductDO::getActivityId, ids); 23 return selectList(SeckillProductDO::getActivityId, ids);
26 } 24 }
27 25
28 - default List<SeckillProductDO> selectListBySkuIds(Collection<Long> skuIds) {  
29 - return selectList(SeckillProductDO::getSkuId, skuIds);  
30 - }  
31 -  
32 - default void updateTimeIdsByActivityId(Long id, List<Long> timeIds) {  
33 - new LambdaUpdateChainWrapper<>(this)  
34 - .set(SeckillProductDO::getConfigIds, CollUtil.join(timeIds, ","))  
35 - .eq(SeckillProductDO::getActivityId, id)  
36 - .update();  
37 - }  
38 -  
39 } 26 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillactivity/SeckillActivityService.java
@@ -56,14 +56,6 @@ public interface SeckillActivityService { @@ -56,14 +56,6 @@ public interface SeckillActivityService {
56 SeckillActivityDO getSeckillActivity(Long id); 56 SeckillActivityDO getSeckillActivity(Long id);
57 57
58 /** 58 /**
59 - * 获得秒杀活动列表  
60 - *  
61 - * @param ids 编号  
62 - * @return 秒杀活动列表  
63 - */  
64 - List<SeckillActivityDO> getSeckillActivityList(Collection<Long> ids);  
65 -  
66 - /**  
67 * 获得秒杀活动分页 59 * 获得秒杀活动分页
68 * 60 *
69 * @param pageReqVO 分页查询 61 * @param pageReqVO 分页查询
@@ -74,17 +66,17 @@ public interface SeckillActivityService { @@ -74,17 +66,17 @@ public interface SeckillActivityService {
74 /** 66 /**
75 * 通过活动编号获取活动商品 67 * 通过活动编号获取活动商品
76 * 68 *
77 - * @param id 活动编号 69 + * @param activityId 活动编号
78 * @return 活动商品列表 70 * @return 活动商品列表
79 */ 71 */
80 - List<SeckillProductDO> getSeckillProductListByActivityId(Long id); 72 + List<SeckillProductDO> getSeckillProductListByActivityId(Long activityId);
81 73
82 /** 74 /**
83 * 通过活动编号获取活动商品 75 * 通过活动编号获取活动商品
84 * 76 *
85 - * @param ids 活动编号 77 + * @param activityIds 活动编号
86 * @return 活动商品列表 78 * @return 活动商品列表
87 */ 79 */
88 - List<SeckillProductDO> getSeckillProductListByActivityId(Collection<Long> ids); 80 + List<SeckillProductDO> getSeckillProductListByActivityId(Collection<Long> activityIds);
89 81
90 } 82 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillactivity/SeckillActivityServiceImpl.java
1 package cn.iocoder.yudao.module.promotion.service.seckill.seckillactivity; 1 package cn.iocoder.yudao.module.promotion.service.seckill.seckillactivity;
2 2
3 -import cn.hutool.core.collection.CollUtil;  
4 import cn.hutool.core.util.ObjectUtil; 3 import cn.hutool.core.util.ObjectUtil;
5 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 4 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
6 import cn.iocoder.yudao.framework.common.pojo.PageResult; 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
@@ -11,8 +10,7 @@ import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; @@ -11,8 +10,7 @@ import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
11 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityCreateReqVO; 10 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityCreateReqVO;
12 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityPageReqVO; 11 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityPageReqVO;
13 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityUpdateReqVO; 12 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityUpdateReqVO;
14 -import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductCreateReqVO;  
15 -import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductUpdateReqVO; 13 +import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductBaseVO;
16 import cn.iocoder.yudao.module.promotion.convert.seckill.seckillactivity.SeckillActivityConvert; 14 import cn.iocoder.yudao.module.promotion.convert.seckill.seckillactivity.SeckillActivityConvert;
17 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO; 15 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO;
18 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO; 16 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO;
@@ -27,7 +25,7 @@ import org.springframework.validation.annotation.Validated; @@ -27,7 +25,7 @@ import org.springframework.validation.annotation.Validated;
27 import javax.annotation.Resource; 25 import javax.annotation.Resource;
28 import java.util.Collection; 26 import java.util.Collection;
29 import java.util.List; 27 import java.util.List;
30 -import java.util.Set; 28 +import java.util.Map;
31 29
32 import static cn.hutool.core.collection.CollUtil.isNotEmpty; 30 import static cn.hutool.core.collection.CollUtil.isNotEmpty;
33 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 31 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
@@ -35,7 +33,7 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils. @@ -35,7 +33,7 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.
35 import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS; 33 import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS;
36 import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS; 34 import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS;
37 import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; 35 import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
38 -import static cn.iocoder.yudao.module.promotion.util.PromotionUtils.validateProductSkuAllExists; 36 +import static java.util.Collections.singletonList;
39 37
40 /** 38 /**
41 * 秒杀活动 Service 实现类 39 * 秒杀活动 Service 实现类
@@ -60,19 +58,15 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { @@ -60,19 +58,15 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
60 @Override 58 @Override
61 @Transactional(rollbackFor = Exception.class) 59 @Transactional(rollbackFor = Exception.class)
62 public Long createSeckillActivity(SeckillActivityCreateReqVO createReqVO) { 60 public Long createSeckillActivity(SeckillActivityCreateReqVO createReqVO) {
63 - // 校验商品秒秒杀时段是否冲突  
64 - validateProductSpuSeckillConflict(createReqVO.getConfigIds(), createReqVO.getSpuId(), null);  
65 - // 获取所选 spu 下的所有 sku  
66 - List<ProductSkuRespDTO> skus = productSkuApi.getSkuListBySpuId(CollUtil.newArrayList(createReqVO.getSpuId()));  
67 - // 校验商品 sku 是否存在  
68 - if (skus.size() != createReqVO.getProducts().size()) {  
69 - throw exception(SKU_NOT_EXISTS);  
70 - } 61 + // 校验商品秒杀时段是否冲突
  62 + validateProductConflict(createReqVO.getConfigIds(), createReqVO.getSpuId(), null);
  63 + // 校验商品是否存在
  64 + validateProductExists(createReqVO.getSpuId(), createReqVO.getProducts());
71 65
72 // 插入秒杀活动 66 // 插入秒杀活动
73 SeckillActivityDO activity = SeckillActivityConvert.INSTANCE.convert(createReqVO) 67 SeckillActivityDO activity = SeckillActivityConvert.INSTANCE.convert(createReqVO)
74 .setStatus(PromotionUtils.calculateActivityStatus(createReqVO.getEndTime())) 68 .setStatus(PromotionUtils.calculateActivityStatus(createReqVO.getEndTime()))
75 - .setTotalStock(getSumValue(createReqVO.getProducts(), SeckillProductCreateReqVO::getStock, Integer::sum)); 69 + .setTotalStock(getSumValue(createReqVO.getProducts(), SeckillProductBaseVO::getStock, Integer::sum));
76 seckillActivityMapper.insert(activity); 70 seckillActivityMapper.insert(activity);
77 // 插入商品 71 // 插入商品
78 List<SeckillProductDO> products = SeckillActivityConvert.INSTANCE.convertList(createReqVO.getProducts(), activity); 72 List<SeckillProductDO> products = SeckillActivityConvert.INSTANCE.convertList(createReqVO.getProducts(), activity);
@@ -80,35 +74,62 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { @@ -80,35 +74,62 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
80 return activity.getId(); 74 return activity.getId();
81 } 75 }
82 76
83 - private void validateProductSpuSeckillConflict(List<Long> configIds, Long spuId, Long activityId) {  
84 - // 校验秒杀时段是否存在 77 + /**
  78 + * 校验秒杀商品参与的活动是否存在冲突
  79 + *
  80 + * 1. 校验秒杀时段是否存在
  81 + * 2. 校验商品 spu 是否存在
  82 + * 3. 秒杀商品是否参加其它活动
  83 + *
  84 + * @param configIds 秒杀时段数组
  85 + * @param spuId 商品 SPU 编号
  86 + * @param activityId 秒杀活动编号
  87 + */
  88 + private void validateProductConflict(List<Long> configIds, Long spuId, Long activityId) {
  89 + // 1. 校验秒杀时段是否存在
85 seckillConfigService.validateSeckillConfigExists(configIds); 90 seckillConfigService.validateSeckillConfigExists(configIds);
86 - // 校验商品 spu 是否存在  
87 - List<ProductSpuRespDTO> spuList = productSpuApi.getSpuList(CollUtil.newArrayList(spuId));  
88 - if (CollUtil.isEmpty(spuList)) {  
89 - throw exception(SPU_NOT_EXISTS);  
90 - }  
91 - // 查询所有开启的秒杀活动  
92 - List<SeckillActivityDO> activityDOs = seckillActivityMapper.selectListByStatus(CommonStatusEnum.ENABLE.getStatus());  
93 - if (activityId != null) {  
94 - // 更新时移除本活动  
95 - activityDOs.removeIf(item -> ObjectUtil.equal(item.getId(), activityId)); 91 +
  92 + // 2.1 查询所有开启的秒杀活动
  93 + List<SeckillActivityDO> activityList = seckillActivityMapper.selectListByStatus(CommonStatusEnum.ENABLE.getStatus());
  94 + if (activityId != null) { // 排除自己
  95 + activityList.removeIf(item -> ObjectUtil.equal(item.getId(), activityId));
96 } 96 }
97 - // 过滤出所有 spuId 有交集的活动  
98 - List<SeckillActivityDO> activityDOs1 = convertList(activityDOs, c -> c, s -> ObjectUtil.equal(s.getSpuId(), spuId)); 97 + // TODO @puhui999:一个 spu,参与两个活动应该没关系,关键是活动时间不充能重叠;
  98 + // 2.2 过滤出所有 spuId 有交集的活动,判断是否存在重叠
  99 + List<SeckillActivityDO> activityDOs1 = filterList(activityList, s -> ObjectUtil.equal(s.getSpuId(), spuId));
99 if (isNotEmpty(activityDOs1)) { 100 if (isNotEmpty(activityDOs1)) {
100 throw exception(SECKILL_ACTIVITY_SPU_CONFLICTS); 101 throw exception(SECKILL_ACTIVITY_SPU_CONFLICTS);
101 } 102 }
102 - List<SeckillActivityDO> activityDOs2 = convertList(activityDOs, c -> c, s -> {  
103 - // 判断秒杀时段是否有交集  
104 - return containsAny(s.getConfigIds(), configIds);  
105 - });  
106 - 103 + // 2.3 过滤出所有 configIds 有交集的活动,判断是否存在重叠
  104 + List<SeckillActivityDO> activityDOs2 = filterList(activityList, s -> containsAny(s.getConfigIds(), configIds));
107 if (isNotEmpty(activityDOs2)) { 105 if (isNotEmpty(activityDOs2)) {
108 - throw exception(SECKILL_TIME_CONFLICTS); 106 + throw exception(SECKILL_ACTIVITY_SPU_CONFLICTS);
109 } 107 }
110 } 108 }
111 109
  110 + /**
  111 + * 校验秒杀商品是否都存在
  112 + *
  113 + * @param spuId 商品 SPU 编号
  114 + * @param products 秒杀商品
  115 + */
  116 + private void validateProductExists(Long spuId, List<SeckillProductBaseVO> products) {
  117 + // 1. 校验商品 spu 是否存在
  118 + ProductSpuRespDTO spu = productSpuApi.getSpu(spuId);
  119 + if (spu == null) {
  120 + throw exception(SPU_NOT_EXISTS);
  121 + }
  122 +
  123 + // 2. 校验商品 sku 都存在
  124 + Map<Long, ProductSkuRespDTO> skuMap = convertMap(productSkuApi.getSkuListBySpuId(singletonList(spuId)),
  125 + ProductSkuRespDTO::getId);
  126 + products.forEach(product -> {
  127 + if (!skuMap.containsKey(product.getSkuId())) {
  128 + throw exception(SKU_NOT_EXISTS);
  129 + }
  130 + });
  131 + }
  132 +
112 @Override 133 @Override
113 @Transactional(rollbackFor = Exception.class) 134 @Transactional(rollbackFor = Exception.class)
114 public void updateSeckillActivity(SeckillActivityUpdateReqVO updateReqVO) { 135 public void updateSeckillActivity(SeckillActivityUpdateReqVO updateReqVO) {
@@ -118,29 +139,26 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { @@ -118,29 +139,26 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
118 throw exception(SECKILL_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED); 139 throw exception(SECKILL_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED);
119 } 140 }
120 // 校验商品是否冲突 141 // 校验商品是否冲突
121 - validateProductSpuSeckillConflict(updateReqVO.getConfigIds(), updateReqVO.getSpuId(), updateReqVO.getId());  
122 - // 获取所选 spu下的所有 sku  
123 - List<ProductSkuRespDTO> skus = productSkuApi.getSkuListBySpuId(CollUtil.newArrayList(updateReqVO.getSpuId()));  
124 - // 校验商品 sku 是否存在  
125 - validateProductSkuAllExists(skus, updateReqVO.getProducts(), SeckillProductUpdateReqVO::getSkuId); 142 + validateProductConflict(updateReqVO.getConfigIds(), updateReqVO.getSpuId(), updateReqVO.getId());
  143 + // 校验商品是否存在
  144 + validateProductExists(updateReqVO.getSpuId(), updateReqVO.getProducts());
126 145
127 // 更新活动 146 // 更新活动
128 SeckillActivityDO updateObj = SeckillActivityConvert.INSTANCE.convert(updateReqVO) 147 SeckillActivityDO updateObj = SeckillActivityConvert.INSTANCE.convert(updateReqVO)
129 .setStatus(PromotionUtils.calculateActivityStatus(updateReqVO.getEndTime())) 148 .setStatus(PromotionUtils.calculateActivityStatus(updateReqVO.getEndTime()))
130 - .setTotalStock(getSumValue(updateReqVO.getProducts(), SeckillProductUpdateReqVO::getStock, Integer::sum)); 149 + .setTotalStock(getSumValue(updateReqVO.getProducts(), SeckillProductBaseVO::getStock, Integer::sum));
131 seckillActivityMapper.updateById(updateObj); 150 seckillActivityMapper.updateById(updateObj);
132 // 更新商品 151 // 更新商品
133 updateSeckillProduct(updateObj, updateReqVO.getProducts()); 152 updateSeckillProduct(updateObj, updateReqVO.getProducts());
134 } 153 }
135 154
136 -  
137 /** 155 /**
138 * 更新秒杀商品 156 * 更新秒杀商品
139 * 157 *
140 * @param activity 秒杀活动 158 * @param activity 秒杀活动
141 * @param products 该活动的最新商品配置 159 * @param products 该活动的最新商品配置
142 */ 160 */
143 - private void updateSeckillProduct(SeckillActivityDO activity, List<SeckillProductUpdateReqVO> products) { 161 + private void updateSeckillProduct(SeckillActivityDO activity, List<SeckillProductBaseVO> products) {
144 // 第一步,对比新老数据,获得添加、修改、删除的列表 162 // 第一步,对比新老数据,获得添加、修改、删除的列表
145 List<SeckillProductDO> newList = SeckillActivityConvert.INSTANCE.convertList(products, activity); 163 List<SeckillProductDO> newList = SeckillActivityConvert.INSTANCE.convertList(products, activity);
146 List<SeckillProductDO> oldList = seckillProductMapper.selectListByActivityId(activity.getId()); 164 List<SeckillProductDO> oldList = seckillProductMapper.selectListByActivityId(activity.getId());
@@ -159,7 +177,6 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { @@ -159,7 +177,6 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
159 if (isNotEmpty(diffList.get(1))) { 177 if (isNotEmpty(diffList.get(1))) {
160 seckillProductMapper.updateBatch(diffList.get(1)); 178 seckillProductMapper.updateBatch(diffList.get(1));
161 } 179 }
162 - // delete  
163 if (isNotEmpty(diffList.get(2))) { 180 if (isNotEmpty(diffList.get(2))) {
164 seckillProductMapper.deleteBatchIds(convertList(diffList.get(2), SeckillProductDO::getId)); 181 seckillProductMapper.deleteBatchIds(convertList(diffList.get(2), SeckillProductDO::getId));
165 } 182 }
@@ -167,7 +184,6 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { @@ -167,7 +184,6 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
167 184
168 @Override 185 @Override
169 public void closeSeckillActivity(Long id) { 186 public void closeSeckillActivity(Long id) {
170 - // TODO 待验证没使用过  
171 // 校验存在 187 // 校验存在
172 SeckillActivityDO activity = validateSeckillActivityExists(id); 188 SeckillActivityDO activity = validateSeckillActivityExists(id);
173 if (CommonStatusEnum.DISABLE.getStatus().equals(activity.getStatus())) { 189 if (CommonStatusEnum.DISABLE.getStatus().equals(activity.getStatus())) {
@@ -191,9 +207,8 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { @@ -191,9 +207,8 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
191 // 删除活动 207 // 删除活动
192 seckillActivityMapper.deleteById(id); 208 seckillActivityMapper.deleteById(id);
193 // 删除活动商品 209 // 删除活动商品
194 - List<SeckillProductDO> productDOs = seckillProductMapper.selectListByActivityId(id);  
195 - Set<Long> convertSet = convertSet(productDOs, SeckillProductDO::getSkuId);  
196 - seckillProductMapper.deleteBatchIds(convertSet); 210 + List<SeckillProductDO> products = seckillProductMapper.selectListByActivityId(id);
  211 + seckillProductMapper.deleteBatchIds(convertSet(products, SeckillProductDO::getId));
197 } 212 }
198 213
199 private SeckillActivityDO validateSeckillActivityExists(Long id) { 214 private SeckillActivityDO validateSeckillActivityExists(Long id) {
@@ -210,23 +225,18 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { @@ -210,23 +225,18 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
210 } 225 }
211 226
212 @Override 227 @Override
213 - public List<SeckillActivityDO> getSeckillActivityList(Collection<Long> ids) {  
214 - return seckillActivityMapper.selectBatchIds(ids);  
215 - }  
216 -  
217 - @Override  
218 public PageResult<SeckillActivityDO> getSeckillActivityPage(SeckillActivityPageReqVO pageReqVO) { 228 public PageResult<SeckillActivityDO> getSeckillActivityPage(SeckillActivityPageReqVO pageReqVO) {
219 return seckillActivityMapper.selectPage(pageReqVO); 229 return seckillActivityMapper.selectPage(pageReqVO);
220 } 230 }
221 231
222 @Override 232 @Override
223 - public List<SeckillProductDO> getSeckillProductListByActivityId(Long id) {  
224 - return seckillProductMapper.selectListByActivityId(id); 233 + public List<SeckillProductDO> getSeckillProductListByActivityId(Long activityId) {
  234 + return seckillProductMapper.selectListByActivityId(activityId);
225 } 235 }
226 236
227 @Override 237 @Override
228 - public List<SeckillProductDO> getSeckillProductListByActivityId(Collection<Long> ids) {  
229 - return seckillProductMapper.selectListByActivityId(ids); 238 + public List<SeckillProductDO> getSeckillProductListByActivityId(Collection<Long> activityIds) {
  239 + return seckillProductMapper.selectListByActivityId(activityIds);
230 } 240 }
231 241
232 } 242 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillconfig/SeckillConfigService.java
@@ -57,10 +57,9 @@ public interface SeckillConfigService { @@ -57,10 +57,9 @@ public interface SeckillConfigService {
57 /** 57 /**
58 * 校验秒杀时段是否存在 58 * 校验秒杀时段是否存在
59 * 59 *
60 - * @param timeIds 秒杀时段id集合 60 + * @param ids 秒杀时段 id 集合
61 */ 61 */
62 - void validateSeckillConfigExists(Collection<Long> timeIds);  
63 - 62 + void validateSeckillConfigExists(Collection<Long> ids);
64 63
65 /** 64 /**
66 * 获得秒杀时间段配置分页数据 65 * 获得秒杀时间段配置分页数据
@@ -85,4 +84,5 @@ public interface SeckillConfigService { @@ -85,4 +84,5 @@ public interface SeckillConfigService {
85 * @param status 状态 84 * @param status 状态
86 */ 85 */
87 void updateSeckillConfigStatus(Long id, Integer status); 86 void updateSeckillConfigStatus(Long id, Integer status);
  87 +
88 } 88 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillconfig/SeckillConfigServiceImpl.java
@@ -4,7 +4,6 @@ import cn.hutool.core.collection.CollUtil; @@ -4,7 +4,6 @@ import cn.hutool.core.collection.CollUtil;
4 import cn.hutool.core.util.ObjectUtil; 4 import cn.hutool.core.util.ObjectUtil;
5 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 5 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
6 import cn.iocoder.yudao.framework.common.pojo.PageResult; 6 import cn.iocoder.yudao.framework.common.pojo.PageResult;
7 -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;  
8 import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; 7 import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils;
9 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigCreateReqVO; 8 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigCreateReqVO;
10 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigPageReqVO; 9 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigPageReqVO;
@@ -13,7 +12,6 @@ import cn.iocoder.yudao.module.promotion.convert.seckill.seckillconfig.SeckillCo @@ -13,7 +12,6 @@ import cn.iocoder.yudao.module.promotion.convert.seckill.seckillconfig.SeckillCo
13 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillconfig.SeckillConfigDO; 12 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillconfig.SeckillConfigDO;
14 import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillconfig.SeckillConfigMapper; 13 import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillconfig.SeckillConfigMapper;
15 import org.springframework.stereotype.Service; 14 import org.springframework.stereotype.Service;
16 -import org.springframework.transaction.annotation.Transactional;  
17 import org.springframework.validation.annotation.Validated; 15 import org.springframework.validation.annotation.Validated;
18 16
19 import javax.annotation.Resource; 17 import javax.annotation.Resource;
@@ -37,7 +35,6 @@ public class SeckillConfigServiceImpl implements SeckillConfigService { @@ -37,7 +35,6 @@ public class SeckillConfigServiceImpl implements SeckillConfigService {
37 private SeckillConfigMapper seckillConfigMapper; 35 private SeckillConfigMapper seckillConfigMapper;
38 36
39 @Override 37 @Override
40 - @Transactional(rollbackFor = Exception.class)  
41 public Long createSeckillConfig(SeckillConfigCreateReqVO createReqVO) { 38 public Long createSeckillConfig(SeckillConfigCreateReqVO createReqVO) {
42 // 校验时间段是否冲突 39 // 校验时间段是否冲突
43 validateSeckillConfigConflict(createReqVO.getStartTime(), createReqVO.getEndTime(), null); 40 validateSeckillConfigConflict(createReqVO.getStartTime(), createReqVO.getEndTime(), null);
@@ -50,7 +47,6 @@ public class SeckillConfigServiceImpl implements SeckillConfigService { @@ -50,7 +47,6 @@ public class SeckillConfigServiceImpl implements SeckillConfigService {
50 } 47 }
51 48
52 @Override 49 @Override
53 - @Transactional(rollbackFor = Exception.class)  
54 public void updateSeckillConfig(SeckillConfigUpdateReqVO updateReqVO) { 50 public void updateSeckillConfig(SeckillConfigUpdateReqVO updateReqVO) {
55 // 校验存在 51 // 校验存在
56 validateSeckillConfigExists(updateReqVO.getId()); 52 validateSeckillConfigExists(updateReqVO.getId());
@@ -62,7 +58,6 @@ public class SeckillConfigServiceImpl implements SeckillConfigService { @@ -62,7 +58,6 @@ public class SeckillConfigServiceImpl implements SeckillConfigService {
62 seckillConfigMapper.updateById(updateObj); 58 seckillConfigMapper.updateById(updateObj);
63 } 59 }
64 60
65 - // TODO @puhui999: 这个要不合并到更新操作里? 不单独有个操作咧; fix: 更新状态不用那么多必须的参数,更新的时候需要校验时间段  
66 @Override 61 @Override
67 public void updateSeckillConfigStatus(Long id, Integer status) { 62 public void updateSeckillConfigStatus(Long id, Integer status) {
68 // 校验秒杀时段是否存在 63 // 校验秒杀时段是否存在
@@ -73,7 +68,6 @@ public class SeckillConfigServiceImpl implements SeckillConfigService { @@ -73,7 +68,6 @@ public class SeckillConfigServiceImpl implements SeckillConfigService {
73 } 68 }
74 69
75 @Override 70 @Override
76 - @Transactional(rollbackFor = Exception.class)  
77 public void deleteSeckillConfig(Long id) { 71 public void deleteSeckillConfig(Long id) {
78 // 校验存在 72 // 校验存在
79 validateSeckillConfigExists(id); 73 validateSeckillConfigExists(id);
@@ -84,35 +78,31 @@ public class SeckillConfigServiceImpl implements SeckillConfigService { @@ -84,35 +78,31 @@ public class SeckillConfigServiceImpl implements SeckillConfigService {
84 78
85 private void validateSeckillConfigExists(Long id) { 79 private void validateSeckillConfigExists(Long id) {
86 if (seckillConfigMapper.selectById(id) == null) { 80 if (seckillConfigMapper.selectById(id) == null) {
87 - throw exception(SECKILL_TIME_NOT_EXISTS); 81 + throw exception(SECKILL_CONFIG_NOT_EXISTS);
88 } 82 }
89 } 83 }
90 84
91 /** 85 /**
92 * 校验时间是否存在冲突 86 * 校验时间是否存在冲突
93 * 87 *
94 - * @param startTime 开始时间  
95 - * @param endTime 结束时间 88 + * @param startTimeStr 开始时间
  89 + * @param endTimeStr 结束时间
96 */ 90 */
97 - private void validateSeckillConfigConflict(String startTime, String endTime, Long seckillConfigId) {  
98 - LocalTime startTime1 = LocalTime.parse(startTime);  
99 - LocalTime endTime1 = LocalTime.parse(endTime);  
100 - // 查询出所有的时段配置  
101 - List<SeckillConfigDO> configDOs = seckillConfigMapper.selectList(); 91 + private void validateSeckillConfigConflict(String startTimeStr, String endTimeStr, Long id) {
  92 + // 1. 查询出所有的时段配置
  93 + LocalTime startTime = LocalTime.parse(startTimeStr);
  94 + LocalTime endTime = LocalTime.parse(endTimeStr);
  95 + List<SeckillConfigDO> configs = seckillConfigMapper.selectList();
102 // 更新时排除自己 96 // 更新时排除自己
103 - if (seckillConfigId != null) {  
104 - configDOs.removeIf(item -> ObjectUtil.equal(item.getId(), seckillConfigId)); 97 + if (id != null) {
  98 + configs.removeIf(item -> ObjectUtil.equal(item.getId(), id));
105 } 99 }
106 - // 过滤出重叠的时段 ids  
107 - boolean hasConflict = configDOs.stream().anyMatch(config -> {  
108 - LocalTime startTime2 = LocalTime.parse(config.getStartTime());  
109 - LocalTime endTime2 = LocalTime.parse(config.getEndTime());  
110 - // 判断时间是否重叠  
111 - return LocalDateTimeUtils.isOverlap(startTime1, endTime1, startTime2, endTime2);  
112 - });  
113 100
  101 + // 2. 判断是否有重叠的时间
  102 + boolean hasConflict = configs.stream().anyMatch(config -> LocalDateTimeUtils.isOverlap(startTime, endTime,
  103 + LocalTime.parse(config.getStartTime()), LocalTime.parse(config.getEndTime())));
114 if (hasConflict) { 104 if (hasConflict) {
115 - throw exception(SECKILL_TIME_CONFLICTS); 105 + throw exception(SECKILL_CONFIG_TIME_CONFLICTS);
116 } 106 }
117 } 107 }
118 108
@@ -128,22 +118,22 @@ public class SeckillConfigServiceImpl implements SeckillConfigService { @@ -128,22 +118,22 @@ public class SeckillConfigServiceImpl implements SeckillConfigService {
128 } 118 }
129 119
130 @Override 120 @Override
131 - public void validateSeckillConfigExists(Collection<Long> configIds) {  
132 - if (CollUtil.isEmpty(configIds)) {  
133 - throw exception(SECKILL_TIME_NOT_EXISTS);  
134 - }  
135 - List<SeckillConfigDO> configDOs = seckillConfigMapper.selectBatchIds(configIds);  
136 - if (CollUtil.isEmpty(configDOs)) {  
137 - throw exception(SECKILL_TIME_NOT_EXISTS);  
138 - }  
139 - // 过滤出关闭的时段  
140 - List<SeckillConfigDO> filterList = CollectionUtils.filterList(configDOs, item -> ObjectUtil.equal(item.getStatus(), CommonStatusEnum.DISABLE.getStatus()));  
141 - if (CollUtil.isNotEmpty(filterList)) {  
142 - throw exception(SECKILL_TIME_DISABLE); 121 + public void validateSeckillConfigExists(Collection<Long> ids) {
  122 + if (CollUtil.isEmpty(ids)) {
  123 + return;
143 } 124 }
144 - if (configDOs.size() != configIds.size()) {  
145 - throw exception(SECKILL_TIME_NOT_EXISTS); 125 + // 1. 如果有数量不匹配,说明有不存在的,则抛出 SECKILL_CONFIG_NOT_EXISTS 业务异常
  126 + List<SeckillConfigDO> configs = seckillConfigMapper.selectBatchIds(ids);
  127 + if (configs.size() != ids.size()) {
  128 + throw exception(SECKILL_CONFIG_NOT_EXISTS);
146 } 129 }
  130 +
  131 + // 2. 如果存在关闭,则抛出 SECKILL_CONFIG_DISABLE 业务异常
  132 + configs.forEach(config -> {
  133 + if (ObjectUtil.equal(config.getStatus(), CommonStatusEnum.DISABLE.getStatus())) {
  134 + throw exception(SECKILL_CONFIG_DISABLE);
  135 + }
  136 + });
147 } 137 }
148 138
149 @Override 139 @Override
yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/seckillconfig/SeckillConfigServiceImplTest.java
@@ -19,7 +19,7 @@ import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEq @@ -19,7 +19,7 @@ import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEq
19 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; 19 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
20 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; 20 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
21 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; 21 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
22 -import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.SECKILL_TIME_NOT_EXISTS; 22 +import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.SECKILL_CONFIG_NOT_EXISTS;
23 import static org.junit.jupiter.api.Assertions.assertNotNull; 23 import static org.junit.jupiter.api.Assertions.assertNotNull;
24 import static org.junit.jupiter.api.Assertions.assertNull; 24 import static org.junit.jupiter.api.Assertions.assertNull;
25 25
@@ -94,7 +94,7 @@ public class SeckillConfigServiceImplTest extends BaseDbUnitTest { @@ -94,7 +94,7 @@ public class SeckillConfigServiceImplTest extends BaseDbUnitTest {
94 SeckillConfigUpdateReqVO reqVO = randomPojo(SeckillConfigUpdateReqVO.class); 94 SeckillConfigUpdateReqVO reqVO = randomPojo(SeckillConfigUpdateReqVO.class);
95 95
96 // 调用, 并断言异常 96 // 调用, 并断言异常
97 - assertServiceException(() -> SeckillConfigService.updateSeckillConfig(reqVO), SECKILL_TIME_NOT_EXISTS); 97 + assertServiceException(() -> SeckillConfigService.updateSeckillConfig(reqVO), SECKILL_CONFIG_NOT_EXISTS);
98 } 98 }
99 99
100 @Test 100 @Test
@@ -117,7 +117,7 @@ public class SeckillConfigServiceImplTest extends BaseDbUnitTest { @@ -117,7 +117,7 @@ public class SeckillConfigServiceImplTest extends BaseDbUnitTest {
117 Long id = randomLongId(); 117 Long id = randomLongId();
118 118
119 // 调用, 并断言异常 119 // 调用, 并断言异常
120 - assertServiceException(() -> SeckillConfigService.deleteSeckillConfig(id), SECKILL_TIME_NOT_EXISTS); 120 + assertServiceException(() -> SeckillConfigService.deleteSeckillConfig(id), SECKILL_CONFIG_NOT_EXISTS);
121 } 121 }
122 122
123 @Test 123 @Test