ソースを参照

Merge branch 'feature/mall_product' of https://gitee.com/puhui999/ruoyi-vue-pro into feature/mall_product

 Conflicts:
	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java
YunaiV 1 年間 前
コミット
2278ad4652
49 ファイル変更528 行追加465 行削除
  1. 26 0
      yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java
  2. 2 3
      yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/ProductSkuRespDTO.java
  3. 6 1
      yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/spu/dto/ProductSpuRespDTO.java
  4. 2 2
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuBaseVO.java
  5. 2 2
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/sku/ProductSkuDO.java
  6. 4 4
      yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java
  7. 20 0
      yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationActivityApi.java
  8. 0 21
      yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationApi.java
  9. 2 23
      yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApi.java
  10. 0 42
      yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationActivityUpdateStockReqDTO.java
  11. 21 8
      yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationRecordCreateReqDTO.java
  12. 4 4
      yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApi.java
  13. 0 42
      yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/dto/SeckillActivityUpdateStockReqDTO.java
  14. 1 0
      yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java
  15. 4 0
      yudao-module-mall/yudao-module-promotion-biz/pom.xml
  16. 3 6
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationActivityApiImpl.java
  17. 0 13
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApiImpl.java
  18. 2 3
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApiImpl.java
  19. 8 1
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/bargain/BargainActivityController.java
  20. 36 67
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/bargain/AppBargainActivityController.java
  21. 1 1
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/bargain/vo/activity/AppBargainActivityDetailRespVO.java
  22. 1 1
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/bargain/vo/activity/AppBargainActivityRespVO.java
  23. 66 88
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/AppSeckillActivityController.java
  24. 23 9
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/AppSeckillConfigController.java
  25. 1 1
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/vo/activity/AppSeckillActivityDetailRespVO.java
  26. 0 1
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/vo/activity/AppSeckillActivityRespVO.java
  27. 66 0
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/bargain/BargainActivityConvert.java
  28. 15 0
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/combination/CombinationActivityConvert.java
  29. 57 0
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckillactivity/SeckillActivityConvert.java
  30. 4 0
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckillconfig/SeckillConfigConvert.java
  31. 1 1
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckillactivity/SeckillActivityDO.java
  32. 10 1
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/bargain/BargainActivityMapper.java
  33. 8 1
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillActivityMapper.java
  34. 1 1
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillProductMapper.java
  35. 17 0
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/bargain/BargainActivityService.java
  36. 21 3
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/bargain/BargainActivityServiceImpl.java
  37. 6 4
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityService.java
  38. 20 23
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImpl.java
  39. 0 10
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordService.java
  40. 3 26
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordServiceImpl.java
  41. 21 3
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityService.java
  42. 21 9
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java
  43. 1 9
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java
  44. 3 2
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java
  45. 8 18
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/TradeBeforeOrderCreateReqBO.java
  46. 2 2
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeBargainHandler.java
  47. 4 4
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeCombinationHandler.java
  48. 2 2
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeOrderHandler.java
  49. 2 3
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeSeckillHandler.java

+ 26 - 0
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java

@@ -43,6 +43,16 @@ public class LocalDateTimeUtils {
         return LocalDateTime.of(year, mouth, day, 0, 0, 0);
     }
 
+    /**
+     * 创建指定时间
+     *
+     * @param timeStr 时间字符串
+     * @return 指定时间
+     */
+    public static LocalDateTime buildTime(String timeStr) {
+        return LocalDateTime.of(LocalDate.now(), LocalTime.parse(timeStr));
+    }
+
     public static LocalDateTime[] buildBetweenTime(int year1, int mouth1, int day1,
                                                    int year2, int mouth2, int day2) {
         return new LocalDateTime[]{buildTime(year1, mouth1, day1), buildTime(year2, mouth2, day2)};
@@ -62,6 +72,22 @@ public class LocalDateTimeUtils {
         return LocalDateTimeUtil.isIn(LocalDateTime.now(), startTime, endTime);
     }
 
+    /**
+     * 判断当前时间是否在该时间范围内
+     *
+     * @param startTime 开始时间
+     * @param endTime   结束时间
+     * @return 是否
+     */
+    public static boolean isBetween(String startTime, String endTime) {
+        if (startTime == null || endTime == null) {
+            return false;
+        }
+        LocalDate nowDate = LocalDate.now();
+        return LocalDateTimeUtil.isIn(LocalDateTime.now(), LocalDateTime.of(nowDate, LocalTime.parse(startTime)),
+                LocalDateTime.of(nowDate, LocalTime.parse(endTime)));
+    }
+
     /**
      * 判断时间段是否重叠
      *

+ 2 - 3
yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/ProductSkuRespDTO.java

@@ -59,14 +59,13 @@ public class ProductSkuRespDTO {
      * 商品体积,单位:m^3 平米
      */
     private Double volume;
-    // TODO @puhui999:firstBrokeragePrice ;尴尬,我当时打错了;secondBrokeragePrice
     /**
      * 一级分销的佣金,单位:分
      */
-    private Integer firstBrokerageRecord;
+    private Integer firstBrokeragePrice;
     /**
      * 二级分销的佣金,单位:分
      */
-    private Integer secondBrokerageRecord;
+    private Integer secondBrokeragePrice;
 
 }

+ 6 - 1
yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/spu/dto/ProductSpuRespDTO.java

@@ -1,6 +1,5 @@
 package cn.iocoder.yudao.module.product.api.spu.dto;
 
-import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
 import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;
 import lombok.Data;
 
@@ -31,6 +30,12 @@ public class ProductSpuRespDTO {
      * 关键字
      */
     private String keyword;
+    /**
+     * 单位
+     *
+     * 对应 product_unit 数据字典
+     */
+    private Integer unit;
     /**
      * 商品简介
      */

+ 2 - 2
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuBaseVO.java

@@ -51,10 +51,10 @@ public class ProductSkuBaseVO {
     private Double volume;
 
     @Schema(description = "一级分销的佣金,单位:分", example = "199")
-    private Integer firstBrokerageRecord;
+    private Integer firstBrokeragePrice;
 
     @Schema(description = "二级分销的佣金,单位:分", example = "19")
-    private Integer secondBrokerageRecord;
+    private Integer secondBrokeragePrice;
 
     @Schema(description = "属性数组")
     private List<Property> properties;

+ 2 - 2
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/sku/ProductSkuDO.java

@@ -81,11 +81,11 @@ public class ProductSkuDO extends BaseDO {
     /**
      * 一级分销的佣金,单位:分
      */
-    private Integer firstBrokerageRecord;
+    private Integer firstBrokeragePrice;
     /**
      * 二级分销的佣金,单位:分
      */
-    private Integer secondBrokerageRecord;
+    private Integer secondBrokeragePrice;
 
     // ========== 营销相关字段 =========
 

+ 4 - 4
yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java

@@ -92,8 +92,8 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
             o.setMarketPrice(generaInt());
             o.setStock(generaInt());
             o.setWarnStock(10);
-            o.setFirstBrokerageRecord(generaInt());
-            o.setSecondBrokerageRecord(generaInt());
+            o.setFirstBrokeragePrice(generaInt());
+            o.setSecondBrokeragePrice(generaInt());
             // 限制分数为两位数
             o.setWeight(RandomUtil.randomDouble(10,2, RoundingMode.HALF_UP));
             o.setVolume(RandomUtil.randomDouble(10,2, RoundingMode.HALF_UP));
@@ -143,8 +143,8 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
             o.setMarketPrice(generaInt());
             o.setStock(generaInt());
             o.setWarnStock(10);
-            o.setFirstBrokerageRecord(generaInt());
-            o.setSecondBrokerageRecord(generaInt());
+            o.setFirstBrokeragePrice(generaInt());
+            o.setSecondBrokeragePrice(generaInt());
             // 限制分数为两位数
             o.setWeight(RandomUtil.randomDouble(10,2, RoundingMode.HALF_UP));
             o.setVolume(RandomUtil.randomDouble(10,2, RoundingMode.HALF_UP));

+ 20 - 0
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationActivityApi.java

@@ -0,0 +1,20 @@
+package cn.iocoder.yudao.module.promotion.api.combination;
+
+/**
+ * 拼团活动 Api 接口
+ *
+ * @author HUIHUI
+ */
+public interface CombinationActivityApi {
+
+    /**
+     * 校验是否满足拼团条件
+     *
+     * @param activityId 活动编号
+     * @param userId 用户编号
+     * @param skuId sku 编号
+     * @param count 数量
+     */
+    void validateCombination(Long activityId, Long userId, Long skuId, Integer count);
+
+}

+ 0 - 21
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationApi.java

@@ -1,21 +0,0 @@
-package cn.iocoder.yudao.module.promotion.api.combination;
-
-import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationActivityUpdateStockReqDTO;
-
-// TODO @puhui999:是不是改成 CombinationActivityApi
-/**
- * 拼团活动 Api 接口
- *
- * @author HUIHUI
- */
-public interface CombinationApi {
-
-    /**
-     * 更新活动库存
-     *
-     * @param reqDTO 请求
-     */
-    // TODO @puhui999:应该是更新哇?还是校验哈;
-    void validateCombination(CombinationActivityUpdateStockReqDTO reqDTO);
-
-}

+ 2 - 23
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApi.java

@@ -1,11 +1,9 @@
 package cn.iocoder.yudao.module.promotion.api.combination;
 
 import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO;
-import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordRespDTO;
 
 import javax.validation.Valid;
 import java.time.LocalDateTime;
-import java.util.List;
 
 // TODO @芋艿:后面也再撸撸这几个接口
 
@@ -33,26 +31,7 @@ public interface CombinationRecordApi {
     boolean isCombinationRecordSuccess(Long userId, Long orderId);
 
     /**
-     * 获取拼团记录
-     *
-     * @param userId     用户编号
-     * @param activityId 活动编号
-     * @return 拼团记录列表
-     */
-    List<CombinationRecordRespDTO> getRecordListByUserIdAndActivityId(Long userId, Long activityId);
-
-    /**
-     * 验证组合限制数
-     * 校验是否满足限购要求
-     *
-     * @param count      本次购买数量
-     * @param sumCount   已购买数量合计
-     * @param activityId 活动编号
-     */
-    void validateCombinationLimitCount(Long activityId, Integer count, Integer sumCount);
-
-    /**
-     * 更新拼团状态为成功
+     * 更新拼团状态为 成功
      *
      * @param userId  用户编号
      * @param orderId 订单编号
@@ -60,7 +39,7 @@ public interface CombinationRecordApi {
     void updateRecordStatusToSuccess(Long userId, Long orderId);
 
     /**
-     * 更新拼团状态为失败
+     * 更新拼团状态为 失败
      *
      * @param userId  用户编号
      * @param orderId 订单编号

+ 0 - 42
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationActivityUpdateStockReqDTO.java

@@ -1,42 +0,0 @@
-package cn.iocoder.yudao.module.promotion.api.combination.dto;
-
-import lombok.Data;
-
-import javax.validation.Valid;
-import javax.validation.constraints.NotNull;
-
-/**
- * 拼团活动更新活动库存 Request DTO
- *
- * @author HUIHUI
- */
-@Data
-public class CombinationActivityUpdateStockReqDTO {
-
-    // TODO @puhui999:是不是一个 activityId、count、skuId 参数就完事啦。
-
-    @NotNull(message = "活动编号不能为空")
-    private Long activityId;
-
-    @NotNull(message = "购买数量不能为空")
-    private Integer count;
-
-    @NotNull(message = "活动商品不能为空")
-    private Item item;
-
-    @Data
-    @Valid
-    public static class Item {
-
-        @NotNull(message = "SPU 编号不能为空")
-        private Long spuId;
-
-        @NotNull(message = "SKU 编号活动商品不能为空")
-        private Long skuId;
-
-        @NotNull(message = "购买数量不能为空")
-        private Integer count;
-
-    }
-
-}

+ 21 - 8
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationRecordCreateReqDTO.java

@@ -13,26 +13,39 @@ import javax.validation.constraints.NotNull;
 @Data
 public class CombinationRecordCreateReqDTO {
 
-    // TODO @puhui999:注释还是要的哈
-
+    /**
+     * 拼团活动编号
+     */
     @NotNull(message = "拼团活动编号不能为空")
     private Long activityId;
-
+    /**
+     * spu 编号
+     */
     @NotNull(message = "spu 编号不能为空")
     private Long spuId;
-
+    /**
+     * sku 编号
+     */
     @NotNull(message = "sku 编号不能为空")
     private Long skuId;
-
+    /**
+     * 订单编号
+     */
     @NotNull(message = "订单编号不能为空")
     private Long orderId;
-
+    /**
+     * 用户编号
+     */
     @NotNull(message = "用户编号不能为空")
     private Long userId;
-
+    /**
+     * 团长编号
+     */
     @NotNull(message = "团长编号不能为空")
     private Long headId;
-
+    /**
+     * 拼团商品单价
+     */
     @NotNull(message = "拼团商品单价不能为空")
     private Integer combinationPrice;
 

+ 4 - 4
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApi.java

@@ -1,7 +1,5 @@
 package cn.iocoder.yudao.module.promotion.api.seckill;
 
-import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillActivityUpdateStockReqDTO;
-
 /**
  * 秒杀活动 API 接口
  *
@@ -12,8 +10,10 @@ public interface SeckillActivityApi {
     /**
      * 更新秒杀库存
      *
-     * @param updateStockReqDTO 请求
+     * @param activityId 活动编号
+     * @param skuId      sku 编号
+     * @param count      数量
      */
-    void updateSeckillStock(SeckillActivityUpdateStockReqDTO updateStockReqDTO);
+    void updateSeckillStock(Long activityId, Long skuId, Integer count);
 
 }

+ 0 - 42
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/dto/SeckillActivityUpdateStockReqDTO.java

@@ -1,42 +0,0 @@
-package cn.iocoder.yudao.module.promotion.api.seckill.dto;
-
-import lombok.Data;
-
-import javax.validation.Valid;
-import javax.validation.constraints.NotNull;
-
-/**
- * 更新秒杀库存 request DTO
- *
- * @author HUIHUI
- */
-@Data
-public class SeckillActivityUpdateStockReqDTO {
-
-    // TODO @puhui999:可以不用 dto,直接 activityId、skuId、count 即可
-
-    @NotNull(message = "活动编号不能为空")
-    private Long activityId;
-
-    @NotNull(message = "购买数量不能为空")
-    private Integer count;
-
-    @NotNull(message = "活动商品不能为空")
-    private Item item;
-
-    @Data
-    @Valid
-    public static class Item {
-
-        @NotNull(message = "SPU 编号不能为空")
-        private Long spuId;
-
-        @NotNull(message = "SKU 编号活动商品不能为空")
-        private Long skuId;
-
-        @NotNull(message = "购买数量不能为空")
-        private Integer count;
-
-    }
-
-}

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

@@ -56,6 +56,7 @@ public interface ErrorCodeConstants {
     ErrorCode SECKILL_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1013008004, "秒杀活动未关闭或未结束,不能删除");
     ErrorCode SECKILL_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1013008005, "秒杀活动已关闭,不能重复关闭");
     ErrorCode SECKILL_ACTIVITY_UPDATE_STOCK_FAIL = new ErrorCode(1013008006, "秒杀失败,原因秒杀库存不足");
+    ErrorCode SECKILL_ACTIVITY_FAIL_STATUS_CLOSED = new ErrorCode(1013008007, "秒杀活动已关闭");
 
     // ========== 秒杀时段 1013009000 ==========
     ErrorCode SECKILL_CONFIG_NOT_EXISTS = new ErrorCode(1013009000, "秒杀时段不存在");

+ 4 - 0
yudao-module-mall/yudao-module-promotion-biz/pom.xml

@@ -77,6 +77,10 @@
             <groupId>cn.iocoder.boot</groupId>
             <artifactId>yudao-spring-boot-starter-excel</artifactId>
         </dependency>
+        <dependency>
+            <groupId>cn.iocoder.boot</groupId>
+            <artifactId>yudao-spring-boot-starter-biz-dict</artifactId>
+        </dependency>
     </dependencies>
 
 </project>

+ 3 - 6
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationApiImpl.java → yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationActivityApiImpl.java

@@ -1,9 +1,7 @@
 package cn.iocoder.yudao.module.promotion.api.combination;
 
-import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationActivityUpdateStockReqDTO;
 import cn.iocoder.yudao.module.promotion.service.combination.CombinationActivityService;
 import org.springframework.stereotype.Service;
-import org.springframework.validation.annotation.Validated;
 
 import javax.annotation.Resource;
 
@@ -13,15 +11,14 @@ import javax.annotation.Resource;
  * @author HUIHUI
  */
 @Service
-@Validated
-public class CombinationApiImpl implements CombinationApi {
+public class CombinationActivityApiImpl implements CombinationActivityApi {
 
     @Resource
     private CombinationActivityService activityService;
 
     @Override
-    public void validateCombination(CombinationActivityUpdateStockReqDTO reqDTO) {
-        activityService.validateCombination(reqDTO);
+    public void validateCombination(Long activityId, Long userId, Long skuId, Integer count) {
+        activityService.validateCombination(activityId, userId, skuId, count);
     }
 
 }

+ 0 - 13
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApiImpl.java

@@ -1,15 +1,12 @@
 package cn.iocoder.yudao.module.promotion.api.combination;
 
 import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO;
-import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordRespDTO;
-import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert;
 import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum;
 import cn.iocoder.yudao.module.promotion.service.combination.CombinationRecordService;
 import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
 import java.time.LocalDateTime;
-import java.util.List;
 
 /**
  * 拼团活动 API 实现类
@@ -32,16 +29,6 @@ public class CombinationRecordApiImpl implements CombinationRecordApi {
         return CombinationRecordStatusEnum.isSuccess(recordService.getCombinationRecord(userId, orderId).getStatus());
     }
 
-    @Override
-    public List<CombinationRecordRespDTO> getRecordListByUserIdAndActivityId(Long userId, Long activityId) {
-        return CombinationActivityConvert.INSTANCE.convert(recordService.getRecordListByUserIdAndActivityId(userId, activityId));
-    }
-
-    @Override
-    public void validateCombinationLimitCount(Long activityId, Integer count, Integer sumCount) {
-        recordService.validateCombinationLimitCount(activityId, count, sumCount);
-    }
-
     @Override
     public void updateRecordStatusToSuccess(Long userId, Long orderId) {
         recordService.updateCombinationRecordStatusByUserIdAndOrderId(CombinationRecordStatusEnum.SUCCESS.getStatus(), userId, orderId);

+ 2 - 3
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApiImpl.java

@@ -1,6 +1,5 @@
 package cn.iocoder.yudao.module.promotion.api.seckill;
 
-import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillActivityUpdateStockReqDTO;
 import cn.iocoder.yudao.module.promotion.service.seckill.SeckillActivityService;
 import org.springframework.stereotype.Service;
 
@@ -18,8 +17,8 @@ public class SeckillActivityApiImpl implements SeckillActivityApi {
     private SeckillActivityService activityService;
 
     @Override
-    public void updateSeckillStock(SeckillActivityUpdateStockReqDTO updateStockReqDTO) {
-        activityService.updateSeckillStock(updateStockReqDTO);
+    public void updateSeckillStock(Long activityId, Long skuId, Integer count) {
+        activityService.updateSeckillStock(activityId, skuId, count);
     }
 
 }

+ 8 - 1
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/bargain/BargainActivityController.java

@@ -3,6 +3,9 @@ package cn.iocoder.yudao.module.promotion.controller.admin.bargain;
 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.framework.common.util.collection.CollectionUtils;
+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.bargain.vo.BargainActivityCreateReqVO;
 import cn.iocoder.yudao.module.promotion.controller.admin.bargain.vo.BargainActivityPageReqVO;
 import cn.iocoder.yudao.module.promotion.controller.admin.bargain.vo.BargainActivityRespVO;
@@ -19,6 +22,7 @@ import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.Resource;
 import javax.validation.Valid;
+import java.util.List;
 
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
 
@@ -30,6 +34,8 @@ public class BargainActivityController {
 
     @Resource
     private BargainActivityService activityService;
+    @Resource
+    private ProductSpuApi spuApi;
 
     @PostMapping("/create")
     @Operation(summary = "创建砍价活动")
@@ -73,7 +79,8 @@ public class BargainActivityController {
         if (CollUtil.isEmpty(pageResult.getList())) {
             return success(PageResult.empty(pageResult.getTotal()));
         }
-        return success(BargainActivityConvert.INSTANCE.convertPage(activityService.getBargainActivityPage(pageVO)));
+        List<ProductSpuRespDTO> spuList = spuApi.getSpuList(CollectionUtils.convertList(pageResult.getList(), BargainActivityDO::getSpuId));
+        return success(BargainActivityConvert.INSTANCE.convertPage(pageResult, spuList));
     }
 
 }

+ 36 - 67
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/bargain/AppBargainActivityController.java

@@ -1,12 +1,19 @@
 package cn.iocoder.yudao.module.promotion.controller.app.bargain;
 
+import cn.hutool.core.collection.CollUtil;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.framework.common.pojo.PageParam;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils;
+import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
+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.app.bargain.vo.activity.AppBargainActivityDetailRespVO;
 import cn.iocoder.yudao.module.promotion.controller.app.bargain.vo.activity.AppBargainActivityRespVO;
+import cn.iocoder.yudao.module.promotion.convert.bargain.BargainActivityConvert;
+import cn.iocoder.yudao.module.promotion.dal.dataobject.bargain.BargainActivityDO;
+import cn.iocoder.yudao.module.promotion.service.bargain.BargainActivityService;
 import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -14,8 +21,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 
-import java.time.Duration;
-import java.util.ArrayList;
+import javax.annotation.Resource;
 import java.util.List;
 
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@@ -25,86 +31,49 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
 @RequestMapping("/promotion/bargain-activity")
 @Validated
 public class AppBargainActivityController {
+    @Resource
+    private BargainActivityService bargainActivityService;
+    @Resource
+    private ProductSpuApi spuApi;
 
     @GetMapping("/page")
-    @Operation(summary = "获得砍价活动活动") // TODO 芋艿:只查询进行中,且在时间范围内的
-    // TODO 芋艿:缺少 swagger 注解
+    @Operation(summary = "获得砍价活动分页")
     public CommonResult<PageResult<AppBargainActivityRespVO>> getBargainActivityPage(PageParam pageReqVO) {
-        List<AppBargainActivityRespVO> activityList = new ArrayList<>();
-        AppBargainActivityRespVO activity1 = new AppBargainActivityRespVO();
-        activity1.setId(1L);
-        activity1.setName("618 大砍价");
-        activity1.setSpuId(2048L);
-        activity1.setPicUrl("https://static.iocoder.cn/mall/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg");
-        activity1.setMarketPrice(50);
-        activity1.setBargainPrice(100);
-        activity1.setStartTime(LocalDateTimeUtils.addTime(Duration.ofDays(-2)));
-        activity1.setEndTime(LocalDateTimeUtils.addTime(Duration.ofDays(1)));
-        activity1.setStock(10);
-        activityList.add(activity1);
+        PageResult<BargainActivityDO> result = bargainActivityService.getBargainActivityAppPage(pageReqVO);
+        if (CollUtil.isEmpty(result.getList())) {
+            return success(PageResult.empty(result.getTotal()));
+        }
 
-        AppBargainActivityRespVO activity2 = new AppBargainActivityRespVO();
-        activity2.setId(2L);
-        activity2.setName("双十一砍价");
-        activity2.setSpuId(4096L);
-        activity2.setPicUrl("https://static.iocoder.cn/mall/132.jpeg");
-        activity2.setMarketPrice(100);
-        activity2.setBargainPrice(200);
-        activity2.setStartTime(LocalDateTimeUtils.addTime(Duration.ofDays(-2)));
-        activity2.setEndTime(LocalDateTimeUtils.addTime(Duration.ofDays(1)));
-        activity2.setStock(0);
-        activityList.add(activity2);
-
-        return success(new PageResult<>(activityList, 10L));
+        List<ProductSpuRespDTO> spuList = spuApi.getSpuList(CollectionUtils.convertList(result.getList(), BargainActivityDO::getSpuId));
+        return success(BargainActivityConvert.INSTANCE.convertAppPage(result, spuList));
     }
 
     @GetMapping("/list")
     @Operation(summary = "获得砍价活动列表", description = "用于小程序首页")
-    // TODO 芋艿:增加 Spring Cache
-    // TODO 芋艿:缺少 swagger 注解
+    @Parameter(name = "count", description = "需要展示的数量", example = "6")
     public CommonResult<List<AppBargainActivityRespVO>> getBargainActivityList(
             @RequestParam(name = "count", defaultValue = "6") Integer count) {
-        List<AppBargainActivityRespVO> activityList = new ArrayList<>();
-        AppBargainActivityRespVO activity1 = new AppBargainActivityRespVO();
-        activity1.setId(1L);
-        activity1.setName("618 大砍价");
-        activity1.setSpuId(2048L);
-        activity1.setPicUrl("https://static.iocoder.cn/mall/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg");
-        activity1.setMarketPrice(50);
-        activity1.setBargainPrice(100);
-        activityList.add(activity1);
-
-        AppBargainActivityRespVO activity2 = new AppBargainActivityRespVO();
-        activity2.setId(2L);
-        activity2.setName("双十一砍价");
-        activity2.setSpuId(4096L);
-        activity2.setPicUrl("https://static.iocoder.cn/mall/132.jpeg");
-        activity2.setMarketPrice(100);
-        activity2.setBargainPrice(200);
-        activityList.add(activity2);
+        List<BargainActivityDO> list = bargainActivityService.getBargainActivityAppList(count);
+        if (CollUtil.isEmpty(list)) {
+            return success(BargainActivityConvert.INSTANCE.convertAppList(list));
+        }
 
-        return success(activityList);
+        List<ProductSpuRespDTO> spuList = spuApi.getSpuList(CollectionUtils.convertList(list, BargainActivityDO::getSpuId));
+        // TODO 芋艿:增加 Spring Cache
+        return success(BargainActivityConvert.INSTANCE.convertAppList(list, spuList));
     }
 
     @GetMapping("/get-detail")
     @Operation(summary = "获得砍价活动详情")
-    // TODO 芋艿:缺少 swagger 注解
+    @Parameter(name = "id", description = "活动编号", example = "1")
     public CommonResult<AppBargainActivityDetailRespVO> getBargainActivityDetail(@RequestParam("id") Long id) {
-        AppBargainActivityDetailRespVO activity = new AppBargainActivityDetailRespVO();
-        activity.setId(2L);
-        activity.setName("618 大砍价");
-        activity.setSpuId(2048L);
-        activity.setPicUrl("https://static.iocoder.cn/mall/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg");
-        activity.setMarketPrice(50);
-        activity.setBargainPrice(100);
-        activity.setStock(10);
-        activity.setUnitName("件");
-        activity.setPrice(40);
-        activity.setStartTime(LocalDateTimeUtils.addTime(Duration.ofDays(-2)));
-        activity.setEndTime(LocalDateTimeUtils.addTime(Duration.ofDays(-10)));
-        activity.setDescription("我吃西红柿");
-        activity.setSuccessCount(10);
-        return success(activity);
+        BargainActivityDO activity = bargainActivityService.getBargainActivity(id);
+        if (activity == null) {
+            return success(null);
+        }
+
+        ProductSpuRespDTO spu = spuApi.getSpu(activity.getSpuId());
+        return success(BargainActivityConvert.INSTANCE.convert1(activity, spu));
     }
 
 }

+ 1 - 1
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/bargain/vo/activity/AppBargainActivityDetailRespVO.java

@@ -45,7 +45,7 @@ public class AppBargainActivityDetailRespVO {
     @Schema(description = "商品单位", required = true, example = "个") // 从 SPU 的 unit 读取,然后转换
     private String unitName;
 
-    @Schema(description = "砍价最低金额,单位:分", required = true, example = "100") // 从砍价商品里取最低价
+    @Schema(description = "砍价最低金额,单位:分", required = true, example = "100")
     private Integer bargainPrice;
 
     @Schema(description = "砍价成功数量", required = true, example = "100")

+ 1 - 1
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/bargain/vo/activity/AppBargainActivityRespVO.java

@@ -36,7 +36,7 @@ public class AppBargainActivityRespVO {
     @Schema(description = "商品市场价,单位:分", required = true, example = "50") // 从 SPU 的 marketPrice 读取
     private Integer marketPrice;
 
-    @Schema(description = "砍价最低金额,单位:分", required = true, example = "100") // 从砍价商品里取最低价
+    @Schema(description = "砍价最低金额,单位:分", required = true, example = "100")
     private Integer bargainPrice;
 
 }

+ 66 - 88
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/AppSeckillActivityController.java

@@ -1,136 +1,114 @@
 package cn.iocoder.yudao.module.promotion.controller.app.seckill;
 
+import cn.hutool.core.util.ObjectUtil;
+import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
+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.app.seckill.vo.activity.AppSeckillActivityDetailRespVO;
 import cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.activity.AppSeckillActivityNowRespVO;
 import cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.activity.AppSeckillActivityPageReqVO;
 import cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.activity.AppSeckillActivityRespVO;
-import cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.config.AppSeckillConfigRespVO;
+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.dal.dataobject.seckill.seckillconfig.SeckillConfigDO;
+import cn.iocoder.yudao.module.promotion.service.seckill.SeckillActivityService;
+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;
+import org.springframework.context.annotation.Lazy;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 
-import java.time.LocalDateTime;
-import java.util.ArrayList;
+import javax.annotation.Resource;
+import java.util.Arrays;
 import java.util.List;
 
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.findFirst;
+import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.isBetween;
+import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.SECKILL_ACTIVITY_FAIL_STATUS_CLOSED;
 
 @Tag(name = "用户 App - 秒杀活动")
 @RestController
 @RequestMapping("/promotion/seckill-activity")
 @Validated
 public class AppSeckillActivityController {
+    @Resource
+    private SeckillActivityService activityService;
+    @Resource
+    @Lazy
+    private SeckillConfigService configService;
+
+    @Resource
+    private ProductSpuApi spuApi;
 
     @GetMapping("/get-now")
     @Operation(summary = "获得当前秒杀活动") // 提供给首页使用
     // TODO 芋艿:需要增加 spring cache
     public CommonResult<AppSeckillActivityNowRespVO> getNowSeckillActivity() {
-        AppSeckillActivityNowRespVO respVO = new AppSeckillActivityNowRespVO();
-        respVO.setConfig(new AppSeckillConfigRespVO().setId(10L).setStartTime("01:00").setEndTime("09:59"));
-        List<AppSeckillActivityRespVO> activityList = new ArrayList<>();
-        AppSeckillActivityRespVO activity1 = new AppSeckillActivityRespVO();
-        activity1.setId(1L);
-        activity1.setName("618 大秒杀");
-        activity1.setSpuId(2048L);
-        activity1.setPicUrl("https://static.iocoder.cn/mall/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg");
-        activity1.setMarketPrice(50);
-        activity1.setSeckillPrice(100);
-        activityList.add(activity1);
+        // 1、获取当前时间处在哪个秒杀阶段
+        List<SeckillConfigDO> configList = configService.getSeckillConfigList();
+        SeckillConfigDO filteredConfig = findFirst(configList, config -> ObjectUtil.equal(config.getStatus(),
+                CommonStatusEnum.ENABLE.getStatus()) && isBetween(config.getStartTime(), config.getEndTime()));
+        // 1、1 时段不存在直接返回 null
+        if (filteredConfig == null) {
+            return success(null);
+        }
 
-        AppSeckillActivityRespVO activity2 = new AppSeckillActivityRespVO();
-        activity2.setId(2L);
-        activity2.setName("双十一大秒杀");
-        activity2.setSpuId(4096L);
-        activity2.setPicUrl("https://static.iocoder.cn/mall/132.jpeg");
-        activity2.setMarketPrice(100);
-        activity2.setSeckillPrice(200);
-        activityList.add(activity2);
-        respVO.setActivities(activityList);
-        return success(respVO);
+        // 2、查询满足当前阶段的活动
+        List<SeckillActivityDO> activityList = activityService.getSeckillActivityListByConfigIds(Arrays.asList(filteredConfig.getId()));
+        List<SeckillActivityDO> filteredList = filterList(activityList, item -> ObjectUtil.equal(item.getStatus(), CommonStatusEnum.ENABLE.getStatus()));
+        // 2、1 获取 spu 信息
+        List<ProductSpuRespDTO> spuList = spuApi.getSpuList(CollectionUtils.convertList(filteredList, SeckillActivityDO::getSpuId));
+        return success(SeckillActivityConvert.INSTANCE.convert(filteredConfig, filteredList, spuList));
     }
 
     @GetMapping("/page")
     @Operation(summary = "获得秒杀活动分页")
-    // TODO @芋艿:分页参数
     public CommonResult<PageResult<AppSeckillActivityRespVO>> getSeckillActivityPage(AppSeckillActivityPageReqVO pageReqVO) {
-        List<AppSeckillActivityRespVO> activityList = new ArrayList<>();
-        AppSeckillActivityRespVO activity1 = new AppSeckillActivityRespVO();
-        activity1.setId(1L);
-        activity1.setName("618 大秒杀");
-        activity1.setSpuId(2048L);
-        activity1.setPicUrl("https://static.iocoder.cn/mall/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg");
-        activity1.setMarketPrice(50);
-        activity1.setSeckillPrice(100);
-        activity1.setUnitName("个");
-        activity1.setStock(1);
-        activity1.setTotalStock(2);
-        activityList.add(activity1);
-
-        AppSeckillActivityRespVO activity2 = new AppSeckillActivityRespVO();
-        activity2.setId(2L);
-        activity2.setName("双十一大秒杀");
-        activity2.setSpuId(4096L);
-        activity2.setPicUrl("https://static.iocoder.cn/mall/132.jpeg");
-        activity2.setMarketPrice(100);
-        activity2.setSeckillPrice(200);
-        activity2.setUnitName("套");
-        activity2.setStock(2);
-        activity2.setTotalStock(3);
-        activityList.add(activity2);
-        return success(new PageResult<>(activityList, 100L));
+        // 1、查询满足当前阶段的活动
+        PageResult<SeckillActivityDO> pageResult = activityService.getSeckillActivityAppPageByConfigId(pageReqVO);
+        // 1、1 获取 spu 信息
+        List<ProductSpuRespDTO> spuList = spuApi.getSpuList(CollectionUtils.convertList(pageResult.getList(), SeckillActivityDO::getSpuId));
+        return success(SeckillActivityConvert.INSTANCE.convertPage(pageResult, spuList));
     }
 
     @GetMapping("/get-detail")
     @Operation(summary = "获得秒杀活动明细")
     @Parameter(name = "id", description = "活动编号", required = true, example = "1024")
     public CommonResult<AppSeckillActivityDetailRespVO> getSeckillActivity(@RequestParam("id") Long id) {
+        // 1、获取当前时间处在哪个秒杀阶段
+        List<SeckillConfigDO> configList = configService.getSeckillConfigList();
+        SeckillConfigDO filteredConfig = findFirst(configList, config -> ObjectUtil.equal(config.getStatus(),
+                CommonStatusEnum.ENABLE.getStatus()) && isBetween(config.getStartTime(), config.getEndTime()));
+        // 1、1 时段不存在直接返回 null
+        if (filteredConfig == null) {
+            return success(null);
+        }
+
+        // 2、获取活动
+        SeckillActivityDO seckillActivity = activityService.getSeckillActivity(id);
+        if (seckillActivity == null) {
+            return success(null);
+        }
         // TODO 芋艿:如果禁用的时候,需要抛出异常;
-        AppSeckillActivityDetailRespVO obj = new AppSeckillActivityDetailRespVO();
-        // 设置其属性的值
-        obj.setId(id);
-        obj.setName("晚九点限时秒杀");
-        obj.setStatus(1);
-        obj.setStartTime(LocalDateTime.of(2023, 6, 16, 0, 0, 0));
-        obj.setEndTime(LocalDateTime.of(2023, 6, 20, 23, 59, 0));
-        obj.setSpuId(633L);
-        obj.setSingleLimitCount(2);
-        obj.setTotalLimitCount(3);
-        obj.setStock(100);
-        obj.setTotalStock(200);
+        if (ObjectUtil.equal(seckillActivity.getStatus(), CommonStatusEnum.DISABLE.getStatus())) {
+            throw exception(SECKILL_ACTIVITY_FAIL_STATUS_CLOSED);
+        }
 
-        // 创建一个Product对象的列表
-        List<AppSeckillActivityDetailRespVO.Product> productList = new ArrayList<>();
-        // 创建三个新的Product对象并设置其属性的值
-        AppSeckillActivityDetailRespVO.Product product1 = new AppSeckillActivityDetailRespVO.Product();
-        product1.setSkuId(1L);
-        product1.setSeckillPrice(100);
-        product1.setStock(50);
-        // 将第一个Product对象添加到列表中
-        productList.add(product1);
-        // 创建第二个Product对象并设置其属性的值
-        AppSeckillActivityDetailRespVO.Product product2 = new AppSeckillActivityDetailRespVO.Product();
-        product2.setSkuId(2L);
-        product2.setSeckillPrice(200);
-        product2.setStock(100);
-        // 将第二个Product对象添加到列表中
-        productList.add(product2);
-        // 创建第三个Product对象并设置其属性的值
-        AppSeckillActivityDetailRespVO.Product product3 = new AppSeckillActivityDetailRespVO.Product();
-        product3.setSkuId(3L);
-        product3.setSeckillPrice(300);
-        product3.setStock(150);
-        // 将第三个Product对象添加到列表中
-        productList.add(product3);
-        // 将Product列表设置为对象的属性值
-        obj.setProducts(productList);
-        return success(obj);
+        // 3、获取活动商品
+        List<SeckillProductDO> products = activityService.getSeckillProductListByActivityId(seckillActivity.getId());
+        return success(SeckillActivityConvert.INSTANCE.convert3(seckillActivity, products, filteredConfig));
     }
 
 }

+ 23 - 9
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/AppSeckillConfigController.java

@@ -1,7 +1,12 @@
 package cn.iocoder.yudao.module.promotion.controller.app.seckill;
 
+import cn.hutool.core.collection.CollectionUtil;
+import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.config.AppSeckillConfigRespVO;
+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.SeckillConfigService;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import org.springframework.validation.annotation.Validated;
@@ -9,7 +14,8 @@ import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
-import java.util.Arrays;
+import javax.annotation.Resource;
+import java.util.Collections;
 import java.util.List;
 
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@@ -19,18 +25,26 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
 @RequestMapping("/promotion/seckill-config")
 @Validated
 public class AppSeckillConfigController {
+    @Resource
+    private SeckillConfigService configService;
 
     @GetMapping("/list")
     @Operation(summary = "获得秒杀时间段列表")
     public CommonResult<List<AppSeckillConfigRespVO>> getSeckillConfigList() {
-        return success(Arrays.asList(
-                new AppSeckillConfigRespVO().setId(1L).setStartTime("00:00").setEndTime("09:59")
-                        .setSliderPicUrls(Arrays.asList("https://static.iocoder.cn/mall/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg",
-                                "https://static.iocoder.cn/mall/132.jpeg")),
-                new AppSeckillConfigRespVO().setId(2L).setStartTime("10:00").setEndTime("12:59"),
-                new AppSeckillConfigRespVO().setId(2L).setStartTime("13:00").setEndTime("22:59"),
-                new AppSeckillConfigRespVO().setId(2L).setStartTime("23:00").setEndTime("23:59")
-        ));
+        List<SeckillConfigDO> list = configService.getSeckillConfigListByStatus(CommonStatusEnum.ENABLE.getStatus());
+        if (CollectionUtil.isEmpty(list)) {
+            return success(Collections.emptyList());
+        }
+
+        return success(SeckillConfigConvert.INSTANCE.convertList2(list));
+        //return success(Arrays.asList(
+        //        new AppSeckillConfigRespVO().setId(1L).setStartTime("00:00").setEndTime("09:59")
+        //                .setSliderPicUrls(Arrays.asList("https://static.iocoder.cn/mall/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg",
+        //                        "https://static.iocoder.cn/mall/132.jpeg")),
+        //        new AppSeckillConfigRespVO().setId(2L).setStartTime("10:00").setEndTime("12:59"),
+        //        new AppSeckillConfigRespVO().setId(2L).setStartTime("13:00").setEndTime("22:59"),
+        //        new AppSeckillConfigRespVO().setId(2L).setStartTime("23:00").setEndTime("23:59")
+        //));
     }
 
 }

+ 1 - 1
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/vo/activity/AppSeckillActivityDetailRespVO.java

@@ -19,7 +19,7 @@ public class AppSeckillActivityDetailRespVO {
     @Schema(description = "活动状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private Integer status;
 
-    // TODO @芋艿:开始时间、结束时间,要和场次结合起来;就是要算到当前场次,是几点哈
+    // TODO @芋艿:开始时间、结束时间,要和场次结合起来;就是要算到当前场次,是几点哈;
 
     @Schema(description = "活动开始时间", requiredMode = Schema.RequiredMode.REQUIRED)
     private LocalDateTime startTime;

+ 0 - 1
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/vo/activity/AppSeckillActivityRespVO.java

@@ -31,7 +31,6 @@ public class AppSeckillActivityRespVO {
     private Integer totalStock;
 
     @Schema(description = "秒杀金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
-    // 从秒杀商品里取最低价
     private Integer seckillPrice;
 
 }

+ 66 - 0
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/bargain/BargainActivityConvert.java

@@ -1,14 +1,24 @@
 package cn.iocoder.yudao.module.promotion.convert.bargain;
 
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
+import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils;
+import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
+import cn.iocoder.yudao.module.product.enums.DictTypeConstants;
 import cn.iocoder.yudao.module.promotion.controller.admin.bargain.vo.BargainActivityBaseVO;
 import cn.iocoder.yudao.module.promotion.controller.admin.bargain.vo.BargainActivityRespVO;
 import cn.iocoder.yudao.module.promotion.controller.admin.bargain.vo.BargainActivityUpdateReqVO;
+import cn.iocoder.yudao.module.promotion.controller.app.bargain.vo.activity.AppBargainActivityDetailRespVO;
+import cn.iocoder.yudao.module.promotion.controller.app.bargain.vo.activity.AppBargainActivityRespVO;
 import cn.iocoder.yudao.module.promotion.dal.dataobject.bargain.BargainActivityDO;
 import org.mapstruct.Mapper;
 import org.mapstruct.factory.Mappers;
 
 import java.util.List;
+import java.util.Map;
+
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
+import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen;
 
 /**
  * 拼团活动 Convert
@@ -30,4 +40,60 @@ public interface BargainActivityConvert {
 
     PageResult<BargainActivityRespVO> convertPage(PageResult<BargainActivityDO> page);
 
+    default PageResult<BargainActivityRespVO> convertPage(PageResult<BargainActivityDO> page, List<ProductSpuRespDTO> spuList) {
+        PageResult<BargainActivityRespVO> result = convertPage(page);
+        Map<Long, ProductSpuRespDTO> spuMap = convertMap(spuList, ProductSpuRespDTO::getId);
+        List<BargainActivityRespVO> list = CollectionUtils.convertList(result.getList(), item -> {
+            findAndThen(spuMap, item.getSpuId(), spu -> {
+                item.setPicUrl(spu.getPicUrl());
+                item.setSpuName(spu.getName());
+            });
+            return item;
+        });
+        result.setList(list);
+        return result;
+    }
+
+    AppBargainActivityDetailRespVO convert1(BargainActivityDO bean);
+
+    default AppBargainActivityDetailRespVO convert1(BargainActivityDO bean, ProductSpuRespDTO spu) {
+        AppBargainActivityDetailRespVO detail = convert1(bean);
+        if (spu != null) {
+            detail.setPicUrl(spu.getPicUrl());
+            detail.setMarketPrice(spu.getMarketPrice());
+            detail.setUnitName(DictFrameworkUtils.getDictDataLabel(DictTypeConstants.PRODUCT_UNIT, spu.getUnit()));
+        }
+        return detail;
+    }
+
+    PageResult<AppBargainActivityRespVO> convertAppPage(PageResult<BargainActivityDO> page);
+
+    default PageResult<AppBargainActivityRespVO> convertAppPage(PageResult<BargainActivityDO> page, List<ProductSpuRespDTO> spuList) {
+        PageResult<AppBargainActivityRespVO> result = convertAppPage(page);
+        Map<Long, ProductSpuRespDTO> spuMap = convertMap(spuList, ProductSpuRespDTO::getId);
+        List<AppBargainActivityRespVO> list = CollectionUtils.convertList(result.getList(), item -> {
+            findAndThen(spuMap, item.getSpuId(), spu -> {
+                item.setPicUrl(spu.getPicUrl());
+                item.setMarketPrice(spu.getMarketPrice());
+            });
+            return item;
+        });
+        result.setList(list);
+        return result;
+    }
+
+    List<AppBargainActivityRespVO> convertAppList(List<BargainActivityDO> list);
+
+    default List<AppBargainActivityRespVO> convertAppList(List<BargainActivityDO> list, List<ProductSpuRespDTO> spuList) {
+        List<AppBargainActivityRespVO> activityList = convertAppList(list);
+        Map<Long, ProductSpuRespDTO> spuMap = convertMap(spuList, ProductSpuRespDTO::getId);
+        return CollectionUtils.convertList(activityList, item -> {
+            findAndThen(spuMap, item.getSpuId(), spu -> {
+                item.setPicUrl(spu.getPicUrl());
+                item.setMarketPrice(spu.getMarketPrice());
+            });
+            return item;
+        });
+    }
+
 }

+ 15 - 0
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/combination/CombinationActivityConvert.java

@@ -3,6 +3,8 @@ package cn.iocoder.yudao.module.promotion.convert.combination;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
 import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
+import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
+import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
 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.CombinationRecordRespDTO;
@@ -92,6 +94,19 @@ public interface CombinationActivityConvert {
 
     CombinationRecordDO convert(CombinationRecordCreateReqDTO reqDTO);
 
+    default CombinationRecordDO convert1(CombinationRecordCreateReqDTO reqDTO, CombinationActivityDO activity, MemberUserRespDTO user,
+                                         ProductSpuRespDTO spu, ProductSkuRespDTO sku) {
+        CombinationRecordDO record = convert(reqDTO);
+        record.setVirtualGroup(false);
+        record.setExpireTime(record.getStartTime().plusHours(activity.getLimitDuration()));
+        record.setUserSize(activity.getUserSize());
+        record.setNickname(user.getNickname());
+        record.setAvatar(user.getAvatar());
+        record.setSpuName(spu.getName());
+        record.setPicUrl(sku.getPicUrl());
+        return record;
+    }
+
     List<CombinationRecordRespDTO> convert(List<CombinationRecordDO> bean);
 
 }

+ 57 - 0
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckillactivity/SeckillActivityConvert.java

@@ -3,15 +3,22 @@ package cn.iocoder.yudao.module.promotion.convert.seckill.seckillactivity;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
 import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
+import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils;
 import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
+import cn.iocoder.yudao.module.product.enums.DictTypeConstants;
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityCreateReqVO;
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityDetailRespVO;
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityRespVO;
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityUpdateReqVO;
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductBaseVO;
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductRespVO;
+import cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.activity.AppSeckillActivityDetailRespVO;
+import cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.activity.AppSeckillActivityNowRespVO;
+import cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.activity.AppSeckillActivityRespVO;
+import cn.iocoder.yudao.module.promotion.convert.seckill.seckillconfig.SeckillConfigConvert;
 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.dal.dataobject.seckill.seckillconfig.SeckillConfigDO;
 import org.mapstruct.Mapper;
 import org.mapstruct.Mapping;
 import org.mapstruct.Mappings;
@@ -20,6 +27,10 @@ import org.mapstruct.factory.Mappers;
 import java.util.List;
 import java.util.Map;
 
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
+import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen;
+import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime;
+
 /**
  * 秒杀活动 Convert
  *
@@ -79,4 +90,50 @@ public interface SeckillActivityConvert {
 
     List<SeckillProductRespVO> convertList2(List<SeckillProductDO> list);
 
+    List<AppSeckillActivityRespVO> convertList3(List<SeckillActivityDO> activityList);
+
+    default AppSeckillActivityNowRespVO convert(SeckillConfigDO filteredConfig, List<SeckillActivityDO> activityList, List<ProductSpuRespDTO> spuList) {
+        AppSeckillActivityNowRespVO respVO = new AppSeckillActivityNowRespVO();
+        respVO.setConfig(SeckillConfigConvert.INSTANCE.convert1(filteredConfig));
+        Map<Long, ProductSpuRespDTO> spuMap = convertMap(spuList, ProductSpuRespDTO::getId);
+        respVO.setActivities(CollectionUtils.convertList(convertList3(activityList), item -> {
+            findAndThen(spuMap, item.getSpuId(), spu -> {
+                item.setPicUrl(spu.getPicUrl());
+                item.setMarketPrice(spu.getMarketPrice());
+                item.setUnitName(DictFrameworkUtils.getDictDataLabel(DictTypeConstants.PRODUCT_UNIT, spu.getUnit()));
+            });
+            return item;
+        }));
+        return respVO;
+    }
+
+    PageResult<AppSeckillActivityRespVO> convertPage1(PageResult<SeckillActivityDO> pageResult);
+
+    default PageResult<AppSeckillActivityRespVO> convertPage(PageResult<SeckillActivityDO> pageResult, List<ProductSpuRespDTO> spuList) {
+        PageResult<AppSeckillActivityRespVO> result = convertPage1(pageResult);
+        Map<Long, ProductSpuRespDTO> spuMap = convertMap(spuList, ProductSpuRespDTO::getId);
+        List<AppSeckillActivityRespVO> list = CollectionUtils.convertList(result.getList(), item -> {
+            findAndThen(spuMap, item.getSpuId(), spu -> {
+                item.setPicUrl(spu.getPicUrl());
+                item.setMarketPrice(spu.getMarketPrice());
+                item.setUnitName(DictFrameworkUtils.getDictDataLabel(DictTypeConstants.PRODUCT_UNIT, spu.getUnit()));
+            });
+            return item;
+        });
+        result.setList(list);
+        return result;
+    }
+
+    AppSeckillActivityDetailRespVO convert2(SeckillActivityDO seckillActivity);
+
+    List<AppSeckillActivityDetailRespVO.Product> convertList1(List<SeckillProductDO> products);
+
+    default AppSeckillActivityDetailRespVO convert3(SeckillActivityDO seckillActivity, List<SeckillProductDO> products, SeckillConfigDO filteredConfig) {
+        AppSeckillActivityDetailRespVO respVO = convert2(seckillActivity);
+        respVO.setProducts(convertList1(products));
+        respVO.setStartTime(buildTime(filteredConfig.getStartTime()));
+        respVO.setEndTime(buildTime(filteredConfig.getEndTime()));
+        return respVO;
+    }
+
 }

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

@@ -5,6 +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.SeckillConfigRespVO;
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigSimpleRespVO;
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigUpdateReqVO;
+import cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.config.AppSeckillConfigRespVO;
 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillconfig.SeckillConfigDO;
 import org.mapstruct.Mapper;
 import org.mapstruct.factory.Mappers;
@@ -33,4 +34,7 @@ public interface SeckillConfigConvert {
 
     PageResult<SeckillConfigRespVO> convertPage(PageResult<SeckillConfigDO> page);
 
+    List<AppSeckillConfigRespVO> convertList2(List<SeckillConfigDO> list);
+
+    AppSeckillConfigRespVO convert1(SeckillConfigDO filteredConfig);
 }

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

@@ -87,7 +87,7 @@ public class SeckillActivityDO extends BaseDO {
      */
     private Integer singleLimitCount;
     /**
-     * 秒杀库存
+     * 秒杀库存(剩余库存秒杀时扣减)
      */
     private Integer stock;
     /**

+ 10 - 1
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/bargain/BargainActivityMapper.java

@@ -1,5 +1,6 @@
 package cn.iocoder.yudao.module.promotion.dal.mysql.bargain;
 
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
@@ -8,6 +9,7 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.bargain.BargainActivityD
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import org.apache.ibatis.annotations.Mapper;
 
+import java.time.LocalDateTime;
 import java.util.List;
 
 /**
@@ -39,8 +41,15 @@ public interface BargainActivityMapper extends BaseMapperX<BargainActivityDO> {
     default int updateActivityStock(Long id, int count) {
         return update(null, new LambdaUpdateWrapper<BargainActivityDO>()
                 .eq(BargainActivityDO::getId, id)
-                .gt(BargainActivityDO::getStock, 0) // TODO @puhui999:不是 > 0,是要大于 count 哈
+                .gt(BargainActivityDO::getStock, count)
                 .setSql("stock = stock - " + count));
     }
 
+    default PageResult<BargainActivityDO> selectAppPage(PageParam pageReqVO, Integer status, LocalDateTime now) {
+        return selectPage(pageReqVO, new LambdaQueryWrapperX<BargainActivityDO>()
+                .eq(BargainActivityDO::getStatus, status)
+                .le(BargainActivityDO::getStartTime, now)
+                .ge(BargainActivityDO::getEndTime, now));
+    }
+
 }

+ 8 - 1
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillActivityMapper.java

@@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityPageReqVO;
+import cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.activity.AppSeckillActivityPageReqVO;
 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import org.apache.ibatis.annotations.Mapper;
@@ -24,7 +25,7 @@ public interface SeckillActivityMapper extends BaseMapperX<SeckillActivityDO> {
                 .likeIfPresent(SeckillActivityDO::getName, reqVO.getName())
                 .eqIfPresent(SeckillActivityDO::getStatus, reqVO.getStatus())
                 .betweenIfPresent(SeckillActivityDO::getCreateTime, reqVO.getCreateTime())
-                .apply(ObjectUtil.isNotNull(reqVO.getConfigId()), "FIND_IN_SET(" + reqVO.getConfigId() + ",time_ids) > 0")
+                .apply(ObjectUtil.isNotNull(reqVO.getConfigId()), "FIND_IN_SET(" + reqVO.getConfigId() + ", config_ids) > 0")
                 .orderByDesc(SeckillActivityDO::getId));
     }
 
@@ -48,4 +49,10 @@ public interface SeckillActivityMapper extends BaseMapperX<SeckillActivityDO> {
                 .setSql("totalStock = totalStock - " + count));
     }
 
+    default PageResult<SeckillActivityDO> selectPage(AppSeckillActivityPageReqVO pageReqVO, Integer status) {
+        return selectPage(pageReqVO, new LambdaQueryWrapperX<SeckillActivityDO>()
+                .eqIfPresent(SeckillActivityDO::getStatus, status)
+                .apply(ObjectUtil.isNotNull(pageReqVO.getConfigId()), "FIND_IN_SET(" + pageReqVO.getConfigId() + ",config_ids) > 0"));
+    }
+
 }

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

@@ -34,7 +34,7 @@ public interface SeckillProductMapper extends BaseMapperX<SeckillProductDO> {
     default int updateActivityStock(Long id, int count) {
         return update(null, new LambdaUpdateWrapper<SeckillProductDO>()
                 .eq(SeckillProductDO::getId, id)
-                .gt(SeckillProductDO::getStock, 0)  // TODO @puhui999:不是 > 0,是要大于 count 哈
+                .gt(SeckillProductDO::getStock, count)
                 .setSql("stock = stock - " + count));
     }
 

+ 17 - 0
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/bargain/BargainActivityService.java

@@ -1,5 +1,6 @@
 package cn.iocoder.yudao.module.promotion.service.bargain;
 
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.module.promotion.controller.admin.bargain.vo.BargainActivityCreateReqVO;
 import cn.iocoder.yudao.module.promotion.controller.admin.bargain.vo.BargainActivityPageReqVO;
@@ -7,6 +8,7 @@ import cn.iocoder.yudao.module.promotion.controller.admin.bargain.vo.BargainActi
 import cn.iocoder.yudao.module.promotion.dal.dataobject.bargain.BargainActivityDO;
 
 import javax.validation.Valid;
+import java.util.List;
 
 /**
  * 砍价活动 Service 接口
@@ -61,4 +63,19 @@ public interface BargainActivityService {
      */
     PageResult<BargainActivityDO> getBargainActivityPage(BargainActivityPageReqVO pageReqVO);
 
+    /**
+     * 获取 APP 端活动分页数据
+     *
+     * @param pageReqVO 分页请求
+     * @return 砍价活动分页
+     */
+    PageResult<BargainActivityDO> getBargainActivityAppPage(PageParam pageReqVO);
+
+    /**
+     * 获取 APP 端活动展示数据
+     *
+     * @param count 需要的数量
+     * @return
+     */
+    List<BargainActivityDO> getBargainActivityAppList(Integer count);
 }

+ 21 - 3
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/bargain/BargainActivityServiceImpl.java

@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.promotion.service.bargain;
 
 import cn.hutool.core.util.ObjectUtil;
 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
@@ -16,6 +17,7 @@ import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;
 
 import javax.annotation.Resource;
+import java.time.LocalDateTime;
 import java.util.List;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
@@ -113,9 +115,9 @@ public class BargainActivityServiceImpl implements BargainActivityService {
         // 校验存在
         BargainActivityDO activityDO = validateBargainActivityExists(id);
         // 校验状态
-        if (ObjectUtil.equal(activityDO.getStatus(), CommonStatusEnum.ENABLE.getStatus())) {
-            throw exception(BARGAIN_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END);
-        }
+        //if (ObjectUtil.equal(activityDO.getStatus(), CommonStatusEnum.ENABLE.getStatus())) {
+        //    throw exception(BARGAIN_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END);
+        //}
 
         // 删除
         bargainActivityMapper.deleteById(id);
@@ -139,4 +141,20 @@ public class BargainActivityServiceImpl implements BargainActivityService {
         return bargainActivityMapper.selectPage(pageReqVO);
     }
 
+    @Override
+    public PageResult<BargainActivityDO> getBargainActivityAppPage(PageParam pageReqVO) {
+        // 只查询进行中,且在时间范围内的
+        return bargainActivityMapper.selectAppPage(pageReqVO, CommonStatusEnum.ENABLE.getStatus(), LocalDateTime.now());
+
+    }
+
+    @Override
+    public List<BargainActivityDO> getBargainActivityAppList(Integer count) {
+        if (count == null) {
+            count = 6;
+        }
+        PageResult<BargainActivityDO> result = bargainActivityMapper.selectAppPage(new PageParam().setPageSize(count), CommonStatusEnum.ENABLE.getStatus(), LocalDateTime.now());
+        return result.getList();
+    }
+
 }

+ 6 - 4
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityService.java

@@ -1,7 +1,6 @@
 package cn.iocoder.yudao.module.promotion.service.combination;
 
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationActivityUpdateStockReqDTO;
 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;
@@ -74,10 +73,13 @@ public interface CombinationActivityService {
     List<CombinationProductDO> getCombinationProductsByActivityIds(Collection<Long> activityIds);
 
     /**
-     * 更新拼图活动库存
+     * 校验是否满足拼团条件
      *
-     * @param reqDTO 请求
+     * @param activityId 活动编号
+     * @param userId     用户编号
+     * @param skuId      sku 编号
+     * @param count      数量
      */
-    void validateCombination(CombinationActivityUpdateStockReqDTO reqDTO);
+    void validateCombination(Long activityId, Long userId, Long skuId, Integer count);
 
 }

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

@@ -9,7 +9,6 @@ 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.CombinationActivityUpdateStockReqDTO;
 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;
@@ -34,7 +33,6 @@ 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.*;
-import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
 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.*;
@@ -88,7 +86,7 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic
     /**
      * 校验拼团商品参与的活动是否存在冲突
      *
-     * @param spuId 商品 SPU 编号
+     * @param spuId      商品 SPU 编号
      * @param activityId 拼团活动编号
      */
     private void validateProductConflict(Long spuId, Long activityId) {
@@ -107,7 +105,7 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic
     /**
      * 校验拼团商品是否都存在
      *
-     * @param spuId 商品 SPU 编号
+     * @param spuId    商品 SPU 编号
      * @param products 拼团商品
      */
     private void validateProductExists(Long spuId, List<CombinationProductBaseVO> products) {
@@ -152,7 +150,7 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic
      * 更新拼团商品
      *
      * @param activity 拼团活动
-     * @param products  该活动的最新商品配置
+     * @param products 该活动的最新商品配置
      */
     private void updateCombinationProduct(CombinationActivityDO activity, List<CombinationProductBaseVO> products) {
         // 第一步,对比新老数据,获得添加、修改、删除的列表
@@ -217,35 +215,34 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic
     }
 
     @Override
-    public void validateCombination(CombinationActivityUpdateStockReqDTO reqDTO) {
+    public void validateCombination(Long activityId, Long userId, Long skuId, Integer count) {
         // 1.1 校验拼团活动是否存在
-        CombinationActivityDO activity = validateCombinationActivityExists(reqDTO.getActivityId());
+        CombinationActivityDO activity = validateCombinationActivityExists(activityId);
         // 1.2 校验活动是否开启
         if (ObjectUtil.equal(activity.getStatus(), CommonStatusEnum.DISABLE.getStatus())) {
             throw exception(COMBINATION_ACTIVITY_STATUS_DISABLE);
         }
         // 1.3 校验是否超出单次限购数量
-        if (activity.getSingleLimitCount() < reqDTO.getCount()) {
+        if (activity.getSingleLimitCount() < count) {
             throw exception(COMBINATION_RECORD_FAILED_SINGLE_LIMIT_COUNT_EXCEED);
         }
 
         // 2. 校验是否超出总限购数量
-        // TODO @puhui999:userId 应该接口传递哈;要保证 service 无状态
-        List<CombinationRecordDO> recordList = combinationRecordService.getRecordListByUserIdAndActivityId(
-                getLoginUserId(), reqDTO.getActivityId());
-        // TODO @puhui999:最好 if true return;减少括号层数
-        if (CollUtil.isNotEmpty(recordList)) {
-            // 过滤出拼团成功的
-            // TODO @puhui999:count 要不存一个在 record 里?
-            List<Long> skuIds = convertList(recordList, CombinationRecordDO::getSkuId,
-                    item -> ObjectUtil.equals(item.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus()));
-            Integer countSum = tradeOrderApi.getOrderItemCountSumByOrderIdAndSkuId(convertList(recordList,
-                    CombinationRecordDO::getOrderId,
-                    item -> ObjectUtil.equals(item.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus())), skuIds);
-            if (activity.getTotalLimitCount() < countSum) {
-                throw exception(COMBINATION_RECORD_FAILED_TOTAL_LIMIT_COUNT_EXCEED);
-            }
+        List<CombinationRecordDO> recordList = combinationRecordService.getRecordListByUserIdAndActivityId(userId, activityId);
+        if (CollUtil.isEmpty(recordList)) {
+            return;
+        }
+        // 过滤出拼团成功的
+        // TODO @puhui999:count 要不存一个在 record 里?
+        List<Long> skuIds = convertList(recordList, CombinationRecordDO::getSkuId,
+                item -> ObjectUtil.equals(item.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus()));
+        Integer countSum = tradeOrderApi.getOrderItemCountSumByOrderIdAndSkuId(convertList(recordList,
+                CombinationRecordDO::getOrderId,
+                item -> ObjectUtil.equals(item.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus())), skuIds);
+        if (activity.getTotalLimitCount() < countSum) {
+            throw exception(COMBINATION_RECORD_FAILED_TOTAL_LIMIT_COUNT_EXCEED);
         }
+
     }
 
 }

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

@@ -57,14 +57,4 @@ public interface CombinationRecordService {
      */
     List<CombinationRecordDO> getRecordListByUserIdAndActivityId(Long userId, Long activityId);
 
-    /**
-     * 验证组合限制数
-     * 校验是否满足限购要求
-     *
-     * @param count      本次购买数量
-     * @param sumCount   已购买数量合计
-     * @param activityId 活动编号
-     */
-    void validateCombinationLimitCount(Long activityId, Integer count, Integer sumCount);
-
 }

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

@@ -129,19 +129,10 @@ public class CombinationRecordServiceImpl implements CombinationRecordService {
         }
 
         // 2. 创建拼团记录
-        // TODO @puhui999:可以把 user、spu、sku 一起放 convert 里哈;
-        CombinationRecordDO record = CombinationActivityConvert.INSTANCE.convert(reqDTO);
-        record.setVirtualGroup(false);
-        record.setExpireTime(record.getStartTime().plusHours(activity.getLimitDuration()));
-        record.setUserSize(activity.getUserSize());
         MemberUserRespDTO user = memberUserApi.getUser(reqDTO.getUserId());
-        record.setNickname(user.getNickname());
-        record.setAvatar(user.getAvatar());
-        ProductSpuRespDTO spu = productSpuApi.getSpu(record.getSpuId());
-        record.setSpuName(spu.getName());
-        ProductSkuRespDTO sku = productSkuApi.getSku(record.getSkuId());
-        record.setPicUrl(sku.getPicUrl());
-        recordMapper.insert(record);
+        ProductSpuRespDTO spu = productSpuApi.getSpu(reqDTO.getSpuId());
+        ProductSkuRespDTO sku = productSkuApi.getSku(reqDTO.getSkuId());
+        recordMapper.insert(CombinationActivityConvert.INSTANCE.convert1(reqDTO, activity, user, spu, sku));
     }
 
     @Override
@@ -154,20 +145,6 @@ public class CombinationRecordServiceImpl implements CombinationRecordService {
         return recordMapper.selectListByUserIdAndActivityId(userId, activityId);
     }
 
-    @Override
-    public void validateCombinationLimitCount(Long activityId, Integer count, Integer sumCount) {
-        // 1.1 校验拼团活动
-        CombinationActivityDO activity = combinationActivityService.validateCombinationActivityExists(activityId);
-        // 校验是否达到限购总限购标准
-        if ((sumCount + count) > activity.getTotalLimitCount()) {
-            throw exception(COMBINATION_RECORD_FAILED_TOTAL_LIMIT_COUNT_EXCEED);
-        }
-        // 单次购买是否达到限购标准
-        if (count > activity.getSingleLimitCount()) {
-            throw exception(COMBINATION_RECORD_FAILED_SINGLE_LIMIT_COUNT_EXCEED);
-        }
-    }
-
     /**
      * APP 端获取开团记录
      *

+ 21 - 3
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityService.java

@@ -1,10 +1,10 @@
 package cn.iocoder.yudao.module.promotion.service.seckill;
 
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillActivityUpdateStockReqDTO;
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityCreateReqVO;
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityPageReqVO;
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityUpdateReqVO;
+import cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.activity.AppSeckillActivityPageReqVO;
 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO;
 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO;
 
@@ -37,9 +37,11 @@ public interface SeckillActivityService {
     /**
      * 更新秒杀库存
      *
-     * @param updateStockReqDTO 更新信息
+     * @param activityId 活动编号
+     * @param skuId      sku 编号
+     * @param count      数量
      */
-    void updateSeckillStock(SeckillActivityUpdateStockReqDTO updateStockReqDTO);
+    void updateSeckillStock(Long activityId, Long skuId, Integer count);
 
     /**
      * 关闭秒杀活动
@@ -87,4 +89,20 @@ public interface SeckillActivityService {
      */
     List<SeckillProductDO> getSeckillProductListByActivityId(Collection<Long> activityIds);
 
+    /**
+     * 通过活动时段获取秒杀活动
+     *
+     * @param ids 时段配置编号
+     * @return 秒杀活动列表
+     */
+    List<SeckillActivityDO> getSeckillActivityListByConfigIds(Collection<Long> ids);
+
+    /**
+     * 通过活动时段获取秒杀活动
+     *
+     * @param pageReqVO 请求
+     * @return 秒杀活动列表
+     */
+    PageResult<SeckillActivityDO> getSeckillActivityAppPageByConfigId(AppSeckillActivityPageReqVO pageReqVO);
+
 }

+ 21 - 9
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java

@@ -3,15 +3,16 @@ package cn.iocoder.yudao.module.promotion.service.seckill;
 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.seckill.dto.SeckillActivityUpdateStockReqDTO;
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityCreateReqVO;
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityPageReqVO;
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityUpdateReqVO;
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductBaseVO;
+import cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.activity.AppSeckillActivityPageReqVO;
 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;
@@ -147,32 +148,32 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
 
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public void updateSeckillStock(SeckillActivityUpdateStockReqDTO updateStockReqDTO) {
+    public void updateSeckillStock(Long activityId, Long skuId, Integer count) {
         // 1、校验秒杀活动是否存在
-        SeckillActivityDO seckillActivity = getSeckillActivity(updateStockReqDTO.getActivityId());
+        SeckillActivityDO seckillActivity = getSeckillActivity(activityId);
         // 1.1、校验库存是否充足
-        if (seckillActivity.getTotalStock() < updateStockReqDTO.getCount()) {
+        if (seckillActivity.getTotalStock() < count) {
             throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL);
         }
 
         // 2、获取活动商品
-        List<SeckillProductDO> products = getSeckillProductListByActivityId(updateStockReqDTO.getActivityId());
+        List<SeckillProductDO> products = getSeckillProductListByActivityId(activityId);
         // 2.1、过滤出购买的商品
-        SeckillProductDO product = findFirst(products, item -> ObjectUtil.equal(updateStockReqDTO.getItem().getSkuId(), item.getSkuId()));
+        SeckillProductDO product = findFirst(products, item -> ObjectUtil.equal(skuId, item.getSkuId()));
         // 2.2、检查活动商品库存是否充足
-        boolean isSufficient = product == null || (product.getStock() == 0 || (product.getStock() < updateStockReqDTO.getItem().getCount()) || (product.getStock() - updateStockReqDTO.getItem().getCount()) < 0);
+        boolean isSufficient = product == null || (product.getStock() == 0 || (product.getStock() < count) || (product.getStock() - count) < 0);
         if (isSufficient) {
             throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL);
         }
 
         // 3、更新活动商品库存
-        int updateCount = seckillProductMapper.updateActivityStock(product.getId(), updateStockReqDTO.getItem().getCount());
+        int updateCount = seckillProductMapper.updateActivityStock(product.getId(), count);
         if (updateCount == 0) {
             throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL);
         }
 
         // 4、更新活动库存
-        updateCount = seckillActivityMapper.updateActivityStock(seckillActivity.getId(), updateStockReqDTO.getCount());
+        updateCount = seckillActivityMapper.updateActivityStock(seckillActivity.getId(), count);
         if (updateCount == 0) {
             throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL);
         }
@@ -265,4 +266,15 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
         return seckillProductMapper.selectListByActivityId(activityIds);
     }
 
+    @Override
+    public List<SeckillActivityDO> getSeckillActivityListByConfigIds(Collection<Long> ids) {
+        return CollectionUtils.filterList(seckillActivityMapper.selectList(),
+                item -> CollectionUtils.anyMatch(item.getConfigIds(), ids::contains));
+    }
+
+    @Override
+    public PageResult<SeckillActivityDO> getSeckillActivityAppPageByConfigId(AppSeckillActivityPageReqVO pageReqVO) {
+        return seckillActivityMapper.selectPage(pageReqVO, CommonStatusEnum.ENABLE.getStatus());
+    }
+
 }

+ 1 - 9
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java

@@ -14,9 +14,7 @@ import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDT
 import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO;
 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO;
-import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationActivityUpdateStockReqDTO;
 import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO;
-import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillActivityUpdateStockReqDTO;
 import cn.iocoder.yudao.module.trade.api.order.dto.TradeOrderRespDTO;
 import cn.iocoder.yudao.module.trade.controller.admin.base.member.user.MemberUserRespVO;
 import cn.iocoder.yudao.module.trade.controller.admin.base.product.property.ProductPropertyValueDetailRespVO;
@@ -279,15 +277,9 @@ public interface TradeOrderConvert {
         return new BrokerageAddReqBO().setBizId(String.valueOf(item.getId())).setSourceUserId(item.getUserId())
                 .setBasePrice(item.getPayPrice() * item.getCount())
                 .setTitle(StrUtil.format("{}成功购买{}", user.getNickname(), item.getSpuName()))
-                .setFirstFixedPrice(sku.getFirstBrokerageRecord()).setSecondFixedPrice(sku.getSecondBrokerageRecord());
+                .setFirstFixedPrice(sku.getFirstBrokeragePrice()).setSecondFixedPrice(sku.getSecondBrokeragePrice());
     }
 
-    @Mapping(target = "activityId", source = "reqBO.seckillActivityId")
-    SeckillActivityUpdateStockReqDTO convert(TradeBeforeOrderCreateReqBO reqBO);
-
-    @Mapping(target = "activityId", source = "reqBO.combinationActivityId")
-    CombinationActivityUpdateStockReqDTO convert1(TradeBeforeOrderCreateReqBO reqBO);
-
     TradeBeforeOrderCreateReqBO convert(AppTradeOrderCreateReqVO createReqVO);
 
     @Mappings({

+ 3 - 2
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java

@@ -184,9 +184,10 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
     @Transactional(rollbackFor = Exception.class)
     public TradeOrderDO createOrder(Long userId, String userIp, AppTradeOrderCreateReqVO createReqVO) {
         // 1、执行订单创建前置处理器
-        // TODO @puhui999:最好也抽个 beforeOrderCreate 方法;
+        // TODO @puhui999:最好也抽个 beforeOrderCreate 方法;不要 BO 各自处理参数岂不美哉?
         TradeBeforeOrderCreateReqBO beforeOrderCreateReqBO = TradeOrderConvert.INSTANCE.convert(createReqVO);
         beforeOrderCreateReqBO.setOrderType(validateActivity(createReqVO));
+        beforeOrderCreateReqBO.setUserId(userId);
         beforeOrderCreateReqBO.setCount(getSumValue(createReqVO.getItems(), AppTradeOrderSettlementReqVO.Item::getCount, Integer::sum));
         // TODO @puhui999:这里有个纠结点;handler 的定义是只处理指定类型的订单的拓展逻辑;还是通用的 handler,类似可以处理优惠劵等等
         tradeOrderHandlers.forEach(handler -> handler.beforeOrderCreate(beforeOrderCreateReqBO));
@@ -730,7 +731,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
         }
 
         // TODO 活动相关库存回滚需要活动 id,活动 id 怎么获取?app 端能否传过来
-        tradeOrderHandlers.forEach(handler -> handler.rollbackStock());
+        tradeOrderHandlers.forEach(handler -> handler.rollback());
 
         // 2.回滚库存
         List<TradeOrderItemDO> orderItems = tradeOrderItemMapper.selectListByOrderId(id);

+ 8 - 18
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/TradeBeforeOrderCreateReqBO.java

@@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.trade.service.order.bo;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
-import javax.validation.Valid;
 import javax.validation.constraints.NotNull;
 
 // TODO 芋艿:在想想这些参数的定义
@@ -34,25 +33,16 @@ public class TradeBeforeOrderCreateReqBO {
     @Schema(description = "砍价活动编号", example = "123")
     private Long bargainActivityId;
 
-    @NotNull(message = "购买数量不能为空")
-    private Integer count;
-
-    @NotNull(message = "活动商品不能为空")
-    private Item item;
-
-    @Data
-    @Valid
-    public static class Item {
+    @NotNull(message = "SPU 编号不能为空")
+    private Long spuId;
 
-        @NotNull(message = "SPU 编号不能为空")
-        private Long spuId;
+    @NotNull(message = "SKU 编号活动商品不能为空")
+    private Long skuId;
 
-        @NotNull(message = "SKU 编号活动商品不能为空")
-        private Long skuId;
+    @NotNull(message = "用户编号不能为空")
+    private Long userId;
 
-        @NotNull(message = "购买数量不能为空")
-        private Integer count;
-
-    }
+    @NotNull(message = "购买数量不能为空")
+    private Integer count;
 
 }

+ 2 - 2
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeBargainHandler.java

@@ -22,7 +22,7 @@ public class TradeBargainHandler implements TradeOrderHandler {
 
     @Override
     public void beforeOrderCreate(TradeBeforeOrderCreateReqBO reqBO) {
-        // 如果是秒杀订单
+        // 如果是砍价订单
         if (ObjectUtil.notEqual(TradeOrderTypeEnum.BARGAIN.getType(), reqBO.getOrderType())) {
             return;
         }
@@ -37,7 +37,7 @@ public class TradeBargainHandler implements TradeOrderHandler {
     }
 
     @Override
-    public void rollbackStock() {
+    public void rollback() {
 
     }
 

+ 4 - 4
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeCombinationHandler.java

@@ -1,7 +1,7 @@
 package cn.iocoder.yudao.module.trade.service.order.handler;
 
 import cn.hutool.core.util.ObjectUtil;
-import cn.iocoder.yudao.module.promotion.api.combination.CombinationApi;
+import cn.iocoder.yudao.module.promotion.api.combination.CombinationActivityApi;
 import cn.iocoder.yudao.module.promotion.api.combination.CombinationRecordApi;
 import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert;
 import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum;
@@ -20,7 +20,7 @@ import javax.annotation.Resource;
 public class TradeCombinationHandler implements TradeOrderHandler {
 
     @Resource
-    private CombinationApi combinationApi;
+    private CombinationActivityApi combinationActivityApi;
     @Resource
     private CombinationRecordApi combinationRecordApi;
 
@@ -32,7 +32,7 @@ public class TradeCombinationHandler implements TradeOrderHandler {
         }
 
         // 校验是否满足拼团活动相关限制
-        combinationApi.validateCombination(TradeOrderConvert.INSTANCE.convert1(reqBO));
+        combinationActivityApi.validateCombination(reqBO.getCombinationActivityId(), reqBO.getUserId(), reqBO.getSkuId(), reqBO.getCount());
     }
 
     @Override
@@ -42,7 +42,7 @@ public class TradeCombinationHandler implements TradeOrderHandler {
     }
 
     @Override
-    public void rollbackStock() {
+    public void rollback() {
 
     }
 

+ 2 - 2
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeOrderHandler.java

@@ -25,8 +25,8 @@ public interface TradeOrderHandler {
     void afterOrderCreate(TradeAfterOrderCreateReqBO reqBO);
 
     /**
-     * 回滚活动相关库存
+     * 回滚
      */
-    void rollbackStock();
+    void rollback();
 
 }

+ 2 - 3
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeSeckillHandler.java

@@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.trade.service.order.handler;
 
 import cn.hutool.core.util.ObjectUtil;
 import cn.iocoder.yudao.module.promotion.api.seckill.SeckillActivityApi;
-import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert;
 import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum;
 import cn.iocoder.yudao.module.trade.service.order.bo.TradeAfterOrderCreateReqBO;
 import cn.iocoder.yudao.module.trade.service.order.bo.TradeBeforeOrderCreateReqBO;
@@ -28,7 +27,7 @@ public class TradeSeckillHandler implements TradeOrderHandler {
             return;
         }
 
-        seckillActivityApi.updateSeckillStock(TradeOrderConvert.INSTANCE.convert(reqBO));
+        seckillActivityApi.updateSeckillStock(reqBO.getSeckillActivityId(), reqBO.getSkuId(), reqBO.getCount());
     }
 
     @Override
@@ -37,7 +36,7 @@ public class TradeSeckillHandler implements TradeOrderHandler {
     }
 
     @Override
-    public void rollbackStock() {
+    public void rollback() {
 
     }