Commit e0d9f7cfbaccf578b9b0351f8eec077404183c7e

Authored by puhui999
1 parent cccad2c6

【功能新增】商城: 满减送活动下单后,赠送积分、优惠劵、包邮

Showing 13 changed files with 135 additions and 41 deletions
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/reward/vo/RewardActivityBaseVO.java
@@ -96,7 +96,7 @@ public class RewardActivityBaseVO { @@ -96,7 +96,7 @@ public class RewardActivityBaseVO {
96 @AssertTrue(message = "优惠劵和数量必须一一对应") 96 @AssertTrue(message = "优惠劵和数量必须一一对应")
97 @JsonIgnore 97 @JsonIgnore
98 public boolean isCouponCountsValid() { 98 public boolean isCouponCountsValid() {
99 - return BooleanUtil.isFalse(givePoint) || CollUtil.size(couponIds) == CollUtil.size(couponCounts); 99 + return BooleanUtil.isFalse(giveCoupon) || CollUtil.size(couponIds) == CollUtil.size(couponCounts);
100 } 100 }
101 101
102 @AssertTrue(message = "赠送的积分不能小于 1") 102 @AssertTrue(message = "赠送的积分不能小于 1")
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordServiceImpl.java
@@ -340,7 +340,7 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { @@ -340,7 +340,7 @@ public class CombinationRecordServiceImpl implements CombinationRecordService {
340 CombinationRecordStatusEnum.FAILED); 340 CombinationRecordStatusEnum.FAILED);
341 // 2. 订单取消 341 // 2. 订单取消
342 headAndRecords.forEach(item -> tradeOrderApi.cancelPaidOrder(item.getUserId(), item.getOrderId(), 342 headAndRecords.forEach(item -> tradeOrderApi.cancelPaidOrder(item.getUserId(), item.getOrderId(),
343 - TradeOrderCancelTypeEnum.COMBINATION_CLOSE)); 343 + TradeOrderCancelTypeEnum.COMBINATION_CLOSE.getType()));
344 } 344 }
345 345
346 /** 346 /**
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/api/order/TradeOrderApi.java
1 package cn.iocoder.yudao.module.trade.api.order; 1 package cn.iocoder.yudao.module.trade.api.order;
2 2
3 import cn.iocoder.yudao.module.trade.api.order.dto.TradeOrderRespDTO; 3 import cn.iocoder.yudao.module.trade.api.order.dto.TradeOrderRespDTO;
4 -import cn.iocoder.yudao.module.trade.enums.order.TradeOrderCancelTypeEnum;  
5 4
6 import java.util.Collection; 5 import java.util.Collection;
7 import java.util.List; 6 import java.util.List;
@@ -34,8 +33,8 @@ public interface TradeOrderApi { @@ -34,8 +33,8 @@ public interface TradeOrderApi {
34 * 33 *
35 * @param userId 用户编号 34 * @param userId 用户编号
36 * @param orderId 订单编号 35 * @param orderId 订单编号
37 - * @param cancelTypeEnum 取消类型 36 + * @param cancelType 取消类型
38 */ 37 */
39 - void cancelPaidOrder(Long userId, Long orderId, TradeOrderCancelTypeEnum cancelTypeEnum); 38 + void cancelPaidOrder(Long userId, Long orderId, Integer cancelType);
40 39
41 } 40 }
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java
@@ -60,6 +60,7 @@ public interface ErrorCodeConstants { @@ -60,6 +60,7 @@ public interface ErrorCodeConstants {
60 ErrorCode PRICE_CALCULATE_DELIVERY_PRICE_TEMPLATE_NOT_FOUND = new ErrorCode(1_011_003_002, "计算快递运费异常,找不到对应的运费模板"); 60 ErrorCode PRICE_CALCULATE_DELIVERY_PRICE_TEMPLATE_NOT_FOUND = new ErrorCode(1_011_003_002, "计算快递运费异常,找不到对应的运费模板");
61 ErrorCode PRICE_CALCULATE_COUPON_NOT_MATCH_NORMAL_ORDER = new ErrorCode(1_011_003_004, "参与秒杀、拼团、砍价的营销商品,无法使用优惠劵"); 61 ErrorCode PRICE_CALCULATE_COUPON_NOT_MATCH_NORMAL_ORDER = new ErrorCode(1_011_003_004, "参与秒杀、拼团、砍价的营销商品,无法使用优惠劵");
62 ErrorCode PRICE_CALCULATE_SECKILL_TOTAL_LIMIT_COUNT = new ErrorCode(1_011_003_005, "参与秒杀的商品,超过了秒杀总限购数量"); 62 ErrorCode PRICE_CALCULATE_SECKILL_TOTAL_LIMIT_COUNT = new ErrorCode(1_011_003_005, "参与秒杀的商品,超过了秒杀总限购数量");
  63 + ErrorCode PRICE_CALCULATE_DELIVERY_PRICE_TYPE_ILLEGAL = new ErrorCode(1_011_003_006, "计算快递运费异常,配送方式不匹配");
63 64
64 // ========== 物流 Express 模块 1-011-004-000 ========== 65 // ========== 物流 Express 模块 1-011-004-000 ==========
65 ErrorCode EXPRESS_NOT_EXISTS = new ErrorCode(1_011_004_000, "快递公司不存在"); 66 ErrorCode EXPRESS_NOT_EXISTS = new ErrorCode(1_011_004_000, "快递公司不存在");
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/api/order/TradeOrderApiImpl.java
@@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.trade.api.order; @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.trade.api.order;
2 2
3 import cn.iocoder.yudao.module.trade.api.order.dto.TradeOrderRespDTO; 3 import cn.iocoder.yudao.module.trade.api.order.dto.TradeOrderRespDTO;
4 import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert; 4 import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert;
5 -import cn.iocoder.yudao.module.trade.enums.order.TradeOrderCancelTypeEnum;  
6 import cn.iocoder.yudao.module.trade.service.order.TradeOrderQueryService; 5 import cn.iocoder.yudao.module.trade.service.order.TradeOrderQueryService;
7 import cn.iocoder.yudao.module.trade.service.order.TradeOrderUpdateService; 6 import cn.iocoder.yudao.module.trade.service.order.TradeOrderUpdateService;
8 import jakarta.annotation.Resource; 7 import jakarta.annotation.Resource;
@@ -37,8 +36,8 @@ public class TradeOrderApiImpl implements TradeOrderApi { @@ -37,8 +36,8 @@ public class TradeOrderApiImpl implements TradeOrderApi {
37 } 36 }
38 37
39 @Override 38 @Override
40 - public void cancelPaidOrder(Long userId, Long orderId, TradeOrderCancelTypeEnum cancelTypeEnum) {  
41 - tradeOrderUpdateService.cancelPaidOrder(userId, orderId, cancelTypeEnum); 39 + public void cancelPaidOrder(Long userId, Long orderId, Integer cancelType) {
  40 + tradeOrderUpdateService.cancelPaidOrder(userId, orderId, cancelType);
42 } 41 }
43 42
44 } 43 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderItemDO.java
@@ -160,6 +160,19 @@ public class TradeOrderItemDO extends BaseDO { @@ -160,6 +160,19 @@ public class TradeOrderItemDO extends BaseDO {
160 */ 160 */
161 private Integer vipPrice; 161 private Integer vipPrice;
162 162
  163 + /**
  164 + * 赠送的优惠劵编号的数组
  165 + *
  166 + * 目的:用于后续取消或者售后订单时,需要扣减赠送
  167 + */
  168 + private List<Long> couponIds;
  169 + /**
  170 + * 赠送的优惠券数量的数组
  171 + *
  172 + * 目的:用于后续取消或者售后订单时,需要扣减赠送
  173 + */
  174 + private List<Integer> couponCounts;
  175 +
163 // ========== 售后基本信息 ========== 176 // ========== 售后基本信息 ==========
164 177
165 /** 178 /**
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateService.java
@@ -9,7 +9,6 @@ import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettle @@ -9,7 +9,6 @@ import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettle
9 import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettlementRespVO; 9 import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettlementRespVO;
10 import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemCommentCreateReqVO; 10 import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemCommentCreateReqVO;
11 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; 11 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
12 -import cn.iocoder.yudao.module.trade.enums.order.TradeOrderCancelTypeEnum;  
13 import jakarta.validation.constraints.NotNull; 12 import jakarta.validation.constraints.NotNull;
14 13
15 /** 14 /**
@@ -186,14 +185,13 @@ public interface TradeOrderUpdateService { @@ -186,14 +185,13 @@ public interface TradeOrderUpdateService {
186 */ 185 */
187 void updateOrderCombinationInfo(Long orderId, Long activityId, Long combinationRecordId, Long headId); 186 void updateOrderCombinationInfo(Long orderId, Long activityId, Long combinationRecordId, Long headId);
188 187
189 - // TODO @puhui999:不传递枚举哈。因为 rpc 不好支持。  
190 /** 188 /**
191 * 取消支付订单 189 * 取消支付订单
192 * 190 *
193 * @param userId 用户编号 191 * @param userId 用户编号
194 * @param orderId 订单编号 192 * @param orderId 订单编号
195 - * @param cancelType 取消类型 193 + * @param cancelType 取消类型
196 */ 194 */
197 - void cancelPaidOrder(Long userId, Long orderId, TradeOrderCancelTypeEnum cancelType); 195 + void cancelPaidOrder(Long userId, Long orderId, Integer cancelType);
198 196
199 } 197 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java
@@ -858,8 +858,11 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @@ -858,8 +858,11 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
858 858
859 @Override 859 @Override
860 @Transactional(rollbackFor = Exception.class) 860 @Transactional(rollbackFor = Exception.class)
861 - public void cancelPaidOrder(Long userId, Long orderId, TradeOrderCancelTypeEnum cancelType) {  
862 - // TODO @puhui999:这里校验下 cancelType 只允许拼团关闭; 861 + public void cancelPaidOrder(Long userId, Long orderId, Integer cancelType) {
  862 + // 1. 这里校验下 cancelType 只允许拼团关闭;
  863 + if (!TradeOrderCancelTypeEnum.COMBINATION_CLOSE.getType().equals(cancelType)) {
  864 + return;
  865 + }
863 // 1.1 检验订单存在 866 // 1.1 检验订单存在
864 TradeOrderDO order = tradeOrderMapper.selectOrderByIdAndUserId(orderId, userId); 867 TradeOrderDO order = tradeOrderMapper.selectOrderByIdAndUserId(orderId, userId);
865 if (order == null) { 868 if (order == null) {
@@ -876,13 +879,13 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @@ -876,13 +879,13 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
876 } 879 }
877 880
878 // 2.1 取消订单 881 // 2.1 取消订单
879 - cancelOrder0(order, cancelType); 882 + cancelOrder0(order, TradeOrderCancelTypeEnum.COMBINATION_CLOSE);
880 // 2.2 创建退款单 883 // 2.2 创建退款单
881 payRefundApi.createRefund(new PayRefundCreateReqDTO() 884 payRefundApi.createRefund(new PayRefundCreateReqDTO()
882 .setAppKey(tradeOrderProperties.getPayAppKey()).setUserIp(getClientIP()) // 支付应用 885 .setAppKey(tradeOrderProperties.getPayAppKey()).setUserIp(getClientIP()) // 支付应用
883 .setMerchantOrderId(String.valueOf(order.getId())) // 支付单号 886 .setMerchantOrderId(String.valueOf(order.getId())) // 支付单号
884 .setMerchantRefundId(String.valueOf(order.getId())) 887 .setMerchantRefundId(String.valueOf(order.getId()))
885 - .setReason(cancelType.getName()).setPrice(order.getPayPrice()));// 价格信息 888 + .setReason(TradeOrderCancelTypeEnum.COMBINATION_CLOSE.getName()).setPrice(order.getPayPrice()));// 价格信息
886 } 889 }
887 890
888 /** 891 /**
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeCouponOrderHandler.java
@@ -4,9 +4,9 @@ import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi; @@ -4,9 +4,9 @@ import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi;
4 import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponUseReqDTO; 4 import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponUseReqDTO;
5 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; 5 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
6 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; 6 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO;
  7 +import jakarta.annotation.Resource;
7 import org.springframework.stereotype.Component; 8 import org.springframework.stereotype.Component;
8 9
9 -import jakarta.annotation.Resource;  
10 import java.util.List; 10 import java.util.List;
11 11
12 /** 12 /**
@@ -31,6 +31,11 @@ public class TradeCouponOrderHandler implements TradeOrderHandler { @@ -31,6 +31,11 @@ public class TradeCouponOrderHandler implements TradeOrderHandler {
31 } 31 }
32 32
33 @Override 33 @Override
  34 + public void afterPayOrder(TradeOrderDO order, List<TradeOrderItemDO> orderItems) {
  35 +
  36 + }
  37 +
  38 + @Override
34 public void afterCancelOrder(TradeOrderDO order, List<TradeOrderItemDO> orderItems) { 39 public void afterCancelOrder(TradeOrderDO order, List<TradeOrderItemDO> orderItems) {
35 if (order.getCouponId() == null || order.getCouponId() <= 0) { 40 if (order.getCouponId() == null || order.getCouponId() <= 0) {
36 return; 41 return;
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/bo/TradePriceCalculateRespBO.java
@@ -68,6 +68,21 @@ public class TradePriceCalculateRespBO { @@ -68,6 +68,21 @@ public class TradePriceCalculateRespBO {
68 private Long bargainActivityId; 68 private Long bargainActivityId;
69 69
70 /** 70 /**
  71 + * 是否包邮
  72 + */
  73 + private Boolean freeDelivery;
  74 +
  75 + // TODO @puhui999: 订单保存时需要保存
  76 + /**
  77 + * 赠送的优惠劵编号的数组
  78 + */
  79 + private List<Long> couponIds;
  80 + /**
  81 + * 赠送的优惠券数量的数组
  82 + */
  83 + private List<Integer> couponCounts;
  84 +
  85 + /**
71 * 订单价格 86 * 订单价格
72 */ 87 */
73 @Data 88 @Data
@@ -213,8 +228,19 @@ public class TradePriceCalculateRespBO { @@ -213,8 +228,19 @@ public class TradePriceCalculateRespBO {
213 */ 228 */
214 private Long categoryId; 229 private Long categoryId;
215 230
  231 + // ========== 物流相关字段 =========
  232 +
216 /** 233 /**
217 - * 运费模板 Id 234 + * 配送方式数组
  235 + *
  236 + * 对应 DeliveryTypeEnum 枚举
  237 + */
  238 + private List<Integer> deliveryTypes;
  239 +
  240 + /**
  241 + * 物流配置模板编号
  242 + *
  243 + * 对应 TradeDeliveryExpressTemplateDO 的 id 编号
218 */ 244 */
219 private Long deliveryTemplateId; 245 private Long deliveryTemplateId;
220 246
@@ -234,7 +260,7 @@ public class TradePriceCalculateRespBO { @@ -234,7 +260,7 @@ public class TradePriceCalculateRespBO {
234 private List<ProductPropertyValueDetailRespDTO> properties; 260 private List<ProductPropertyValueDetailRespDTO> properties;
235 261
236 /** 262 /**
237 - * 使用的积分 263 + * 赠送的积分
238 */ 264 */
239 private Integer givePoint; 265 private Integer givePoint;
240 266
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeDeliveryPriceCalculator.java
@@ -6,8 +6,6 @@ import cn.hutool.core.util.StrUtil; @@ -6,8 +6,6 @@ import cn.hutool.core.util.StrUtil;
6 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 6 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
7 import cn.iocoder.yudao.module.member.api.address.MemberAddressApi; 7 import cn.iocoder.yudao.module.member.api.address.MemberAddressApi;
8 import cn.iocoder.yudao.module.member.api.address.dto.MemberAddressRespDTO; 8 import cn.iocoder.yudao.module.member.api.address.dto.MemberAddressRespDTO;
9 -import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;  
10 -import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;  
11 import cn.iocoder.yudao.module.trade.dal.dataobject.config.TradeConfigDO; 9 import cn.iocoder.yudao.module.trade.dal.dataobject.config.TradeConfigDO;
12 import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryPickUpStoreDO; 10 import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryPickUpStoreDO;
13 import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryExpressChargeModeEnum; 11 import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryExpressChargeModeEnum;
@@ -30,8 +28,7 @@ import java.util.Set; @@ -30,8 +28,7 @@ import java.util.Set;
30 28
31 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 29 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
32 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; 30 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
33 -import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.PICK_UP_STORE_NOT_EXISTS;  
34 -import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.PRICE_CALCULATE_DELIVERY_PRICE_TEMPLATE_NOT_FOUND; 31 +import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*;
35 32
36 /** 33 /**
37 * 运费的 {@link TradePriceCalculator} 实现类 34 * 运费的 {@link TradePriceCalculator} 实现类
@@ -52,19 +49,15 @@ public class TradeDeliveryPriceCalculator implements TradePriceCalculator { @@ -52,19 +49,15 @@ public class TradeDeliveryPriceCalculator implements TradePriceCalculator {
52 private DeliveryExpressTemplateService deliveryExpressTemplateService; 49 private DeliveryExpressTemplateService deliveryExpressTemplateService;
53 @Resource 50 @Resource
54 private TradeConfigService tradeConfigService; 51 private TradeConfigService tradeConfigService;
55 - @Resource  
56 - private ProductSpuApi productSpuApi;  
57 52
58 @Override 53 @Override
59 public void calculate(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result) { 54 public void calculate(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result) {
60 if (param.getDeliveryType() == null) { 55 if (param.getDeliveryType() == null) {
61 return; 56 return;
62 } 57 }
63 - // TODO @puhui999:1)TradePriceCalculateRespBO 传递进来 delveryType 配送方式,减少读取;2)如果不匹配,抛出业务异常; = = 不然就不扣钱啦。  
64 // 校验是不是存在商品不能门店自提,或者不能快递发货的情况。就是说,配送方式不匹配哈 58 // 校验是不是存在商品不能门店自提,或者不能快递发货的情况。就是说,配送方式不匹配哈
65 - List<ProductSpuRespDTO> spuList = productSpuApi.getSpuList(convertSet(result.getItems(), OrderItem::getSpuId));  
66 - if (anyMatch(spuList, item -> !item.getDeliveryTypes().contains(param.getDeliveryType()))) {  
67 - return; 59 + if (anyMatch(result.getItems(), item -> !item.getDeliveryTypes().contains(param.getDeliveryType()))) {
  60 + throw exception(PRICE_CALCULATE_DELIVERY_PRICE_TYPE_ILLEGAL);
68 } 61 }
69 62
70 if (DeliveryTypeEnum.PICK_UP.getType().equals(param.getDeliveryType())) { 63 if (DeliveryTypeEnum.PICK_UP.getType().equals(param.getDeliveryType())) {
@@ -101,7 +94,12 @@ public class TradeDeliveryPriceCalculator implements TradePriceCalculator { @@ -101,7 +94,12 @@ public class TradeDeliveryPriceCalculator implements TradePriceCalculator {
101 return; 94 return;
102 } 95 }
103 96
104 - // 情况二:快递模版 97 + // 情况二:活动包邮
  98 + if (Boolean.TRUE.equals(result.getFreeDelivery())) {
  99 + return;
  100 + }
  101 +
  102 + // 情况三:快递模版
105 // 2.1 过滤出已选中的商品 SKU 103 // 2.1 过滤出已选中的商品 SKU
106 List<OrderItem> selectedItem = filterList(result.getItems(), OrderItem::getSelected); 104 List<OrderItem> selectedItem = filterList(result.getItems(), OrderItem::getSelected);
107 Set<Long> deliveryTemplateIds = convertSet(selectedItem, OrderItem::getDeliveryTemplateId); 105 Set<Long> deliveryTemplateIds = convertSet(selectedItem, OrderItem::getDeliveryTemplateId);
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradePriceCalculatorHelper.java
@@ -31,8 +31,8 @@ public class TradePriceCalculatorHelper { @@ -31,8 +31,8 @@ public class TradePriceCalculatorHelper {
31 List<ProductSpuRespDTO> spuList, List<ProductSkuRespDTO> skuList) { 31 List<ProductSpuRespDTO> spuList, List<ProductSkuRespDTO> skuList) {
32 // 创建 PriceCalculateRespDTO 对象 32 // 创建 PriceCalculateRespDTO 对象
33 TradePriceCalculateRespBO result = new TradePriceCalculateRespBO(); 33 TradePriceCalculateRespBO result = new TradePriceCalculateRespBO();
34 - result.setType(getOrderType(param));  
35 - result.setPromotions(new ArrayList<>()); 34 + result.setType(getOrderType(param)).setPromotions(new ArrayList<>())
  35 + .setCouponIds(new ArrayList<>()).setCouponCounts(new ArrayList<>());
36 36
37 // 创建它的 OrderItem 属性 37 // 创建它的 OrderItem 属性
38 result.setItems(new ArrayList<>(param.getItems().size())); 38 result.setItems(new ArrayList<>(param.getItems().size()));
@@ -60,7 +60,7 @@ public class TradePriceCalculatorHelper { @@ -60,7 +60,7 @@ public class TradePriceCalculatorHelper {
60 .setWeight(sku.getWeight()).setVolume(sku.getVolume()); 60 .setWeight(sku.getWeight()).setVolume(sku.getVolume());
61 // spu 信息 61 // spu 信息
62 orderItem.setSpuName(spu.getName()).setCategoryId(spu.getCategoryId()) 62 orderItem.setSpuName(spu.getName()).setCategoryId(spu.getCategoryId())
63 - .setDeliveryTemplateId(spu.getDeliveryTemplateId()) 63 + .setDeliveryTypes(spu.getDeliveryTypes()).setDeliveryTemplateId(spu.getDeliveryTemplateId())
64 .setGivePoint(spu.getGiveIntegral()).setUsePoint(0); 64 .setGivePoint(spu.getGiveIntegral()).setUsePoint(0);
65 if (StrUtil.isBlank(orderItem.getPicUrl())) { 65 if (StrUtil.isBlank(orderItem.getPicUrl())) {
66 orderItem.setPicUrl(spu.getPicUrl()); 66 orderItem.setPicUrl(spu.getPicUrl());
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeRewardActivityPriceCalculator.java
@@ -3,9 +3,11 @@ package cn.iocoder.yudao.module.trade.service.price.calculator; @@ -3,9 +3,11 @@ package cn.iocoder.yudao.module.trade.service.price.calculator;
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 import cn.hutool.core.util.ObjectUtil; 4 import cn.hutool.core.util.ObjectUtil;
5 import cn.hutool.core.util.StrUtil; 5 import cn.hutool.core.util.StrUtil;
  6 +import cn.iocoder.yudao.framework.common.util.number.MoneyUtils;
6 import cn.iocoder.yudao.module.promotion.api.reward.RewardActivityApi; 7 import cn.iocoder.yudao.module.promotion.api.reward.RewardActivityApi;
7 import cn.iocoder.yudao.module.promotion.api.reward.dto.RewardActivityMatchRespDTO; 8 import cn.iocoder.yudao.module.promotion.api.reward.dto.RewardActivityMatchRespDTO;
8 import cn.iocoder.yudao.module.promotion.enums.common.PromotionConditionTypeEnum; 9 import cn.iocoder.yudao.module.promotion.enums.common.PromotionConditionTypeEnum;
  10 +import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum;
9 import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum; 11 import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum;
10 import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; 12 import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum;
11 import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; 13 import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO;
@@ -14,6 +16,8 @@ import jakarta.annotation.Resource; @@ -14,6 +16,8 @@ import jakarta.annotation.Resource;
14 import org.springframework.core.annotation.Order; 16 import org.springframework.core.annotation.Order;
15 import org.springframework.stereotype.Component; 17 import org.springframework.stereotype.Component;
16 18
  19 +import java.util.ArrayList;
  20 +import java.util.Comparator;
17 import java.util.List; 21 import java.util.List;
18 22
19 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; 23 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
@@ -61,7 +65,7 @@ public class TradeRewardActivityPriceCalculator implements TradePriceCalculator @@ -61,7 +65,7 @@ public class TradeRewardActivityPriceCalculator implements TradePriceCalculator
61 if (rule == null) { 65 if (rule == null) {
62 TradePriceCalculatorHelper.addNotMatchPromotion(result, orderItems, 66 TradePriceCalculatorHelper.addNotMatchPromotion(result, orderItems,
63 rewardActivity.getId(), rewardActivity.getName(), PromotionTypeEnum.REWARD_ACTIVITY.getType(), 67 rewardActivity.getId(), rewardActivity.getName(), PromotionTypeEnum.REWARD_ACTIVITY.getType(),
64 - getRewardActivityNotMeetTip(rewardActivity)); 68 + getRewardActivityNotMeetTip(rewardActivity, orderItems));
65 return; 69 return;
66 } 70 }
67 71
@@ -84,6 +88,26 @@ public class TradeRewardActivityPriceCalculator implements TradePriceCalculator @@ -84,6 +88,26 @@ public class TradeRewardActivityPriceCalculator implements TradePriceCalculator
84 TradePriceCalculatorHelper.recountPayPrice(orderItem); 88 TradePriceCalculatorHelper.recountPayPrice(orderItem);
85 } 89 }
86 TradePriceCalculatorHelper.recountAllPrice(result); 90 TradePriceCalculatorHelper.recountAllPrice(result);
  91 +
  92 + // 4.1 记录赠送的积分
  93 + if (rule.getGivePoint()) {
  94 + List<Integer> dividePoints = TradePriceCalculatorHelper.dividePrice(orderItems, rule.getPoint());
  95 + for (int i = 0; i < orderItems.size(); i++) {
  96 + TradePriceCalculateRespBO.OrderItem orderItem = orderItems.get(i);
  97 + // 商品可能赠送了积分,所以这里要加上
  98 + orderItem.setGivePoint(orderItem.getGivePoint() + dividePoints.get(i));
  99 + }
  100 + }
  101 + // 4.2 记录订单是否包邮
  102 + if (rule.getFreeDelivery()) {
  103 + // 只要满足一个活动包邮那么这单就包邮
  104 + result.setFreeDelivery(true);
  105 + }
  106 + // 4.3 记录赠送的优惠券
  107 + if (rule.getGiveCoupon()) {
  108 + // TODO @puhui999: 需要考虑赠送的优惠券是否重叠,重叠则对数量进行累加
  109 + result.setCouponIds(rule.getCouponIds()).setCouponCounts(rule.getCouponCounts());
  110 + }
87 } 111 }
88 112
89 /** 113 /**
@@ -95,9 +119,21 @@ public class TradeRewardActivityPriceCalculator implements TradePriceCalculator @@ -95,9 +119,21 @@ public class TradeRewardActivityPriceCalculator implements TradePriceCalculator
95 */ 119 */
96 private List<TradePriceCalculateRespBO.OrderItem> filterMatchActivityOrderItems(TradePriceCalculateRespBO result, 120 private List<TradePriceCalculateRespBO.OrderItem> filterMatchActivityOrderItems(TradePriceCalculateRespBO result,
97 RewardActivityMatchRespDTO rewardActivity) { 121 RewardActivityMatchRespDTO rewardActivity) {
98 - // TODO @puhui999:是不是得根据类型过滤哈  
99 - return filterList(result.getItems(),  
100 - orderItem -> CollUtil.contains(rewardActivity.getProductScopeValues(), orderItem.getSpuId())); 122 + // 情况一:全部商品都可以参与
  123 + if (PromotionProductScopeEnum.isAll(rewardActivity.getProductScope())) {
  124 + return result.getItems();
  125 + }
  126 + // 情况二:指定商品参与
  127 + if (PromotionProductScopeEnum.isSpu(rewardActivity.getProductScope())) {
  128 + return filterList(result.getItems(),
  129 + orderItem -> CollUtil.contains(rewardActivity.getProductScopeValues(), orderItem.getSpuId()));
  130 + }
  131 + // 情况三:指定商品类型参与
  132 + if (PromotionProductScopeEnum.isCategory(rewardActivity.getProductScope())) {
  133 + return filterList(result.getItems(),
  134 + orderItem -> CollUtil.contains(rewardActivity.getProductScopeValues(), orderItem.getCategoryId()));
  135 + }
  136 + return List.of();
101 } 137 }
102 138
103 /** 139 /**
@@ -130,14 +166,30 @@ public class TradeRewardActivityPriceCalculator implements TradePriceCalculator @@ -130,14 +166,30 @@ public class TradeRewardActivityPriceCalculator implements TradePriceCalculator
130 } 166 }
131 167
132 /** 168 /**
133 - * 获得满减送活动部匹配时的提示 169 + * 获得满减送活动不匹配时的提示
134 * 170 *
135 * @param rewardActivity 满减送活动 171 * @param rewardActivity 满减送活动
136 * @return 提示 172 * @return 提示
137 */ 173 */
138 - private String getRewardActivityNotMeetTip(RewardActivityMatchRespDTO rewardActivity) {  
139 - // TODO 芋艿:后面再想想;应该找第一个规则,算下还差多少即可。  
140 - return "TODO"; 174 + private String getRewardActivityNotMeetTip(RewardActivityMatchRespDTO rewardActivity,
  175 + List<TradePriceCalculateRespBO.OrderItem> orderItems) {
  176 + // 1. 计算数量和价格
  177 + Integer count = TradePriceCalculatorHelper.calculateTotalCount(orderItems);
  178 + Integer price = TradePriceCalculatorHelper.calculateTotalPayPrice(orderItems);
  179 + assert count != null && price != null;
  180 +
  181 + // 2. 构建不满足时的提示信息-按最低档规则算
  182 + String meetTip = "满减送:购满 {} {},可以减 {} 元";
  183 + List<RewardActivityMatchRespDTO.Rule> rules = new ArrayList<>(rewardActivity.getRules());
  184 + rules.sort(Comparator.comparing(RewardActivityMatchRespDTO.Rule::getLimit)); // 按优惠门槛降序
  185 + RewardActivityMatchRespDTO.Rule rule = rules.get(0);
  186 + if (PromotionConditionTypeEnum.PRICE.getType().equals(rewardActivity.getConditionType())) {
  187 + return StrUtil.format(meetTip, rule.getLimit(), "元", MoneyUtils.fenToYuanStr(rule.getDiscountPrice()));
  188 + }
  189 + if (PromotionConditionTypeEnum.COUNT.getType().equals(rewardActivity.getConditionType())) {
  190 + return StrUtil.format(meetTip, rule.getLimit(), "件", MoneyUtils.fenToYuanStr(rule.getDiscountPrice()));
  191 + }
  192 + return StrUtil.EMPTY;
141 } 193 }
142 194
143 } 195 }