Ver código fonte

秒回活动:订单金额计算初步设计

puhui999 1 ano atrás
pai
commit
42c47d9b44
11 arquivos alterados com 207 adições e 7 exclusões
  1. 14 0
      yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApi.java
  2. 65 0
      yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/dto/SeckillActivityProductRespDTO.java
  3. 9 0
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApiImpl.java
  4. 3 0
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckillactivity/SeckillActivityConvert.java
  5. 12 3
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityService.java
  6. 15 0
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java
  7. 3 3
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java
  8. 18 0
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/bo/TradePriceCalculateReqBO.java
  9. 18 1
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/bo/TradePriceCalculateRespBO.java
  10. 3 0
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradePriceCalculatorHelper.java
  11. 47 0
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeSeckillActivityPriceCalculator.java

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

@@ -1,5 +1,10 @@
 package cn.iocoder.yudao.module.promotion.api.seckill;
 
+import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillActivityProductRespDTO;
+
+import java.util.Collection;
+import java.util.List;
+
 /**
  * 秒杀活动 API 接口
  *
@@ -16,4 +21,13 @@ public interface SeckillActivityApi {
      */
     void updateSeckillStock(Long id, Long skuId, Integer count);
 
+    /**
+     * 获取秒杀活动商品信息
+     *
+     * @param id     活动编号
+     * @param skuIds sku 编号
+     * @return 秒杀活动商品信息列表
+     */
+    List<SeckillActivityProductRespDTO> getSeckillActivityProductList(Long id, Collection<Long> skuIds);
+
 }

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

@@ -0,0 +1,65 @@
+package cn.iocoder.yudao.module.promotion.api.seckill.dto;
+
+import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+/**
+ * 秒杀活动商品 Response DTO
+ *
+ * @author HUIHUI
+ */
+@Data
+public class SeckillActivityProductRespDTO {
+
+    /**
+     * 秒杀参与商品编号
+     */
+    private Long id;
+    /**
+     * 秒杀活动 id
+     *
+     * 关联 SeckillActivityDO#getId()
+     */
+    private Long activityId;
+    /**
+     * 秒杀时段 id
+     *
+     * 关联 SeckillConfigDO#getId()
+     */
+    private List<Long> configIds;
+    /**
+     * 商品 SPU 编号
+     */
+    private Long spuId;
+    /**
+     * 商品 SKU 编号
+     */
+    private Long skuId;
+    /**
+     * 秒杀金额,单位:分
+     */
+    private Integer seckillPrice;
+    /**
+     * 秒杀库存
+     */
+    private Integer stock;
+
+    /**
+     * 秒杀商品状态
+     *
+     * 枚举 {@link CommonStatusEnum 对应的类}
+     */
+    private Integer activityStatus;
+    /**
+     * 活动开始时间点
+     */
+    private LocalDateTime activityStartTime;
+    /**
+     * 活动结束时间点
+     */
+    private LocalDateTime activityEndTime;
+
+}

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

@@ -1,9 +1,13 @@
 package cn.iocoder.yudao.module.promotion.api.seckill;
 
+import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillActivityProductRespDTO;
+import cn.iocoder.yudao.module.promotion.convert.seckill.seckillactivity.SeckillActivityConvert;
 import cn.iocoder.yudao.module.promotion.service.seckill.SeckillActivityService;
 import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
+import java.util.Collection;
+import java.util.List;
 
 /**
  * 秒杀活动接口 Api 接口实现类
@@ -21,4 +25,9 @@ public class SeckillActivityApiImpl implements SeckillActivityApi {
         activityService.updateSeckillStock(id, skuId, count);
     }
 
+    @Override
+    public List<SeckillActivityProductRespDTO> getSeckillActivityProductList(Long id, Collection<Long> skuIds) {
+        return SeckillActivityConvert.INSTANCE.convertList4(activityService.getSeckillActivityProductList(id, skuIds));
+    }
+
 }

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

@@ -7,6 +7,7 @@ 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.api.seckill.dto.SeckillActivityProductRespDTO;
 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;
@@ -137,4 +138,6 @@ public interface SeckillActivityConvert {
                         "yyyy-MM-dd HH:mm:ss")); // 活动结束日期和时段结合
     }
 
+    List<SeckillActivityProductRespDTO> convertList4(List<SeckillProductDO> seckillActivityProductList);
+
 }

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

@@ -37,9 +37,9 @@ public interface SeckillActivityService {
     /**
      * 更新秒杀库存
      *
-     * @param id 活动编号
-     * @param skuId      sku 编号
-     * @param count      数量
+     * @param id    活动编号
+     * @param skuId sku 编号
+     * @param count 数量
      */
     void updateSeckillStock(Long id, Long skuId, Integer count);
 
@@ -114,4 +114,13 @@ public interface SeckillActivityService {
      */
     PageResult<SeckillActivityDO> getSeckillActivityAppPageByConfigId(AppSeckillActivityPageReqVO pageReqVO);
 
+    /**
+     * 获取秒杀活动商品信息
+     *
+     * @param id     活动编号
+     * @param skuIds sku 编号
+     * @return 秒杀活动商品信息列表
+     */
+    List<SeckillProductDO> getSeckillActivityProductList(Long id, Collection<Long> skuIds);
+
 }

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

@@ -1,5 +1,6 @@
 package cn.iocoder.yudao.module.promotion.service.seckill;
 
+import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.core.util.ObjectUtil;
 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
@@ -284,4 +285,18 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
         return seckillActivityMapper.selectPage(pageReqVO, CommonStatusEnum.ENABLE.getStatus());
     }
 
+    @Override
+    public List<SeckillProductDO> getSeckillActivityProductList(Long id, Collection<Long> skuIds) {
+        // 1、校验秒杀活动是否存在
+        validateSeckillActivityExists(id);
+        // 2、校验活动商品是否存在
+        List<SeckillProductDO> productList = filterList(seckillProductMapper.selectListByActivityId(id),
+                item -> skuIds.contains(item.getSkuId()));
+        if (CollectionUtil.isEmpty(productList)) {
+            throw exception(SKU_NOT_EXISTS);
+        }
+
+        return productList;
+    }
+
 }

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

@@ -216,11 +216,11 @@ public interface TradeOrderConvert {
     })
     ProductCommentCreateReqDTO convert04(AppTradeOrderItemCommentCreateReqVO createReqVO, TradeOrderItemDO tradeOrderItemDO);
 
+    TradePriceCalculateReqBO convert(AppTradeOrderSettlementReqVO settlementReqVO);
+
     default TradePriceCalculateReqBO convert(Long userId, AppTradeOrderSettlementReqVO settlementReqVO,
                                              List<CartDO> cartList) {
-        TradePriceCalculateReqBO reqBO = new TradePriceCalculateReqBO();
-        reqBO.setUserId(userId).setCouponId(settlementReqVO.getCouponId()).setAddressId(settlementReqVO.getAddressId())
-                .setItems(new ArrayList<>(settlementReqVO.getItems().size()));
+        TradePriceCalculateReqBO reqBO = convert(settlementReqVO).setUserId(userId).setItems(new ArrayList<>(settlementReqVO.getItems().size()));
         // 商品项的构建
         Map<Long, CartDO> cartMap = convertMap(cartList, CartDO::getId);
         for (AppTradeOrderSettlementReqVO.Item item : settlementReqVO.getItems()) {

+ 18 - 0
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/bo/TradePriceCalculateReqBO.java

@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.trade.service.price.bo;
 
 import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum;
 import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum;
+import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import javax.validation.Valid;
@@ -52,6 +53,23 @@ public class TradePriceCalculateReqBO {
      */
     private Integer deliveryType;
 
+    // ========== 秒杀活动相关字段 ==========
+    @Schema(description = "秒杀活动编号", example = "1024")
+    private Long seckillActivityId;
+
+    // ========== 拼团活动相关字段 ==========
+    // TODO @puhui999:是不是拼团记录的编号哈?
+    @Schema(description = "拼团活动编号", example = "1024")
+    private Long combinationActivityId;
+
+    @Schema(description = "拼团团长编号", example = "2048")
+    private Long combinationHeadId;
+
+    // ========== 砍价活动相关字段 ==========
+    // TODO @puhui999:是不是砍价记录的编号哈?
+    @Schema(description = "砍价活动编号", example = "123")
+    private Long bargainActivityId;
+
     /**
      * 商品 SKU 数组
      */

+ 18 - 1
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/bo/TradePriceCalculateRespBO.java

@@ -84,9 +84,19 @@ public class TradePriceCalculateRespBO {
          * 对应 taobao 的 trade.point_fee 字段
          */
         private Integer pointPrice;
+        /**
+         * 秒杀、拼团、砍价活动商品的总金额,单位:分
+         *
+         * 基于 {@link OrderItem#getActivityPrice()} ()} * {@link OrderItem#getCount()} 求和
+         */
+        private Integer activityPrice;
         /**
          * 最终购买金额(总),单位:分
          *
+         * ==========活动情况===========
+         * = {@link #activityPrice}
+         * + {@link #deliveryPrice}
+         * ==========正常情况===========
          * = {@link #totalPrice}
          * - {@link #couponPrice}
          * - {@link #pointPrice}
@@ -153,9 +163,16 @@ public class TradePriceCalculateRespBO {
          * 对应 taobao 的 trade.point_fee 字段
          */
         private Integer pointPrice;
+        /**
+         * 秒杀、拼团、砍价活动商品的金额,单位:分
+         */
+        private Integer activityPrice;
         /**
          * 应付金额(总),单位:分
-         *
+         * ==========活动情况===========
+         * = {@link #activityPrice} * {@link #count}
+         * + {@link #deliveryPrice}
+         * ==========正常情况===========
          * = {@link #price} * {@link #count}
          * - {@link #couponPrice}
          * - {@link #pointPrice}

+ 3 - 0
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradePriceCalculatorHelper.java

@@ -84,6 +84,9 @@ public class TradePriceCalculatorHelper {
             if (!item.getSelected()) {
                 return;
             }
+            // TODO puhui: 需要在这里计算活动的价格
+            // ========== 一、活动情况 ==========
+            // ========== 二、正常情况 ==========
             price.setTotalPrice(price.getTotalPrice() + item.getPrice() * item.getCount());
             price.setDiscountPrice(price.getDiscountPrice() + item.getDiscountPrice());
             price.setDeliveryPrice(price.getDeliveryPrice() + item.getDeliveryPrice());

+ 47 - 0
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeSeckillActivityPriceCalculator.java

@@ -0,0 +1,47 @@
+package cn.iocoder.yudao.module.trade.service.price.calculator;
+
+import cn.hutool.core.util.ObjectUtil;
+import cn.iocoder.yudao.module.promotion.api.seckill.SeckillActivityApi;
+import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillActivityProductRespDTO;
+import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum;
+import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO;
+import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO;
+import org.springframework.core.annotation.Order;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+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.CollectionUtils.convertSet;
+
+/**
+ * 秒杀活动的 {@link TradePriceCalculator} 实现类
+ *
+ * @author HUIHUI
+ */
+@Component
+@Order(TradePriceCalculator.ORDER_DISCOUNT_ACTIVITY)
+public class TradeSeckillActivityPriceCalculator implements TradePriceCalculator {
+
+    @Resource
+    private SeckillActivityApi activityApi;
+
+    @Override
+    public void calculate(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result) {
+        // 1、判断订单类型和是否具有秒杀活动编号
+        if (ObjectUtil.notEqual(param.getType(), TradeOrderTypeEnum.SECKILL.getType()) && param.getSeckillActivityId() == null) {
+            return;
+        }
+        // 2、获取秒杀活动商品信息
+        List<SeckillActivityProductRespDTO> productList = activityApi.getSeckillActivityProductList(param.getSeckillActivityId(), convertSet(param.getItems(),
+                TradePriceCalculateReqBO.Item::getSkuId));
+        Map<Long, SeckillActivityProductRespDTO> productMap = convertMap(productList, SeckillActivityProductRespDTO::getSkuId);
+        result.getItems().forEach(item -> {
+            SeckillActivityProductRespDTO product = productMap.get(item.getSkuId());
+            item.setActivityPrice(product.getSeckillPrice()); // 设置活动金额
+        });
+    }
+
+}