소스 검색

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

YunaiV 1 년 전
부모
커밋
ba31d5f6fb
28개의 변경된 파일425개의 추가작업 그리고 439개의 파일을 삭제
  1. 12 7
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/CombinationActivityController.java
  2. 2 2
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityBaseVO.java
  3. 2 2
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityCreateReqVO.java
  4. 0 31
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityPageReqVO.java
  5. 10 16
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityRespVO.java
  6. 2 2
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityUpdateReqVO.java
  7. 2 2
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductBaseVO.java
  8. 0 14
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductCreateReqVO.java
  9. 0 14
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductUpdateReqVO.java
  10. 1 1
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillActivityController.java
  11. 1 1
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillConfigController.java
  12. 15 19
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/combination/CombinationActivityConvert.java
  13. 3 3
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/CombinationActivityDO.java
  14. 9 4
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/CombinationProductDO.java
  15. 3 0
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/CombinationActivityMapper.java
  16. 1 1
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/CombinationProductMapper.java
  17. 8 8
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityService.java
  18. 208 0
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImpl.java
  19. 1 1
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordService.java
  20. 127 0
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordServiceImpl.java
  21. 0 291
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationServiceImpl.java
  22. 1 1
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityService.java
  23. 2 4
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java
  24. 1 1
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillConfigService.java
  25. 1 1
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillConfigServiceImpl.java
  26. 11 11
      yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImplTest.java
  27. 1 1
      yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/seckillactivity/SeckillActivityServiceImplTest.java
  28. 1 1
      yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/seckillconfig/SeckillConfigServiceImplTest.java

+ 12 - 7
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/CombinationActivityController.java

@@ -1,8 +1,10 @@
 package cn.iocoder.yudao.module.promotion.controller.admin.combination;
 
+import cn.hutool.core.collection.CollUtil;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
+import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityCreateReqVO;
 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityPageReqVO;
 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityRespVO;
@@ -21,7 +23,6 @@ import org.springframework.web.bind.annotation.*;
 import javax.annotation.Resource;
 import javax.validation.Valid;
 import java.util.List;
-import java.util.Set;
 
 import static cn.hutool.core.collection.CollectionUtil.newArrayList;
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@@ -37,7 +38,7 @@ public class CombinationActivityController {
     private CombinationActivityService combinationActivityService;
 
     @Resource
-    private ProductSpuApi spuApi;
+    private ProductSpuApi productSpuApi;
 
     @PostMapping("/create")
     @Operation(summary = "创建拼团活动")
@@ -80,12 +81,16 @@ public class CombinationActivityController {
             @Valid CombinationActivityPageReqVO pageVO) {
         // 查询拼团活动
         PageResult<CombinationActivityDO> pageResult = combinationActivityService.getCombinationActivityPage(pageVO);
+        if (CollUtil.isEmpty(pageResult.getList())) {
+            return success(PageResult.empty(pageResult.getTotal()));
+        }
+
         // 拼接数据
-        Set<Long> activityIds = convertSet(pageResult.getList(), CombinationActivityDO::getId);
-        Set<Long> spuIds = convertSet(pageResult.getList(), CombinationActivityDO::getSpuId);
-        return success(CombinationActivityConvert.INSTANCE.convertPage(pageResult,
-                combinationActivityService.getCombinationProductsByActivityIds(activityIds),
-                spuApi.getSpuList(spuIds)));
+        List<CombinationProductDO> products = combinationActivityService.getCombinationProductsByActivityIds(
+                convertSet(pageResult.getList(), CombinationActivityDO::getId));
+        List<ProductSpuRespDTO> spus = productSpuApi.getSpuList(
+                convertSet(pageResult.getList(), CombinationActivityDO::getSpuId));
+        return success(CombinationActivityConvert.INSTANCE.convertPage(pageResult, products, spus));
     }
 
 }

+ 2 - 2
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 {
     @NotNull(message = "拼团名称不能为空")
     private String name;
 
-    @Schema(description = "商品 SPU 编号,关联 ProductSpuDO 的 id", example = "[1,2,3]")
+    @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     @NotNull(message = "拼团商品不能为空")
     private Long spuId;
 
@@ -48,7 +48,7 @@ public class CombinationActivityBaseVO {
     @NotNull(message = "开团人数不能为空")
     private Integer userSize;
 
-    @Schema(description = "限制时长(小时)", requiredMode = Schema.RequiredMode.REQUIRED)
+    @Schema(description = "限制时长(小时)", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
     @NotNull(message = "限制时长不能为空")
     private Integer limitDuration;
 

+ 2 - 2
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityCreateReqVO.java

@@ -1,6 +1,6 @@
 package cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity;
 
-import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductCreateReqVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductBaseVO;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
@@ -17,6 +17,6 @@ public class CombinationActivityCreateReqVO extends CombinationActivityBaseVO {
 
     @Schema(description = "拼团商品", requiredMode = Schema.RequiredMode.REQUIRED)
     @Valid
-    private List<CombinationProductCreateReqVO> products;
+    private List<CombinationProductBaseVO> products;
 
 }

+ 0 - 31
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 {
     @Schema(description = "拼团名称", example = "赵六")
     private String name;
 
-    @Schema(description = "商品 SPU 编号关联 ProductSpuDO 的 id", example = "14016")
-    private Long spuId;
-
-    @Schema(description = "总限购数量", example = "16218")
-    private Integer totalLimitCount;
-
-    @Schema(description = "单次限购数量", example = "28265")
-    private Integer singleLimitCount;
-
     @Schema(description = "开始时间")
     @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
     private LocalDateTime[] startTime;
@@ -37,29 +28,7 @@ public class CombinationActivityPageReqVO extends PageParam {
     @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
     private LocalDateTime[] endTime;
 
-    @Schema(description = "开团人数")
-    private Integer userSize;
-
-    @Schema(description = "开团组数")
-    private Integer totalNum;
-
-    @Schema(description = "成团组数")
-    private Integer successNum;
-
-    @Schema(description = "参与人数", example = "25222")
-    private Integer orderUserCount;
-
-    @Schema(description = "虚拟成团")
-    private Integer virtualGroup;
-
     @Schema(description = "活动状态:0开启 1关闭", example = "0")
     private Integer status;
 
-    @Schema(description = "限制时长(小时)")
-    private Integer limitDuration;
-
-    @Schema(description = "创建时间")
-    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
-    private LocalDateTime[] createTime;
-
 }

+ 10 - 16
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;
 @ToString(callSuper = true)
 public class CombinationActivityRespVO extends CombinationActivityBaseVO {
 
-    @Schema(description = "商品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "618大促")
+    @Schema(description = "活动编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "22901")
+    private Long id;
+
+    @Schema(description = "商品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "618 大促")
     private String spuName;
 
     @Schema(description = "商品主图", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xx.png")
     private String picUrl;
 
-    @Schema(description = "活动编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "22901")
-    private Long id;
-
     @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
     private LocalDateTime createTime;
 
-    @Schema(description = "开团人数", requiredMode = Schema.RequiredMode.REQUIRED)
-    @NotNull(message = "开团人数不能为空")
+    @Schema(description = "开团人数", requiredMode = Schema.RequiredMode.REQUIRED, example = "666")
     private Integer userSize;
 
-    @Schema(description = "开团组数", requiredMode = Schema.RequiredMode.REQUIRED)
-    @NotNull(message = "开团组数不能为空")
-    private Integer totalNum;
+    @Schema(description = "开团组数", requiredMode = Schema.RequiredMode.REQUIRED, example = "33")
+    private Integer totalCount;
 
-    @Schema(description = "成团组数", requiredMode = Schema.RequiredMode.REQUIRED)
-    @NotNull(message = "成团组数不能为空")
-    private Integer successNum;
+    @Schema(description = "成团组数", requiredMode = Schema.RequiredMode.REQUIRED, example = "20")
+    private Integer successCount;
 
-    @Schema(description = "虚拟成团", requiredMode = Schema.RequiredMode.REQUIRED)
-    @NotNull(message = "虚拟成团不能为空")
+    @Schema(description = "虚拟成团", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
     private Integer virtualGroup;
 
     @Schema(description = "活动状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
-    @NotNull(message = "活动状态不能为空")
     private Integer status;
 
     @Schema(description = "拼团商品", requiredMode = Schema.RequiredMode.REQUIRED)
-    @Valid
     private List<CombinationProductRespVO> products;
 
 }

+ 2 - 2
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityUpdateReqVO.java

@@ -1,6 +1,6 @@
 package cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity;
 
-import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductUpdateReqVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductBaseVO;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
@@ -22,6 +22,6 @@ public class CombinationActivityUpdateReqVO extends CombinationActivityBaseVO {
 
     @Schema(description = "拼团商品", requiredMode = Schema.RequiredMode.REQUIRED)
     @Valid
-    private List<CombinationProductUpdateReqVO> products;
+    private List<CombinationProductBaseVO> products;
 
 }

+ 2 - 2
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 {
     private Long skuId;
 
     @Schema(description = "拼团价格,单位分", requiredMode = Schema.RequiredMode.REQUIRED, example = "27682")
-    @NotNull(message = "拼团价格,单位分不能为空")
-    private Integer activePrice;
+    @NotNull(message = "拼团价格不能为空")
+    private Integer combinationPrice;
 
 }

+ 0 - 14
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductCreateReqVO.java

@@ -1,14 +0,0 @@
-package cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.ToString;
-
-@Schema(description = "管理后台 - 拼团商品创建 Request VO")
-@Data
-@EqualsAndHashCode(callSuper = true)
-@ToString(callSuper = true)
-public class CombinationProductCreateReqVO extends CombinationProductBaseVO {
-
-}

+ 0 - 14
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/product/CombinationProductUpdateReqVO.java

@@ -1,14 +0,0 @@
-package cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.ToString;
-
-@Schema(description = "管理后台 - 拼团商品更新 Request VO")
-@Data
-@EqualsAndHashCode(callSuper = true)
-@ToString(callSuper = true)
-public class CombinationProductUpdateReqVO extends CombinationProductBaseVO {
-
-}

+ 1 - 1
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.*;
 import cn.iocoder.yudao.module.promotion.convert.seckill.seckillactivity.SeckillActivityConvert;
 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO;
 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO;
-import cn.iocoder.yudao.module.promotion.service.seckill.seckillactivity.SeckillActivityService;
+import cn.iocoder.yudao.module.promotion.service.seckill.SeckillActivityService;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.Parameter;
 import io.swagger.v3.oas.annotations.tags.Tag;

+ 1 - 1
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;
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.*;
 import cn.iocoder.yudao.module.promotion.convert.seckill.seckillconfig.SeckillConfigConvert;
 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillconfig.SeckillConfigDO;
-import cn.iocoder.yudao.module.promotion.service.seckill.seckillconfig.SeckillConfigService;
+import cn.iocoder.yudao.module.promotion.service.seckill.SeckillConfigService;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.Parameter;
 import io.swagger.v3.oas.annotations.tags.Tag;

+ 15 - 19
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
 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityUpdateReqVO;
 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductBaseVO;
 import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductRespVO;
-import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductUpdateReqVO;
 import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO;
 import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationProductDO;
 import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO;
@@ -53,37 +52,34 @@ public interface CombinationActivityConvert {
     default PageResult<CombinationActivityRespVO> convertPage(PageResult<CombinationActivityDO> page,
                                                               List<CombinationProductDO> productList,
                                                               List<ProductSpuRespDTO> spuList) {
-        Map<Long, ProductSpuRespDTO> spuMap = convertMap(spuList, ProductSpuRespDTO::getId);
         PageResult<CombinationActivityRespVO> pageResult = convertPage(page);
+        // 拼接商品
+        Map<Long, ProductSpuRespDTO> spuMap = convertMap(spuList, ProductSpuRespDTO::getId);
         pageResult.getList().forEach(item -> {
-            MapUtils.findAndThen(spuMap, item.getSpuId(), spu -> {
-                item.setSpuName(spu.getName());
-                item.setPicUrl(spu.getPicUrl());
-            });
             item.setProducts(convertList2(productList));
+            MapUtils.findAndThen(spuMap, item.getSpuId(),
+                    spu -> item.setSpuName(spu.getName()).setPicUrl(spu.getPicUrl()));
         });
         return pageResult;
     }
 
     List<CombinationProductRespVO> convertList2(List<CombinationProductDO> productDOs);
 
-    // TODO @puhui999:参数改成 activity、product 会不会干净一点哈
-    @Mappings({
-            @Mapping(target = "id", ignore = true),
-            @Mapping(target = "activityId", source = "activityDO.id"),
-            @Mapping(target = "spuId", source = "activityDO.spuId"),
-            @Mapping(target = "skuId", source = "vo.skuId"),
-            @Mapping(target = "activePrice", source = "vo.activePrice"),
-            @Mapping(target = "activityStartTime", source = "activityDO.startTime"),
-            @Mapping(target = "activityEndTime", source = "activityDO.endTime")
-    })
-    CombinationProductDO convert(CombinationActivityDO activityDO, CombinationProductBaseVO vo);
-
     default List<CombinationProductDO> convertList(List<? extends CombinationProductBaseVO> products, CombinationActivityDO activityDO) {
         return CollectionUtils.convertList(products, item -> convert(activityDO, item).setActivityStatus(activityDO.getStatus()));
     }
+    @Mappings({
+            @Mapping(target = "id", ignore = true),
+            @Mapping(target = "activityId", source = "activity.id"),
+            @Mapping(target = "spuId", source = "activity.spuId"),
+            @Mapping(target = "skuId", source = "product.skuId"),
+            @Mapping(target = "combinationPrice", source = "product.combinationPrice"),
+            @Mapping(target = "activityStartTime", source = "activity.startTime"),
+            @Mapping(target = "activityEndTime", source = "activity.endTime")
+    })
+    CombinationProductDO convert(CombinationActivityDO activity, CombinationProductBaseVO product);
 
-    default List<CombinationProductDO> convertList(List<CombinationProductUpdateReqVO> updateProductVOs,
+    default List<CombinationProductDO> convertList(List<CombinationProductBaseVO> updateProductVOs,
                                                    List<CombinationProductDO> products, CombinationActivityDO activity) {
         Map<Long, Long> productMap = convertMap(products, CombinationProductDO::getSkuId, CombinationProductDO::getId);
         return CollectionUtils.convertList(updateProductVOs, updateProductVO -> convert(activity, updateProductVO)

+ 3 - 3
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 {
     /**
      * 开团组数
      */
-    private Integer totalNum;
+    private Integer totalCount;
     /**
      * 成团组数
      */
-    private Integer successNum;
+    private Integer successCount;
     /**
      * 参与人数
      */
@@ -76,7 +76,7 @@ public class CombinationActivityDO extends BaseDO {
      */
     private Integer virtualGroup;
     /**
-     * 活动状态:0开启 1关闭
+     * 活动状态
      *
      * 枚举 {@link CommonStatusEnum}
      */

+ 9 - 4
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/CombinationProductDO.java

@@ -40,6 +40,11 @@ public class CombinationProductDO extends BaseDO {
      * 商品 SKU 编号
      */
     private Long skuId;
+    /**
+     * 拼团价格,单位分
+     */
+    private Integer combinationPrice;
+
     /**
      * 拼团商品状态
      *
@@ -48,15 +53,15 @@ public class CombinationProductDO extends BaseDO {
     private Integer activityStatus;
     /**
      * 活动开始时间点
+     *
+     * 冗余 {@link CombinationActivityDO#getStartTime()}
      */
     private LocalDateTime activityStartTime;
     /**
      * 活动结束时间点
+     *
+     * 冗余 {@link CombinationActivityDO#getEndTime()}
      */
     private LocalDateTime activityEndTime;
-    /**
-     * 拼团价格,单位分
-     */
-    private Integer activePrice;
 
 }

+ 3 - 0
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<CombinationActivi
     default PageResult<CombinationActivityDO> selectPage(CombinationActivityPageReqVO reqVO) {
         return selectPage(reqVO, new LambdaQueryWrapperX<CombinationActivityDO>()
                 .likeIfPresent(CombinationActivityDO::getName, reqVO.getName())
+                .betweenIfPresent(CombinationActivityDO::getStartTime, reqVO.getStartTime())
+                .betweenIfPresent(CombinationActivityDO::getEndTime, reqVO.getEndTime())
+                .eqIfPresent(CombinationActivityDO::getStatus, reqVO.getStatus())
                 .orderByDesc(CombinationActivityDO::getId));
     }
 

+ 1 - 1
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<CombinationProduct
                 .eqIfPresent(CombinationProductDO::getActivityStatus, reqVO.getActivityStatus())
                 .betweenIfPresent(CombinationProductDO::getActivityStartTime, reqVO.getActivityStartTime())
                 .betweenIfPresent(CombinationProductDO::getActivityEndTime, reqVO.getActivityEndTime())
-                .eqIfPresent(CombinationProductDO::getActivePrice, reqVO.getActivePrice())
+                .eqIfPresent(CombinationProductDO::getCombinationPrice, reqVO.getActivePrice())
                 .betweenIfPresent(CombinationProductDO::getCreateTime, reqVO.getCreateTime())
                 .orderByDesc(CombinationProductDO::getId));
     }

+ 8 - 8
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 {
     void deleteCombinationActivity(Long id);
 
     /**
-     * 获得拼团活动
+     * 校验拼团活动是否存在
      *
      * @param id 编号
      * @return 拼团活动
      */
-    CombinationActivityDO getCombinationActivity(Long id);
+    CombinationActivityDO validateCombinationActivityExists(Long id);
 
     /**
-     * 获得拼团活动列表
+     * 获得拼团活动
      *
-     * @param ids 编号
-     * @return 拼团活动列表
+     * @param id 编号
+     * @return 拼团活动
      */
-    List<CombinationActivityDO> getCombinationActivityList(Collection<Long> ids);
+    CombinationActivityDO getCombinationActivity(Long id);
 
     /**
      * 获得拼团活动分页
@@ -67,9 +67,9 @@ public interface CombinationActivityService {
     /**
      * 获得拼团活动商品列表
      *
-     * @param ids 拼团活动 ids
+     * @param activityIds 拼团活动 ids
      * @return 拼团活动的商品列表
      */
-    List<CombinationProductDO> getCombinationProductsByActivityIds(Collection<Long> ids);
+    List<CombinationProductDO> getCombinationProductsByActivityIds(Collection<Long> activityIds);
 
 }

+ 208 - 0
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImpl.java

@@ -0,0 +1,208 @@
+package cn.iocoder.yudao.module.promotion.service.combination;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.ObjectUtil;
+import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
+import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
+import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
+import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
+import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
+import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityCreateReqVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityPageReqVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityUpdateReqVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductBaseVO;
+import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert;
+import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO;
+import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationProductDO;
+import cn.iocoder.yudao.module.promotion.dal.mysql.combination.CombinationActivityMapper;
+import cn.iocoder.yudao.module.promotion.dal.mysql.combination.CombinationProductMapper;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.validation.annotation.Validated;
+
+import javax.annotation.Resource;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList;
+import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS;
+import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS;
+import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
+import static java.util.Collections.singletonList;
+
+/**
+ * 拼团活动 Service 实现类
+ *
+ * @author HUIHUI
+ */
+@Service
+@Validated
+public class CombinationActivityServiceImpl implements CombinationActivityService {
+
+    @Resource
+    private CombinationActivityMapper combinationActivityMapper;
+    @Resource
+    private CombinationProductMapper combinationProductMapper;
+
+    @Resource
+    private ProductSpuApi productSpuApi;
+    @Resource
+    private ProductSkuApi productSkuApi;
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Long createCombinationActivity(CombinationActivityCreateReqVO createReqVO) {
+        // 校验商品 SPU 是否存在是否参加的别的活动
+        validateProductConflict(createReqVO.getSpuId(), null);
+        // 校验商品是否存在
+        validateProductExists(createReqVO.getSpuId(), createReqVO.getProducts());
+
+        // 插入拼团活动
+        CombinationActivityDO activity = CombinationActivityConvert.INSTANCE.convert(createReqVO)
+                .setStatus(CommonStatusEnum.ENABLE.getStatus())
+                .setTotalCount(0).setSuccessCount(0).setOrderUserCount(0).setVirtualGroup(0);
+        combinationActivityMapper.insert(activity);
+        // 插入商品
+        List<CombinationProductDO> products = CombinationActivityConvert.INSTANCE.convertList(createReqVO.getProducts(), activity);
+        combinationProductMapper.insertBatch(products);
+        // 返回
+        return activity.getId();
+    }
+
+    /**
+     * 校验拼团商品参与的活动是否存在冲突
+     *
+     * @param spuId 商品 SPU 编号
+     * @param activityId 拼团活动编号
+     */
+    private void validateProductConflict(Long spuId, Long activityId) {
+        // 查询所有开启的拼团活动
+        List<CombinationActivityDO> activityList = combinationActivityMapper.selectListByStatus(CommonStatusEnum.ENABLE.getStatus());
+        if (activityId != null) { // 时排除自己
+            activityList.removeIf(item -> ObjectUtil.equal(item.getId(), activityId));
+        }
+        // 查找是否有其它活动,选择了该产品
+        List<CombinationActivityDO> matchActivityList = filterList(activityList, activity -> ObjectUtil.equal(activity.getId(), spuId));
+        if (CollUtil.isNotEmpty(matchActivityList)) {
+            throw exception(COMBINATION_ACTIVITY_SPU_CONFLICTS);
+        }
+    }
+
+    /**
+     * 校验拼团商品是否都存在
+     *
+     * @param spuId 商品 SPU 编号
+     * @param products 秒杀商品
+     */
+    private void validateProductExists(Long spuId, List<CombinationProductBaseVO> products) {
+        // 1. 校验商品 spu 是否存在
+        ProductSpuRespDTO spu = productSpuApi.getSpu(spuId);
+        if (spu == null) {
+            throw exception(SPU_NOT_EXISTS);
+        }
+
+        // 2. 校验商品 sku 都存在
+        Map<Long, ProductSkuRespDTO> skuMap = convertMap(productSkuApi.getSkuListBySpuId(singletonList(spuId)),
+                ProductSkuRespDTO::getId);
+        products.forEach(product -> {
+            if (!skuMap.containsKey(product.getSkuId())) {
+                throw exception(SKU_NOT_EXISTS);
+            }
+        });
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void updateCombinationActivity(CombinationActivityUpdateReqVO updateReqVO) {
+        // 校验存在
+        CombinationActivityDO activityDO = validateCombinationActivityExists(updateReqVO.getId());
+        // 校验状态
+        if (ObjectUtil.equal(activityDO.getStatus(), CommonStatusEnum.DISABLE.getStatus())) {
+            throw exception(COMBINATION_ACTIVITY_STATUS_DISABLE);
+        }
+        // 校验商品冲突
+        validateProductConflict(updateReqVO.getSpuId(), updateReqVO.getId());
+        // 校验商品是否存在
+        validateProductExists(updateReqVO.getSpuId(), updateReqVO.getProducts());
+
+        // 更新活动
+        CombinationActivityDO updateObj = CombinationActivityConvert.INSTANCE.convert(updateReqVO);
+        combinationActivityMapper.updateById(updateObj);
+        // 更新商品
+        updateCombinationProduct(updateObj, updateReqVO.getProducts());
+    }
+
+    /**
+     * 更新拼团商品
+     *
+     * @param activity 拼团活动
+     * @param products  该活动的最新商品配置
+     */
+    private void updateCombinationProduct(CombinationActivityDO activity, List<CombinationProductBaseVO> products) {
+        // 第一步,对比新老数据,获得添加、修改、删除的列表
+        List<CombinationProductDO> newList = CombinationActivityConvert.INSTANCE.convertList(products, activity);
+        List<CombinationProductDO> oldList = combinationProductMapper.selectListByActivityIds(CollUtil.newArrayList(activity.getId()));
+        List<List<CombinationProductDO>> diffList = CollectionUtils.diffList(oldList, newList, (oldVal, newVal) -> {
+            boolean same = ObjectUtil.equal(oldVal.getSkuId(), newVal.getSkuId());
+            if (same) {
+                newVal.setId(oldVal.getId());
+            }
+            return same;
+        });
+
+        // 第二步,批量添加、修改、删除
+        if (CollUtil.isNotEmpty(diffList.get(0))) {
+            combinationProductMapper.insertBatch(diffList.get(0));
+        }
+        if (CollUtil.isNotEmpty(diffList.get(1))) {
+            combinationProductMapper.updateBatch(diffList.get(1));
+        }
+        if (CollUtil.isNotEmpty(diffList.get(2))) {
+            combinationProductMapper.deleteBatchIds(CollectionUtils.convertList(diffList.get(2), CombinationProductDO::getId));
+        }
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void deleteCombinationActivity(Long id) {
+        // 校验存在
+        CombinationActivityDO activityDO = validateCombinationActivityExists(id);
+        // 校验状态
+        if (ObjectUtil.equal(activityDO.getStatus(), CommonStatusEnum.ENABLE.getStatus())) {
+            throw exception(COMBINATION_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END);
+        }
+
+        // 删除
+        combinationActivityMapper.deleteById(id);
+    }
+
+    @Override
+    public CombinationActivityDO validateCombinationActivityExists(Long id) {
+        CombinationActivityDO activityDO = combinationActivityMapper.selectById(id);
+        if (activityDO == null) {
+            throw exception(COMBINATION_ACTIVITY_NOT_EXISTS);
+        }
+        return activityDO;
+    }
+
+    @Override
+    public CombinationActivityDO getCombinationActivity(Long id) {
+        return validateCombinationActivityExists(id);
+    }
+
+    @Override
+    public PageResult<CombinationActivityDO> getCombinationActivityPage(CombinationActivityPageReqVO pageReqVO) {
+        return combinationActivityMapper.selectPage(pageReqVO);
+    }
+
+    @Override
+    public List<CombinationProductDO> getCombinationProductsByActivityIds(Collection<Long> activityIds) {
+        return combinationProductMapper.selectListByActivityIds(activityIds);
+    }
+
+}

+ 1 - 1
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
 import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO;
 
 /**
- * 商品活动记录 service
+ * 拼团记录 Service 接口
  *
  * @author HUIHUI
  */

+ 127 - 0
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordServiceImpl.java

@@ -0,0 +1,127 @@
+package cn.iocoder.yudao.module.promotion.service.combination;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.ObjectUtil;
+import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO;
+import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordUpdateStatusReqDTO;
+import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert;
+import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO;
+import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO;
+import cn.iocoder.yudao.module.promotion.dal.mysql.combination.CombinationRecordMapper;
+import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.validation.annotation.Validated;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
+import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COMBINATION_RECORD_USER_FULL;
+
+// TODO 芋艿:等拼团记录做完,完整 review 下
+/**
+ * 拼团记录 Service 实现类
+ *
+ * @author HUIHUI
+ */
+@Service
+@Validated
+public class CombinationRecordServiceImpl implements CombinationRecordService {
+
+    @Resource
+    private CombinationActivityService combinationActivityService;
+
+    @Resource
+    private CombinationRecordMapper recordMapper;
+
+    @Override
+    public void updateCombinationRecordStatusByUserIdAndOrderId(CombinationRecordUpdateStatusReqDTO reqDTO) {
+        // 校验拼团是否存在
+        CombinationRecordDO recordDO = validateCombinationRecord(reqDTO.getUserId(), reqDTO.getOrderId());
+
+        // 更新状态
+        recordDO.setStatus(reqDTO.getStatus());
+        recordMapper.updateById(recordDO);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void updateCombinationRecordStatusAndStartTimeByUserIdAndOrderId(CombinationRecordUpdateStatusReqDTO reqDTO) {
+        CombinationRecordDO recordDO = validateCombinationRecord(reqDTO.getUserId(), reqDTO.getOrderId());
+        // 更新状态
+        recordDO.setStatus(reqDTO.getStatus());
+        // 更新开始时间
+        recordDO.setStartTime(reqDTO.getStartTime());
+        recordMapper.updateById(recordDO);
+
+        // 更新拼团参入人数
+        List<CombinationRecordDO> recordDOs = recordMapper.selectListByHeadIdAndStatus(recordDO.getHeadId(), reqDTO.getStatus());
+        if (CollUtil.isNotEmpty(recordDOs)) {
+            recordDOs.forEach(item -> {
+                item.setUserCount(recordDOs.size());
+                // 校验拼团是否满足要求
+                if (ObjectUtil.equal(recordDOs.size(), recordDO.getUserSize())) {
+                    item.setStatus(CombinationRecordStatusEnum.SUCCESS.getStatus());
+                }
+            });
+        }
+        recordMapper.updateBatch(recordDOs);
+    }
+
+    private CombinationRecordDO validateCombinationRecord(Long userId, Long orderId) {
+        // 校验拼团是否存在
+        CombinationRecordDO recordDO = recordMapper.selectByUserIdAndOrderId(userId, orderId);
+        if (recordDO == null) {
+            throw exception(COMBINATION_RECORD_NOT_EXISTS);
+        }
+        return recordDO;
+    }
+
+    @Override
+    public void createCombinationRecord(CombinationRecordCreateReqDTO reqDTO) {
+        // 1.1 校验拼团活动
+        CombinationActivityDO activity = combinationActivityService.validateCombinationActivityExists(reqDTO.getActivityId());
+        // 1.2 需要校验下,他当前是不是已经参加了该拼团;
+        CombinationRecordDO recordDO = recordMapper.selectByUserIdAndOrderId(reqDTO.getUserId(), reqDTO.getOrderId());
+        if (recordDO != null) {
+            throw exception(COMBINATION_RECORD_EXISTS);
+        }
+        // 1.3 父拼团是否存在,是否已经满了
+        if (reqDTO.getHeadId() != null) {
+            CombinationRecordDO recordDO1 = recordMapper.selectRecordByHeadId(reqDTO.getHeadId(), reqDTO.getActivityId(), CombinationRecordStatusEnum.IN_PROGRESS.getStatus());
+            if (recordDO1 == null) {
+                throw exception(COMBINATION_RECORD_HEAD_NOT_EXISTS);
+            }
+            // 校验拼团是否满足要求
+            if (ObjectUtil.equal(recordDO1.getUserCount(), recordDO1.getUserSize())) {
+                throw exception(COMBINATION_RECORD_USER_FULL);
+            }
+        }
+        // TODO @puhui999:应该还有一些校验,后续补噶;例如说,一个团,自己已经参与进去了,不能再参与进去;
+
+        // 2. 创建拼团记录
+        CombinationRecordDO record = CombinationActivityConvert.INSTANCE.convert(reqDTO);
+        record.setVirtualGroup(false);
+        // TODO @puhui999:过期时间,应该是 Date 哈;
+        record.setExpireTime(activity.getLimitDuration());
+        record.setUserSize(activity.getUserSize());
+        recordMapper.insert(record);
+    }
+
+    @Override
+    public CombinationRecordDO getCombinationRecord(Long userId, Long orderId) {
+        return validateCombinationRecord(userId, orderId);
+    }
+
+    /**
+     * APP 端获取开团记录
+     *
+     * @return 开团记录
+     */
+    public List<CombinationRecordDO> getRecordListByStatus(Integer status) {
+        return recordMapper.selectListByStatus(status);
+    }
+
+}

+ 0 - 291
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationServiceImpl.java

@@ -1,291 +0,0 @@
-package cn.iocoder.yudao.module.promotion.service.combination;
-
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.collection.CollectionUtil;
-import cn.hutool.core.util.ObjectUtil;
-import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
-import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
-import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
-import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
-import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
-import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO;
-import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordUpdateStatusReqDTO;
-import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityCreateReqVO;
-import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityPageReqVO;
-import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityUpdateReqVO;
-import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductCreateReqVO;
-import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductUpdateReqVO;
-import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert;
-import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO;
-import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationProductDO;
-import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO;
-import cn.iocoder.yudao.module.promotion.dal.mysql.combination.CombinationActivityMapper;
-import cn.iocoder.yudao.module.promotion.dal.mysql.combination.CombinationProductMapper;
-import cn.iocoder.yudao.module.promotion.dal.mysql.combination.CombinationRecordMapper;
-import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-import org.springframework.validation.annotation.Validated;
-
-import javax.annotation.Resource;
-import java.util.Collection;
-import java.util.List;
-
-import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
-import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS;
-import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
-import static cn.iocoder.yudao.module.promotion.util.PromotionUtils.validateProductSkuAllExists;
-
-/**
- * 拼团活动 Service 实现类
- *
- * @author HUIHUI
- */
-@Service
-@Validated
-public class CombinationServiceImpl implements CombinationActivityService, CombinationRecordService {
-
-    @Resource
-    private CombinationActivityMapper combinationActivityMapper;
-    @Resource
-    private CombinationRecordMapper recordMapper;
-    @Resource
-    private CombinationProductMapper combinationProductMapper;
-    @Resource
-    private ProductSpuApi productSpuApi;
-    @Resource
-    private ProductSkuApi productSkuApi;
-
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public Long createCombinationActivity(CombinationActivityCreateReqVO createReqVO) {
-        // 校验商品 SPU 是否存在是否参加的别的活动
-        validateProductCombinationConflict(createReqVO.getSpuId(), null);
-        // 获取所选 spu下的所有 sku
-        List<ProductSkuRespDTO> skus = productSkuApi.getSkuListBySpuId(CollectionUtil.newArrayList(createReqVO.getSpuId()));
-        // 校验商品 sku 是否存在
-        validateProductSkuAllExists(skus, createReqVO.getProducts(), CombinationProductCreateReqVO::getSkuId);
-
-        // TODO 艿艿 有个小问题:现在有活动时间和限制时长,活动时间的结束时间早于设置的限制时间怎么算状态比如:
-        //  活动时间 2023-08-05 15:00:00 - 2023-08-05 15:20:00 限制时长 2小时,那么活动时间结束就结束还是加时到满两小时
-        // 插入拼团活动
-        CombinationActivityDO activityDO = CombinationActivityConvert.INSTANCE.convert(createReqVO);
-        // TODO 营销相关属性初始化 拼团成功更新相关属性
-        activityDO.setTotalNum(0);
-        activityDO.setSuccessNum(0);
-        activityDO.setOrderUserCount(0);
-        activityDO.setVirtualGroup(0);
-        activityDO.setStatus(CommonStatusEnum.ENABLE.getStatus());
-        combinationActivityMapper.insert(activityDO);
-        // 插入商品
-        List<CombinationProductDO> productDOs = CombinationActivityConvert.INSTANCE.convertList(createReqVO.getProducts(), activityDO);
-        combinationProductMapper.insertBatch(productDOs);
-        // 返回
-        return activityDO.getId();
-    }
-
-    private void validateProductCombinationConflict(Long spuId, Long activityId) {
-        // 校验商品 spu 是否存在
-        List<ProductSpuRespDTO> spuList = productSpuApi.getSpuList(CollUtil.newArrayList(spuId));
-        if (CollUtil.isEmpty(spuList)) {
-            throw exception(SPU_NOT_EXISTS);
-        }
-        // 查询所有开启的拼团活动
-        List<CombinationActivityDO> activityDOs = combinationActivityMapper.selectListByStatus(CommonStatusEnum.ENABLE.getStatus());
-        // 更新时排除自己
-        if (activityId != null) {
-            activityDOs.removeIf(item -> ObjectUtil.equal(item.getId(), activityId));
-        }
-        // 过滤出所有 spuIds 有交集的活动
-        List<CombinationActivityDO> doList = CollectionUtils.convertList(activityDOs, c -> c, s -> ObjectUtil.equal(s.getId(), spuId));
-        if (CollUtil.isNotEmpty(doList)) {
-            throw exception(COMBINATION_ACTIVITY_SPU_CONFLICTS);
-        }
-    }
-
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public void updateCombinationActivity(CombinationActivityUpdateReqVO updateReqVO) {
-        // 校验存在
-        CombinationActivityDO activityDO = validateCombinationActivityExists(updateReqVO.getId());
-        // 校验状态
-        if (ObjectUtil.equal(activityDO.getStatus(), CommonStatusEnum.DISABLE.getStatus())) {
-            throw exception(COMBINATION_ACTIVITY_STATUS_DISABLE);
-        }
-        // 校验商品冲突
-        validateProductCombinationConflict(updateReqVO.getSpuId(), updateReqVO.getId());
-        // 获取所选 spu下的所有 sku
-        List<ProductSkuRespDTO> skus = productSkuApi.getSkuListBySpuId(CollectionUtil.newArrayList(updateReqVO.getSpuId()));
-        // 校验商品 sku 是否存在
-        validateProductSkuAllExists(skus, updateReqVO.getProducts(), CombinationProductUpdateReqVO::getSkuId);
-
-        // 更新
-        CombinationActivityDO updateObj = CombinationActivityConvert.INSTANCE.convert(updateReqVO);
-        combinationActivityMapper.updateById(updateObj);
-        // 更新商品
-        updateCombinationProduct(updateObj, updateReqVO.getProducts());
-    }
-
-    /**
-     * 更新拼团商品
-     *
-     * @param activity 拼团活动
-     * @param products  该活动的最新商品配置
-     */
-    private void updateCombinationProduct(CombinationActivityDO activity, List<CombinationProductUpdateReqVO> products) {
-        // 第一步,对比新老数据,获得添加、修改、删除的列表
-        List<CombinationProductDO> newList = CombinationActivityConvert.INSTANCE.convertList(products, activity);
-        List<CombinationProductDO> oldList = combinationProductMapper.selectListByActivityIds(CollUtil.newArrayList(activity.getId()));
-        List<List<CombinationProductDO>> diffList = CollectionUtils.diffList(oldList, newList, (oldVal, newVal) -> {
-            boolean same = ObjectUtil.equal(oldVal.getSkuId(), newVal.getSkuId());
-            if (same) {
-                newVal.setId(oldVal.getId());
-            }
-            return same;
-        });
-
-        // 第二步,批量添加、修改、删除
-        if (CollUtil.isNotEmpty(diffList.get(0))) {
-            combinationProductMapper.insertBatch(diffList.get(0));
-        }
-        if (CollUtil.isNotEmpty(diffList.get(1))) {
-            combinationProductMapper.updateBatch(diffList.get(1));
-        }
-        if (CollUtil.isNotEmpty(diffList.get(2))) {
-            combinationProductMapper.deleteBatchIds(CollectionUtils.convertList(diffList.get(2), CombinationProductDO::getId));
-        }
-    }
-
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public void deleteCombinationActivity(Long id) {
-        // 校验存在
-        CombinationActivityDO activityDO = validateCombinationActivityExists(id);
-        // 校验状态
-        if (ObjectUtil.equal(activityDO.getStatus(), CommonStatusEnum.ENABLE.getStatus())) {
-            throw exception(COMBINATION_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END);
-        }
-
-        // 删除
-        combinationActivityMapper.deleteById(id);
-    }
-
-    private CombinationActivityDO validateCombinationActivityExists(Long id) {
-        CombinationActivityDO activityDO = combinationActivityMapper.selectById(id);
-        if (activityDO == null) {
-            throw exception(COMBINATION_ACTIVITY_NOT_EXISTS);
-        }
-        return activityDO;
-    }
-
-    @Override
-    public CombinationActivityDO getCombinationActivity(Long id) {
-        return validateCombinationActivityExists(id);
-    }
-
-    @Override
-    public List<CombinationActivityDO> getCombinationActivityList(Collection<Long> ids) {
-        return combinationActivityMapper.selectBatchIds(ids);
-    }
-
-    @Override
-    public PageResult<CombinationActivityDO> getCombinationActivityPage(CombinationActivityPageReqVO pageReqVO) {
-        return combinationActivityMapper.selectPage(pageReqVO);
-    }
-
-    @Override
-    public List<CombinationProductDO> getCombinationProductsByActivityIds(Collection<Long> ids) {
-        return combinationProductMapper.selectListByActivityIds(ids);
-    }
-
-    @Override
-    public void updateCombinationRecordStatusByUserIdAndOrderId(CombinationRecordUpdateStatusReqDTO reqDTO) {
-        // 校验拼团是否存在
-        CombinationRecordDO recordDO = validateCombinationRecord(reqDTO.getUserId(), reqDTO.getOrderId());
-
-        // 更新状态
-        recordDO.setStatus(reqDTO.getStatus());
-        recordMapper.updateById(recordDO);
-    }
-
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public void updateCombinationRecordStatusAndStartTimeByUserIdAndOrderId(CombinationRecordUpdateStatusReqDTO reqDTO) {
-        CombinationRecordDO recordDO = validateCombinationRecord(reqDTO.getUserId(), reqDTO.getOrderId());
-        // 更新状态
-        recordDO.setStatus(reqDTO.getStatus());
-        // 更新开始时间
-        recordDO.setStartTime(reqDTO.getStartTime());
-        recordMapper.updateById(recordDO);
-
-        // 更新拼团参入人数
-        List<CombinationRecordDO> recordDOs = recordMapper.selectListByHeadIdAndStatus(recordDO.getHeadId(), reqDTO.getStatus());
-        if (CollUtil.isNotEmpty(recordDOs)) {
-            recordDOs.forEach(item -> {
-                item.setUserCount(recordDOs.size());
-                // 校验拼团是否满足要求
-                if (ObjectUtil.equal(recordDOs.size(), recordDO.getUserSize())) {
-                    item.setStatus(CombinationRecordStatusEnum.SUCCESS.getStatus());
-                }
-            });
-        }
-        recordMapper.updateBatch(recordDOs);
-    }
-
-    private CombinationRecordDO validateCombinationRecord(Long userId, Long orderId) {
-        // 校验拼团是否存在
-        CombinationRecordDO recordDO = recordMapper.selectByUserIdAndOrderId(userId, orderId);
-        if (recordDO == null) {
-            throw exception(COMBINATION_RECORD_NOT_EXISTS);
-        }
-        return recordDO;
-    }
-
-    @Override
-    public void createCombinationRecord(CombinationRecordCreateReqDTO reqDTO) {
-        // 1.1 校验拼团活动
-        CombinationActivityDO activity = validateCombinationActivityExists(reqDTO.getActivityId());
-        // 1.2 需要校验下,他当前是不是已经参加了该拼团;
-        CombinationRecordDO recordDO = recordMapper.selectByUserIdAndOrderId(reqDTO.getUserId(), reqDTO.getOrderId());
-        if (recordDO != null) {
-            throw exception(COMBINATION_RECORD_EXISTS);
-        }
-        // 1.3 父拼团是否存在,是否已经满了
-        if (reqDTO.getHeadId() != null) {
-            CombinationRecordDO recordDO1 = recordMapper.selectRecordByHeadId(reqDTO.getHeadId(), reqDTO.getActivityId(), CombinationRecordStatusEnum.IN_PROGRESS.getStatus());
-            if (recordDO1 == null) {
-                throw exception(COMBINATION_RECORD_HEAD_NOT_EXISTS);
-            }
-            // 校验拼团是否满足要求
-            if (ObjectUtil.equal(recordDO1.getUserCount(), recordDO1.getUserSize())) {
-                throw exception(COMBINATION_RECORD_USER_FULL);
-            }
-        }
-        // TODO @puhui999:应该还有一些校验,后续补噶;例如说,一个团,自己已经参与进去了,不能再参与进去;
-
-        // 2. 创建拼团记录
-        CombinationRecordDO record = CombinationActivityConvert.INSTANCE.convert(reqDTO);
-        record.setVirtualGroup(false);
-        // TODO @puhui999:过期时间,应该是 Date 哈;
-        record.setExpireTime(activity.getLimitDuration());
-        record.setUserSize(activity.getUserSize());
-        recordMapper.insert(record);
-    }
-
-    @Override
-    public CombinationRecordDO getCombinationRecord(Long userId, Long orderId) {
-        return validateCombinationRecord(userId, orderId);
-    }
-
-    /**
-     * APP 端获取开团记录
-     *
-     * @return 开团记录
-     */
-    public List<CombinationRecordDO> getRecordListByStatus(Integer status) {
-        return recordMapper.selectListByStatus(status);
-    }
-
-}

+ 1 - 1
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillactivity/SeckillActivityService.java → yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityService.java

@@ -1,4 +1,4 @@
-package cn.iocoder.yudao.module.promotion.service.seckill.seckillactivity;
+package cn.iocoder.yudao.module.promotion.service.seckill;
 
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityCreateReqVO;

+ 2 - 4
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillactivity/SeckillActivityServiceImpl.java → yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java

@@ -1,4 +1,4 @@
-package cn.iocoder.yudao.module.promotion.service.seckill.seckillactivity;
+package cn.iocoder.yudao.module.promotion.service.seckill;
 
 import cn.hutool.core.util.ObjectUtil;
 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
@@ -16,7 +16,6 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.
 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO;
 import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillactivity.SeckillActivityMapper;
 import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillactivity.SeckillProductMapper;
-import cn.iocoder.yudao.module.promotion.service.seckill.seckillconfig.SeckillConfigService;
 import cn.iocoder.yudao.module.promotion.util.PromotionUtils;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -78,8 +77,7 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
      * 校验秒杀商品参与的活动是否存在冲突
      *
      * 1. 校验秒杀时段是否存在
-     * 2. 校验商品 spu 是否存在
-     * 3. 秒杀商品是否参加其它活动
+     * 2. 秒杀商品是否参加其它活动
      *
      * @param configIds 秒杀时段数组
      * @param spuId 商品 SPU 编号

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

@@ -1,4 +1,4 @@
-package cn.iocoder.yudao.module.promotion.service.seckill.seckillconfig;
+package cn.iocoder.yudao.module.promotion.service.seckill;
 
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigCreateReqVO;

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

@@ -1,4 +1,4 @@
-package cn.iocoder.yudao.module.promotion.service.seckill.seckillconfig;
+package cn.iocoder.yudao.module.promotion.service.seckill;
 
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.ObjectUtil;

+ 11 - 11
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.*;
 
 // TODO 芋艿:等完成后,在补全单测
 /**
- * {@link CombinationServiceImpl} 的单元测试类
+ * {@link CombinationActivityServiceImpl} 的单元测试类
  *
  * @author HUIHUI
  */
-@Import(CombinationServiceImpl.class)
+@Import(CombinationActivityServiceImpl.class)
 public class CombinationActivityServiceImplTest extends BaseDbUnitTest {
 
     @Resource
-    private CombinationServiceImpl combinationActivityService;
+    private CombinationActivityServiceImpl combinationActivityService;
 
     @Resource
     private CombinationActivityMapper combinationActivityMapper;
@@ -112,8 +112,8 @@ public class CombinationActivityServiceImplTest extends BaseDbUnitTest {
             o.setStartTime(null);
             o.setEndTime(null);
             o.setUserSize(null);
-            o.setTotalNum(null);
-            o.setSuccessNum(null);
+            o.setTotalCount(null);
+            o.setSuccessCount(null);
             o.setOrderUserCount(null);
             o.setVirtualGroup(null);
             o.setStatus(null);
@@ -136,9 +136,9 @@ public class CombinationActivityServiceImplTest extends BaseDbUnitTest {
         // 测试 userSize 不匹配
         combinationActivityMapper.insert(cloneIgnoreId(dbCombinationActivity, o -> o.setUserSize(null)));
         // 测试 totalNum 不匹配
-        combinationActivityMapper.insert(cloneIgnoreId(dbCombinationActivity, o -> o.setTotalNum(null)));
+        combinationActivityMapper.insert(cloneIgnoreId(dbCombinationActivity, o -> o.setTotalCount(null)));
         // 测试 successNum 不匹配
-        combinationActivityMapper.insert(cloneIgnoreId(dbCombinationActivity, o -> o.setSuccessNum(null)));
+        combinationActivityMapper.insert(cloneIgnoreId(dbCombinationActivity, o -> o.setSuccessCount(null)));
         // 测试 orderUserCount 不匹配
         combinationActivityMapper.insert(cloneIgnoreId(dbCombinationActivity, o -> o.setOrderUserCount(null)));
         // 测试 virtualGroup 不匹配
@@ -186,8 +186,8 @@ public class CombinationActivityServiceImplTest extends BaseDbUnitTest {
             o.setStartTime(null);
             o.setEndTime(null);
             o.setUserSize(null);
-            o.setTotalNum(null);
-            o.setSuccessNum(null);
+            o.setTotalCount(null);
+            o.setSuccessCount(null);
             o.setOrderUserCount(null);
             o.setVirtualGroup(null);
             o.setStatus(null);
@@ -210,9 +210,9 @@ public class CombinationActivityServiceImplTest extends BaseDbUnitTest {
         // 测试 userSize 不匹配
         combinationActivityMapper.insert(cloneIgnoreId(dbCombinationActivity, o -> o.setUserSize(null)));
         // 测试 totalNum 不匹配
-        combinationActivityMapper.insert(cloneIgnoreId(dbCombinationActivity, o -> o.setTotalNum(null)));
+        combinationActivityMapper.insert(cloneIgnoreId(dbCombinationActivity, o -> o.setTotalCount(null)));
         // 测试 successNum 不匹配
-        combinationActivityMapper.insert(cloneIgnoreId(dbCombinationActivity, o -> o.setSuccessNum(null)));
+        combinationActivityMapper.insert(cloneIgnoreId(dbCombinationActivity, o -> o.setSuccessCount(null)));
         // 测试 orderUserCount 不匹配
         combinationActivityMapper.insert(cloneIgnoreId(dbCombinationActivity, o -> o.setOrderUserCount(null)));
         // 测试 virtualGroup 不匹配

+ 1 - 1
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
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityUpdateReqVO;
 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO;
 import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillactivity.SeckillActivityMapper;
-import cn.iocoder.yudao.module.promotion.service.seckill.seckillactivity.SeckillActivityServiceImpl;
+import cn.iocoder.yudao.module.promotion.service.seckill.SeckillActivityServiceImpl;
 import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
 import org.springframework.context.annotation.Import;

+ 1 - 1
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
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigUpdateReqVO;
 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillconfig.SeckillConfigDO;
 import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillconfig.SeckillConfigMapper;
-import cn.iocoder.yudao.module.promotion.service.seckill.seckillconfig.SeckillConfigServiceImpl;
+import cn.iocoder.yudao.module.promotion.service.seckill.SeckillConfigServiceImpl;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import org.junit.jupiter.api.Disabled;