Commit ef807be89ce128d4920632d1de92f6ee5f40351a
1 parent
41d56350
🐞 fix(trade): 修复价格计算 3 处缺陷并补齐单测
1. 运费模板「包邮件数 / 包邮金额」判断方向反向,统一改为 >= 并对齐 DO / BO 注释 2. 砍价活动促销明细 id 错用 seckillActivityId,改为 bargainActivity.getActivityId() 3. TradePriceCalculatorHelper.buildCalculateResp 对 spu.giveIntegral 兜底 0,防止拆箱 NPE 4. 恢复 / 重写 Delivery、Coupon、Discount、PointUse、Reward、PriceService 单测,新增 BargainActivity 单测,共 30 用例
Showing
11 changed files
with
481 additions
and
292 deletions
yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/delivery/DeliveryExpressTemplateFreeDO.java
| @@ -43,14 +43,14 @@ public class DeliveryExpressTemplateFreeDO extends BaseDO { | @@ -43,14 +43,14 @@ public class DeliveryExpressTemplateFreeDO extends BaseDO { | ||
| 43 | /** | 43 | /** |
| 44 | * 包邮金额,单位:分 | 44 | * 包邮金额,单位:分 |
| 45 | * | 45 | * |
| 46 | - * 订单总金额 > 包邮金额时,才免运费 | 46 | + * 订单总金额 >= 包邮金额时,才免运费 |
| 47 | */ | 47 | */ |
| 48 | private Integer freePrice; | 48 | private Integer freePrice; |
| 49 | 49 | ||
| 50 | /** | 50 | /** |
| 51 | * 包邮件数 | 51 | * 包邮件数 |
| 52 | * | 52 | * |
| 53 | - * 订单总件数 > 包邮件数时,才免运费 | 53 | + * 订单总件数 >= 包邮件数时,才免运费 |
| 54 | */ | 54 | */ |
| 55 | private Integer freeCount; | 55 | private Integer freeCount; |
| 56 | 56 |
yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/bo/DeliveryExpressTemplateRespBO.java
| @@ -65,14 +65,14 @@ public class DeliveryExpressTemplateRespBO { | @@ -65,14 +65,14 @@ public class DeliveryExpressTemplateRespBO { | ||
| 65 | /** | 65 | /** |
| 66 | * 包邮金额,单位:分 | 66 | * 包邮金额,单位:分 |
| 67 | * | 67 | * |
| 68 | - * 订单总金额 > 包邮金额时,才免运费 | 68 | + * 订单总金额 >= 包邮金额时,才免运费 |
| 69 | */ | 69 | */ |
| 70 | private Integer freePrice; | 70 | private Integer freePrice; |
| 71 | 71 | ||
| 72 | /** | 72 | /** |
| 73 | * 包邮件数 | 73 | * 包邮件数 |
| 74 | * | 74 | * |
| 75 | - * 订单总件数 > 包邮件数时,才免运费 | 75 | + * 订单总件数 >= 包邮件数时,才免运费 |
| 76 | */ | 76 | */ |
| 77 | private Integer freeCount; | 77 | private Integer freeCount; |
| 78 | } | 78 | } |
yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeBargainActivityPriceCalculator.java
| @@ -14,7 +14,6 @@ import org.springframework.stereotype.Component; | @@ -14,7 +14,6 @@ import org.springframework.stereotype.Component; | ||
| 14 | 14 | ||
| 15 | import jakarta.annotation.Resource; | 15 | import jakarta.annotation.Resource; |
| 16 | 16 | ||
| 17 | -// TODO huihui:单测需要补充 | ||
| 18 | /** | 17 | /** |
| 19 | * 砍价活动的 {@link TradePriceCalculator} 实现类 | 18 | * 砍价活动的 {@link TradePriceCalculator} 实现类 |
| 20 | * | 19 | * |
| @@ -29,12 +28,12 @@ public class TradeBargainActivityPriceCalculator implements TradePriceCalculator | @@ -29,12 +28,12 @@ public class TradeBargainActivityPriceCalculator implements TradePriceCalculator | ||
| 29 | 28 | ||
| 30 | @Override | 29 | @Override |
| 31 | public void calculate(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result) { | 30 | public void calculate(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result) { |
| 32 | - // 1. 判断订单类型和是否具有拼团记录编号 | 31 | + // 1. 判断订单类型和是否具有砍价记录编号 |
| 33 | if (ObjectUtil.notEqual(result.getType(), TradeOrderTypeEnum.BARGAIN.getType())) { | 32 | if (ObjectUtil.notEqual(result.getType(), TradeOrderTypeEnum.BARGAIN.getType())) { |
| 34 | return; | 33 | return; |
| 35 | } | 34 | } |
| 36 | Assert.isTrue(param.getItems().size() == 1, "砍价时,只允许选择一个商品"); | 35 | Assert.isTrue(param.getItems().size() == 1, "砍价时,只允许选择一个商品"); |
| 37 | - Assert.isTrue(param.getItems().get(0).getCount() == 1, "砍价时,只允许选择一个商品"); | 36 | + Assert.isTrue(param.getItems().get(0).getCount() == 1, "砍价时,商品数量只允许为 1"); |
| 38 | // 2. 校验是否可以参与砍价 | 37 | // 2. 校验是否可以参与砍价 |
| 39 | TradePriceCalculateRespBO.OrderItem orderItem = result.getItems().get(0); | 38 | TradePriceCalculateRespBO.OrderItem orderItem = result.getItems().get(0); |
| 40 | BargainValidateJoinRespDTO bargainActivity = bargainRecordApi.validateJoinBargain( | 39 | BargainValidateJoinRespDTO bargainActivity = bargainRecordApi.validateJoinBargain( |
| @@ -44,7 +43,7 @@ public class TradeBargainActivityPriceCalculator implements TradePriceCalculator | @@ -44,7 +43,7 @@ public class TradeBargainActivityPriceCalculator implements TradePriceCalculator | ||
| 44 | Integer discountPrice = orderItem.getPayPrice() - bargainActivity.getBargainPrice() * orderItem.getCount(); | 43 | Integer discountPrice = orderItem.getPayPrice() - bargainActivity.getBargainPrice() * orderItem.getCount(); |
| 45 | // TODO 芋艿:极端情况,优惠金额为负数,需要处理 | 44 | // TODO 芋艿:极端情况,优惠金额为负数,需要处理 |
| 46 | TradePriceCalculatorHelper.addPromotion(result, orderItem, | 45 | TradePriceCalculatorHelper.addPromotion(result, orderItem, |
| 47 | - param.getSeckillActivityId(), bargainActivity.getName(), PromotionTypeEnum.BARGAIN_ACTIVITY.getType(), | 46 | + bargainActivity.getActivityId(), bargainActivity.getName(), PromotionTypeEnum.BARGAIN_ACTIVITY.getType(), |
| 48 | StrUtil.format("砍价活动:省 {} 元", TradePriceCalculatorHelper.formatPrice(discountPrice)), | 47 | StrUtil.format("砍价活动:省 {} 元", TradePriceCalculatorHelper.formatPrice(discountPrice)), |
| 49 | discountPrice); | 48 | discountPrice); |
| 50 | // 3.2 更新 SKU 优惠金额 | 49 | // 3.2 更新 SKU 优惠金额 |
yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeDeliveryPriceCalculator.java
| @@ -213,7 +213,7 @@ public class TradeDeliveryPriceCalculator implements TradePriceCalculator { | @@ -213,7 +213,7 @@ public class TradeDeliveryPriceCalculator implements TradePriceCalculator { | ||
| 213 | } | 213 | } |
| 214 | double totalChargeValue = getTotalChargeValue(orderItems, chargeMode); | 214 | double totalChargeValue = getTotalChargeValue(orderItems, chargeMode); |
| 215 | double totalPrice = TradePriceCalculatorHelper.calculateTotalPayPrice(orderItems); | 215 | double totalPrice = TradePriceCalculatorHelper.calculateTotalPayPrice(orderItems); |
| 216 | - return totalChargeValue <= templateFree.getFreeCount() && totalPrice >= templateFree.getFreePrice(); | 216 | + return totalChargeValue >= templateFree.getFreeCount() && totalPrice >= templateFree.getFreePrice(); |
| 217 | } | 217 | } |
| 218 | 218 | ||
| 219 | private double getTotalChargeValue(List<OrderItem> orderItems, Integer chargeMode) { | 219 | private double getTotalChargeValue(List<OrderItem> orderItems, Integer chargeMode) { |
yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradePriceCalculatorHelper.java
| 1 | package cn.iocoder.yudao.module.trade.service.price.calculator; | 1 | package cn.iocoder.yudao.module.trade.service.price.calculator; |
| 2 | 2 | ||
| 3 | import cn.hutool.core.lang.Assert; | 3 | import cn.hutool.core.lang.Assert; |
| 4 | +import cn.hutool.core.util.ObjectUtil; | ||
| 4 | import cn.hutool.core.util.StrUtil; | 5 | import cn.hutool.core.util.StrUtil; |
| 5 | import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | 6 | import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; |
| 6 | import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; | 7 | import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; |
| @@ -61,7 +62,7 @@ public class TradePriceCalculatorHelper { | @@ -61,7 +62,7 @@ public class TradePriceCalculatorHelper { | ||
| 61 | // spu 信息 | 62 | // spu 信息 |
| 62 | orderItem.setSpuName(spu.getName()).setCategoryId(spu.getCategoryId()) | 63 | orderItem.setSpuName(spu.getName()).setCategoryId(spu.getCategoryId()) |
| 63 | .setDeliveryTypes(spu.getDeliveryTypes()).setDeliveryTemplateId(spu.getDeliveryTemplateId()) | 64 | .setDeliveryTypes(spu.getDeliveryTypes()).setDeliveryTemplateId(spu.getDeliveryTemplateId()) |
| 64 | - .setGivePoint(spu.getGiveIntegral()).setUsePoint(0); | 65 | + .setGivePoint(ObjectUtil.defaultIfNull(spu.getGiveIntegral(), 0)).setUsePoint(0); |
| 65 | if (StrUtil.isBlank(orderItem.getPicUrl())) { | 66 | if (StrUtil.isBlank(orderItem.getPicUrl())) { |
| 66 | orderItem.setPicUrl(spu.getPicUrl()); | 67 | orderItem.setPicUrl(spu.getPicUrl()); |
| 67 | } | 68 | } |
yudao-module-mall/yudao-module-trade/src/test/java/cn/iocoder/yudao/module/trade/service/price/TradePriceServiceImplTest.java
| @@ -6,12 +6,10 @@ import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; | @@ -6,12 +6,10 @@ import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; | ||
| 6 | import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; | 6 | import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; |
| 7 | import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi; | 7 | import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi; |
| 8 | import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; | 8 | import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; |
| 9 | -import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum; | ||
| 10 | import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; | 9 | import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; |
| 11 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; | 10 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; |
| 12 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; | 11 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; |
| 13 | import cn.iocoder.yudao.module.trade.service.price.calculator.TradePriceCalculator; | 12 | import cn.iocoder.yudao.module.trade.service.price.calculator.TradePriceCalculator; |
| 14 | -import org.junit.jupiter.api.Disabled; | ||
| 15 | import org.junit.jupiter.api.Test; | 13 | import org.junit.jupiter.api.Test; |
| 16 | import org.mockito.InjectMocks; | 14 | import org.mockito.InjectMocks; |
| 17 | import org.mockito.Mock; | 15 | import org.mockito.Mock; |
| @@ -30,7 +28,6 @@ import static org.mockito.Mockito.when; | @@ -30,7 +28,6 @@ import static org.mockito.Mockito.when; | ||
| 30 | * | 28 | * |
| 31 | * @author 芋道源码 | 29 | * @author 芋道源码 |
| 32 | */ | 30 | */ |
| 33 | -@Disabled // TODO 芋艿:后续 fix 补充的单测 | ||
| 34 | public class TradePriceServiceImplTest extends BaseMockitoUnitTest { | 31 | public class TradePriceServiceImplTest extends BaseMockitoUnitTest { |
| 35 | 32 | ||
| 36 | @InjectMocks | 33 | @InjectMocks |
| @@ -67,9 +64,8 @@ public class TradePriceServiceImplTest extends BaseMockitoUnitTest { | @@ -67,9 +64,8 @@ public class TradePriceServiceImplTest extends BaseMockitoUnitTest { | ||
| 67 | .setValueId(4L).setValueName("黑色"))) | 64 | .setValueId(4L).setValueName("黑色"))) |
| 68 | ); | 65 | ); |
| 69 | when(productSkuApi.getSkuList(Mockito.eq(asSet(100L, 200L, 300L)))).thenReturn(skuList); | 66 | when(productSkuApi.getSkuList(Mockito.eq(asSet(100L, 200L, 300L)))).thenReturn(skuList); |
| 70 | - when(productSpuApi.getSpuList(Mockito.eq(asSet(1001L)))) | ||
| 71 | - .thenReturn(singletonList(new ProductSpuRespDTO().setId(1001L).setName("小菜").setCategoryId(666L) | ||
| 72 | - .setStatus(ProductSpuStatusEnum.ENABLE.getStatus()))); | 67 | + when(productSpuApi.validateSpuList(Mockito.eq(asSet(1001L)))) |
| 68 | + .thenReturn(singletonList(new ProductSpuRespDTO().setId(1001L).setName("小菜").setCategoryId(666L))); | ||
| 73 | 69 | ||
| 74 | // 调用 | 70 | // 调用 |
| 75 | TradePriceCalculateRespBO calculateRespBO = tradePriceService.calculateOrderPrice(calculateReqBO); | 71 | TradePriceCalculateRespBO calculateRespBO = tradePriceService.calculateOrderPrice(calculateReqBO); |
yudao-module-mall/yudao-module-trade/src/test/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeCouponPriceCalculatorTest.java
| @@ -11,7 +11,6 @@ import cn.iocoder.yudao.module.promotion.enums.coupon.CouponStatusEnum; | @@ -11,7 +11,6 @@ import cn.iocoder.yudao.module.promotion.enums.coupon.CouponStatusEnum; | ||
| 11 | import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; | 11 | import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; |
| 12 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; | 12 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; |
| 13 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; | 13 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; |
| 14 | -import org.junit.jupiter.api.Disabled; | ||
| 15 | import org.junit.jupiter.api.Test; | 14 | import org.junit.jupiter.api.Test; |
| 16 | import org.mockito.InjectMocks; | 15 | import org.mockito.InjectMocks; |
| 17 | import org.mockito.Mock; | 16 | import org.mockito.Mock; |
| @@ -32,7 +31,6 @@ import static org.mockito.Mockito.when; | @@ -32,7 +31,6 @@ import static org.mockito.Mockito.when; | ||
| 32 | * | 31 | * |
| 33 | * @author 芋道源码 | 32 | * @author 芋道源码 |
| 34 | */ | 33 | */ |
| 35 | -@Disabled // TODO 芋艿:后续修复 | ||
| 36 | public class TradeCouponPriceCalculatorTest extends BaseMockitoUnitTest { | 34 | public class TradeCouponPriceCalculatorTest extends BaseMockitoUnitTest { |
| 37 | 35 | ||
| 38 | @InjectMocks | 36 | @InjectMocks |
| @@ -75,7 +73,7 @@ public class TradeCouponPriceCalculatorTest extends BaseMockitoUnitTest { | @@ -75,7 +73,7 @@ public class TradeCouponPriceCalculatorTest extends BaseMockitoUnitTest { | ||
| 75 | .setProductScope(PromotionProductScopeEnum.SPU.getScope()).setProductScopeValues(asList(1L, 2L)) | 73 | .setProductScope(PromotionProductScopeEnum.SPU.getScope()).setProductScopeValues(asList(1L, 2L)) |
| 76 | .setUsePrice(350).setDiscountType(PromotionDiscountTypeEnum.PERCENT.getType()) | 74 | .setUsePrice(350).setDiscountType(PromotionDiscountTypeEnum.PERCENT.getType()) |
| 77 | .setDiscountPercent(50).setDiscountLimitPrice(70)) | 75 | .setDiscountPercent(50).setDiscountLimitPrice(70)) |
| 78 | - .setValidStartTime(addTime(Duration.ofDays(1))).setValidEndTime(addTime(Duration.ofDays(2))); | 76 | + .setValidStartTime(addTime(Duration.ofDays(-1))).setValidEndTime(addTime(Duration.ofDays(1))); |
| 79 | when(couponApi.getCouponListByUserId(eq(233L), eq(CouponStatusEnum.UNUSED.getStatus()))) | 77 | when(couponApi.getCouponListByUserId(eq(233L), eq(CouponStatusEnum.UNUSED.getStatus()))) |
| 80 | .thenReturn(ListUtil.toList(coupon)); | 78 | .thenReturn(ListUtil.toList(coupon)); |
| 81 | 79 |
yudao-module-mall/yudao-module-trade/src/test/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeDeliveryPriceCalculatorTest.java
| 1 | package cn.iocoder.yudao.module.trade.service.price.calculator; | 1 | package cn.iocoder.yudao.module.trade.service.price.calculator; |
| 2 | 2 | ||
| 3 | import cn.hutool.core.map.MapUtil; | 3 | import cn.hutool.core.map.MapUtil; |
| 4 | +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | ||
| 4 | import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; | 5 | import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; |
| 5 | import cn.iocoder.yudao.module.member.api.address.MemberAddressApi; | 6 | import cn.iocoder.yudao.module.member.api.address.MemberAddressApi; |
| 6 | import cn.iocoder.yudao.module.member.api.address.dto.MemberAddressRespDTO; | 7 | import cn.iocoder.yudao.module.member.api.address.dto.MemberAddressRespDTO; |
| 7 | import cn.iocoder.yudao.module.trade.dal.dataobject.config.TradeConfigDO; | 8 | import cn.iocoder.yudao.module.trade.dal.dataobject.config.TradeConfigDO; |
| 9 | +import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryPickUpStoreDO; | ||
| 8 | import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryExpressChargeModeEnum; | 10 | import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryExpressChargeModeEnum; |
| 9 | import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum; | 11 | import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum; |
| 10 | import cn.iocoder.yudao.module.trade.service.config.TradeConfigService; | 12 | import cn.iocoder.yudao.module.trade.service.config.TradeConfigService; |
| 11 | import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressTemplateService; | 13 | import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressTemplateService; |
| 14 | +import cn.iocoder.yudao.module.trade.service.delivery.DeliveryPickUpStoreService; | ||
| 12 | import cn.iocoder.yudao.module.trade.service.delivery.bo.DeliveryExpressTemplateRespBO; | 15 | import cn.iocoder.yudao.module.trade.service.delivery.bo.DeliveryExpressTemplateRespBO; |
| 13 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; | 16 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; |
| 14 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; | 17 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; |
| 15 | import org.junit.jupiter.api.BeforeEach; | 18 | import org.junit.jupiter.api.BeforeEach; |
| 16 | -import org.junit.jupiter.api.Disabled; | ||
| 17 | import org.junit.jupiter.api.DisplayName; | 19 | import org.junit.jupiter.api.DisplayName; |
| 18 | import org.junit.jupiter.api.Test; | 20 | import org.junit.jupiter.api.Test; |
| 19 | import org.mockito.InjectMocks; | 21 | import org.mockito.InjectMocks; |
| 20 | import org.mockito.Mock; | 22 | import org.mockito.Mock; |
| 21 | 23 | ||
| 22 | import java.util.ArrayList; | 24 | import java.util.ArrayList; |
| 25 | +import java.util.Collections; | ||
| 23 | 26 | ||
| 24 | import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet; | 27 | import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet; |
| 28 | +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; | ||
| 25 | import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; | 29 | import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; |
| 30 | +import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.PICK_UP_STORE_NOT_EXISTS; | ||
| 31 | +import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.PRICE_CALCULATE_DELIVERY_PRICE_TEMPLATE_NOT_FOUND; | ||
| 32 | +import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.PRICE_CALCULATE_DELIVERY_PRICE_TYPE_ILLEGAL; | ||
| 26 | import static java.util.Arrays.asList; | 33 | import static java.util.Arrays.asList; |
| 34 | +import static java.util.Collections.singletonList; | ||
| 27 | import static org.assertj.core.api.Assertions.assertThat; | 35 | import static org.assertj.core.api.Assertions.assertThat; |
| 28 | import static org.mockito.ArgumentMatchers.eq; | 36 | import static org.mockito.ArgumentMatchers.eq; |
| 29 | import static org.mockito.Mockito.when; | 37 | import static org.mockito.Mockito.when; |
| @@ -33,15 +41,15 @@ import static org.mockito.Mockito.when; | @@ -33,15 +41,15 @@ import static org.mockito.Mockito.when; | ||
| 33 | * | 41 | * |
| 34 | * @author jason | 42 | * @author jason |
| 35 | */ | 43 | */ |
| 36 | -@Disabled // TODO 芋艿:后续修复 | ||
| 37 | -public class TradeDeliveryPriceCalculatorTest extends BaseMockitoUnitTest { | 44 | +public class TradeDeliveryPriceCalculatorTest extends BaseMockitoUnitTest { |
| 38 | 45 | ||
| 39 | @InjectMocks | 46 | @InjectMocks |
| 40 | private TradeDeliveryPriceCalculator calculator; | 47 | private TradeDeliveryPriceCalculator calculator; |
| 41 | 48 | ||
| 42 | @Mock | 49 | @Mock |
| 43 | private MemberAddressApi addressApi; | 50 | private MemberAddressApi addressApi; |
| 44 | - | 51 | + @Mock |
| 52 | + private DeliveryPickUpStoreService deliveryPickUpStoreService; | ||
| 45 | @Mock | 53 | @Mock |
| 46 | private DeliveryExpressTemplateService deliveryExpressTemplateService; | 54 | private DeliveryExpressTemplateService deliveryExpressTemplateService; |
| 47 | @Mock | 55 | @Mock |
| @@ -55,7 +63,7 @@ public class TradeDeliveryPriceCalculatorTest extends BaseMockitoUnitTest { | @@ -55,7 +63,7 @@ public class TradeDeliveryPriceCalculatorTest extends BaseMockitoUnitTest { | ||
| 55 | private DeliveryExpressTemplateRespBO.Free freeBO; | 63 | private DeliveryExpressTemplateRespBO.Free freeBO; |
| 56 | 64 | ||
| 57 | @BeforeEach | 65 | @BeforeEach |
| 58 | - public void init(){ | 66 | + public void init() { |
| 59 | // 准备参数 | 67 | // 准备参数 |
| 60 | reqBO = new TradePriceCalculateReqBO() | 68 | reqBO = new TradePriceCalculateReqBO() |
| 61 | .setDeliveryType(DeliveryTypeEnum.EXPRESS.getType()) | 69 | .setDeliveryType(DeliveryTypeEnum.EXPRESS.getType()) |
| @@ -71,24 +79,23 @@ public class TradeDeliveryPriceCalculatorTest extends BaseMockitoUnitTest { | @@ -71,24 +79,23 @@ public class TradeDeliveryPriceCalculatorTest extends BaseMockitoUnitTest { | ||
| 71 | .setPromotions(new ArrayList<>()) | 79 | .setPromotions(new ArrayList<>()) |
| 72 | .setItems(asList( | 80 | .setItems(asList( |
| 73 | new TradePriceCalculateRespBO.OrderItem().setDeliveryTemplateId(1L).setSkuId(10L).setCount(2).setSelected(true) | 81 | new TradePriceCalculateRespBO.OrderItem().setDeliveryTemplateId(1L).setSkuId(10L).setCount(2).setSelected(true) |
| 74 | - .setWeight(10d).setVolume(10d).setPrice(100), | 82 | + .setWeight(10d).setVolume(10d).setPrice(100) |
| 83 | + .setDeliveryTypes(asList(DeliveryTypeEnum.EXPRESS.getType(), DeliveryTypeEnum.PICK_UP.getType())), | ||
| 75 | new TradePriceCalculateRespBO.OrderItem().setDeliveryTemplateId(1L).setSkuId(20L).setCount(10).setSelected(true) | 84 | new TradePriceCalculateRespBO.OrderItem().setDeliveryTemplateId(1L).setSkuId(20L).setCount(10).setSelected(true) |
| 76 | - .setWeight(10d).setVolume(10d).setPrice(200), | 85 | + .setWeight(10d).setVolume(10d).setPrice(200) |
| 86 | + .setDeliveryTypes(asList(DeliveryTypeEnum.EXPRESS.getType(), DeliveryTypeEnum.PICK_UP.getType())), | ||
| 77 | new TradePriceCalculateRespBO.OrderItem().setDeliveryTemplateId(1L).setSkuId(30L).setCount(1).setSelected(false) | 87 | new TradePriceCalculateRespBO.OrderItem().setDeliveryTemplateId(1L).setSkuId(30L).setCount(1).setSelected(false) |
| 78 | .setWeight(10d).setVolume(10d).setPrice(300) | 88 | .setWeight(10d).setVolume(10d).setPrice(300) |
| 89 | + .setDeliveryTypes(asList(DeliveryTypeEnum.EXPRESS.getType(), DeliveryTypeEnum.PICK_UP.getType())) | ||
| 79 | )); | 90 | )); |
| 80 | // 保证价格被初始化上 | 91 | // 保证价格被初始化上 |
| 81 | TradePriceCalculatorHelper.recountPayPrice(resultBO.getItems()); | 92 | TradePriceCalculatorHelper.recountPayPrice(resultBO.getItems()); |
| 82 | TradePriceCalculatorHelper.recountAllPrice(resultBO); | 93 | TradePriceCalculatorHelper.recountAllPrice(resultBO); |
| 83 | 94 | ||
| 84 | - // 准备收件地址数据 | ||
| 85 | - MemberAddressRespDTO addressResp = randomPojo(MemberAddressRespDTO.class, item -> item.setAreaId(10)); | ||
| 86 | - when(addressApi.getAddress(eq(10L), eq(1L))).thenReturn(addressResp); | ||
| 87 | - | ||
| 88 | - // 准备运费模板费用配置数据 | 95 | + // 准备运费模板费用配置数据:起步 10 件 1000 分,续 10 件 2000 分 |
| 89 | chargeBO = randomPojo(DeliveryExpressTemplateRespBO.Charge.class, | 96 | chargeBO = randomPojo(DeliveryExpressTemplateRespBO.Charge.class, |
| 90 | item -> item.setStartCount(10D).setStartPrice(1000).setExtraCount(10D).setExtraPrice(2000)); | 97 | item -> item.setStartCount(10D).setStartPrice(1000).setExtraCount(10D).setExtraPrice(2000)); |
| 91 | - // 准备运费模板包邮配置数据:订单总件数 < 包邮件数时 12 < 20 | 98 | + // 准备运费模板包邮配置数据:默认不包邮(订单总件数 12 不大于 包邮件数 20) |
| 92 | freeBO = randomPojo(DeliveryExpressTemplateRespBO.Free.class, | 99 | freeBO = randomPojo(DeliveryExpressTemplateRespBO.Free.class, |
| 93 | item -> item.setFreeCount(20).setFreePrice(100)); | 100 | item -> item.setFreeCount(20).setFreePrice(100)); |
| 94 | // 准备 SP 运费模板数据 | 101 | // 准备 SP 运费模板数据 |
| @@ -97,99 +104,320 @@ public class TradeDeliveryPriceCalculatorTest extends BaseMockitoUnitTest { | @@ -97,99 +104,320 @@ public class TradeDeliveryPriceCalculatorTest extends BaseMockitoUnitTest { | ||
| 97 | .setCharge(chargeBO).setFree(freeBO)); | 104 | .setCharge(chargeBO).setFree(freeBO)); |
| 98 | } | 105 | } |
| 99 | 106 | ||
| 107 | + // ========== 配送方式校验 ========== | ||
| 108 | + | ||
| 100 | @Test | 109 | @Test |
| 101 | - @DisplayName("全场包邮") | ||
| 102 | - public void testCalculate_expressGlobalFree() { | ||
| 103 | - // mock 方法(全场包邮) | ||
| 104 | - when(tradeConfigService.getTradeConfig()).thenReturn(new TradeConfigDO().setDeliveryExpressFreeEnabled(true) | ||
| 105 | - .setDeliveryExpressFreePrice(2200)); | 110 | + @DisplayName("配送方式为空:直接返回,不计算运费") |
| 111 | + public void testCalculate_deliveryTypeNull() { | ||
| 112 | + // 准备参数 | ||
| 113 | + reqBO.setDeliveryType(null); | ||
| 106 | 114 | ||
| 107 | // 调用 | 115 | // 调用 |
| 108 | calculator.calculate(reqBO, resultBO); | 116 | calculator.calculate(reqBO, resultBO); |
| 117 | + | ||
| 118 | + // 断言:未计算运费 | ||
| 119 | + assertThat(resultBO.getPrice().getDeliveryPrice()).isEqualTo(0); | ||
| 120 | + } | ||
| 121 | + | ||
| 122 | + @Test | ||
| 123 | + @DisplayName("配送方式与商品不匹配:抛出异常") | ||
| 124 | + public void testCalculate_deliveryTypeMismatch() { | ||
| 125 | + // 准备参数:商品 deliveryTypes 不包含 EXPRESS | ||
| 126 | + resultBO.getItems().forEach(item -> item.setDeliveryTypes(singletonList(DeliveryTypeEnum.PICK_UP.getType()))); | ||
| 127 | + | ||
| 128 | + // 调用并断言异常 | ||
| 129 | + assertServiceException(() -> calculator.calculate(reqBO, resultBO), | ||
| 130 | + PRICE_CALCULATE_DELIVERY_PRICE_TYPE_ILLEGAL); | ||
| 131 | + } | ||
| 132 | + | ||
| 133 | + // ========== 自提模式 ========== | ||
| 134 | + | ||
| 135 | + @Test | ||
| 136 | + @DisplayName("自提:未选择门店时直接返回") | ||
| 137 | + public void testCalculate_pickUp_storeIdNull() { | ||
| 138 | + // 准备参数 | ||
| 139 | + reqBO.setDeliveryType(DeliveryTypeEnum.PICK_UP.getType()).setPickUpStoreId(null); | ||
| 140 | + | ||
| 141 | + // 调用 | ||
| 142 | + calculator.calculate(reqBO, resultBO); | ||
| 143 | + | ||
| 144 | + // 断言:未计算运费 | ||
| 145 | + assertThat(resultBO.getPrice().getDeliveryPrice()).isEqualTo(0); | ||
| 146 | + } | ||
| 147 | + | ||
| 148 | + @Test | ||
| 149 | + @DisplayName("自提:门店不存在时抛出异常") | ||
| 150 | + public void testCalculate_pickUp_storeNotFound() { | ||
| 151 | + // 准备参数 | ||
| 152 | + reqBO.setDeliveryType(DeliveryTypeEnum.PICK_UP.getType()).setPickUpStoreId(99L); | ||
| 153 | + // mock:门店不存在 | ||
| 154 | + when(deliveryPickUpStoreService.getDeliveryPickUpStore(eq(99L))).thenReturn(null); | ||
| 155 | + | ||
| 156 | + // 调用并断言异常 | ||
| 157 | + assertServiceException(() -> calculator.calculate(reqBO, resultBO), | ||
| 158 | + PICK_UP_STORE_NOT_EXISTS); | ||
| 159 | + } | ||
| 160 | + | ||
| 161 | + @Test | ||
| 162 | + @DisplayName("自提:门店被禁用时抛出异常") | ||
| 163 | + public void testCalculate_pickUp_storeDisabled() { | ||
| 164 | + // 准备参数 | ||
| 165 | + reqBO.setDeliveryType(DeliveryTypeEnum.PICK_UP.getType()).setPickUpStoreId(99L); | ||
| 166 | + // mock:门店被禁用 | ||
| 167 | + when(deliveryPickUpStoreService.getDeliveryPickUpStore(eq(99L))).thenReturn( | ||
| 168 | + new DeliveryPickUpStoreDO().setStatus(CommonStatusEnum.DISABLE.getStatus())); | ||
| 169 | + | ||
| 170 | + // 调用并断言异常 | ||
| 171 | + assertServiceException(() -> calculator.calculate(reqBO, resultBO), | ||
| 172 | + PICK_UP_STORE_NOT_EXISTS); | ||
| 173 | + } | ||
| 174 | + | ||
| 175 | + @Test | ||
| 176 | + @DisplayName("自提:门店正常时不计算运费") | ||
| 177 | + public void testCalculate_pickUp_ok() { | ||
| 178 | + // 准备参数 | ||
| 179 | + reqBO.setDeliveryType(DeliveryTypeEnum.PICK_UP.getType()).setPickUpStoreId(99L); | ||
| 180 | + // mock:门店正常 | ||
| 181 | + when(deliveryPickUpStoreService.getDeliveryPickUpStore(eq(99L))).thenReturn( | ||
| 182 | + new DeliveryPickUpStoreDO().setStatus(CommonStatusEnum.ENABLE.getStatus())); | ||
| 183 | + | ||
| 184 | + // 调用 | ||
| 185 | + calculator.calculate(reqBO, resultBO); | ||
| 186 | + | ||
| 187 | + // 断言:未计算运费 | ||
| 188 | + assertThat(resultBO.getPrice().getDeliveryPrice()).isEqualTo(0); | ||
| 189 | + } | ||
| 190 | + | ||
| 191 | + // ========== 快递模式 ========== | ||
| 192 | + | ||
| 193 | + @Test | ||
| 194 | + @DisplayName("快递:收件地址为空时直接返回") | ||
| 195 | + public void testCalculate_express_addressIdNull() { | ||
| 196 | + // 准备参数 | ||
| 197 | + reqBO.setAddressId(null); | ||
| 198 | + | ||
| 199 | + // 调用 | ||
| 200 | + calculator.calculate(reqBO, resultBO); | ||
| 201 | + | ||
| 202 | + // 断言:未计算运费 | ||
| 203 | + assertThat(resultBO.getPrice().getDeliveryPrice()).isEqualTo(0); | ||
| 204 | + } | ||
| 205 | + | ||
| 206 | + @Test | ||
| 207 | + @DisplayName("快递:全场包邮(开关开启 && 总金额满足全场包邮金额)") | ||
| 208 | + public void testCalculate_globalFree() { | ||
| 209 | + // mock:收件地址 + 全场包邮配置 | ||
| 210 | + mockAddress(); | ||
| 211 | + when(tradeConfigService.getTradeConfig()).thenReturn(new TradeConfigDO() | ||
| 212 | + .setDeliveryExpressFreeEnabled(true).setDeliveryExpressFreePrice(2200)); | ||
| 213 | + | ||
| 214 | + // 调用 | ||
| 215 | + calculator.calculate(reqBO, resultBO); | ||
| 216 | + | ||
| 217 | + // 断言 | ||
| 109 | TradePriceCalculateRespBO.Price price = resultBO.getPrice(); | 218 | TradePriceCalculateRespBO.Price price = resultBO.getPrice(); |
| 110 | assertThat(price) | 219 | assertThat(price) |
| 111 | - .extracting("totalPrice","discountPrice","couponPrice","pointPrice","deliveryPrice","payPrice") | ||
| 112 | - .containsExactly(2200, 0, 0, 0, 0, 2200); | 220 | + .extracting("totalPrice", "discountPrice", "couponPrice", "pointPrice", "deliveryPrice", "payPrice") |
| 221 | + .containsExactly(2200, 0, 0, 0, 0, 2200); | ||
| 113 | assertThat(resultBO.getItems()).hasSize(3); | 222 | assertThat(resultBO.getItems()).hasSize(3); |
| 114 | - // 断言:SKU1 | ||
| 115 | assertThat(resultBO.getItems().get(0)) | 223 | assertThat(resultBO.getItems().get(0)) |
| 116 | - .extracting("price", "count","discountPrice" ,"couponPrice", "pointPrice","deliveryPrice","payPrice") | 224 | + .extracting("price", "count", "discountPrice", "couponPrice", "pointPrice", "deliveryPrice", "payPrice") |
| 117 | .containsExactly(100, 2, 0, 0, 0, 0, 200); | 225 | .containsExactly(100, 2, 0, 0, 0, 0, 200); |
| 118 | - // 断言:SKU2 | ||
| 119 | assertThat(resultBO.getItems().get(1)) | 226 | assertThat(resultBO.getItems().get(1)) |
| 120 | - .extracting("price", "count","discountPrice" ,"couponPrice", "pointPrice","deliveryPrice","payPrice") | 227 | + .extracting("price", "count", "discountPrice", "couponPrice", "pointPrice", "deliveryPrice", "payPrice") |
| 121 | .containsExactly(200, 10, 0, 0, 0, 0, 2000); | 228 | .containsExactly(200, 10, 0, 0, 0, 0, 2000); |
| 122 | - // 断言:SKU3 未选中 | ||
| 123 | assertThat(resultBO.getItems().get(2)) | 229 | assertThat(resultBO.getItems().get(2)) |
| 124 | - .extracting("price", "count","discountPrice" ,"couponPrice", "pointPrice","deliveryPrice","payPrice") | 230 | + .extracting("price", "count", "discountPrice", "couponPrice", "pointPrice", "deliveryPrice", "payPrice") |
| 125 | .containsExactly(300, 1, 0, 0, 0, 0, 300); | 231 | .containsExactly(300, 1, 0, 0, 0, 0, 300); |
| 126 | } | 232 | } |
| 127 | 233 | ||
| 128 | @Test | 234 | @Test |
| 129 | - @DisplayName("按件计算运费不包邮的情况") | ||
| 130 | - public void testCalculate_expressTemplateCharge() { | ||
| 131 | - // SKU 1 : 100 * 2 = 200 | ||
| 132 | - // SKU 2 :200 * 10 = 2000 | ||
| 133 | - // 运费 首件 1000 + 续件 2000 = 3000 | ||
| 134 | - // mock 方法 | 235 | + @DisplayName("快递:活动包邮(freeDelivery=true)时不计算运费") |
| 236 | + public void testCalculate_activityFree() { | ||
| 237 | + // 准备参数 | ||
| 238 | + resultBO.setFreeDelivery(true); | ||
| 239 | + // mock:收件地址 | ||
| 240 | + mockAddress(); | ||
| 241 | + | ||
| 242 | + // 调用 | ||
| 243 | + calculator.calculate(reqBO, resultBO); | ||
| 244 | + | ||
| 245 | + // 断言:未计算运费 | ||
| 246 | + assertThat(resultBO.getPrice().getDeliveryPrice()).isEqualTo(0); | ||
| 247 | + } | ||
| 248 | + | ||
| 249 | + @Test | ||
| 250 | + @DisplayName("快递:找不到运费模板时抛出异常") | ||
| 251 | + public void testCalculate_express_templateNotFound() { | ||
| 252 | + // mock:收件地址 + 空模板 | ||
| 253 | + mockAddress(); | ||
| 135 | when(deliveryExpressTemplateService.getExpressTemplateMapByIdsAndArea(eq(asSet(1L)), eq(10))) | 254 | when(deliveryExpressTemplateService.getExpressTemplateMapByIdsAndArea(eq(asSet(1L)), eq(10))) |
| 136 | - .thenReturn(MapUtil.of(1L, templateRespBO)); | 255 | + .thenReturn(Collections.emptyMap()); |
| 256 | + | ||
| 257 | + // 调用并断言异常 | ||
| 258 | + assertServiceException(() -> calculator.calculate(reqBO, resultBO), | ||
| 259 | + PRICE_CALCULATE_DELIVERY_PRICE_TEMPLATE_NOT_FOUND); | ||
| 260 | + } | ||
| 261 | + | ||
| 262 | + @Test | ||
| 263 | + @DisplayName("按件计算运费:不包邮的情况") | ||
| 264 | + public void testCalculate_expressTemplateCharge() { | ||
| 265 | + // SKU 1:100 * 2 = 200 | ||
| 266 | + // SKU 2:200 * 10 = 2000 | ||
| 267 | + // 运费:首件 1000 + 续件 ceil((12-10)/10)=1 倍 * 2000 = 3000 | ||
| 268 | + // mock 方法:默认 freeCount=20,订单 12 件 不大于 20,不包邮 | ||
| 269 | + mockAddress(); | ||
| 270 | + mockTemplate(templateRespBO); | ||
| 137 | 271 | ||
| 138 | // 调用 | 272 | // 调用 |
| 139 | calculator.calculate(reqBO, resultBO); | 273 | calculator.calculate(reqBO, resultBO); |
| 274 | + | ||
| 140 | // 断言 | 275 | // 断言 |
| 141 | TradePriceCalculateRespBO.Price price = resultBO.getPrice(); | 276 | TradePriceCalculateRespBO.Price price = resultBO.getPrice(); |
| 142 | assertThat(price) | 277 | assertThat(price) |
| 143 | - .extracting("totalPrice","discountPrice","couponPrice","pointPrice","deliveryPrice","payPrice") | ||
| 144 | - .containsExactly(2200, 0, 0, 0, 3000, 5200); | 278 | + .extracting("totalPrice", "discountPrice", "couponPrice", "pointPrice", "deliveryPrice", "payPrice") |
| 279 | + .containsExactly(2200, 0, 0, 0, 3000, 5200); | ||
| 145 | assertThat(resultBO.getItems()).hasSize(3); | 280 | assertThat(resultBO.getItems()).hasSize(3); |
| 146 | - // 断言:SKU1 | 281 | + // 断言:SKU1 分摊运费 (int)(3000 * 2/12) = 500 |
| 147 | assertThat(resultBO.getItems().get(0)) | 282 | assertThat(resultBO.getItems().get(0)) |
| 148 | - .extracting("price", "count","discountPrice" ,"couponPrice", "pointPrice","deliveryPrice","payPrice") | 283 | + .extracting("price", "count", "discountPrice", "couponPrice", "pointPrice", "deliveryPrice", "payPrice") |
| 149 | .containsExactly(100, 2, 0, 0, 0, 500, 700); | 284 | .containsExactly(100, 2, 0, 0, 0, 500, 700); |
| 150 | - // 断言:SKU2 | 285 | + // 断言:SKU2 分摊运费 3000 - 500 = 2500 |
| 151 | assertThat(resultBO.getItems().get(1)) | 286 | assertThat(resultBO.getItems().get(1)) |
| 152 | - .extracting("price", "count","discountPrice" ,"couponPrice", "pointPrice","deliveryPrice","payPrice") | 287 | + .extracting("price", "count", "discountPrice", "couponPrice", "pointPrice", "deliveryPrice", "payPrice") |
| 153 | .containsExactly(200, 10, 0, 0, 0, 2500, 4500); | 288 | .containsExactly(200, 10, 0, 0, 0, 2500, 4500); |
| 154 | - // 断言:SKU3 未选中 | 289 | + // 断言:SKU3 未选中,不计运费 |
| 155 | assertThat(resultBO.getItems().get(2)) | 290 | assertThat(resultBO.getItems().get(2)) |
| 156 | - .extracting("price", "count","discountPrice" ,"couponPrice", "pointPrice","deliveryPrice","payPrice") | 291 | + .extracting("price", "count", "discountPrice", "couponPrice", "pointPrice", "deliveryPrice", "payPrice") |
| 157 | .containsExactly(300, 1, 0, 0, 0, 0, 300); | 292 | .containsExactly(300, 1, 0, 0, 0, 0, 300); |
| 158 | } | 293 | } |
| 159 | 294 | ||
| 160 | @Test | 295 | @Test |
| 161 | - @DisplayName("按件计算运费包邮的情况") | 296 | + @DisplayName("按件计算运费:包邮(订单总件数 >= 包邮件数 && 总金额 >= 包邮金额)") |
| 162 | public void testCalculate_expressTemplateFree() { | 297 | public void testCalculate_expressTemplateFree() { |
| 163 | - // SKU 1 : 100 * 2 = 200 | ||
| 164 | - // SKU 2 :200 * 10 = 2000 | ||
| 165 | - // 运费 0 | ||
| 166 | - // mock 方法 | ||
| 167 | - // 准备运费模板包邮配置数据 包邮 订单总件数 > 包邮件数时 12 > 10 | 298 | + // SKU 1:100 * 2 = 200 |
| 299 | + // SKU 2:200 * 10 = 2000 | ||
| 300 | + // 总件数 12 >= 包邮件数 10 && 总金额 2200 >= 包邮金额 1000,包邮 | ||
| 168 | templateRespBO.setFree(randomPojo(DeliveryExpressTemplateRespBO.Free.class, | 301 | templateRespBO.setFree(randomPojo(DeliveryExpressTemplateRespBO.Free.class, |
| 169 | item -> item.setFreeCount(10).setFreePrice(1000))); | 302 | item -> item.setFreeCount(10).setFreePrice(1000))); |
| 170 | - when(deliveryExpressTemplateService.getExpressTemplateMapByIdsAndArea(eq(asSet(1L)), eq(10))) | ||
| 171 | - .thenReturn(MapUtil.of(1L, templateRespBO)); | 303 | + mockAddress(); |
| 304 | + mockTemplate(templateRespBO); | ||
| 172 | 305 | ||
| 173 | // 调用 | 306 | // 调用 |
| 174 | calculator.calculate(reqBO, resultBO); | 307 | calculator.calculate(reqBO, resultBO); |
| 308 | + | ||
| 175 | // 断言 | 309 | // 断言 |
| 176 | TradePriceCalculateRespBO.Price price = resultBO.getPrice(); | 310 | TradePriceCalculateRespBO.Price price = resultBO.getPrice(); |
| 177 | assertThat(price) | 311 | assertThat(price) |
| 178 | - .extracting("totalPrice","discountPrice","couponPrice","pointPrice","deliveryPrice","payPrice") | ||
| 179 | - .containsExactly(2200, 0, 0, 0, 0, 2200); | 312 | + .extracting("totalPrice", "discountPrice", "couponPrice", "pointPrice", "deliveryPrice", "payPrice") |
| 313 | + .containsExactly(2200, 0, 0, 0, 0, 2200); | ||
| 180 | assertThat(resultBO.getItems()).hasSize(3); | 314 | assertThat(resultBO.getItems()).hasSize(3); |
| 181 | - // 断言:SKU1 | ||
| 182 | assertThat(resultBO.getItems().get(0)) | 315 | assertThat(resultBO.getItems().get(0)) |
| 183 | - .extracting("price", "count","discountPrice" ,"couponPrice", "pointPrice","deliveryPrice","payPrice") | 316 | + .extracting("price", "count", "discountPrice", "couponPrice", "pointPrice", "deliveryPrice", "payPrice") |
| 184 | .containsExactly(100, 2, 0, 0, 0, 0, 200); | 317 | .containsExactly(100, 2, 0, 0, 0, 0, 200); |
| 185 | - // 断言:SKU2 | ||
| 186 | assertThat(resultBO.getItems().get(1)) | 318 | assertThat(resultBO.getItems().get(1)) |
| 187 | - .extracting("price", "count","discountPrice" ,"couponPrice", "pointPrice","deliveryPrice","payPrice") | 319 | + .extracting("price", "count", "discountPrice", "couponPrice", "pointPrice", "deliveryPrice", "payPrice") |
| 188 | .containsExactly(200, 10, 0, 0, 0, 0, 2000); | 320 | .containsExactly(200, 10, 0, 0, 0, 0, 2000); |
| 189 | - // 断言:SKU3 未选中 | ||
| 190 | assertThat(resultBO.getItems().get(2)) | 321 | assertThat(resultBO.getItems().get(2)) |
| 191 | - .extracting("price", "count","discountPrice" ,"couponPrice", "pointPrice","deliveryPrice","payPrice") | 322 | + .extracting("price", "count", "discountPrice", "couponPrice", "pointPrice", "deliveryPrice", "payPrice") |
| 192 | .containsExactly(300, 1, 0, 0, 0, 0, 300); | 323 | .containsExactly(300, 1, 0, 0, 0, 0, 300); |
| 193 | } | 324 | } |
| 194 | 325 | ||
| 326 | + @Test | ||
| 327 | + @DisplayName("按件计算运费:边界场景(总件数 = 包邮件数 → 包邮)") | ||
| 328 | + public void testCalculate_expressTemplateFree_countBoundary() { | ||
| 329 | + // 总件数 12 等于 包邮件数 12 && 总金额 2200 >= 包邮金额 1000,包邮 | ||
| 330 | + templateRespBO.setFree(randomPojo(DeliveryExpressTemplateRespBO.Free.class, | ||
| 331 | + item -> item.setFreeCount(12).setFreePrice(1000))); | ||
| 332 | + mockAddress(); | ||
| 333 | + mockTemplate(templateRespBO); | ||
| 334 | + | ||
| 335 | + // 调用 | ||
| 336 | + calculator.calculate(reqBO, resultBO); | ||
| 337 | + | ||
| 338 | + // 断言:包邮,运费 = 0 | ||
| 339 | + assertThat(resultBO.getPrice().getDeliveryPrice()).isEqualTo(0); | ||
| 340 | + } | ||
| 341 | + | ||
| 342 | + @Test | ||
| 343 | + @DisplayName("按件计算运费:总金额未达到包邮金额 → 不包邮") | ||
| 344 | + public void testCalculate_expressTemplateFree_priceNotMatch() { | ||
| 345 | + // 总件数 12 > 包邮件数 10,但总金额 2200 < 包邮金额 5000,不包邮 | ||
| 346 | + templateRespBO.setFree(randomPojo(DeliveryExpressTemplateRespBO.Free.class, | ||
| 347 | + item -> item.setFreeCount(10).setFreePrice(5000))); | ||
| 348 | + mockAddress(); | ||
| 349 | + mockTemplate(templateRespBO); | ||
| 350 | + | ||
| 351 | + // 调用 | ||
| 352 | + calculator.calculate(reqBO, resultBO); | ||
| 353 | + | ||
| 354 | + // 断言:仍按运费模板计算 = 3000 | ||
| 355 | + assertThat(resultBO.getPrice().getDeliveryPrice()).isEqualTo(3000); | ||
| 356 | + } | ||
| 357 | + | ||
| 358 | + @Test | ||
| 359 | + @DisplayName("按件计算运费:边界场景(总金额 = 包邮金额 → 包邮)") | ||
| 360 | + public void testCalculate_expressTemplateFree_priceBoundary() { | ||
| 361 | + // 总件数 12 >= 包邮件数 10 && 总金额 2200 等于 包邮金额 2200,包邮 | ||
| 362 | + templateRespBO.setFree(randomPojo(DeliveryExpressTemplateRespBO.Free.class, | ||
| 363 | + item -> item.setFreeCount(10).setFreePrice(2200))); | ||
| 364 | + mockAddress(); | ||
| 365 | + mockTemplate(templateRespBO); | ||
| 366 | + | ||
| 367 | + // 调用 | ||
| 368 | + calculator.calculate(reqBO, resultBO); | ||
| 369 | + | ||
| 370 | + // 断言:包邮,运费 = 0 | ||
| 371 | + assertThat(resultBO.getPrice().getDeliveryPrice()).isEqualTo(0); | ||
| 372 | + } | ||
| 373 | + | ||
| 374 | + @Test | ||
| 375 | + @DisplayName("按重量计算运费") | ||
| 376 | + public void testCalculate_expressTemplate_byWeight() { | ||
| 377 | + // SKU1 weight 10 * count 2 = 20 | ||
| 378 | + // SKU2 weight 10 * count 10 = 100 | ||
| 379 | + // 总重量 120kg | ||
| 380 | + // 运费:首件 1000 + 续件 ceil((120-10)/10)=11 倍 * 2000 = 23000 | ||
| 381 | + templateRespBO.setChargeMode(DeliveryExpressChargeModeEnum.WEIGHT.getType()); | ||
| 382 | + templateRespBO.setFree(randomPojo(DeliveryExpressTemplateRespBO.Free.class, | ||
| 383 | + item -> item.setFreeCount(200).setFreePrice(100))); | ||
| 384 | + mockAddress(); | ||
| 385 | + mockTemplate(templateRespBO); | ||
| 386 | + | ||
| 387 | + // 调用 | ||
| 388 | + calculator.calculate(reqBO, resultBO); | ||
| 389 | + | ||
| 390 | + // 断言 | ||
| 391 | + assertThat(resultBO.getPrice().getDeliveryPrice()).isEqualTo(23000); | ||
| 392 | + } | ||
| 393 | + | ||
| 394 | + @Test | ||
| 395 | + @DisplayName("按体积计算运费") | ||
| 396 | + public void testCalculate_expressTemplate_byVolume() { | ||
| 397 | + // SKU1 volume 10 * count 2 = 20 | ||
| 398 | + // SKU2 volume 10 * count 10 = 100 | ||
| 399 | + // 总体积 120m³,与按重量场景同 | ||
| 400 | + templateRespBO.setChargeMode(DeliveryExpressChargeModeEnum.VOLUME.getType()); | ||
| 401 | + templateRespBO.setFree(randomPojo(DeliveryExpressTemplateRespBO.Free.class, | ||
| 402 | + item -> item.setFreeCount(200).setFreePrice(100))); | ||
| 403 | + mockAddress(); | ||
| 404 | + mockTemplate(templateRespBO); | ||
| 405 | + | ||
| 406 | + // 调用 | ||
| 407 | + calculator.calculate(reqBO, resultBO); | ||
| 408 | + | ||
| 409 | + // 断言 | ||
| 410 | + assertThat(resultBO.getPrice().getDeliveryPrice()).isEqualTo(23000); | ||
| 411 | + } | ||
| 412 | + | ||
| 413 | + private void mockAddress() { | ||
| 414 | + MemberAddressRespDTO addressResp = randomPojo(MemberAddressRespDTO.class, item -> item.setAreaId(10)); | ||
| 415 | + when(addressApi.getAddress(eq(10L), eq(1L))).thenReturn(addressResp); | ||
| 416 | + } | ||
| 417 | + | ||
| 418 | + private void mockTemplate(DeliveryExpressTemplateRespBO template) { | ||
| 419 | + when(deliveryExpressTemplateService.getExpressTemplateMapByIdsAndArea(eq(asSet(1L)), eq(10))) | ||
| 420 | + .thenReturn(MapUtil.of(1L, template)); | ||
| 421 | + } | ||
| 422 | + | ||
| 195 | } | 423 | } |
yudao-module-mall/yudao-module-trade/src/test/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeDiscountActivityPriceCalculatorTest.java
| 1 | package cn.iocoder.yudao.module.trade.service.price.calculator; | 1 | package cn.iocoder.yudao.module.trade.service.price.calculator; |
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; | 3 | import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; |
| 4 | +import cn.iocoder.yudao.module.member.api.level.MemberLevelApi; | ||
| 5 | +import cn.iocoder.yudao.module.member.api.user.MemberUserApi; | ||
| 4 | import cn.iocoder.yudao.module.promotion.api.discount.DiscountActivityApi; | 6 | import cn.iocoder.yudao.module.promotion.api.discount.DiscountActivityApi; |
| 5 | import cn.iocoder.yudao.module.promotion.api.discount.dto.DiscountProductRespDTO; | 7 | import cn.iocoder.yudao.module.promotion.api.discount.dto.DiscountProductRespDTO; |
| 6 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionDiscountTypeEnum; | 8 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionDiscountTypeEnum; |
| @@ -8,7 +10,6 @@ import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum; | @@ -8,7 +10,6 @@ import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum; | ||
| 8 | import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; | 10 | import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; |
| 9 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; | 11 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; |
| 10 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; | 12 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; |
| 11 | -import org.junit.jupiter.api.Disabled; | ||
| 12 | import org.junit.jupiter.api.Test; | 13 | import org.junit.jupiter.api.Test; |
| 13 | import org.mockito.InjectMocks; | 14 | import org.mockito.InjectMocks; |
| 14 | import org.mockito.Mock; | 15 | import org.mockito.Mock; |
| @@ -27,7 +28,6 @@ import static org.mockito.Mockito.when; | @@ -27,7 +28,6 @@ import static org.mockito.Mockito.when; | ||
| 27 | * | 28 | * |
| 28 | * @author 芋道源码 | 29 | * @author 芋道源码 |
| 29 | */ | 30 | */ |
| 30 | -@Disabled // TODO 芋艿:后续修复 | ||
| 31 | public class TradeDiscountActivityPriceCalculatorTest extends BaseMockitoUnitTest { | 31 | public class TradeDiscountActivityPriceCalculatorTest extends BaseMockitoUnitTest { |
| 32 | 32 | ||
| 33 | @InjectMocks | 33 | @InjectMocks |
| @@ -35,6 +35,10 @@ public class TradeDiscountActivityPriceCalculatorTest extends BaseMockitoUnitTes | @@ -35,6 +35,10 @@ public class TradeDiscountActivityPriceCalculatorTest extends BaseMockitoUnitTes | ||
| 35 | 35 | ||
| 36 | @Mock | 36 | @Mock |
| 37 | private DiscountActivityApi discountActivityApi; | 37 | private DiscountActivityApi discountActivityApi; |
| 38 | + @Mock | ||
| 39 | + private MemberLevelApi memberLevelApi; | ||
| 40 | + @Mock | ||
| 41 | + private MemberUserApi memberUserApi; | ||
| 38 | 42 | ||
| 39 | @Test | 43 | @Test |
| 40 | public void testCalculate() { | 44 | public void testCalculate() { |
| @@ -92,16 +96,16 @@ public class TradeDiscountActivityPriceCalculatorTest extends BaseMockitoUnitTes | @@ -92,16 +96,16 @@ public class TradeDiscountActivityPriceCalculatorTest extends BaseMockitoUnitTes | ||
| 92 | assertEquals(orderItem01.getCouponPrice(), 0); | 96 | assertEquals(orderItem01.getCouponPrice(), 0); |
| 93 | assertEquals(orderItem01.getPointPrice(), 0); | 97 | assertEquals(orderItem01.getPointPrice(), 0); |
| 94 | assertEquals(orderItem01.getPayPrice(), 120); | 98 | assertEquals(orderItem01.getPayPrice(), 120); |
| 95 | - // 断言:SKU 2 | 99 | + // 断言:SKU 2 未选中,不参与计算 |
| 96 | TradePriceCalculateRespBO.OrderItem orderItem02 = result.getItems().get(1); | 100 | TradePriceCalculateRespBO.OrderItem orderItem02 = result.getItems().get(1); |
| 97 | assertEquals(orderItem02.getSkuId(), 20L); | 101 | assertEquals(orderItem02.getSkuId(), 20L); |
| 98 | assertEquals(orderItem02.getCount(), 3); | 102 | assertEquals(orderItem02.getCount(), 3); |
| 99 | assertEquals(orderItem02.getPrice(), 50); | 103 | assertEquals(orderItem02.getPrice(), 50); |
| 100 | - assertEquals(orderItem02.getDiscountPrice(), 60); | 104 | + assertEquals(orderItem02.getDiscountPrice(), 0); |
| 101 | assertEquals(orderItem02.getDeliveryPrice(), 0); | 105 | assertEquals(orderItem02.getDeliveryPrice(), 0); |
| 102 | assertEquals(orderItem02.getCouponPrice(), 0); | 106 | assertEquals(orderItem02.getCouponPrice(), 0); |
| 103 | assertEquals(orderItem02.getPointPrice(), 0); | 107 | assertEquals(orderItem02.getPointPrice(), 0); |
| 104 | - assertEquals(orderItem02.getPayPrice(), 90); | 108 | + assertEquals(orderItem02.getPayPrice(), 150); |
| 105 | // 断言:Promotion 部分 | 109 | // 断言:Promotion 部分 |
| 106 | assertEquals(result.getPromotions().size(), 1); | 110 | assertEquals(result.getPromotions().size(), 1); |
| 107 | TradePriceCalculateRespBO.Promotion promotion01 = result.getPromotions().get(0); | 111 | TradePriceCalculateRespBO.Promotion promotion01 = result.getPromotions().get(0); |
yudao-module-mall/yudao-module-trade/src/test/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradePointUsePriceCalculatorTest.java
| @@ -9,7 +9,6 @@ import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum; | @@ -9,7 +9,6 @@ import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum; | ||
| 9 | import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; | 9 | import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; |
| 10 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; | 10 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; |
| 11 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; | 11 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; |
| 12 | -import org.junit.jupiter.api.Disabled; | ||
| 13 | import org.junit.jupiter.api.Test; | 12 | import org.junit.jupiter.api.Test; |
| 14 | import org.mockito.InjectMocks; | 13 | import org.mockito.InjectMocks; |
| 15 | import org.mockito.Mock; | 14 | import org.mockito.Mock; |
| @@ -22,13 +21,11 @@ import static org.junit.jupiter.api.Assertions.assertEquals; | @@ -22,13 +21,11 @@ import static org.junit.jupiter.api.Assertions.assertEquals; | ||
| 22 | import static org.junit.jupiter.api.Assertions.assertTrue; | 21 | import static org.junit.jupiter.api.Assertions.assertTrue; |
| 23 | import static org.mockito.Mockito.when; | 22 | import static org.mockito.Mockito.when; |
| 24 | 23 | ||
| 25 | -// TODO 芋艿:晚点 review | ||
| 26 | /** | 24 | /** |
| 27 | * {@link TradePointUsePriceCalculator } 的单元测试类 | 25 | * {@link TradePointUsePriceCalculator } 的单元测试类 |
| 28 | * | 26 | * |
| 29 | * @author owen | 27 | * @author owen |
| 30 | */ | 28 | */ |
| 31 | -@Disabled // TODO 芋艿:后续修复 | ||
| 32 | public class TradePointUsePriceCalculatorTest extends BaseMockitoUnitTest { | 29 | public class TradePointUsePriceCalculatorTest extends BaseMockitoUnitTest { |
| 33 | 30 | ||
| 34 | @InjectMocks | 31 | @InjectMocks |
| @@ -245,6 +242,10 @@ public class TradePointUsePriceCalculatorTest extends BaseMockitoUnitTest { | @@ -245,6 +242,10 @@ public class TradePointUsePriceCalculatorTest extends BaseMockitoUnitTest { | ||
| 245 | TradePriceCalculatorHelper.recountPayPrice(result.getItems()); | 242 | TradePriceCalculatorHelper.recountPayPrice(result.getItems()); |
| 246 | TradePriceCalculatorHelper.recountAllPrice(result); | 243 | TradePriceCalculatorHelper.recountAllPrice(result); |
| 247 | 244 | ||
| 245 | + // mock 方法(会员 信息):不使用积分仍需获取用户初始化 totalPoint | ||
| 246 | + MemberUserRespDTO user = randomPojo(MemberUserRespDTO.class, o -> o.setId(param.getUserId()).setPoint(100)); | ||
| 247 | + when(memberUserApi.getUser(user.getId())).thenReturn(user); | ||
| 248 | + | ||
| 248 | // 调用 | 249 | // 调用 |
| 249 | tradePointUsePriceCalculator.calculate(param, result); | 250 | tradePointUsePriceCalculator.calculate(param, result); |
| 250 | // 断言:没有使用积分 | 251 | // 断言:没有使用积分 |
yudao-module-mall/yudao-module-trade/src/test/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeRewardActivityPriceCalculatorTest.java
| @@ -2,10 +2,29 @@ package cn.iocoder.yudao.module.trade.service.price.calculator; | @@ -2,10 +2,29 @@ package cn.iocoder.yudao.module.trade.service.price.calculator; | ||
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; | 3 | import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; |
| 4 | import cn.iocoder.yudao.module.promotion.api.reward.RewardActivityApi; | 4 | import cn.iocoder.yudao.module.promotion.api.reward.RewardActivityApi; |
| 5 | +import cn.iocoder.yudao.module.promotion.api.reward.dto.RewardActivityMatchRespDTO; | ||
| 6 | +import cn.iocoder.yudao.module.promotion.enums.common.PromotionConditionTypeEnum; | ||
| 7 | +import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum; | ||
| 8 | +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; | ||
| 9 | +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; | ||
| 10 | +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; | ||
| 11 | +import org.junit.jupiter.api.Test; | ||
| 5 | import org.mockito.InjectMocks; | 12 | import org.mockito.InjectMocks; |
| 6 | import org.mockito.Mock; | 13 | import org.mockito.Mock; |
| 7 | 14 | ||
| 8 | -// TODO 芋艿:后续在修复 | 15 | +import java.util.ArrayList; |
| 16 | +import java.util.LinkedHashMap; | ||
| 17 | + | ||
| 18 | +import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet; | ||
| 19 | +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; | ||
| 20 | +import static java.util.Arrays.asList; | ||
| 21 | +import static java.util.Collections.singletonList; | ||
| 22 | +import static org.junit.jupiter.api.Assertions.assertEquals; | ||
| 23 | +import static org.junit.jupiter.api.Assertions.assertFalse; | ||
| 24 | +import static org.junit.jupiter.api.Assertions.assertTrue; | ||
| 25 | +import static org.mockito.ArgumentMatchers.eq; | ||
| 26 | +import static org.mockito.Mockito.when; | ||
| 27 | + | ||
| 9 | /** | 28 | /** |
| 10 | * {@link TradeRewardActivityPriceCalculator} 的单元测试类 | 29 | * {@link TradeRewardActivityPriceCalculator} 的单元测试类 |
| 11 | * | 30 | * |
| @@ -19,212 +38,155 @@ public class TradeRewardActivityPriceCalculatorTest extends BaseMockitoUnitTest | @@ -19,212 +38,155 @@ public class TradeRewardActivityPriceCalculatorTest extends BaseMockitoUnitTest | ||
| 19 | @Mock | 38 | @Mock |
| 20 | private RewardActivityApi rewardActivityApi; | 39 | private RewardActivityApi rewardActivityApi; |
| 21 | 40 | ||
| 22 | -// @Test | ||
| 23 | -// public void testCalculate_match() { | ||
| 24 | -// // 准备参数 | ||
| 25 | -// TradePriceCalculateReqBO param = new TradePriceCalculateReqBO() | ||
| 26 | -// .setItems(asList( | ||
| 27 | -// new TradePriceCalculateReqBO.Item().setSkuId(10L).setCount(2).setSelected(true), // 匹配活动 1 | ||
| 28 | -// new TradePriceCalculateReqBO.Item().setSkuId(20L).setCount(3).setSelected(true), // 匹配活动 1 | ||
| 29 | -// new TradePriceCalculateReqBO.Item().setSkuId(30L).setCount(4).setSelected(true) // 匹配活动 2 | ||
| 30 | -// )); | ||
| 31 | -// TradePriceCalculateRespBO result = new TradePriceCalculateRespBO() | ||
| 32 | -// .setType(TradeOrderTypeEnum.NORMAL.getType()) | ||
| 33 | -// .setPrice(new TradePriceCalculateRespBO.Price()) | ||
| 34 | -// .setPromotions(new ArrayList<>()).setGiveCouponTemplateCounts(new LinkedHashMap<>()) | ||
| 35 | -// .setItems(asList( | ||
| 36 | -// new TradePriceCalculateRespBO.OrderItem().setSkuId(10L).setCount(2).setSelected(true) | ||
| 37 | -// .setPrice(100).setSpuId(1L), | ||
| 38 | -// new TradePriceCalculateRespBO.OrderItem().setSkuId(20L).setCount(3).setSelected(true) | ||
| 39 | -// .setPrice(50).setSpuId(2L), | ||
| 40 | -// new TradePriceCalculateRespBO.OrderItem().setSkuId(30L).setCount(4).setSelected(true) | ||
| 41 | -// .setPrice(30).setSpuId(3L) | ||
| 42 | -// )); | ||
| 43 | -// // 保证价格被初始化上 | ||
| 44 | -// TradePriceCalculatorHelper.recountPayPrice(result.getItems()); | ||
| 45 | -// TradePriceCalculatorHelper.recountAllPrice(result); | ||
| 46 | -// | ||
| 47 | -// // mock 方法(满减送 RewardActivity 信息) | ||
| 48 | -// when(rewardActivityApi.getRewardActivityListByStatusAndNow(CommonStatusEnum.ENABLE.getStatus(), LocalDateTime.now())) | ||
| 49 | -// .thenReturn(asList( | ||
| 50 | -// randomPojo(RewardActivityMatchRespDTO.class, o -> o.setId(1000L).setName("活动 1000 号") | ||
| 51 | -// .setConditionType(PromotionConditionTypeEnum.PRICE.getType()) | ||
| 52 | -// .setProductScope(PromotionProductScopeEnum.SPU.getScope()).setProductScopeValues(asList(1L, 2L)) | ||
| 53 | -// .setRules(singletonList(new RewardActivityMatchRespDTO.Rule().setLimit(20).setDiscountPrice(70) | ||
| 54 | -// .setFreeDelivery(false)))), | ||
| 55 | -// randomPojo(RewardActivityMatchRespDTO.class, o -> o.setId(2000L).setName("活动 2000 号") | ||
| 56 | -// .setConditionType(PromotionConditionTypeEnum.COUNT.getType()) | ||
| 57 | -// .setProductScope(PromotionProductScopeEnum.SPU.getScope()).setProductScopeValues(singletonList(3L)) | ||
| 58 | -// .setRules(asList(new RewardActivityMatchRespDTO.Rule().setLimit(1).setDiscountPrice(10) | ||
| 59 | -// .setPoint(50).setFreeDelivery(false), | ||
| 60 | -// new RewardActivityMatchRespDTO.Rule().setLimit(2).setDiscountPrice(60) | ||
| 61 | -// .setPoint(100).setFreeDelivery(false), // 最大可满足,因为是 4 个 | ||
| 62 | -// new RewardActivityMatchRespDTO.Rule().setLimit(10).setDiscountPrice(100) | ||
| 63 | -// .setFreeDelivery(false)))) | ||
| 64 | -// )); | ||
| 65 | -// | ||
| 66 | -// // 调用 | ||
| 67 | -// tradeRewardActivityPriceCalculator.calculate(param, result); | ||
| 68 | -// // 断言 Order 部分 | ||
| 69 | -// TradePriceCalculateRespBO.Price price = result.getPrice(); | ||
| 70 | -// assertEquals(price.getTotalPrice(), 470); | ||
| 71 | -// assertEquals(price.getDiscountPrice(), 130); | ||
| 72 | -// assertEquals(price.getPointPrice(), 0); | ||
| 73 | -// assertEquals(price.getDeliveryPrice(), 0); | ||
| 74 | -// assertEquals(price.getCouponPrice(), 0); | ||
| 75 | -// assertEquals(price.getPayPrice(), 340); | ||
| 76 | -// assertNull(result.getCouponId()); | ||
| 77 | -// // 断言:SKU 1 | ||
| 78 | -// assertEquals(result.getItems().size(), 3); | ||
| 79 | -// TradePriceCalculateRespBO.OrderItem orderItem01 = result.getItems().get(0); | ||
| 80 | -// assertEquals(orderItem01.getSkuId(), 10L); | ||
| 81 | -// assertEquals(orderItem01.getCount(), 2); | ||
| 82 | -// assertEquals(orderItem01.getPrice(), 100); | ||
| 83 | -// assertEquals(orderItem01.getDiscountPrice(), 40); | ||
| 84 | -// assertEquals(orderItem01.getDeliveryPrice(), 0); | ||
| 85 | -// assertEquals(orderItem01.getCouponPrice(), 0); | ||
| 86 | -// assertEquals(orderItem01.getPointPrice(), 0); | ||
| 87 | -// assertEquals(orderItem01.getPayPrice(), 160); | ||
| 88 | -// assertEquals(orderItem01.getGivePoint(), 0); | ||
| 89 | -// // 断言:SKU 2 | ||
| 90 | -// TradePriceCalculateRespBO.OrderItem orderItem02 = result.getItems().get(1); | ||
| 91 | -// assertEquals(orderItem02.getSkuId(), 20L); | ||
| 92 | -// assertEquals(orderItem02.getCount(), 3); | ||
| 93 | -// assertEquals(orderItem02.getPrice(), 50); | ||
| 94 | -// assertEquals(orderItem02.getDiscountPrice(), 30); | ||
| 95 | -// assertEquals(orderItem02.getDeliveryPrice(), 0); | ||
| 96 | -// assertEquals(orderItem02.getCouponPrice(), 0); | ||
| 97 | -// assertEquals(orderItem02.getPointPrice(), 0); | ||
| 98 | -// assertEquals(orderItem02.getPayPrice(), 120); | ||
| 99 | -// assertEquals(orderItem02.getGivePoint(), 0); | ||
| 100 | -// // 断言:SKU 3 | ||
| 101 | -// TradePriceCalculateRespBO.OrderItem orderItem03 = result.getItems().get(2); | ||
| 102 | -// assertEquals(orderItem03.getSkuId(), 30L); | ||
| 103 | -// assertEquals(orderItem03.getCount(), 4); | ||
| 104 | -// assertEquals(orderItem03.getPrice(), 30); | ||
| 105 | -// assertEquals(orderItem03.getDiscountPrice(), 60); | ||
| 106 | -// assertEquals(orderItem03.getDeliveryPrice(), 0); | ||
| 107 | -// assertEquals(orderItem03.getCouponPrice(), 0); | ||
| 108 | -// assertEquals(orderItem03.getPointPrice(), 0); | ||
| 109 | -// assertEquals(orderItem03.getPayPrice(), 60); | ||
| 110 | -// assertEquals(orderItem03.getGivePoint(), 100); | ||
| 111 | -// // 断言:Promotion 部分(第一个) | ||
| 112 | -// assertEquals(result.getPromotions().size(), 2); | ||
| 113 | -// TradePriceCalculateRespBO.Promotion promotion01 = result.getPromotions().get(0); | ||
| 114 | -// assertEquals(promotion01.getId(), 1000L); | ||
| 115 | -// assertEquals(promotion01.getName(), "活动 1000 号"); | ||
| 116 | -// assertEquals(promotion01.getType(), PromotionTypeEnum.REWARD_ACTIVITY.getType()); | ||
| 117 | -// assertEquals(promotion01.getTotalPrice(), 350); | ||
| 118 | -// assertEquals(promotion01.getDiscountPrice(), 70); | ||
| 119 | -// assertTrue(promotion01.getMatch()); | ||
| 120 | -// assertEquals(promotion01.getDescription(), "满减送:省 0.70 元"); | ||
| 121 | -// assertEquals(promotion01.getItems().size(), 2); | ||
| 122 | -// TradePriceCalculateRespBO.PromotionItem promotionItem011 = promotion01.getItems().get(0); | ||
| 123 | -// assertEquals(promotionItem011.getSkuId(), 10L); | ||
| 124 | -// assertEquals(promotionItem011.getTotalPrice(), 200); | ||
| 125 | -// assertEquals(promotionItem011.getDiscountPrice(), 40); | ||
| 126 | -// TradePriceCalculateRespBO.PromotionItem promotionItem012 = promotion01.getItems().get(1); | ||
| 127 | -// assertEquals(promotionItem012.getSkuId(), 20L); | ||
| 128 | -// assertEquals(promotionItem012.getTotalPrice(), 150); | ||
| 129 | -// assertEquals(promotionItem012.getDiscountPrice(), 30); | ||
| 130 | -// // 断言:Promotion 部分(第二个) | ||
| 131 | -// TradePriceCalculateRespBO.Promotion promotion02 = result.getPromotions().get(1); | ||
| 132 | -// assertEquals(promotion02.getId(), 2000L); | ||
| 133 | -// assertEquals(promotion02.getName(), "活动 2000 号"); | ||
| 134 | -// assertEquals(promotion02.getType(), PromotionTypeEnum.REWARD_ACTIVITY.getType()); | ||
| 135 | -// assertEquals(promotion02.getTotalPrice(), 120); | ||
| 136 | -// assertEquals(promotion02.getDiscountPrice(), 60); | ||
| 137 | -// assertTrue(promotion02.getMatch()); | ||
| 138 | -// assertEquals(promotion02.getDescription(), "满减送:省 0.60 元"); | ||
| 139 | -// TradePriceCalculateRespBO.PromotionItem promotionItem02 = promotion02.getItems().get(0); | ||
| 140 | -// assertEquals(promotion02.getItems().size(), 1); | ||
| 141 | -// assertEquals(promotionItem02.getSkuId(), 30L); | ||
| 142 | -// assertEquals(promotionItem02.getTotalPrice(), 120); | ||
| 143 | -// assertEquals(promotionItem02.getDiscountPrice(), 60); | ||
| 144 | -// } | ||
| 145 | -// | ||
| 146 | -// @Test | ||
| 147 | -// public void testCalculate_notMatch() { | ||
| 148 | -// // 准备参数 | ||
| 149 | -// TradePriceCalculateReqBO param = new TradePriceCalculateReqBO() | ||
| 150 | -// .setItems(asList( | ||
| 151 | -// new TradePriceCalculateReqBO.Item().setSkuId(10L).setCount(2).setSelected(true), | ||
| 152 | -// new TradePriceCalculateReqBO.Item().setSkuId(20L).setCount(3).setSelected(true), | ||
| 153 | -// new TradePriceCalculateReqBO.Item().setSkuId(30L).setCount(4).setSelected(true) | ||
| 154 | -// )); | ||
| 155 | -// TradePriceCalculateRespBO result = new TradePriceCalculateRespBO() | ||
| 156 | -// .setType(TradeOrderTypeEnum.NORMAL.getType()) | ||
| 157 | -// .setPrice(new TradePriceCalculateRespBO.Price()) | ||
| 158 | -// .setPromotions(new ArrayList<>()) | ||
| 159 | -// .setItems(asList( | ||
| 160 | -// new TradePriceCalculateRespBO.OrderItem().setSkuId(10L).setCount(2).setSelected(true) | ||
| 161 | -// .setPrice(100).setSpuId(1L), | ||
| 162 | -// new TradePriceCalculateRespBO.OrderItem().setSkuId(20L).setCount(3).setSelected(true) | ||
| 163 | -// .setPrice(50).setSpuId(2L) | ||
| 164 | -// )); | ||
| 165 | -// // 保证价格被初始化上 | ||
| 166 | -// TradePriceCalculatorHelper.recountPayPrice(result.getItems()); | ||
| 167 | -// TradePriceCalculatorHelper.recountAllPrice(result); | ||
| 168 | -// | ||
| 169 | -// // mock 方法(限时折扣 DiscountActivity 信息) | ||
| 170 | -// when(rewardActivityApi.getRewardActivityListByStatusAndNow(CommonStatusEnum.ENABLE.getStatus(), LocalDateTime.now())) | ||
| 171 | -// .thenReturn(singletonList( | ||
| 172 | -// randomPojo(RewardActivityMatchRespDTO.class, o -> o.setId(1000L).setName("活动 1000 号") | ||
| 173 | -// .setProductScopeValues(asList(1L, 2L)).setConditionType(PromotionConditionTypeEnum.PRICE.getType()) | ||
| 174 | -// .setRules(singletonList(new RewardActivityMatchRespDTO.Rule().setLimit(351).setDiscountPrice(70)))) | ||
| 175 | -// )); | ||
| 176 | -// | ||
| 177 | -// // 调用 | ||
| 178 | -// tradeRewardActivityPriceCalculator.calculate(param, result); | ||
| 179 | -// // 断言 Order 部分 | ||
| 180 | -// TradePriceCalculateRespBO.Price price = result.getPrice(); | ||
| 181 | -// assertEquals(price.getTotalPrice(), 350); | ||
| 182 | -// assertEquals(price.getDiscountPrice(), 0); | ||
| 183 | -// assertEquals(price.getPointPrice(), 0); | ||
| 184 | -// assertEquals(price.getDeliveryPrice(), 0); | ||
| 185 | -// assertEquals(price.getCouponPrice(), 0); | ||
| 186 | -// assertEquals(price.getPayPrice(), 350); | ||
| 187 | -// assertNull(result.getCouponId()); | ||
| 188 | -// // 断言:SKU 1 | ||
| 189 | -// assertEquals(result.getItems().size(), 2); | ||
| 190 | -// TradePriceCalculateRespBO.OrderItem orderItem01 = result.getItems().get(0); | ||
| 191 | -// assertEquals(orderItem01.getSkuId(), 10L); | ||
| 192 | -// assertEquals(orderItem01.getCount(), 2); | ||
| 193 | -// assertEquals(orderItem01.getPrice(), 100); | ||
| 194 | -// assertEquals(orderItem01.getDiscountPrice(), 0); | ||
| 195 | -// assertEquals(orderItem01.getDeliveryPrice(), 0); | ||
| 196 | -// assertEquals(orderItem01.getCouponPrice(), 0); | ||
| 197 | -// assertEquals(orderItem01.getPointPrice(), 0); | ||
| 198 | -// assertEquals(orderItem01.getPayPrice(), 200); | ||
| 199 | -// // 断言:SKU 2 | ||
| 200 | -// TradePriceCalculateRespBO.OrderItem orderItem02 = result.getItems().get(1); | ||
| 201 | -// assertEquals(orderItem02.getSkuId(), 20L); | ||
| 202 | -// assertEquals(orderItem02.getCount(), 3); | ||
| 203 | -// assertEquals(orderItem02.getPrice(), 50); | ||
| 204 | -// assertEquals(orderItem02.getDiscountPrice(), 0); | ||
| 205 | -// assertEquals(orderItem02.getDeliveryPrice(), 0); | ||
| 206 | -// assertEquals(orderItem02.getCouponPrice(), 0); | ||
| 207 | -// assertEquals(orderItem02.getPointPrice(), 0); | ||
| 208 | -// assertEquals(orderItem02.getPayPrice(), 150); | ||
| 209 | -// // 断言 Promotion 部分 | ||
| 210 | -// assertEquals(result.getPromotions().size(), 1); | ||
| 211 | -// TradePriceCalculateRespBO.Promotion promotion01 = result.getPromotions().get(0); | ||
| 212 | -// assertEquals(promotion01.getId(), 1000L); | ||
| 213 | -// assertEquals(promotion01.getName(), "活动 1000 号"); | ||
| 214 | -// assertEquals(promotion01.getType(), PromotionTypeEnum.REWARD_ACTIVITY.getType()); | ||
| 215 | -// assertEquals(promotion01.getTotalPrice(), 350); | ||
| 216 | -// assertEquals(promotion01.getDiscountPrice(), 0); | ||
| 217 | -// assertFalse(promotion01.getMatch()); | ||
| 218 | -// assertEquals(promotion01.getDescription(), "TODO"); // TODO 芋艿:后面再想想 | ||
| 219 | -// assertEquals(promotion01.getItems().size(), 2); | ||
| 220 | -// TradePriceCalculateRespBO.PromotionItem promotionItem011 = promotion01.getItems().get(0); | ||
| 221 | -// assertEquals(promotionItem011.getSkuId(), 10L); | ||
| 222 | -// assertEquals(promotionItem011.getTotalPrice(), 200); | ||
| 223 | -// assertEquals(promotionItem011.getDiscountPrice(), 0); | ||
| 224 | -// TradePriceCalculateRespBO.PromotionItem promotionItem012 = promotion01.getItems().get(1); | ||
| 225 | -// assertEquals(promotionItem012.getSkuId(), 20L); | ||
| 226 | -// assertEquals(promotionItem012.getTotalPrice(), 150); | ||
| 227 | -// assertEquals(promotionItem012.getDiscountPrice(), 0); | ||
| 228 | -// } | 41 | + @Test |
| 42 | + public void testCalculate_match() { | ||
| 43 | + // 准备参数:SPU 1、SPU 2 命中活动;SPU 3 不在活动范围 | ||
| 44 | + TradePriceCalculateReqBO param = new TradePriceCalculateReqBO() | ||
| 45 | + .setItems(asList( | ||
| 46 | + new TradePriceCalculateReqBO.Item().setSkuId(10L).setCount(2).setSelected(true), | ||
| 47 | + new TradePriceCalculateReqBO.Item().setSkuId(20L).setCount(3).setSelected(true), | ||
| 48 | + new TradePriceCalculateReqBO.Item().setSkuId(30L).setCount(4).setSelected(true) | ||
| 49 | + )); | ||
| 50 | + TradePriceCalculateRespBO result = new TradePriceCalculateRespBO() | ||
| 51 | + .setType(TradeOrderTypeEnum.NORMAL.getType()) | ||
| 52 | + .setPrice(new TradePriceCalculateRespBO.Price()) | ||
| 53 | + .setPromotions(new ArrayList<>()) | ||
| 54 | + .setGiveCouponTemplateCounts(new LinkedHashMap<>()) | ||
| 55 | + .setItems(asList( | ||
| 56 | + new TradePriceCalculateRespBO.OrderItem().setSkuId(10L).setCount(2).setSelected(true) | ||
| 57 | + .setPrice(100).setSpuId(1L).setGivePoint(0), | ||
| 58 | + new TradePriceCalculateRespBO.OrderItem().setSkuId(20L).setCount(3).setSelected(true) | ||
| 59 | + .setPrice(50).setSpuId(2L).setGivePoint(0), | ||
| 60 | + new TradePriceCalculateRespBO.OrderItem().setSkuId(30L).setCount(4).setSelected(true) | ||
| 61 | + .setPrice(30).setSpuId(3L).setGivePoint(0) | ||
| 62 | + )); | ||
| 63 | + // 保证价格被初始化上 | ||
| 64 | + TradePriceCalculatorHelper.recountPayPrice(result.getItems()); | ||
| 65 | + TradePriceCalculatorHelper.recountAllPrice(result); | ||
| 66 | + | ||
| 67 | + // mock 方法(满减送活动) | ||
| 68 | + when(rewardActivityApi.getMatchRewardActivityListBySpuIds(eq(asSet(1L, 2L, 3L)))).thenReturn(singletonList( | ||
| 69 | + randomPojo(RewardActivityMatchRespDTO.class, o -> o.setId(1000L).setName("活动 1000 号") | ||
| 70 | + .setConditionType(PromotionConditionTypeEnum.PRICE.getType()) | ||
| 71 | + .setSpuIds(asList(1L, 2L)) | ||
| 72 | + .setRules(asList( | ||
| 73 | + new RewardActivityMatchRespDTO.Rule().setLimit(100).setDiscountPrice(20) | ||
| 74 | + .setPoint(50).setFreeDelivery(false), | ||
| 75 | + new RewardActivityMatchRespDTO.Rule().setLimit(200).setDiscountPrice(50) | ||
| 76 | + .setPoint(100).setFreeDelivery(true)))))); | ||
| 77 | + | ||
| 78 | + // 调用:SKU1+SKU2 总 payPrice=200+150=350, 命中 limit=200 规则 | ||
| 79 | + tradeRewardActivityPriceCalculator.calculate(param, result); | ||
| 80 | + | ||
| 81 | + // 断言:Price 部分(SKU3 仍按原价计入) | ||
| 82 | + TradePriceCalculateRespBO.Price price = result.getPrice(); | ||
| 83 | + assertEquals(price.getTotalPrice(), 470); | ||
| 84 | + assertEquals(price.getDiscountPrice(), 50); | ||
| 85 | + assertEquals(price.getPayPrice(), 420); | ||
| 86 | + // 断言:包邮标记 | ||
| 87 | + assertTrue(result.getFreeDelivery()); | ||
| 88 | + | ||
| 89 | + // 断言:SKU 1 优惠 50 * 200/350 = 28 | ||
| 90 | + TradePriceCalculateRespBO.OrderItem orderItem01 = result.getItems().get(0); | ||
| 91 | + assertEquals(orderItem01.getSkuId(), 10L); | ||
| 92 | + assertEquals(orderItem01.getDiscountPrice(), 28); | ||
| 93 | + assertEquals(orderItem01.getPayPrice(), 172); | ||
| 94 | + assertEquals(orderItem01.getGivePoint(), 57); // 100 * 200/350 | ||
| 95 | + // 断言:SKU 2 优惠 50 - 28 = 22 | ||
| 96 | + TradePriceCalculateRespBO.OrderItem orderItem02 = result.getItems().get(1); | ||
| 97 | + assertEquals(orderItem02.getSkuId(), 20L); | ||
| 98 | + assertEquals(orderItem02.getDiscountPrice(), 22); | ||
| 99 | + assertEquals(orderItem02.getPayPrice(), 128); | ||
| 100 | + assertEquals(orderItem02.getGivePoint(), 43); // 100 - 57 | ||
| 101 | + // 断言:SKU 3 不在活动范围,不参与 | ||
| 102 | + TradePriceCalculateRespBO.OrderItem orderItem03 = result.getItems().get(2); | ||
| 103 | + assertEquals(orderItem03.getSkuId(), 30L); | ||
| 104 | + assertEquals(orderItem03.getDiscountPrice(), 0); | ||
| 105 | + assertEquals(orderItem03.getPayPrice(), 120); | ||
| 106 | + assertEquals(orderItem03.getGivePoint(), 0); | ||
| 107 | + | ||
| 108 | + // 断言:Promotion 部分 | ||
| 109 | + assertEquals(result.getPromotions().size(), 1); | ||
| 110 | + TradePriceCalculateRespBO.Promotion promotion = result.getPromotions().get(0); | ||
| 111 | + assertEquals(promotion.getId(), 1000L); | ||
| 112 | + assertEquals(promotion.getName(), "活动 1000 号"); | ||
| 113 | + assertEquals(promotion.getType(), PromotionTypeEnum.REWARD_ACTIVITY.getType()); | ||
| 114 | + assertEquals(promotion.getTotalPrice(), 350); | ||
| 115 | + assertEquals(promotion.getDiscountPrice(), 50); | ||
| 116 | + assertTrue(promotion.getMatch()); | ||
| 117 | + assertEquals(promotion.getDescription(), "满减送:省 0.50 元"); | ||
| 118 | + assertEquals(promotion.getItems().size(), 2); | ||
| 119 | + } | ||
| 120 | + | ||
| 121 | + @Test | ||
| 122 | + public void testCalculate_notMatch() { | ||
| 123 | + // 准备参数 | ||
| 124 | + TradePriceCalculateReqBO param = new TradePriceCalculateReqBO() | ||
| 125 | + .setItems(singletonList( | ||
| 126 | + new TradePriceCalculateReqBO.Item().setSkuId(10L).setCount(2).setSelected(true) | ||
| 127 | + )); | ||
| 128 | + TradePriceCalculateRespBO result = new TradePriceCalculateRespBO() | ||
| 129 | + .setType(TradeOrderTypeEnum.NORMAL.getType()) | ||
| 130 | + .setPrice(new TradePriceCalculateRespBO.Price()) | ||
| 131 | + .setPromotions(new ArrayList<>()) | ||
| 132 | + .setGiveCouponTemplateCounts(new LinkedHashMap<>()) | ||
| 133 | + .setItems(singletonList( | ||
| 134 | + new TradePriceCalculateRespBO.OrderItem().setSkuId(10L).setCount(2).setSelected(true) | ||
| 135 | + .setPrice(100).setSpuId(1L).setGivePoint(0) | ||
| 136 | + )); | ||
| 137 | + TradePriceCalculatorHelper.recountPayPrice(result.getItems()); | ||
| 138 | + TradePriceCalculatorHelper.recountAllPrice(result); | ||
| 139 | + | ||
| 140 | + // mock 方法:要求 limit=300,订单总额 200 不满足 | ||
| 141 | + when(rewardActivityApi.getMatchRewardActivityListBySpuIds(eq(asSet(1L)))).thenReturn(singletonList( | ||
| 142 | + randomPojo(RewardActivityMatchRespDTO.class, o -> o.setId(1000L).setName("活动 1000 号") | ||
| 143 | + .setConditionType(PromotionConditionTypeEnum.PRICE.getType()) | ||
| 144 | + .setSpuIds(singletonList(1L)) | ||
| 145 | + .setRules(singletonList(new RewardActivityMatchRespDTO.Rule() | ||
| 146 | + .setLimit(300).setDiscountPrice(70).setDescription("满 3 元减 0.7 元")))))); | ||
| 147 | + | ||
| 148 | + // 调用 | ||
| 149 | + tradeRewardActivityPriceCalculator.calculate(param, result); | ||
| 150 | + | ||
| 151 | + // 断言:未优惠 | ||
| 152 | + TradePriceCalculateRespBO.Price price = result.getPrice(); | ||
| 153 | + assertEquals(price.getTotalPrice(), 200); | ||
| 154 | + assertEquals(price.getDiscountPrice(), 0); | ||
| 155 | + assertEquals(price.getPayPrice(), 200); | ||
| 156 | + | ||
| 157 | + // 断言:促销明细记录为不匹配 | ||
| 158 | + assertEquals(result.getPromotions().size(), 1); | ||
| 159 | + TradePriceCalculateRespBO.Promotion promotion = result.getPromotions().get(0); | ||
| 160 | + assertEquals(promotion.getId(), 1000L); | ||
| 161 | + assertEquals(promotion.getType(), PromotionTypeEnum.REWARD_ACTIVITY.getType()); | ||
| 162 | + assertFalse(promotion.getMatch()); | ||
| 163 | + assertEquals(promotion.getDiscountPrice(), 0); | ||
| 164 | + assertEquals(promotion.getDescription(), "满减送:满 3 元减 0.7 元"); | ||
| 165 | + } | ||
| 166 | + | ||
| 167 | + @Test | ||
| 168 | + public void testCalculate_skipNonNormalOrder() { | ||
| 169 | + // 准备参数:秒杀订单 | ||
| 170 | + TradePriceCalculateReqBO param = new TradePriceCalculateReqBO() | ||
| 171 | + .setItems(singletonList( | ||
| 172 | + new TradePriceCalculateReqBO.Item().setSkuId(10L).setCount(2).setSelected(true) | ||
| 173 | + )); | ||
| 174 | + TradePriceCalculateRespBO result = new TradePriceCalculateRespBO() | ||
| 175 | + .setType(TradeOrderTypeEnum.SECKILL.getType()) | ||
| 176 | + .setPrice(new TradePriceCalculateRespBO.Price()) | ||
| 177 | + .setPromotions(new ArrayList<>()) | ||
| 178 | + .setItems(singletonList( | ||
| 179 | + new TradePriceCalculateRespBO.OrderItem().setSkuId(10L).setCount(2).setSelected(true) | ||
| 180 | + .setPrice(100).setSpuId(1L) | ||
| 181 | + )); | ||
| 182 | + TradePriceCalculatorHelper.recountPayPrice(result.getItems()); | ||
| 183 | + TradePriceCalculatorHelper.recountAllPrice(result); | ||
| 184 | + | ||
| 185 | + // 调用:非普通订单直接跳过,不会调用 API | ||
| 186 | + tradeRewardActivityPriceCalculator.calculate(param, result); | ||
| 187 | + | ||
| 188 | + // 断言:未产生促销 | ||
| 189 | + assertEquals(result.getPromotions().size(), 0); | ||
| 190 | + } | ||
| 229 | 191 | ||
| 230 | } | 192 | } |