Commit 4e9fe4bc547fa8d8f9172b5e68b482fba74bd1c8

Authored by YunaiV
1 parent 084d4bab

price:完成限时折扣的价格计算~

yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/dal/dataobject/discount/DiscountProductDO.java
@@ -32,6 +32,12 @@ public class DiscountProductDO extends BaseDO { @@ -32,6 +32,12 @@ public class DiscountProductDO extends BaseDO {
32 */ 32 */
33 private Long activityId; 33 private Long activityId;
34 /** 34 /**
  35 + * 限时折扣活动的名字
  36 + *
  37 + * 冗余 {@link DiscountActivityDO#getName()}
  38 + */
  39 + private String activityName;
  40 + /**
35 * 商品 SPU 编号 41 * 商品 SPU 编号
36 * 42 *
37 * 关联 ProductSpuDO 的 id 编号 43 * 关联 ProductSpuDO 的 id 编号
yudao-module-mall/yudao-module-market-biz/src/main/java/cn/iocoder/yudao/module/market/service/price/PriceServiceImpl.java
@@ -107,33 +107,35 @@ public class PriceServiceImpl implements PriceService { @@ -107,33 +107,35 @@ public class PriceServiceImpl implements PriceService {
107 Integer memberPrice = memberDiscount != null ? (int) (orderItem.getPayPrice() * memberDiscount / 100) : null; 107 Integer memberPrice = memberDiscount != null ? (int) (orderItem.getPayPrice() * memberDiscount / 100) : null;
108 Integer promotionPrice = discountProduct != null ? discountProduct.getPromotionPrice() * orderItem.getCount() : null; 108 Integer promotionPrice = discountProduct != null ? discountProduct.getPromotionPrice() * orderItem.getCount() : null;
109 if (memberPrice == null) { 109 if (memberPrice == null) {
110 - 110 + calculatePriceByDiscountActivity(priceCalculate, orderItem, discountProduct, promotionPrice);
111 } else if (promotionPrice == null) { 111 } else if (promotionPrice == null) {
112 - calculatePriceByMemberDiscount(orderItem, memberDiscount, memberPrice, priceCalculate); 112 + calculatePriceByMemberDiscount(priceCalculate, orderItem, memberPrice);
113 } else if (memberPrice < promotionPrice) { 113 } else if (memberPrice < promotionPrice) {
114 - 114 + calculatePriceByDiscountActivity(priceCalculate, orderItem, discountProduct, promotionPrice);
115 } else { 115 } else {
116 - calculatePriceByMemberDiscount(orderItem, memberDiscount, memberPrice, priceCalculate); 116 + calculatePriceByMemberDiscount(priceCalculate, orderItem, memberPrice);
117 } 117 }
118 }); 118 });
119 } 119 }
120 120
121 - private void calculatePriceByMemberDiscount(PriceCalculateRespDTO.OrderItem orderItem,  
122 - Double memberDiscount, Integer memberPrice,  
123 - PriceCalculateRespDTO priceCalculate) { 121 + private void calculatePriceByMemberDiscount(PriceCalculateRespDTO priceCalculate, PriceCalculateRespDTO.OrderItem orderItem,
  122 + Integer memberPrice) {
124 // 记录优惠明细 123 // 记录优惠明细
125 - addPromotion(priceCalculate, orderItem, null,  
126 - PromotionTypeEnum.MEMBER.getName(), 124 + addPromotion(priceCalculate, orderItem, null, PromotionTypeEnum.MEMBER.getName(),
127 PromotionTypeEnum.MEMBER.getType(), PromotionLevelEnum.SKU.getLevel(), memberPrice, 125 PromotionTypeEnum.MEMBER.getType(), PromotionLevelEnum.SKU.getLevel(), memberPrice,
128 true, StrUtil.format("会员折扣:省 {} 元", formatPrice(orderItem.getPayPrice() - memberPrice))); 126 true, StrUtil.format("会员折扣:省 {} 元", formatPrice(orderItem.getPayPrice() - memberPrice)));
129 // 修改 SKU 的优惠 127 // 修改 SKU 的优惠
130 modifyOrderItemPayPrice(orderItem, memberPrice, priceCalculate); 128 modifyOrderItemPayPrice(orderItem, memberPrice, priceCalculate);
131 } 129 }
132 130
133 - private void calculatePriceByDiscountActivity(PriceCalculateRespDTO.OrderItem orderItem,  
134 - DiscountProductDO discountProduct, Integer promotionPrice,  
135 - PriceCalculateRespDTO priceCalculate) {  
136 - 131 + private void calculatePriceByDiscountActivity(PriceCalculateRespDTO priceCalculate, PriceCalculateRespDTO.OrderItem orderItem,
  132 + DiscountProductDO discountProduct, Integer promotionPrice) {
  133 + // 记录优惠明细
  134 + addPromotion(priceCalculate, orderItem, discountProduct.getActivityId(), discountProduct.getActivityName(),
  135 + PromotionTypeEnum.DISCOUNT_ACTIVITY.getType(), PromotionLevelEnum.SKU.getLevel(), promotionPrice,
  136 + true, StrUtil.format("限时折扣:省 {} 元", formatPrice(orderItem.getPayPrice() - promotionPrice)));
  137 + // 修改 SKU 的优惠
  138 + modifyOrderItemPayPrice(orderItem, promotionPrice, priceCalculate);
137 } 139 }
138 140
139 private void addPromotion(PriceCalculateRespDTO priceCalculate, PriceCalculateRespDTO.OrderItem orderItem, 141 private void addPromotion(PriceCalculateRespDTO priceCalculate, PriceCalculateRespDTO.OrderItem orderItem,
yudao-module-mall/yudao-module-market-biz/src/test/java/cn/iocoder/yudao/module/market/service/price/PriceServiceTest.java
1 package cn.iocoder.yudao.module.market.service.price; 1 package cn.iocoder.yudao.module.market.service.price;
2 2
  3 +import cn.hutool.core.map.MapUtil;
3 import cn.iocoder.yudao.framework.common.util.collection.SetUtils; 4 import cn.iocoder.yudao.framework.common.util.collection.SetUtils;
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.market.api.price.dto.PriceCalculateReqDTO; 6 import cn.iocoder.yudao.module.market.api.price.dto.PriceCalculateReqDTO;
6 import cn.iocoder.yudao.module.market.api.price.dto.PriceCalculateRespDTO; 7 import cn.iocoder.yudao.module.market.api.price.dto.PriceCalculateRespDTO;
  8 +import cn.iocoder.yudao.module.market.dal.dataobject.discount.DiscountProductDO;
7 import cn.iocoder.yudao.module.market.enums.common.PromotionLevelEnum; 9 import cn.iocoder.yudao.module.market.enums.common.PromotionLevelEnum;
8 import cn.iocoder.yudao.module.market.enums.common.PromotionTypeEnum; 10 import cn.iocoder.yudao.module.market.enums.common.PromotionTypeEnum;
9 import cn.iocoder.yudao.module.market.service.discount.DiscountService; 11 import cn.iocoder.yudao.module.market.service.discount.DiscountService;
@@ -13,7 +15,9 @@ import org.junit.jupiter.api.Test; @@ -13,7 +15,9 @@ import org.junit.jupiter.api.Test;
13 import org.mockito.InjectMocks; 15 import org.mockito.InjectMocks;
14 import org.mockito.Mock; 16 import org.mockito.Mock;
15 17
  18 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
16 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; 19 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
  20 +import static java.util.Arrays.asList;
17 import static java.util.Collections.singletonList; 21 import static java.util.Collections.singletonList;
18 import static org.junit.jupiter.api.Assertions.*; 22 import static org.junit.jupiter.api.Assertions.*;
19 import static org.mockito.ArgumentMatchers.eq; 23 import static org.mockito.ArgumentMatchers.eq;
@@ -55,8 +59,8 @@ public class PriceServiceTest extends BaseMockitoUnitTest { @@ -55,8 +59,8 @@ public class PriceServiceTest extends BaseMockitoUnitTest {
55 assertEquals(order.getPayPrice(), 180); 59 assertEquals(order.getPayPrice(), 180);
56 assertNull(order.getCouponId()); 60 assertNull(order.getCouponId());
57 // 断言 OrderItem 部分 61 // 断言 OrderItem 部分
58 - PriceCalculateRespDTO.OrderItem orderItem = order.getItems().get(0);  
59 assertEquals(order.getItems().size(), 1); 62 assertEquals(order.getItems().size(), 1);
  63 + PriceCalculateRespDTO.OrderItem orderItem = order.getItems().get(0);
60 assertEquals(orderItem.getSkuId(), 10L); 64 assertEquals(orderItem.getSkuId(), 10L);
61 assertEquals(orderItem.getCount(), 2); 65 assertEquals(orderItem.getCount(), 2);
62 assertEquals(orderItem.getOriginalPrice(), 200); 66 assertEquals(orderItem.getOriginalPrice(), 200);
@@ -66,8 +70,8 @@ public class PriceServiceTest extends BaseMockitoUnitTest { @@ -66,8 +70,8 @@ public class PriceServiceTest extends BaseMockitoUnitTest {
66 assertEquals(orderItem.getOrderPartPrice(), 0); 70 assertEquals(orderItem.getOrderPartPrice(), 0);
67 assertEquals(orderItem.getOrderDividePrice(), 180); 71 assertEquals(orderItem.getOrderDividePrice(), 180);
68 // 断言 Promotion 部分 72 // 断言 Promotion 部分
69 - PriceCalculateRespDTO.Promotion promotion = priceCalculate.getPromotions().get(0);  
70 assertEquals(priceCalculate.getPromotions().size(), 1); 73 assertEquals(priceCalculate.getPromotions().size(), 1);
  74 + PriceCalculateRespDTO.Promotion promotion = priceCalculate.getPromotions().get(0);
71 assertNull(promotion.getId()); 75 assertNull(promotion.getId());
72 assertEquals(promotion.getName(), "会员折扣"); 76 assertEquals(promotion.getName(), "会员折扣");
73 assertEquals(promotion.getType(), PromotionTypeEnum.MEMBER.getType()); 77 assertEquals(promotion.getType(), PromotionTypeEnum.MEMBER.getType());
@@ -83,4 +87,84 @@ public class PriceServiceTest extends BaseMockitoUnitTest { @@ -83,4 +87,84 @@ public class PriceServiceTest extends BaseMockitoUnitTest {
83 assertEquals(promotionItem.getDiscountPrice(), 20); 87 assertEquals(promotionItem.getDiscountPrice(), 20);
84 } 88 }
85 89
  90 + @Test
  91 + public void testCalculatePrice_discountActivity() {
  92 + // 准备参数
  93 + PriceCalculateReqDTO calculateReqDTO = new PriceCalculateReqDTO().setUserId(randomLongId())
  94 + .setItems(asList(new PriceCalculateReqDTO.Item().setSkuId(10L).setCount(2),
  95 + new PriceCalculateReqDTO.Item().setSkuId(20L).setCount(3)));
  96 + // mock 方法(商品 SKU 信息)
  97 + ProductSkuRespDTO productSku01 = randomPojo(ProductSkuRespDTO.class, o -> o.setId(10L).setPrice(100));
  98 + ProductSkuRespDTO productSku02 = randomPojo(ProductSkuRespDTO.class, o -> o.setId(20L).setPrice(50));
  99 + when(productSkuApi.getSkuList(eq(SetUtils.asSet(10L, 20L)))).thenReturn(asList(productSku01, productSku02));
  100 + // mock 方法(限时折扣 DiscountActivity 信息)
  101 + DiscountProductDO discountProduct01 = randomPojo(DiscountProductDO.class, o -> o.setActivityId(1000L).setActivityName("活动 1000 号")
  102 + .setSkuId(10L).setPromotionPrice(80));
  103 + DiscountProductDO discountProduct02 = randomPojo(DiscountProductDO.class, o -> o.setActivityId(2000L).setActivityName("活动 2000 号")
  104 + .setSkuId(20L).setPromotionPrice(40));
  105 + when(discountService.getMatchDiscountProducts(eq(SetUtils.asSet(10L, 20L)))).thenReturn(
  106 + MapUtil.builder(10L, discountProduct01).put(20L, discountProduct02).map());
  107 +
  108 + // 调用
  109 + PriceCalculateRespDTO priceCalculate = priceService.calculatePrice(calculateReqDTO);
  110 + // 断言 Order 部分
  111 + PriceCalculateRespDTO.Order order = priceCalculate.getOrder();
  112 + assertEquals(order.getOriginalPrice(), 350);
  113 + assertEquals(order.getDiscountPrice(), 0);
  114 + assertEquals(order.getPointPrice(), 0);
  115 + assertEquals(order.getDeliveryPrice(), 0);
  116 + assertEquals(order.getPayPrice(), 280);
  117 + assertNull(order.getCouponId());
  118 + // 断言 OrderItem 部分
  119 + assertEquals(order.getItems().size(), 2);
  120 + PriceCalculateRespDTO.OrderItem orderItem01 = order.getItems().get(0);
  121 + assertEquals(orderItem01.getSkuId(), 10L);
  122 + assertEquals(orderItem01.getCount(), 2);
  123 + assertEquals(orderItem01.getOriginalPrice(), 200);
  124 + assertEquals(orderItem01.getOriginalUnitPrice(), 100);
  125 + assertEquals(orderItem01.getDiscountPrice(), 40);
  126 + assertEquals(orderItem01.getPayPrice(), 160);
  127 + assertEquals(orderItem01.getOrderPartPrice(), 0);
  128 + assertEquals(orderItem01.getOrderDividePrice(), 160);
  129 + PriceCalculateRespDTO.OrderItem orderItem02 = order.getItems().get(1);
  130 + assertEquals(orderItem02.getSkuId(), 20L);
  131 + assertEquals(orderItem02.getCount(), 3);
  132 + assertEquals(orderItem02.getOriginalPrice(), 150);
  133 + assertEquals(orderItem02.getOriginalUnitPrice(), 50);
  134 + assertEquals(orderItem02.getDiscountPrice(), 30);
  135 + assertEquals(orderItem02.getPayPrice(), 120);
  136 + assertEquals(orderItem02.getOrderPartPrice(), 0);
  137 + assertEquals(orderItem02.getOrderDividePrice(), 120);
  138 + // 断言 Promotion 部分
  139 + assertEquals(priceCalculate.getPromotions().size(), 2);
  140 + PriceCalculateRespDTO.Promotion promotion01 = priceCalculate.getPromotions().get(0);
  141 + assertEquals(promotion01.getId(), 1000L);
  142 + assertEquals(promotion01.getName(), "活动 1000 号");
  143 + assertEquals(promotion01.getType(), PromotionTypeEnum.DISCOUNT_ACTIVITY.getType());
  144 + assertEquals(promotion01.getLevel(), PromotionLevelEnum.SKU.getLevel());
  145 + assertEquals(promotion01.getOriginalPrice(), 200);
  146 + assertEquals(promotion01.getDiscountPrice(), 40);
  147 + assertTrue(promotion01.getMeet());
  148 + assertEquals(promotion01.getMeetTip(), "限时折扣:省 0.40 元");
  149 + PriceCalculateRespDTO.PromotionItem promotionItem01 = promotion01.getItems().get(0);
  150 + assertEquals(promotion01.getItems().size(), 1);
  151 + assertEquals(promotionItem01.getSkuId(), 10L);
  152 + assertEquals(promotionItem01.getOriginalPrice(), 200);
  153 + assertEquals(promotionItem01.getDiscountPrice(), 40);
  154 + PriceCalculateRespDTO.Promotion promotion02 = priceCalculate.getPromotions().get(1);
  155 + assertEquals(promotion02.getId(), 2000L);
  156 + assertEquals(promotion02.getName(), "活动 2000 号");
  157 + assertEquals(promotion02.getType(), PromotionTypeEnum.DISCOUNT_ACTIVITY.getType());
  158 + assertEquals(promotion02.getLevel(), PromotionLevelEnum.SKU.getLevel());
  159 + assertEquals(promotion02.getOriginalPrice(), 150);
  160 + assertEquals(promotion02.getDiscountPrice(), 30);
  161 + assertTrue(promotion02.getMeet());
  162 + assertEquals(promotion02.getMeetTip(), "限时折扣:省 0.30 元");
  163 + PriceCalculateRespDTO.PromotionItem promotionItem02 = promotion02.getItems().get(0);
  164 + assertEquals(promotion02.getItems().size(), 1);
  165 + assertEquals(promotionItem02.getSkuId(), 20L);
  166 + assertEquals(promotionItem02.getOriginalPrice(), 150);
  167 + assertEquals(promotionItem02.getDiscountPrice(), 30);
  168 + }
  169 +
86 } 170 }