Commit ba31d5f6fb9601e024d0d1c60e9ffee4d62567fe

Authored by YunaiV
1 parent 6fdd4da0

优化拼团活动的管理后台代码

Showing 28 changed files with 425 additions and 439 deletions
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/CombinationActivityController.java
1 1 package cn.iocoder.yudao.module.promotion.controller.admin.combination;
2 2  
  3 +import cn.hutool.core.collection.CollUtil;
3 4 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 6 import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
  7 +import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
6 8 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityCreateReqVO;
7 9 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityPageReqVO;
8 10 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityRespVO;
... ... @@ -21,7 +23,6 @@ import org.springframework.web.bind.annotation.*;
21 23 import javax.annotation.Resource;
22 24 import javax.validation.Valid;
23 25 import java.util.List;
24   -import java.util.Set;
25 26  
26 27 import static cn.hutool.core.collection.CollectionUtil.newArrayList;
27 28 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
... ... @@ -37,7 +38,7 @@ public class CombinationActivityController {
37 38 private CombinationActivityService combinationActivityService;
38 39  
39 40 @Resource
40   - private ProductSpuApi spuApi;
  41 + private ProductSpuApi productSpuApi;
41 42  
42 43 @PostMapping("/create")
43 44 @Operation(summary = "创建拼团活动")
... ... @@ -80,12 +81,16 @@ public class CombinationActivityController {
80 81 @Valid CombinationActivityPageReqVO pageVO) {
81 82 // 查询拼团活动
82 83 PageResult<CombinationActivityDO> pageResult = combinationActivityService.getCombinationActivityPage(pageVO);
  84 + if (CollUtil.isEmpty(pageResult.getList())) {
  85 + return success(PageResult.empty(pageResult.getTotal()));
  86 + }
  87 +
83 88 // 拼接数据
84   - Set<Long> activityIds = convertSet(pageResult.getList(), CombinationActivityDO::getId);
85   - Set<Long> spuIds = convertSet(pageResult.getList(), CombinationActivityDO::getSpuId);
86   - return success(CombinationActivityConvert.INSTANCE.convertPage(pageResult,
87   - combinationActivityService.getCombinationProductsByActivityIds(activityIds),
88   - spuApi.getSpuList(spuIds)));
  89 + List<CombinationProductDO> products = combinationActivityService.getCombinationProductsByActivityIds(
  90 + convertSet(pageResult.getList(), CombinationActivityDO::getId));
  91 + List<ProductSpuRespDTO> spus = productSpuApi.getSpuList(
  92 + convertSet(pageResult.getList(), CombinationActivityDO::getSpuId));
  93 + return success(CombinationActivityConvert.INSTANCE.convertPage(pageResult, products, spus));
89 94 }
90 95  
91 96 }
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityBaseVO.java
... ... @@ -22,7 +22,7 @@ public class CombinationActivityBaseVO {
22 22 @NotNull(message = "拼团名称不能为空")
23 23 private String name;
24 24  
25   - @Schema(description = "商品 SPU 编号,关联 ProductSpuDO 的 id", example = "[1,2,3]")
  25 + @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
26 26 @NotNull(message = "拼团商品不能为空")
27 27 private Long spuId;
28 28  
... ... @@ -48,7 +48,7 @@ public class CombinationActivityBaseVO {
48 48 @NotNull(message = "开团人数不能为空")
49 49 private Integer userSize;
50 50  
51   - @Schema(description = "限制时长(小时)", requiredMode = Schema.RequiredMode.REQUIRED)
  51 + @Schema(description = "限制时长(小时)", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
52 52 @NotNull(message = "限制时长不能为空")
53 53 private Integer limitDuration;
54 54  
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityCreateReqVO.java
1 1 package cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity;
2 2  
3   -import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductCreateReqVO;
  3 +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductBaseVO;
4 4 import io.swagger.v3.oas.annotations.media.Schema;
5 5 import lombok.Data;
6 6 import lombok.EqualsAndHashCode;
... ... @@ -17,6 +17,6 @@ public class CombinationActivityCreateReqVO extends CombinationActivityBaseVO {
17 17  
18 18 @Schema(description = "拼团商品", requiredMode = Schema.RequiredMode.REQUIRED)
19 19 @Valid
20   - private List<CombinationProductCreateReqVO> products;
  20 + private List<CombinationProductBaseVO> products;
21 21  
22 22 }
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityPageReqVO.java
... ... @@ -20,15 +20,6 @@ public class CombinationActivityPageReqVO extends PageParam {
20 20 @Schema(description = "拼团名称", example = "赵六")
21 21 private String name;
22 22  
23   - @Schema(description = "商品 SPU 编号关联 ProductSpuDO 的 id", example = "14016")
24   - private Long spuId;
25   -
26   - @Schema(description = "总限购数量", example = "16218")
27   - private Integer totalLimitCount;
28   -
29   - @Schema(description = "单次限购数量", example = "28265")
30   - private Integer singleLimitCount;
31   -
32 23 @Schema(description = "开始时间")
33 24 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
34 25 private LocalDateTime[] startTime;
... ... @@ -37,29 +28,7 @@ public class CombinationActivityPageReqVO extends PageParam {
37 28 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
38 29 private LocalDateTime[] endTime;
39 30  
40   - @Schema(description = "开团人数")
41   - private Integer userSize;
42   -
43   - @Schema(description = "开团组数")
44   - private Integer totalNum;
45   -
46   - @Schema(description = "成团组数")
47   - private Integer successNum;
48   -
49   - @Schema(description = "参与人数", example = "25222")
50   - private Integer orderUserCount;
51   -
52   - @Schema(description = "虚拟成团")
53   - private Integer virtualGroup;
54   -
55 31 @Schema(description = "活动状态:0开启 1关闭", example = "0")
56 32 private Integer status;
57 33  
58   - @Schema(description = "限制时长(小时)")
59   - private Integer limitDuration;
60   -
61   - @Schema(description = "创建时间")
62   - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
63   - private LocalDateTime[] createTime;
64   -
65 34 }
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityRespVO.java
... ... @@ -17,40 +17,34 @@ import java.util.List;
17 17 @ToString(callSuper = true)
18 18 public class CombinationActivityRespVO extends CombinationActivityBaseVO {
19 19  
20   - @Schema(description = "商品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "618大促")
  20 + @Schema(description = "活动编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "22901")
  21 + private Long id;
  22 +
  23 + @Schema(description = "商品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "618 大促")
21 24 private String spuName;
22 25  
23 26 @Schema(description = "商品主图", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xx.png")
24 27 private String picUrl;
25 28  
26   - @Schema(description = "活动编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "22901")
27   - private Long id;
28   -
29 29 @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
30 30 private LocalDateTime createTime;
31 31  
32   - @Schema(description = "开团人数", requiredMode = Schema.RequiredMode.REQUIRED)
33   - @NotNull(message = "开团人数不能为空")
  32 + @Schema(description = "开团人数", requiredMode = Schema.RequiredMode.REQUIRED, example = "666")
34 33 private Integer userSize;
35 34  
36   - @Schema(description = "开团组数", requiredMode = Schema.RequiredMode.REQUIRED)
37   - @NotNull(message = "开团组数不能为空")
38   - private Integer totalNum;
  35 + @Schema(description = "开团组数", requiredMode = Schema.RequiredMode.REQUIRED, example = "33")
  36 + private Integer totalCount;
39 37  
40   - @Schema(description = "成团组数", requiredMode = Schema.RequiredMode.REQUIRED)
41   - @NotNull(message = "成团组数不能为空")
42   - private Integer successNum;
  38 + @Schema(description = "成团组数", requiredMode = Schema.RequiredMode.REQUIRED, example = "20")
  39 + private Integer successCount;
43 40  
44   - @Schema(description = "虚拟成团", requiredMode = Schema.RequiredMode.REQUIRED)
45   - @NotNull(message = "虚拟成团不能为空")
  41 + @Schema(description = "虚拟成团", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
46 42 private Integer virtualGroup;
47 43  
48 44 @Schema(description = "活动状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
49   - @NotNull(message = "活动状态不能为空")
50 45 private Integer status;
51 46  
52 47 @Schema(description = "拼团商品", requiredMode = Schema.RequiredMode.REQUIRED)
53   - @Valid
54 48 private List<CombinationProductRespVO> products;
55 49  
56 50 }
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityUpdateReqVO.java
1 1 package cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity;
2 2  
3   -import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductUpdateReqVO;
  3 +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductBaseVO;
4 4 import io.swagger.v3.oas.annotations.media.Schema;
5 5 import lombok.Data;
6 6 import lombok.EqualsAndHashCode;
... ... @@ -22,6 +22,6 @@ public class CombinationActivityUpdateReqVO extends CombinationActivityBaseVO {
22 22  
23 23 @Schema(description = "拼团商品", requiredMode = Schema.RequiredMode.REQUIRED)
24 24 @Valid
25   - private List<CombinationProductUpdateReqVO> products;
  25 + private List<CombinationProductBaseVO> products;
26 26  
27 27 }
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductBaseVO.java
... ... @@ -21,7 +21,7 @@ public class CombinationProductBaseVO {
21 21 private Long skuId;
22 22  
23 23 @Schema(description = "拼团价格,单位分", requiredMode = Schema.RequiredMode.REQUIRED, example = "27682")
24   - @NotNull(message = "拼团价格,单位分不能为空")
25   - private Integer activePrice;
  24 + @NotNull(message = "拼团价格不能为空")
  25 + private Integer combinationPrice;
26 26  
27 27 }
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductCreateReqVO.java deleted
1   -package cn.iocoder.yudao.module.promotion.controller.admin.combination.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 CombinationProductCreateReqVO extends CombinationProductBaseVO {
13   -
14   -}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductUpdateReqVO.java deleted
1   -package cn.iocoder.yudao.module.promotion.controller.admin.combination.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 CombinationProductUpdateReqVO extends CombinationProductBaseVO {
13   -
14   -}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillActivityController.java
... ... @@ -9,7 +9,7 @@ import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.*;
9 9 import cn.iocoder.yudao.module.promotion.convert.seckill.seckillactivity.SeckillActivityConvert;
10 10 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO;
11 11 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO;
12   -import cn.iocoder.yudao.module.promotion.service.seckill.seckillactivity.SeckillActivityService;
  12 +import cn.iocoder.yudao.module.promotion.service.seckill.SeckillActivityService;
13 13 import io.swagger.v3.oas.annotations.Operation;
14 14 import io.swagger.v3.oas.annotations.Parameter;
15 15 import io.swagger.v3.oas.annotations.tags.Tag;
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillConfigController.java
... ... @@ -6,7 +6,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
6 6 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.*;
7 7 import cn.iocoder.yudao.module.promotion.convert.seckill.seckillconfig.SeckillConfigConvert;
8 8 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillconfig.SeckillConfigDO;
9   -import cn.iocoder.yudao.module.promotion.service.seckill.seckillconfig.SeckillConfigService;
  9 +import cn.iocoder.yudao.module.promotion.service.seckill.SeckillConfigService;
10 10 import io.swagger.v3.oas.annotations.Operation;
11 11 import io.swagger.v3.oas.annotations.Parameter;
12 12 import io.swagger.v3.oas.annotations.tags.Tag;
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/combination/CombinationActivityConvert.java
... ... @@ -10,7 +10,6 @@ import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activit
10 10 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityUpdateReqVO;
11 11 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductBaseVO;
12 12 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductRespVO;
13   -import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductUpdateReqVO;
14 13 import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO;
15 14 import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationProductDO;
16 15 import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO;
... ... @@ -53,37 +52,34 @@ public interface CombinationActivityConvert {
53 52 default PageResult<CombinationActivityRespVO> convertPage(PageResult<CombinationActivityDO> page,
54 53 List<CombinationProductDO> productList,
55 54 List<ProductSpuRespDTO> spuList) {
56   - Map<Long, ProductSpuRespDTO> spuMap = convertMap(spuList, ProductSpuRespDTO::getId);
57 55 PageResult<CombinationActivityRespVO> pageResult = convertPage(page);
  56 + // 拼接商品
  57 + Map<Long, ProductSpuRespDTO> spuMap = convertMap(spuList, ProductSpuRespDTO::getId);
58 58 pageResult.getList().forEach(item -> {
59   - MapUtils.findAndThen(spuMap, item.getSpuId(), spu -> {
60   - item.setSpuName(spu.getName());
61   - item.setPicUrl(spu.getPicUrl());
62   - });
63 59 item.setProducts(convertList2(productList));
  60 + MapUtils.findAndThen(spuMap, item.getSpuId(),
  61 + spu -> item.setSpuName(spu.getName()).setPicUrl(spu.getPicUrl()));
64 62 });
65 63 return pageResult;
66 64 }
67 65  
68 66 List<CombinationProductRespVO> convertList2(List<CombinationProductDO> productDOs);
69 67  
70   - // TODO @puhui999:参数改成 activity、product 会不会干净一点哈
71   - @Mappings({
72   - @Mapping(target = "id", ignore = true),
73   - @Mapping(target = "activityId", source = "activityDO.id"),
74   - @Mapping(target = "spuId", source = "activityDO.spuId"),
75   - @Mapping(target = "skuId", source = "vo.skuId"),
76   - @Mapping(target = "activePrice", source = "vo.activePrice"),
77   - @Mapping(target = "activityStartTime", source = "activityDO.startTime"),
78   - @Mapping(target = "activityEndTime", source = "activityDO.endTime")
79   - })
80   - CombinationProductDO convert(CombinationActivityDO activityDO, CombinationProductBaseVO vo);
81   -
82 68 default List<CombinationProductDO> convertList(List<? extends CombinationProductBaseVO> products, CombinationActivityDO activityDO) {
83 69 return CollectionUtils.convertList(products, item -> convert(activityDO, item).setActivityStatus(activityDO.getStatus()));
84 70 }
  71 + @Mappings({
  72 + @Mapping(target = "id", ignore = true),
  73 + @Mapping(target = "activityId", source = "activity.id"),
  74 + @Mapping(target = "spuId", source = "activity.spuId"),
  75 + @Mapping(target = "skuId", source = "product.skuId"),
  76 + @Mapping(target = "combinationPrice", source = "product.combinationPrice"),
  77 + @Mapping(target = "activityStartTime", source = "activity.startTime"),
  78 + @Mapping(target = "activityEndTime", source = "activity.endTime")
  79 + })
  80 + CombinationProductDO convert(CombinationActivityDO activity, CombinationProductBaseVO product);
85 81  
86   - default List<CombinationProductDO> convertList(List<CombinationProductUpdateReqVO> updateProductVOs,
  82 + default List<CombinationProductDO> convertList(List<CombinationProductBaseVO> updateProductVOs,
87 83 List<CombinationProductDO> products, CombinationActivityDO activity) {
88 84 Map<Long, Long> productMap = convertMap(products, CombinationProductDO::getSkuId, CombinationProductDO::getId);
89 85 return CollectionUtils.convertList(updateProductVOs, updateProductVO -> convert(activity, updateProductVO)
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/CombinationActivityDO.java
... ... @@ -62,11 +62,11 @@ public class CombinationActivityDO extends BaseDO {
62 62 /**
63 63 * 开团组数
64 64 */
65   - private Integer totalNum;
  65 + private Integer totalCount;
66 66 /**
67 67 * 成团组数
68 68 */
69   - private Integer successNum;
  69 + private Integer successCount;
70 70 /**
71 71 * 参与人数
72 72 */
... ... @@ -76,7 +76,7 @@ public class CombinationActivityDO extends BaseDO {
76 76 */
77 77 private Integer virtualGroup;
78 78 /**
79   - * 活动状态:0开启 1关闭
  79 + * 活动状态
80 80 *
81 81 * 枚举 {@link CommonStatusEnum}
82 82 */
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/CombinationProductDO.java
... ... @@ -41,6 +41,11 @@ public class CombinationProductDO extends BaseDO {
41 41 */
42 42 private Long skuId;
43 43 /**
  44 + * 拼团价格,单位分
  45 + */
  46 + private Integer combinationPrice;
  47 +
  48 + /**
44 49 * 拼团商品状态
45 50 *
46 51 * 关联 {@link CombinationActivityDO#getStatus()}
... ... @@ -48,15 +53,15 @@ public class CombinationProductDO extends BaseDO {
48 53 private Integer activityStatus;
49 54 /**
50 55 * 活动开始时间点
  56 + *
  57 + * 冗余 {@link CombinationActivityDO#getStartTime()}
51 58 */
52 59 private LocalDateTime activityStartTime;
53 60 /**
54 61 * 活动结束时间点
  62 + *
  63 + * 冗余 {@link CombinationActivityDO#getEndTime()}
55 64 */
56 65 private LocalDateTime activityEndTime;
57   - /**
58   - * 拼团价格,单位分
59   - */
60   - private Integer activePrice;
61 66  
62 67 }
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/CombinationActivityMapper.java
... ... @@ -20,6 +20,9 @@ public interface CombinationActivityMapper extends BaseMapperX&lt;CombinationActivi
20 20 default PageResult<CombinationActivityDO> selectPage(CombinationActivityPageReqVO reqVO) {
21 21 return selectPage(reqVO, new LambdaQueryWrapperX<CombinationActivityDO>()
22 22 .likeIfPresent(CombinationActivityDO::getName, reqVO.getName())
  23 + .betweenIfPresent(CombinationActivityDO::getStartTime, reqVO.getStartTime())
  24 + .betweenIfPresent(CombinationActivityDO::getEndTime, reqVO.getEndTime())
  25 + .eqIfPresent(CombinationActivityDO::getStatus, reqVO.getStatus())
23 26 .orderByDesc(CombinationActivityDO::getId));
24 27 }
25 28  
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/CombinationProductMapper.java
... ... @@ -26,7 +26,7 @@ public interface CombinationProductMapper extends BaseMapperX&lt;CombinationProduct
26 26 .eqIfPresent(CombinationProductDO::getActivityStatus, reqVO.getActivityStatus())
27 27 .betweenIfPresent(CombinationProductDO::getActivityStartTime, reqVO.getActivityStartTime())
28 28 .betweenIfPresent(CombinationProductDO::getActivityEndTime, reqVO.getActivityEndTime())
29   - .eqIfPresent(CombinationProductDO::getActivePrice, reqVO.getActivePrice())
  29 + .eqIfPresent(CombinationProductDO::getCombinationPrice, reqVO.getActivePrice())
30 30 .betweenIfPresent(CombinationProductDO::getCreateTime, reqVO.getCreateTime())
31 31 .orderByDesc(CombinationProductDO::getId));
32 32 }
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityService.java
... ... @@ -41,20 +41,20 @@ public interface CombinationActivityService {
41 41 void deleteCombinationActivity(Long id);
42 42  
43 43 /**
44   - * 获得拼团活动
  44 + * 校验拼团活动是否存在
45 45 *
46 46 * @param id 编号
47 47 * @return 拼团活动
48 48 */
49   - CombinationActivityDO getCombinationActivity(Long id);
  49 + CombinationActivityDO validateCombinationActivityExists(Long id);
50 50  
51 51 /**
52   - * 获得拼团活动列表
  52 + * 获得拼团活动
53 53 *
54   - * @param ids 编号
55   - * @return 拼团活动列表
  54 + * @param id 编号
  55 + * @return 拼团活动
56 56 */
57   - List<CombinationActivityDO> getCombinationActivityList(Collection<Long> ids);
  57 + CombinationActivityDO getCombinationActivity(Long id);
58 58  
59 59 /**
60 60 * 获得拼团活动分页
... ... @@ -67,9 +67,9 @@ public interface CombinationActivityService {
67 67 /**
68 68 * 获得拼团活动商品列表
69 69 *
70   - * @param ids 拼团活动 ids
  70 + * @param activityIds 拼团活动 ids
71 71 * @return 拼团活动的商品列表
72 72 */
73   - List<CombinationProductDO> getCombinationProductsByActivityIds(Collection<Long> ids);
  73 + List<CombinationProductDO> getCombinationProductsByActivityIds(Collection<Long> activityIds);
74 74  
75 75 }
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.service.combination;
  2 +
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.util.ObjectUtil;
  5 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
  6 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  7 +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
  8 +import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
  9 +import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
  10 +import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
  11 +import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
  12 +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityCreateReqVO;
  13 +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityPageReqVO;
  14 +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityUpdateReqVO;
  15 +import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductBaseVO;
  16 +import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert;
  17 +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO;
  18 +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationProductDO;
  19 +import cn.iocoder.yudao.module.promotion.dal.mysql.combination.CombinationActivityMapper;
  20 +import cn.iocoder.yudao.module.promotion.dal.mysql.combination.CombinationProductMapper;
  21 +import org.springframework.stereotype.Service;
  22 +import org.springframework.transaction.annotation.Transactional;
  23 +import org.springframework.validation.annotation.Validated;
  24 +
  25 +import javax.annotation.Resource;
  26 +import java.util.Collection;
  27 +import java.util.List;
  28 +import java.util.Map;
  29 +
  30 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  31 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
  32 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList;
  33 +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS;
  34 +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS;
  35 +import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
  36 +import static java.util.Collections.singletonList;
  37 +
  38 +/**
  39 + * 拼团活动 Service 实现类
  40 + *
  41 + * @author HUIHUI
  42 + */
  43 +@Service
  44 +@Validated
  45 +public class CombinationActivityServiceImpl implements CombinationActivityService {
  46 +
  47 + @Resource
  48 + private CombinationActivityMapper combinationActivityMapper;
  49 + @Resource
  50 + private CombinationProductMapper combinationProductMapper;
  51 +
  52 + @Resource
  53 + private ProductSpuApi productSpuApi;
  54 + @Resource
  55 + private ProductSkuApi productSkuApi;
  56 +
  57 + @Override
  58 + @Transactional(rollbackFor = Exception.class)
  59 + public Long createCombinationActivity(CombinationActivityCreateReqVO createReqVO) {
  60 + // 校验商品 SPU 是否存在是否参加的别的活动
  61 + validateProductConflict(createReqVO.getSpuId(), null);
  62 + // 校验商品是否存在
  63 + validateProductExists(createReqVO.getSpuId(), createReqVO.getProducts());
  64 +
  65 + // 插入拼团活动
  66 + CombinationActivityDO activity = CombinationActivityConvert.INSTANCE.convert(createReqVO)
  67 + .setStatus(CommonStatusEnum.ENABLE.getStatus())
  68 + .setTotalCount(0).setSuccessCount(0).setOrderUserCount(0).setVirtualGroup(0);
  69 + combinationActivityMapper.insert(activity);
  70 + // 插入商品
  71 + List<CombinationProductDO> products = CombinationActivityConvert.INSTANCE.convertList(createReqVO.getProducts(), activity);
  72 + combinationProductMapper.insertBatch(products);
  73 + // 返回
  74 + return activity.getId();
  75 + }
  76 +
  77 + /**
  78 + * 校验拼团商品参与的活动是否存在冲突
  79 + *
  80 + * @param spuId 商品 SPU 编号
  81 + * @param activityId 拼团活动编号
  82 + */
  83 + private void validateProductConflict(Long spuId, Long activityId) {
  84 + // 查询所有开启的拼团活动
  85 + List<CombinationActivityDO> activityList = combinationActivityMapper.selectListByStatus(CommonStatusEnum.ENABLE.getStatus());
  86 + if (activityId != null) { // 时排除自己
  87 + activityList.removeIf(item -> ObjectUtil.equal(item.getId(), activityId));
  88 + }
  89 + // 查找是否有其它活动,选择了该产品
  90 + List<CombinationActivityDO> matchActivityList = filterList(activityList, activity -> ObjectUtil.equal(activity.getId(), spuId));
  91 + if (CollUtil.isNotEmpty(matchActivityList)) {
  92 + throw exception(COMBINATION_ACTIVITY_SPU_CONFLICTS);
  93 + }
  94 + }
  95 +
  96 + /**
  97 + * 校验拼团商品是否都存在
  98 + *
  99 + * @param spuId 商品 SPU 编号
  100 + * @param products 秒杀商品
  101 + */
  102 + private void validateProductExists(Long spuId, List<CombinationProductBaseVO> products) {
  103 + // 1. 校验商品 spu 是否存在
  104 + ProductSpuRespDTO spu = productSpuApi.getSpu(spuId);
  105 + if (spu == null) {
  106 + throw exception(SPU_NOT_EXISTS);
  107 + }
  108 +
  109 + // 2. 校验商品 sku 都存在
  110 + Map<Long, ProductSkuRespDTO> skuMap = convertMap(productSkuApi.getSkuListBySpuId(singletonList(spuId)),
  111 + ProductSkuRespDTO::getId);
  112 + products.forEach(product -> {
  113 + if (!skuMap.containsKey(product.getSkuId())) {
  114 + throw exception(SKU_NOT_EXISTS);
  115 + }
  116 + });
  117 + }
  118 +
  119 + @Override
  120 + @Transactional(rollbackFor = Exception.class)
  121 + public void updateCombinationActivity(CombinationActivityUpdateReqVO updateReqVO) {
  122 + // 校验存在
  123 + CombinationActivityDO activityDO = validateCombinationActivityExists(updateReqVO.getId());
  124 + // 校验状态
  125 + if (ObjectUtil.equal(activityDO.getStatus(), CommonStatusEnum.DISABLE.getStatus())) {
  126 + throw exception(COMBINATION_ACTIVITY_STATUS_DISABLE);
  127 + }
  128 + // 校验商品冲突
  129 + validateProductConflict(updateReqVO.getSpuId(), updateReqVO.getId());
  130 + // 校验商品是否存在
  131 + validateProductExists(updateReqVO.getSpuId(), updateReqVO.getProducts());
  132 +
  133 + // 更新活动
  134 + CombinationActivityDO updateObj = CombinationActivityConvert.INSTANCE.convert(updateReqVO);
  135 + combinationActivityMapper.updateById(updateObj);
  136 + // 更新商品
  137 + updateCombinationProduct(updateObj, updateReqVO.getProducts());
  138 + }
  139 +
  140 + /**
  141 + * 更新拼团商品
  142 + *
  143 + * @param activity 拼团活动
  144 + * @param products 该活动的最新商品配置
  145 + */
  146 + private void updateCombinationProduct(CombinationActivityDO activity, List<CombinationProductBaseVO> products) {
  147 + // 第一步,对比新老数据,获得添加、修改、删除的列表
  148 + List<CombinationProductDO> newList = CombinationActivityConvert.INSTANCE.convertList(products, activity);
  149 + List<CombinationProductDO> oldList = combinationProductMapper.selectListByActivityIds(CollUtil.newArrayList(activity.getId()));
  150 + List<List<CombinationProductDO>> diffList = CollectionUtils.diffList(oldList, newList, (oldVal, newVal) -> {
  151 + boolean same = ObjectUtil.equal(oldVal.getSkuId(), newVal.getSkuId());
  152 + if (same) {
  153 + newVal.setId(oldVal.getId());
  154 + }
  155 + return same;
  156 + });
  157 +
  158 + // 第二步,批量添加、修改、删除
  159 + if (CollUtil.isNotEmpty(diffList.get(0))) {
  160 + combinationProductMapper.insertBatch(diffList.get(0));
  161 + }
  162 + if (CollUtil.isNotEmpty(diffList.get(1))) {
  163 + combinationProductMapper.updateBatch(diffList.get(1));
  164 + }
  165 + if (CollUtil.isNotEmpty(diffList.get(2))) {
  166 + combinationProductMapper.deleteBatchIds(CollectionUtils.convertList(diffList.get(2), CombinationProductDO::getId));
  167 + }
  168 + }
  169 +
  170 + @Override
  171 + @Transactional(rollbackFor = Exception.class)
  172 + public void deleteCombinationActivity(Long id) {
  173 + // 校验存在
  174 + CombinationActivityDO activityDO = validateCombinationActivityExists(id);
  175 + // 校验状态
  176 + if (ObjectUtil.equal(activityDO.getStatus(), CommonStatusEnum.ENABLE.getStatus())) {
  177 + throw exception(COMBINATION_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END);
  178 + }
  179 +
  180 + // 删除
  181 + combinationActivityMapper.deleteById(id);
  182 + }
  183 +
  184 + @Override
  185 + public CombinationActivityDO validateCombinationActivityExists(Long id) {
  186 + CombinationActivityDO activityDO = combinationActivityMapper.selectById(id);
  187 + if (activityDO == null) {
  188 + throw exception(COMBINATION_ACTIVITY_NOT_EXISTS);
  189 + }
  190 + return activityDO;
  191 + }
  192 +
  193 + @Override
  194 + public CombinationActivityDO getCombinationActivity(Long id) {
  195 + return validateCombinationActivityExists(id);
  196 + }
  197 +
  198 + @Override
  199 + public PageResult<CombinationActivityDO> getCombinationActivityPage(CombinationActivityPageReqVO pageReqVO) {
  200 + return combinationActivityMapper.selectPage(pageReqVO);
  201 + }
  202 +
  203 + @Override
  204 + public List<CombinationProductDO> getCombinationProductsByActivityIds(Collection<Long> activityIds) {
  205 + return combinationProductMapper.selectListByActivityIds(activityIds);
  206 + }
  207 +
  208 +}
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordService.java
... ... @@ -5,7 +5,7 @@ import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordUp
5 5 import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO;
6 6  
7 7 /**
8   - * 商品活动记录 service
  8 + * 拼团记录 Service 接口
9 9 *
10 10 * @author HUIHUI
11 11 */
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.service.combination;
  2 +
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.util.ObjectUtil;
  5 +import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO;
  6 +import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordUpdateStatusReqDTO;
  7 +import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert;
  8 +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO;
  9 +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO;
  10 +import cn.iocoder.yudao.module.promotion.dal.mysql.combination.CombinationRecordMapper;
  11 +import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum;
  12 +import org.springframework.stereotype.Service;
  13 +import org.springframework.transaction.annotation.Transactional;
  14 +import org.springframework.validation.annotation.Validated;
  15 +
  16 +import javax.annotation.Resource;
  17 +import java.util.List;
  18 +
  19 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  20 +import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
  21 +import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COMBINATION_RECORD_USER_FULL;
  22 +
  23 +// TODO 芋艿:等拼团记录做完,完整 review 下
  24 +/**
  25 + * 拼团记录 Service 实现类
  26 + *
  27 + * @author HUIHUI
  28 + */
  29 +@Service
  30 +@Validated
  31 +public class CombinationRecordServiceImpl implements CombinationRecordService {
  32 +
  33 + @Resource
  34 + private CombinationActivityService combinationActivityService;
  35 +
  36 + @Resource
  37 + private CombinationRecordMapper recordMapper;
  38 +
  39 + @Override
  40 + public void updateCombinationRecordStatusByUserIdAndOrderId(CombinationRecordUpdateStatusReqDTO reqDTO) {
  41 + // 校验拼团是否存在
  42 + CombinationRecordDO recordDO = validateCombinationRecord(reqDTO.getUserId(), reqDTO.getOrderId());
  43 +
  44 + // 更新状态
  45 + recordDO.setStatus(reqDTO.getStatus());
  46 + recordMapper.updateById(recordDO);
  47 + }
  48 +
  49 + @Override
  50 + @Transactional(rollbackFor = Exception.class)
  51 + public void updateCombinationRecordStatusAndStartTimeByUserIdAndOrderId(CombinationRecordUpdateStatusReqDTO reqDTO) {
  52 + CombinationRecordDO recordDO = validateCombinationRecord(reqDTO.getUserId(), reqDTO.getOrderId());
  53 + // 更新状态
  54 + recordDO.setStatus(reqDTO.getStatus());
  55 + // 更新开始时间
  56 + recordDO.setStartTime(reqDTO.getStartTime());
  57 + recordMapper.updateById(recordDO);
  58 +
  59 + // 更新拼团参入人数
  60 + List<CombinationRecordDO> recordDOs = recordMapper.selectListByHeadIdAndStatus(recordDO.getHeadId(), reqDTO.getStatus());
  61 + if (CollUtil.isNotEmpty(recordDOs)) {
  62 + recordDOs.forEach(item -> {
  63 + item.setUserCount(recordDOs.size());
  64 + // 校验拼团是否满足要求
  65 + if (ObjectUtil.equal(recordDOs.size(), recordDO.getUserSize())) {
  66 + item.setStatus(CombinationRecordStatusEnum.SUCCESS.getStatus());
  67 + }
  68 + });
  69 + }
  70 + recordMapper.updateBatch(recordDOs);
  71 + }
  72 +
  73 + private CombinationRecordDO validateCombinationRecord(Long userId, Long orderId) {
  74 + // 校验拼团是否存在
  75 + CombinationRecordDO recordDO = recordMapper.selectByUserIdAndOrderId(userId, orderId);
  76 + if (recordDO == null) {
  77 + throw exception(COMBINATION_RECORD_NOT_EXISTS);
  78 + }
  79 + return recordDO;
  80 + }
  81 +
  82 + @Override
  83 + public void createCombinationRecord(CombinationRecordCreateReqDTO reqDTO) {
  84 + // 1.1 校验拼团活动
  85 + CombinationActivityDO activity = combinationActivityService.validateCombinationActivityExists(reqDTO.getActivityId());
  86 + // 1.2 需要校验下,他当前是不是已经参加了该拼团;
  87 + CombinationRecordDO recordDO = recordMapper.selectByUserIdAndOrderId(reqDTO.getUserId(), reqDTO.getOrderId());
  88 + if (recordDO != null) {
  89 + throw exception(COMBINATION_RECORD_EXISTS);
  90 + }
  91 + // 1.3 父拼团是否存在,是否已经满了
  92 + if (reqDTO.getHeadId() != null) {
  93 + CombinationRecordDO recordDO1 = recordMapper.selectRecordByHeadId(reqDTO.getHeadId(), reqDTO.getActivityId(), CombinationRecordStatusEnum.IN_PROGRESS.getStatus());
  94 + if (recordDO1 == null) {
  95 + throw exception(COMBINATION_RECORD_HEAD_NOT_EXISTS);
  96 + }
  97 + // 校验拼团是否满足要求
  98 + if (ObjectUtil.equal(recordDO1.getUserCount(), recordDO1.getUserSize())) {
  99 + throw exception(COMBINATION_RECORD_USER_FULL);
  100 + }
  101 + }
  102 + // TODO @puhui999:应该还有一些校验,后续补噶;例如说,一个团,自己已经参与进去了,不能再参与进去;
  103 +
  104 + // 2. 创建拼团记录
  105 + CombinationRecordDO record = CombinationActivityConvert.INSTANCE.convert(reqDTO);
  106 + record.setVirtualGroup(false);
  107 + // TODO @puhui999:过期时间,应该是 Date 哈;
  108 + record.setExpireTime(activity.getLimitDuration());
  109 + record.setUserSize(activity.getUserSize());
  110 + recordMapper.insert(record);
  111 + }
  112 +
  113 + @Override
  114 + public CombinationRecordDO getCombinationRecord(Long userId, Long orderId) {
  115 + return validateCombinationRecord(userId, orderId);
  116 + }
  117 +
  118 + /**
  119 + * APP 端获取开团记录
  120 + *
  121 + * @return 开团记录
  122 + */
  123 + public List<CombinationRecordDO> getRecordListByStatus(Integer status) {
  124 + return recordMapper.selectListByStatus(status);
  125 + }
  126 +
  127 +}
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationServiceImpl.java deleted
1   -package cn.iocoder.yudao.module.promotion.service.combination;
2   -
3   -import cn.hutool.core.collection.CollUtil;
4   -import cn.hutool.core.collection.CollectionUtil;
5   -import cn.hutool.core.util.ObjectUtil;
6   -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
7   -import cn.iocoder.yudao.framework.common.pojo.PageResult;
8   -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
9   -import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
10   -import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
11   -import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
12   -import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
13   -import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO;
14   -import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordUpdateStatusReqDTO;
15   -import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityCreateReqVO;
16   -import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityPageReqVO;
17   -import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityUpdateReqVO;
18   -import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductCreateReqVO;
19   -import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductUpdateReqVO;
20   -import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert;
21   -import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO;
22   -import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationProductDO;
23   -import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO;
24   -import cn.iocoder.yudao.module.promotion.dal.mysql.combination.CombinationActivityMapper;
25   -import cn.iocoder.yudao.module.promotion.dal.mysql.combination.CombinationProductMapper;
26   -import cn.iocoder.yudao.module.promotion.dal.mysql.combination.CombinationRecordMapper;
27   -import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum;
28   -import org.springframework.stereotype.Service;
29   -import org.springframework.transaction.annotation.Transactional;
30   -import org.springframework.validation.annotation.Validated;
31   -
32   -import javax.annotation.Resource;
33   -import java.util.Collection;
34   -import java.util.List;
35   -
36   -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
37   -import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS;
38   -import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
39   -import static cn.iocoder.yudao.module.promotion.util.PromotionUtils.validateProductSkuAllExists;
40   -
41   -/**
42   - * 拼团活动 Service 实现类
43   - *
44   - * @author HUIHUI
45   - */
46   -@Service
47   -@Validated
48   -public class CombinationServiceImpl implements CombinationActivityService, CombinationRecordService {
49   -
50   - @Resource
51   - private CombinationActivityMapper combinationActivityMapper;
52   - @Resource
53   - private CombinationRecordMapper recordMapper;
54   - @Resource
55   - private CombinationProductMapper combinationProductMapper;
56   - @Resource
57   - private ProductSpuApi productSpuApi;
58   - @Resource
59   - private ProductSkuApi productSkuApi;
60   -
61   - @Override
62   - @Transactional(rollbackFor = Exception.class)
63   - public Long createCombinationActivity(CombinationActivityCreateReqVO createReqVO) {
64   - // 校验商品 SPU 是否存在是否参加的别的活动
65   - validateProductCombinationConflict(createReqVO.getSpuId(), null);
66   - // 获取所选 spu下的所有 sku
67   - List<ProductSkuRespDTO> skus = productSkuApi.getSkuListBySpuId(CollectionUtil.newArrayList(createReqVO.getSpuId()));
68   - // 校验商品 sku 是否存在
69   - validateProductSkuAllExists(skus, createReqVO.getProducts(), CombinationProductCreateReqVO::getSkuId);
70   -
71   - // TODO 艿艿 有个小问题:现在有活动时间和限制时长,活动时间的结束时间早于设置的限制时间怎么算状态比如:
72   - // 活动时间 2023-08-05 15:00:00 - 2023-08-05 15:20:00 限制时长 2小时,那么活动时间结束就结束还是加时到满两小时
73   - // 插入拼团活动
74   - CombinationActivityDO activityDO = CombinationActivityConvert.INSTANCE.convert(createReqVO);
75   - // TODO 营销相关属性初始化 拼团成功更新相关属性
76   - activityDO.setTotalNum(0);
77   - activityDO.setSuccessNum(0);
78   - activityDO.setOrderUserCount(0);
79   - activityDO.setVirtualGroup(0);
80   - activityDO.setStatus(CommonStatusEnum.ENABLE.getStatus());
81   - combinationActivityMapper.insert(activityDO);
82   - // 插入商品
83   - List<CombinationProductDO> productDOs = CombinationActivityConvert.INSTANCE.convertList(createReqVO.getProducts(), activityDO);
84   - combinationProductMapper.insertBatch(productDOs);
85   - // 返回
86   - return activityDO.getId();
87   - }
88   -
89   - private void validateProductCombinationConflict(Long spuId, Long activityId) {
90   - // 校验商品 spu 是否存在
91   - List<ProductSpuRespDTO> spuList = productSpuApi.getSpuList(CollUtil.newArrayList(spuId));
92   - if (CollUtil.isEmpty(spuList)) {
93   - throw exception(SPU_NOT_EXISTS);
94   - }
95   - // 查询所有开启的拼团活动
96   - List<CombinationActivityDO> activityDOs = combinationActivityMapper.selectListByStatus(CommonStatusEnum.ENABLE.getStatus());
97   - // 更新时排除自己
98   - if (activityId != null) {
99   - activityDOs.removeIf(item -> ObjectUtil.equal(item.getId(), activityId));
100   - }
101   - // 过滤出所有 spuIds 有交集的活动
102   - List<CombinationActivityDO> doList = CollectionUtils.convertList(activityDOs, c -> c, s -> ObjectUtil.equal(s.getId(), spuId));
103   - if (CollUtil.isNotEmpty(doList)) {
104   - throw exception(COMBINATION_ACTIVITY_SPU_CONFLICTS);
105   - }
106   - }
107   -
108   - @Override
109   - @Transactional(rollbackFor = Exception.class)
110   - public void updateCombinationActivity(CombinationActivityUpdateReqVO updateReqVO) {
111   - // 校验存在
112   - CombinationActivityDO activityDO = validateCombinationActivityExists(updateReqVO.getId());
113   - // 校验状态
114   - if (ObjectUtil.equal(activityDO.getStatus(), CommonStatusEnum.DISABLE.getStatus())) {
115   - throw exception(COMBINATION_ACTIVITY_STATUS_DISABLE);
116   - }
117   - // 校验商品冲突
118   - validateProductCombinationConflict(updateReqVO.getSpuId(), updateReqVO.getId());
119   - // 获取所选 spu下的所有 sku
120   - List<ProductSkuRespDTO> skus = productSkuApi.getSkuListBySpuId(CollectionUtil.newArrayList(updateReqVO.getSpuId()));
121   - // 校验商品 sku 是否存在
122   - validateProductSkuAllExists(skus, updateReqVO.getProducts(), CombinationProductUpdateReqVO::getSkuId);
123   -
124   - // 更新
125   - CombinationActivityDO updateObj = CombinationActivityConvert.INSTANCE.convert(updateReqVO);
126   - combinationActivityMapper.updateById(updateObj);
127   - // 更新商品
128   - updateCombinationProduct(updateObj, updateReqVO.getProducts());
129   - }
130   -
131   - /**
132   - * 更新拼团商品
133   - *
134   - * @param activity 拼团活动
135   - * @param products 该活动的最新商品配置
136   - */
137   - private void updateCombinationProduct(CombinationActivityDO activity, List<CombinationProductUpdateReqVO> products) {
138   - // 第一步,对比新老数据,获得添加、修改、删除的列表
139   - List<CombinationProductDO> newList = CombinationActivityConvert.INSTANCE.convertList(products, activity);
140   - List<CombinationProductDO> oldList = combinationProductMapper.selectListByActivityIds(CollUtil.newArrayList(activity.getId()));
141   - List<List<CombinationProductDO>> diffList = CollectionUtils.diffList(oldList, newList, (oldVal, newVal) -> {
142   - boolean same = ObjectUtil.equal(oldVal.getSkuId(), newVal.getSkuId());
143   - if (same) {
144   - newVal.setId(oldVal.getId());
145   - }
146   - return same;
147   - });
148   -
149   - // 第二步,批量添加、修改、删除
150   - if (CollUtil.isNotEmpty(diffList.get(0))) {
151   - combinationProductMapper.insertBatch(diffList.get(0));
152   - }
153   - if (CollUtil.isNotEmpty(diffList.get(1))) {
154   - combinationProductMapper.updateBatch(diffList.get(1));
155   - }
156   - if (CollUtil.isNotEmpty(diffList.get(2))) {
157   - combinationProductMapper.deleteBatchIds(CollectionUtils.convertList(diffList.get(2), CombinationProductDO::getId));
158   - }
159   - }
160   -
161   - @Override
162   - @Transactional(rollbackFor = Exception.class)
163   - public void deleteCombinationActivity(Long id) {
164   - // 校验存在
165   - CombinationActivityDO activityDO = validateCombinationActivityExists(id);
166   - // 校验状态
167   - if (ObjectUtil.equal(activityDO.getStatus(), CommonStatusEnum.ENABLE.getStatus())) {
168   - throw exception(COMBINATION_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END);
169   - }
170   -
171   - // 删除
172   - combinationActivityMapper.deleteById(id);
173   - }
174   -
175   - private CombinationActivityDO validateCombinationActivityExists(Long id) {
176   - CombinationActivityDO activityDO = combinationActivityMapper.selectById(id);
177   - if (activityDO == null) {
178   - throw exception(COMBINATION_ACTIVITY_NOT_EXISTS);
179   - }
180   - return activityDO;
181   - }
182   -
183   - @Override
184   - public CombinationActivityDO getCombinationActivity(Long id) {
185   - return validateCombinationActivityExists(id);
186   - }
187   -
188   - @Override
189   - public List<CombinationActivityDO> getCombinationActivityList(Collection<Long> ids) {
190   - return combinationActivityMapper.selectBatchIds(ids);
191   - }
192   -
193   - @Override
194   - public PageResult<CombinationActivityDO> getCombinationActivityPage(CombinationActivityPageReqVO pageReqVO) {
195   - return combinationActivityMapper.selectPage(pageReqVO);
196   - }
197   -
198   - @Override
199   - public List<CombinationProductDO> getCombinationProductsByActivityIds(Collection<Long> ids) {
200   - return combinationProductMapper.selectListByActivityIds(ids);
201   - }
202   -
203   - @Override
204   - public void updateCombinationRecordStatusByUserIdAndOrderId(CombinationRecordUpdateStatusReqDTO reqDTO) {
205   - // 校验拼团是否存在
206   - CombinationRecordDO recordDO = validateCombinationRecord(reqDTO.getUserId(), reqDTO.getOrderId());
207   -
208   - // 更新状态
209   - recordDO.setStatus(reqDTO.getStatus());
210   - recordMapper.updateById(recordDO);
211   - }
212   -
213   - @Override
214   - @Transactional(rollbackFor = Exception.class)
215   - public void updateCombinationRecordStatusAndStartTimeByUserIdAndOrderId(CombinationRecordUpdateStatusReqDTO reqDTO) {
216   - CombinationRecordDO recordDO = validateCombinationRecord(reqDTO.getUserId(), reqDTO.getOrderId());
217   - // 更新状态
218   - recordDO.setStatus(reqDTO.getStatus());
219   - // 更新开始时间
220   - recordDO.setStartTime(reqDTO.getStartTime());
221   - recordMapper.updateById(recordDO);
222   -
223   - // 更新拼团参入人数
224   - List<CombinationRecordDO> recordDOs = recordMapper.selectListByHeadIdAndStatus(recordDO.getHeadId(), reqDTO.getStatus());
225   - if (CollUtil.isNotEmpty(recordDOs)) {
226   - recordDOs.forEach(item -> {
227   - item.setUserCount(recordDOs.size());
228   - // 校验拼团是否满足要求
229   - if (ObjectUtil.equal(recordDOs.size(), recordDO.getUserSize())) {
230   - item.setStatus(CombinationRecordStatusEnum.SUCCESS.getStatus());
231   - }
232   - });
233   - }
234   - recordMapper.updateBatch(recordDOs);
235   - }
236   -
237   - private CombinationRecordDO validateCombinationRecord(Long userId, Long orderId) {
238   - // 校验拼团是否存在
239   - CombinationRecordDO recordDO = recordMapper.selectByUserIdAndOrderId(userId, orderId);
240   - if (recordDO == null) {
241   - throw exception(COMBINATION_RECORD_NOT_EXISTS);
242   - }
243   - return recordDO;
244   - }
245   -
246   - @Override
247   - public void createCombinationRecord(CombinationRecordCreateReqDTO reqDTO) {
248   - // 1.1 校验拼团活动
249   - CombinationActivityDO activity = validateCombinationActivityExists(reqDTO.getActivityId());
250   - // 1.2 需要校验下,他当前是不是已经参加了该拼团;
251   - CombinationRecordDO recordDO = recordMapper.selectByUserIdAndOrderId(reqDTO.getUserId(), reqDTO.getOrderId());
252   - if (recordDO != null) {
253   - throw exception(COMBINATION_RECORD_EXISTS);
254   - }
255   - // 1.3 父拼团是否存在,是否已经满了
256   - if (reqDTO.getHeadId() != null) {
257   - CombinationRecordDO recordDO1 = recordMapper.selectRecordByHeadId(reqDTO.getHeadId(), reqDTO.getActivityId(), CombinationRecordStatusEnum.IN_PROGRESS.getStatus());
258   - if (recordDO1 == null) {
259   - throw exception(COMBINATION_RECORD_HEAD_NOT_EXISTS);
260   - }
261   - // 校验拼团是否满足要求
262   - if (ObjectUtil.equal(recordDO1.getUserCount(), recordDO1.getUserSize())) {
263   - throw exception(COMBINATION_RECORD_USER_FULL);
264   - }
265   - }
266   - // TODO @puhui999:应该还有一些校验,后续补噶;例如说,一个团,自己已经参与进去了,不能再参与进去;
267   -
268   - // 2. 创建拼团记录
269   - CombinationRecordDO record = CombinationActivityConvert.INSTANCE.convert(reqDTO);
270   - record.setVirtualGroup(false);
271   - // TODO @puhui999:过期时间,应该是 Date 哈;
272   - record.setExpireTime(activity.getLimitDuration());
273   - record.setUserSize(activity.getUserSize());
274   - recordMapper.insert(record);
275   - }
276   -
277   - @Override
278   - public CombinationRecordDO getCombinationRecord(Long userId, Long orderId) {
279   - return validateCombinationRecord(userId, orderId);
280   - }
281   -
282   - /**
283   - * APP 端获取开团记录
284   - *
285   - * @return 开团记录
286   - */
287   - public List<CombinationRecordDO> getRecordListByStatus(Integer status) {
288   - return recordMapper.selectListByStatus(status);
289   - }
290   -
291   -}
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillactivity/SeckillActivityService.java renamed to yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityService.java
1   -package cn.iocoder.yudao.module.promotion.service.seckill.seckillactivity;
  1 +package cn.iocoder.yudao.module.promotion.service.seckill;
2 2  
3 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 4 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityCreateReqVO;
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillactivity/SeckillActivityServiceImpl.java renamed to yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java
1   -package cn.iocoder.yudao.module.promotion.service.seckill.seckillactivity;
  1 +package cn.iocoder.yudao.module.promotion.service.seckill;
2 2  
3 3 import cn.hutool.core.util.ObjectUtil;
4 4 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
... ... @@ -16,7 +16,6 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.
16 16 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO;
17 17 import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillactivity.SeckillActivityMapper;
18 18 import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillactivity.SeckillProductMapper;
19   -import cn.iocoder.yudao.module.promotion.service.seckill.seckillconfig.SeckillConfigService;
20 19 import cn.iocoder.yudao.module.promotion.util.PromotionUtils;
21 20 import org.springframework.stereotype.Service;
22 21 import org.springframework.transaction.annotation.Transactional;
... ... @@ -78,8 +77,7 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
78 77 * 校验秒杀商品参与的活动是否存在冲突
79 78 *
80 79 * 1. 校验秒杀时段是否存在
81   - * 2. 校验商品 spu 是否存在
82   - * 3. 秒杀商品是否参加其它活动
  80 + * 2. 秒杀商品是否参加其它活动
83 81 *
84 82 * @param configIds 秒杀时段数组
85 83 * @param spuId 商品 SPU 编号
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillconfig/SeckillConfigService.java renamed to yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillConfigService.java
1   -package cn.iocoder.yudao.module.promotion.service.seckill.seckillconfig;
  1 +package cn.iocoder.yudao.module.promotion.service.seckill;
2 2  
3 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 4 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigCreateReqVO;
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillconfig/SeckillConfigServiceImpl.java renamed to yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillConfigServiceImpl.java
1   -package cn.iocoder.yudao.module.promotion.service.seckill.seckillconfig;
  1 +package cn.iocoder.yudao.module.promotion.service.seckill;
2 2  
3 3 import cn.hutool.core.collection.CollUtil;
4 4 import cn.hutool.core.util.ObjectUtil;
... ...
yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImplTest.java
... ... @@ -24,15 +24,15 @@ import static org.junit.jupiter.api.Assertions.*;
24 24  
25 25 // TODO 芋艿:等完成后,在补全单测
26 26 /**
27   - * {@link CombinationServiceImpl} 的单元测试类
  27 + * {@link CombinationActivityServiceImpl} 的单元测试类
28 28 *
29 29 * @author HUIHUI
30 30 */
31   -@Import(CombinationServiceImpl.class)
  31 +@Import(CombinationActivityServiceImpl.class)
32 32 public class CombinationActivityServiceImplTest extends BaseDbUnitTest {
33 33  
34 34 @Resource
35   - private CombinationServiceImpl combinationActivityService;
  35 + private CombinationActivityServiceImpl combinationActivityService;
36 36  
37 37 @Resource
38 38 private CombinationActivityMapper combinationActivityMapper;
... ... @@ -112,8 +112,8 @@ public class CombinationActivityServiceImplTest extends BaseDbUnitTest {
112 112 o.setStartTime(null);
113 113 o.setEndTime(null);
114 114 o.setUserSize(null);
115   - o.setTotalNum(null);
116   - o.setSuccessNum(null);
  115 + o.setTotalCount(null);
  116 + o.setSuccessCount(null);
117 117 o.setOrderUserCount(null);
118 118 o.setVirtualGroup(null);
119 119 o.setStatus(null);
... ... @@ -136,9 +136,9 @@ public class CombinationActivityServiceImplTest extends BaseDbUnitTest {
136 136 // 测试 userSize 不匹配
137 137 combinationActivityMapper.insert(cloneIgnoreId(dbCombinationActivity, o -> o.setUserSize(null)));
138 138 // 测试 totalNum 不匹配
139   - combinationActivityMapper.insert(cloneIgnoreId(dbCombinationActivity, o -> o.setTotalNum(null)));
  139 + combinationActivityMapper.insert(cloneIgnoreId(dbCombinationActivity, o -> o.setTotalCount(null)));
140 140 // 测试 successNum 不匹配
141   - combinationActivityMapper.insert(cloneIgnoreId(dbCombinationActivity, o -> o.setSuccessNum(null)));
  141 + combinationActivityMapper.insert(cloneIgnoreId(dbCombinationActivity, o -> o.setSuccessCount(null)));
142 142 // 测试 orderUserCount 不匹配
143 143 combinationActivityMapper.insert(cloneIgnoreId(dbCombinationActivity, o -> o.setOrderUserCount(null)));
144 144 // 测试 virtualGroup 不匹配
... ... @@ -186,8 +186,8 @@ public class CombinationActivityServiceImplTest extends BaseDbUnitTest {
186 186 o.setStartTime(null);
187 187 o.setEndTime(null);
188 188 o.setUserSize(null);
189   - o.setTotalNum(null);
190   - o.setSuccessNum(null);
  189 + o.setTotalCount(null);
  190 + o.setSuccessCount(null);
191 191 o.setOrderUserCount(null);
192 192 o.setVirtualGroup(null);
193 193 o.setStatus(null);
... ... @@ -210,9 +210,9 @@ public class CombinationActivityServiceImplTest extends BaseDbUnitTest {
210 210 // 测试 userSize 不匹配
211 211 combinationActivityMapper.insert(cloneIgnoreId(dbCombinationActivity, o -> o.setUserSize(null)));
212 212 // 测试 totalNum 不匹配
213   - combinationActivityMapper.insert(cloneIgnoreId(dbCombinationActivity, o -> o.setTotalNum(null)));
  213 + combinationActivityMapper.insert(cloneIgnoreId(dbCombinationActivity, o -> o.setTotalCount(null)));
214 214 // 测试 successNum 不匹配
215   - combinationActivityMapper.insert(cloneIgnoreId(dbCombinationActivity, o -> o.setSuccessNum(null)));
  215 + combinationActivityMapper.insert(cloneIgnoreId(dbCombinationActivity, o -> o.setSuccessCount(null)));
216 216 // 测试 orderUserCount 不匹配
217 217 combinationActivityMapper.insert(cloneIgnoreId(dbCombinationActivity, o -> o.setOrderUserCount(null)));
218 218 // 测试 virtualGroup 不匹配
... ...
yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/seckillactivity/SeckillActivityServiceImplTest.java
... ... @@ -7,7 +7,7 @@ import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.Se
7 7 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityUpdateReqVO;
8 8 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO;
9 9 import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillactivity.SeckillActivityMapper;
10   -import cn.iocoder.yudao.module.promotion.service.seckill.seckillactivity.SeckillActivityServiceImpl;
  10 +import cn.iocoder.yudao.module.promotion.service.seckill.SeckillActivityServiceImpl;
11 11 import org.junit.jupiter.api.Disabled;
12 12 import org.junit.jupiter.api.Test;
13 13 import org.springframework.context.annotation.Import;
... ...
yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/seckillconfig/SeckillConfigServiceImplTest.java
... ... @@ -5,7 +5,7 @@ import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.Seck
5 5 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigUpdateReqVO;
6 6 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillconfig.SeckillConfigDO;
7 7 import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillconfig.SeckillConfigMapper;
8   -import cn.iocoder.yudao.module.promotion.service.seckill.seckillconfig.SeckillConfigServiceImpl;
  8 +import cn.iocoder.yudao.module.promotion.service.seckill.SeckillConfigServiceImpl;
9 9 import com.fasterxml.jackson.core.JsonProcessingException;
10 10 import com.fasterxml.jackson.databind.ObjectMapper;
11 11 import org.junit.jupiter.api.Disabled;
... ...