Quellcode durchsuchen

trade:全局配送价格配置

YunaiV vor 1 Jahr
Ursprung
Commit
5949727c8d

+ 11 - 0
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/config/TradeConfigDO.java

@@ -35,6 +35,17 @@ public class TradeConfigDO extends BaseDO {
     @TableId
     private Long id;
 
+    // ========== 配送相关 ==========
+    // TODO 芋艿:未配置
+    /**
+     * 是否启用全场包邮
+     */
+    private Boolean deliveryExpressFreeEnabled;
+    /**
+     * 全场包邮的最小金额,单位:分
+     */
+    private Integer deliveryExpressFreePrice;
+
     // ========== 分销相关 ==========
 
     /**

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

@@ -5,9 +5,11 @@ import cn.hutool.core.lang.Assert;
 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.yudao.module.member.api.address.AddressApi;
 import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO;
+import cn.iocoder.yudao.module.trade.dal.dataobject.config.TradeConfigDO;
 import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryPickUpStoreDO;
 import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryExpressChargeModeEnum;
 import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum;
+import cn.iocoder.yudao.module.trade.service.config.TradeConfigService;
 import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressTemplateService;
 import cn.iocoder.yudao.module.trade.service.delivery.DeliveryPickUpStoreService;
 import cn.iocoder.yudao.module.trade.service.delivery.bo.DeliveryExpressTemplateRespBO;
@@ -44,6 +46,8 @@ public class TradeDeliveryPriceCalculator implements TradePriceCalculator {
     private DeliveryPickUpStoreService deliveryPickUpStoreService;
     @Resource
     private DeliveryExpressTemplateService deliveryExpressTemplateService;
+    @Resource
+    private TradeConfigService tradeConfigService;
 
     @Override
     public void calculate(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result) {
@@ -70,19 +74,25 @@ public class TradeDeliveryPriceCalculator implements TradePriceCalculator {
     // ========= 快递发货 ==========
 
     private void calculateExpress(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result) {
-        // 1. 得到收件地址区域
+        // 0. 得到收件地址区域
         if (param.getAddressId() == null) {
             throw exception(PRICE_CALCULATE_DELIVERY_PRICE_USER_ADDRESS_IS_EMPTY);
         }
         AddressRespDTO address = addressApi.getAddress(param.getAddressId(), param.getUserId());
         Assert.notNull(address, "收件人({})的地址,不能为空", param.getUserId());
 
-        // 2. 过滤出已选中的商品SKU
+        // 情况一:全局包邮
+        if (isGlobalExpressFree(param, result)) {
+            return;
+        }
+
+        // 情况二:
+        // 2.1 过滤出已选中的商品SKU
         List<OrderItem> selectedItem = filterList(result.getItems(), OrderItem::getSelected);
         Set<Long> deliveryTemplateIds = convertSet(selectedItem, OrderItem::getDeliveryTemplateId);
         Map<Long, DeliveryExpressTemplateRespBO> expressTemplateMap =
                 deliveryExpressTemplateService.getExpressTemplateMapByIdsAndArea(deliveryTemplateIds, address.getAreaId());
-        // 3. 计算配送费用
+        // 2.2 计算配送费用
         if (CollUtil.isEmpty(expressTemplateMap)) {
             log.error("[calculate][找不到商品 templateIds {} areaId{} 对应的运费模板]", deliveryTemplateIds, address.getAreaId());
             throw exception(PRICE_CALCULATE_DELIVERY_PRICE_TEMPLATE_NOT_FOUND);
@@ -90,6 +100,20 @@ public class TradeDeliveryPriceCalculator implements TradePriceCalculator {
         calculateDeliveryPrice(selectedItem, expressTemplateMap, result);
     }
 
+    /**
+     * 是否全局包邮
+     *
+     * @param param 计算信息
+     * @param result 计算结果
+     * @return 是否包邮
+     */
+    private boolean isGlobalExpressFree(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result) {
+        TradeConfigDO config = tradeConfigService.getTradeConfig();
+        return config != null
+                && Boolean.TRUE.equals(config.getDeliveryExpressFreeEnabled()) // 开启包邮
+                && result.getPrice().getPayPrice() >= config.getDeliveryExpressFreePrice(); // 满足包邮的价格
+    }
+
     private void calculateDeliveryPrice(List<OrderItem> selectedSkus,
                                         Map<Long, DeliveryExpressTemplateRespBO> expressTemplateMap,
                                         TradePriceCalculateRespBO result) {

+ 36 - 2
yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeDeliveryPriceCalculatorTest.java

@@ -4,8 +4,10 @@ import cn.hutool.core.map.MapUtil;
 import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
 import cn.iocoder.yudao.module.member.api.address.AddressApi;
 import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO;
+import cn.iocoder.yudao.module.trade.dal.dataobject.config.TradeConfigDO;
 import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryExpressChargeModeEnum;
 import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum;
+import cn.iocoder.yudao.module.trade.service.config.TradeConfigService;
 import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressTemplateService;
 import cn.iocoder.yudao.module.trade.service.delivery.bo.DeliveryExpressTemplateRespBO;
 import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO;
@@ -34,10 +36,14 @@ public class TradeDeliveryPriceCalculatorTest  extends BaseMockitoUnitTest {
 
     @InjectMocks
     private TradeDeliveryPriceCalculator calculator;
+
     @Mock
     private AddressApi addressApi;
+
     @Mock
     private DeliveryExpressTemplateService deliveryExpressTemplateService;
+    @Mock
+    private TradeConfigService tradeConfigService;
 
     private TradePriceCalculateReqBO reqBO;
     private TradePriceCalculateRespBO resultBO;
@@ -89,9 +95,37 @@ public class TradeDeliveryPriceCalculatorTest  extends BaseMockitoUnitTest {
                         .setCharge(chargeBO).setFree(freeBO));
     }
 
+    @Test
+    @DisplayName("全场包邮")
+    public void testCalculate_expressGlobalFree() {
+        // mock 方法(全场包邮)
+        when(tradeConfigService.getTradeConfig()).thenReturn(new TradeConfigDO().setDeliveryExpressFreeEnabled(true)
+                .setDeliveryExpressFreePrice(2200));
+
+        // 调用
+        calculator.calculate(reqBO, resultBO);
+        TradePriceCalculateRespBO.Price price = resultBO.getPrice();
+        assertThat(price)
+                .extracting("totalPrice","discountPrice","couponPrice","pointPrice","deliveryPrice","payPrice")
+                .containsExactly(2200, 0, 0, 0, 0,  2200);
+        assertThat(resultBO.getItems()).hasSize(3);
+        // 断言:SKU1
+        assertThat(resultBO.getItems().get(0))
+                .extracting("price", "count","discountPrice" ,"couponPrice", "pointPrice","deliveryPrice","payPrice")
+                .containsExactly(100, 2, 0, 0, 0, 0, 200);
+        // 断言:SKU2
+        assertThat(resultBO.getItems().get(1))
+                .extracting("price", "count","discountPrice" ,"couponPrice", "pointPrice","deliveryPrice","payPrice")
+                .containsExactly(200, 10, 0, 0, 0, 0, 2000);
+        // 断言:SKU3 未选中
+        assertThat(resultBO.getItems().get(2))
+                .extracting("price", "count","discountPrice" ,"couponPrice", "pointPrice","deliveryPrice","payPrice")
+                .containsExactly(300, 1, 0, 0, 0, 0, 300);
+    }
+
     @Test
     @DisplayName("按件计算运费不包邮的情况")
-    public void testCalculateByExpressTemplateCharge() {
+    public void testCalculate_expressTemplateCharge() {
         // SKU 1 : 100 * 2  = 200
         // SKU 2 :200 * 10 = 2000
         // 运费  首件 1000 +  续件 2000 = 3000
@@ -123,7 +157,7 @@ public class TradeDeliveryPriceCalculatorTest  extends BaseMockitoUnitTest {
 
     @Test
     @DisplayName("按件计算运费包邮的情况")
-    public void testCalculateByExpressTemplateFree() {
+    public void testCalculate_expressTemplateFree() {
         // SKU 1 : 100 * 2  = 200
         // SKU 2 :200 * 10 = 2000
         // 运费  0