Commit 42c47d9b4481366f03ec16612bacd874f3f67aaa
1 parent
8060aeb5
秒回活动:订单金额计算初步设计
Showing
11 changed files
with
207 additions
and
7 deletions
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApi.java
| 1 | 1 | package cn.iocoder.yudao.module.promotion.api.seckill; |
| 2 | 2 | |
| 3 | +import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillActivityProductRespDTO; | |
| 4 | + | |
| 5 | +import java.util.Collection; | |
| 6 | +import java.util.List; | |
| 7 | + | |
| 3 | 8 | /** |
| 4 | 9 | * 秒杀活动 API 接口 |
| 5 | 10 | * |
| ... | ... | @@ -16,4 +21,13 @@ public interface SeckillActivityApi { |
| 16 | 21 | */ |
| 17 | 22 | void updateSeckillStock(Long id, Long skuId, Integer count); |
| 18 | 23 | |
| 24 | + /** | |
| 25 | + * 获取秒杀活动商品信息 | |
| 26 | + * | |
| 27 | + * @param id 活动编号 | |
| 28 | + * @param skuIds sku 编号 | |
| 29 | + * @return 秒杀活动商品信息列表 | |
| 30 | + */ | |
| 31 | + List<SeckillActivityProductRespDTO> getSeckillActivityProductList(Long id, Collection<Long> skuIds); | |
| 32 | + | |
| 19 | 33 | } | ... | ... |
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/dto/SeckillActivityProductRespDTO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.promotion.api.seckill.dto; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | |
| 4 | +import lombok.Data; | |
| 5 | + | |
| 6 | +import java.time.LocalDateTime; | |
| 7 | +import java.util.List; | |
| 8 | + | |
| 9 | +/** | |
| 10 | + * 秒杀活动商品 Response DTO | |
| 11 | + * | |
| 12 | + * @author HUIHUI | |
| 13 | + */ | |
| 14 | +@Data | |
| 15 | +public class SeckillActivityProductRespDTO { | |
| 16 | + | |
| 17 | + /** | |
| 18 | + * 秒杀参与商品编号 | |
| 19 | + */ | |
| 20 | + private Long id; | |
| 21 | + /** | |
| 22 | + * 秒杀活动 id | |
| 23 | + * | |
| 24 | + * 关联 SeckillActivityDO#getId() | |
| 25 | + */ | |
| 26 | + private Long activityId; | |
| 27 | + /** | |
| 28 | + * 秒杀时段 id | |
| 29 | + * | |
| 30 | + * 关联 SeckillConfigDO#getId() | |
| 31 | + */ | |
| 32 | + private List<Long> configIds; | |
| 33 | + /** | |
| 34 | + * 商品 SPU 编号 | |
| 35 | + */ | |
| 36 | + private Long spuId; | |
| 37 | + /** | |
| 38 | + * 商品 SKU 编号 | |
| 39 | + */ | |
| 40 | + private Long skuId; | |
| 41 | + /** | |
| 42 | + * 秒杀金额,单位:分 | |
| 43 | + */ | |
| 44 | + private Integer seckillPrice; | |
| 45 | + /** | |
| 46 | + * 秒杀库存 | |
| 47 | + */ | |
| 48 | + private Integer stock; | |
| 49 | + | |
| 50 | + /** | |
| 51 | + * 秒杀商品状态 | |
| 52 | + * | |
| 53 | + * 枚举 {@link CommonStatusEnum 对应的类} | |
| 54 | + */ | |
| 55 | + private Integer activityStatus; | |
| 56 | + /** | |
| 57 | + * 活动开始时间点 | |
| 58 | + */ | |
| 59 | + private LocalDateTime activityStartTime; | |
| 60 | + /** | |
| 61 | + * 活动结束时间点 | |
| 62 | + */ | |
| 63 | + private LocalDateTime activityEndTime; | |
| 64 | + | |
| 65 | +} | ... | ... |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApiImpl.java
| 1 | 1 | package cn.iocoder.yudao.module.promotion.api.seckill; |
| 2 | 2 | |
| 3 | +import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillActivityProductRespDTO; | |
| 4 | +import cn.iocoder.yudao.module.promotion.convert.seckill.seckillactivity.SeckillActivityConvert; | |
| 3 | 5 | import cn.iocoder.yudao.module.promotion.service.seckill.SeckillActivityService; |
| 4 | 6 | import org.springframework.stereotype.Service; |
| 5 | 7 | |
| 6 | 8 | import javax.annotation.Resource; |
| 9 | +import java.util.Collection; | |
| 10 | +import java.util.List; | |
| 7 | 11 | |
| 8 | 12 | /** |
| 9 | 13 | * 秒杀活动接口 Api 接口实现类 |
| ... | ... | @@ -21,4 +25,9 @@ public class SeckillActivityApiImpl implements SeckillActivityApi { |
| 21 | 25 | activityService.updateSeckillStock(id, skuId, count); |
| 22 | 26 | } |
| 23 | 27 | |
| 28 | + @Override | |
| 29 | + public List<SeckillActivityProductRespDTO> getSeckillActivityProductList(Long id, Collection<Long> skuIds) { | |
| 30 | + return SeckillActivityConvert.INSTANCE.convertList4(activityService.getSeckillActivityProductList(id, skuIds)); | |
| 31 | + } | |
| 32 | + | |
| 24 | 33 | } | ... | ... |
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; |
| 7 | 7 | import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils; |
| 8 | 8 | import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; |
| 9 | 9 | import cn.iocoder.yudao.module.product.enums.DictTypeConstants; |
| 10 | +import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillActivityProductRespDTO; | |
| 10 | 11 | import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityCreateReqVO; |
| 11 | 12 | import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityDetailRespVO; |
| 12 | 13 | import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityRespVO; |
| ... | ... | @@ -137,4 +138,6 @@ public interface SeckillActivityConvert { |
| 137 | 138 | "yyyy-MM-dd HH:mm:ss")); // 活动结束日期和时段结合 |
| 138 | 139 | } |
| 139 | 140 | |
| 141 | + List<SeckillActivityProductRespDTO> convertList4(List<SeckillProductDO> seckillActivityProductList); | |
| 142 | + | |
| 140 | 143 | } | ... | ... |
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 { |
| 37 | 37 | /** |
| 38 | 38 | * 更新秒杀库存 |
| 39 | 39 | * |
| 40 | - * @param id 活动编号 | |
| 41 | - * @param skuId sku 编号 | |
| 42 | - * @param count 数量 | |
| 40 | + * @param id 活动编号 | |
| 41 | + * @param skuId sku 编号 | |
| 42 | + * @param count 数量 | |
| 43 | 43 | */ |
| 44 | 44 | void updateSeckillStock(Long id, Long skuId, Integer count); |
| 45 | 45 | |
| ... | ... | @@ -114,4 +114,13 @@ public interface SeckillActivityService { |
| 114 | 114 | */ |
| 115 | 115 | PageResult<SeckillActivityDO> getSeckillActivityAppPageByConfigId(AppSeckillActivityPageReqVO pageReqVO); |
| 116 | 116 | |
| 117 | + /** | |
| 118 | + * 获取秒杀活动商品信息 | |
| 119 | + * | |
| 120 | + * @param id 活动编号 | |
| 121 | + * @param skuIds sku 编号 | |
| 122 | + * @return 秒杀活动商品信息列表 | |
| 123 | + */ | |
| 124 | + List<SeckillProductDO> getSeckillActivityProductList(Long id, Collection<Long> skuIds); | |
| 125 | + | |
| 117 | 126 | } | ... | ... |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java
| 1 | 1 | package cn.iocoder.yudao.module.promotion.service.seckill; |
| 2 | 2 | |
| 3 | +import cn.hutool.core.collection.CollectionUtil; | |
| 3 | 4 | import cn.hutool.core.util.ObjectUtil; |
| 4 | 5 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| 5 | 6 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| ... | ... | @@ -284,4 +285,18 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { |
| 284 | 285 | return seckillActivityMapper.selectPage(pageReqVO, CommonStatusEnum.ENABLE.getStatus()); |
| 285 | 286 | } |
| 286 | 287 | |
| 288 | + @Override | |
| 289 | + public List<SeckillProductDO> getSeckillActivityProductList(Long id, Collection<Long> skuIds) { | |
| 290 | + // 1、校验秒杀活动是否存在 | |
| 291 | + validateSeckillActivityExists(id); | |
| 292 | + // 2、校验活动商品是否存在 | |
| 293 | + List<SeckillProductDO> productList = filterList(seckillProductMapper.selectListByActivityId(id), | |
| 294 | + item -> skuIds.contains(item.getSkuId())); | |
| 295 | + if (CollectionUtil.isEmpty(productList)) { | |
| 296 | + throw exception(SKU_NOT_EXISTS); | |
| 297 | + } | |
| 298 | + | |
| 299 | + return productList; | |
| 300 | + } | |
| 301 | + | |
| 287 | 302 | } | ... | ... |
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 { |
| 216 | 216 | }) |
| 217 | 217 | ProductCommentCreateReqDTO convert04(AppTradeOrderItemCommentCreateReqVO createReqVO, TradeOrderItemDO tradeOrderItemDO); |
| 218 | 218 | |
| 219 | + TradePriceCalculateReqBO convert(AppTradeOrderSettlementReqVO settlementReqVO); | |
| 220 | + | |
| 219 | 221 | default TradePriceCalculateReqBO convert(Long userId, AppTradeOrderSettlementReqVO settlementReqVO, |
| 220 | 222 | List<CartDO> cartList) { |
| 221 | - TradePriceCalculateReqBO reqBO = new TradePriceCalculateReqBO(); | |
| 222 | - reqBO.setUserId(userId).setCouponId(settlementReqVO.getCouponId()).setAddressId(settlementReqVO.getAddressId()) | |
| 223 | - .setItems(new ArrayList<>(settlementReqVO.getItems().size())); | |
| 223 | + TradePriceCalculateReqBO reqBO = convert(settlementReqVO).setUserId(userId).setItems(new ArrayList<>(settlementReqVO.getItems().size())); | |
| 224 | 224 | // 商品项的构建 |
| 225 | 225 | Map<Long, CartDO> cartMap = convertMap(cartList, CartDO::getId); |
| 226 | 226 | for (AppTradeOrderSettlementReqVO.Item item : settlementReqVO.getItems()) { | ... | ... |
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; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum; |
| 4 | 4 | import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; |
| 5 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 5 | 6 | import lombok.Data; |
| 6 | 7 | |
| 7 | 8 | import javax.validation.Valid; |
| ... | ... | @@ -52,6 +53,23 @@ public class TradePriceCalculateReqBO { |
| 52 | 53 | */ |
| 53 | 54 | private Integer deliveryType; |
| 54 | 55 | |
| 56 | + // ========== 秒杀活动相关字段 ========== | |
| 57 | + @Schema(description = "秒杀活动编号", example = "1024") | |
| 58 | + private Long seckillActivityId; | |
| 59 | + | |
| 60 | + // ========== 拼团活动相关字段 ========== | |
| 61 | + // TODO @puhui999:是不是拼团记录的编号哈? | |
| 62 | + @Schema(description = "拼团活动编号", example = "1024") | |
| 63 | + private Long combinationActivityId; | |
| 64 | + | |
| 65 | + @Schema(description = "拼团团长编号", example = "2048") | |
| 66 | + private Long combinationHeadId; | |
| 67 | + | |
| 68 | + // ========== 砍价活动相关字段 ========== | |
| 69 | + // TODO @puhui999:是不是砍价记录的编号哈? | |
| 70 | + @Schema(description = "砍价活动编号", example = "123") | |
| 71 | + private Long bargainActivityId; | |
| 72 | + | |
| 55 | 73 | /** |
| 56 | 74 | * 商品 SKU 数组 |
| 57 | 75 | */ | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/bo/TradePriceCalculateRespBO.java
| ... | ... | @@ -85,8 +85,18 @@ public class TradePriceCalculateRespBO { |
| 85 | 85 | */ |
| 86 | 86 | private Integer pointPrice; |
| 87 | 87 | /** |
| 88 | + * 秒杀、拼团、砍价活动商品的总金额,单位:分 | |
| 89 | + * | |
| 90 | + * 基于 {@link OrderItem#getActivityPrice()} ()} * {@link OrderItem#getCount()} 求和 | |
| 91 | + */ | |
| 92 | + private Integer activityPrice; | |
| 93 | + /** | |
| 88 | 94 | * 最终购买金额(总),单位:分 |
| 89 | 95 | * |
| 96 | + * ==========活动情况=========== | |
| 97 | + * = {@link #activityPrice} | |
| 98 | + * + {@link #deliveryPrice} | |
| 99 | + * ==========正常情况=========== | |
| 90 | 100 | * = {@link #totalPrice} |
| 91 | 101 | * - {@link #couponPrice} |
| 92 | 102 | * - {@link #pointPrice} |
| ... | ... | @@ -154,8 +164,15 @@ public class TradePriceCalculateRespBO { |
| 154 | 164 | */ |
| 155 | 165 | private Integer pointPrice; |
| 156 | 166 | /** |
| 167 | + * 秒杀、拼团、砍价活动商品的金额,单位:分 | |
| 168 | + */ | |
| 169 | + private Integer activityPrice; | |
| 170 | + /** | |
| 157 | 171 | * 应付金额(总),单位:分 |
| 158 | - * | |
| 172 | + * ==========活动情况=========== | |
| 173 | + * = {@link #activityPrice} * {@link #count} | |
| 174 | + * + {@link #deliveryPrice} | |
| 175 | + * ==========正常情况=========== | |
| 159 | 176 | * = {@link #price} * {@link #count} |
| 160 | 177 | * - {@link #couponPrice} |
| 161 | 178 | * - {@link #pointPrice} | ... | ... |
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 { |
| 84 | 84 | if (!item.getSelected()) { |
| 85 | 85 | return; |
| 86 | 86 | } |
| 87 | + // TODO puhui: 需要在这里计算活动的价格 | |
| 88 | + // ========== 一、活动情况 ========== | |
| 89 | + // ========== 二、正常情况 ========== | |
| 87 | 90 | price.setTotalPrice(price.getTotalPrice() + item.getPrice() * item.getCount()); |
| 88 | 91 | price.setDiscountPrice(price.getDiscountPrice() + item.getDiscountPrice()); |
| 89 | 92 | price.setDeliveryPrice(price.getDeliveryPrice() + item.getDeliveryPrice()); | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeSeckillActivityPriceCalculator.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.trade.service.price.calculator; | |
| 2 | + | |
| 3 | +import cn.hutool.core.util.ObjectUtil; | |
| 4 | +import cn.iocoder.yudao.module.promotion.api.seckill.SeckillActivityApi; | |
| 5 | +import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillActivityProductRespDTO; | |
| 6 | +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; | |
| 7 | +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; | |
| 8 | +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; | |
| 9 | +import org.springframework.core.annotation.Order; | |
| 10 | +import org.springframework.stereotype.Component; | |
| 11 | + | |
| 12 | +import javax.annotation.Resource; | |
| 13 | +import java.util.List; | |
| 14 | +import java.util.Map; | |
| 15 | + | |
| 16 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; | |
| 17 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; | |
| 18 | + | |
| 19 | +/** | |
| 20 | + * 秒杀活动的 {@link TradePriceCalculator} 实现类 | |
| 21 | + * | |
| 22 | + * @author HUIHUI | |
| 23 | + */ | |
| 24 | +@Component | |
| 25 | +@Order(TradePriceCalculator.ORDER_DISCOUNT_ACTIVITY) | |
| 26 | +public class TradeSeckillActivityPriceCalculator implements TradePriceCalculator { | |
| 27 | + | |
| 28 | + @Resource | |
| 29 | + private SeckillActivityApi activityApi; | |
| 30 | + | |
| 31 | + @Override | |
| 32 | + public void calculate(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result) { | |
| 33 | + // 1、判断订单类型和是否具有秒杀活动编号 | |
| 34 | + if (ObjectUtil.notEqual(param.getType(), TradeOrderTypeEnum.SECKILL.getType()) && param.getSeckillActivityId() == null) { | |
| 35 | + return; | |
| 36 | + } | |
| 37 | + // 2、获取秒杀活动商品信息 | |
| 38 | + List<SeckillActivityProductRespDTO> productList = activityApi.getSeckillActivityProductList(param.getSeckillActivityId(), convertSet(param.getItems(), | |
| 39 | + TradePriceCalculateReqBO.Item::getSkuId)); | |
| 40 | + Map<Long, SeckillActivityProductRespDTO> productMap = convertMap(productList, SeckillActivityProductRespDTO::getSkuId); | |
| 41 | + result.getItems().forEach(item -> { | |
| 42 | + SeckillActivityProductRespDTO product = productMap.get(item.getSkuId()); | |
| 43 | + item.setActivityPrice(product.getSeckillPrice()); // 设置活动金额 | |
| 44 | + }); | |
| 45 | + } | |
| 46 | + | |
| 47 | +} | ... | ... |