From 42c47d9b4481366f03ec16612bacd874f3f67aaa Mon Sep 17 00:00:00 2001 From: puhui999 Date: Mon, 25 Sep 2023 14:56:56 +0800 Subject: [PATCH] =?UTF-8?q?=E7=A7=92=E5=9B=9E=E6=B4=BB=E5=8A=A8=EF=BC=9A?= =?UTF-8?q?=E8=AE=A2=E5=8D=95=E9=87=91=E9=A2=9D=E8=AE=A1=E7=AE=97=E5=88=9D?= =?UTF-8?q?=E6=AD=A5=E8=AE=BE=E8=AE=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/seckill/SeckillActivityApi.java | 14 ++++ .../dto/SeckillActivityProductRespDTO.java | 65 +++++++++++++++++++ .../api/seckill/SeckillActivityApiImpl.java | 9 +++ .../SeckillActivityConvert.java | 3 + .../seckill/SeckillActivityService.java | 15 ++++- .../seckill/SeckillActivityServiceImpl.java | 15 +++++ .../convert/order/TradeOrderConvert.java | 6 +- .../price/bo/TradePriceCalculateReqBO.java | 18 +++++ .../price/bo/TradePriceCalculateRespBO.java | 19 +++++- .../TradePriceCalculatorHelper.java | 3 + .../TradeSeckillActivityPriceCalculator.java | 47 ++++++++++++++ 11 files changed, 207 insertions(+), 7 deletions(-) create mode 100644 yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/dto/SeckillActivityProductRespDTO.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeSeckillActivityPriceCalculator.java diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApi.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApi.java index 11cc22864..6f01d57ba 100644 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApi.java +++ b/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 getSeckillActivityProductList(Long id, Collection skuIds); + } diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/dto/SeckillActivityProductRespDTO.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/dto/SeckillActivityProductRespDTO.java new file mode 100644 index 000000000..5fb0554d3 --- /dev/null +++ b/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 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; + +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApiImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApiImpl.java index 9a15a0ca9..b837dac7e 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApiImpl.java +++ b/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 getSeckillActivityProductList(Long id, Collection skuIds) { + return SeckillActivityConvert.INSTANCE.convertList4(activityService.getSeckillActivityProductList(id, skuIds)); + } + } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckillactivity/SeckillActivityConvert.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckillactivity/SeckillActivityConvert.java index f0da88cbc..6219d9032 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckillactivity/SeckillActivityConvert.java +++ b/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 convertList4(List seckillActivityProductList); + } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityService.java index 3cbee8126..b517bb237 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityService.java +++ b/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 getSeckillActivityAppPageByConfigId(AppSeckillActivityPageReqVO pageReqVO); + /** + * 获取秒杀活动商品信息 + * + * @param id 活动编号 + * @param skuIds sku 编号 + * @return 秒杀活动商品信息列表 + */ + List getSeckillActivityProductList(Long id, Collection skuIds); + } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java index 0092cf1b8..687fa3127 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java +++ b/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 getSeckillActivityProductList(Long id, Collection skuIds) { + // 1、校验秒杀活动是否存在 + validateSeckillActivityExists(id); + // 2、校验活动商品是否存在 + List productList = filterList(seckillProductMapper.selectListByActivityId(id), + item -> skuIds.contains(item.getSkuId())); + if (CollectionUtil.isEmpty(productList)) { + throw exception(SKU_NOT_EXISTS); + } + + return productList; + } + } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java index d5b9546d0..9fc0cdb64 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java +++ b/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 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 cartMap = convertMap(cartList, CartDO::getId); for (AppTradeOrderSettlementReqVO.Item item : settlementReqVO.getItems()) { diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/bo/TradePriceCalculateReqBO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/bo/TradePriceCalculateReqBO.java index ff5faea26..c52f80073 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/bo/TradePriceCalculateReqBO.java +++ b/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 数组 */ diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/bo/TradePriceCalculateRespBO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/bo/TradePriceCalculateRespBO.java index 76fb68c1f..2aee9c65a 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/bo/TradePriceCalculateRespBO.java +++ b/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} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradePriceCalculatorHelper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradePriceCalculatorHelper.java index bd3d3b5be..9e85bc390 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradePriceCalculatorHelper.java +++ b/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()); diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeSeckillActivityPriceCalculator.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeSeckillActivityPriceCalculator.java new file mode 100644 index 000000000..5d33bc286 --- /dev/null +++ b/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 productList = activityApi.getSeckillActivityProductList(param.getSeckillActivityId(), convertSet(param.getItems(), + TradePriceCalculateReqBO.Item::getSkuId)); + Map productMap = convertMap(productList, SeckillActivityProductRespDTO::getSkuId); + result.getItems().forEach(item -> { + SeckillActivityProductRespDTO product = productMap.get(item.getSkuId()); + item.setActivityPrice(product.getSeckillPrice()); // 设置活动金额 + }); + } + +}