Commit 71c40cf5adfba02f7d7e1181d75536c5d66889e6
1 parent
ad1ceaaf
【代码优化】商城: 限时折扣活动
Showing
7 changed files
with
53 additions
and
41 deletions
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/DiscountActivityApi.java
| @@ -15,9 +15,9 @@ public interface DiscountActivityApi { | @@ -15,9 +15,9 @@ public interface DiscountActivityApi { | ||
| 15 | /** | 15 | /** |
| 16 | * 获得商品匹配的的限时折扣信息 | 16 | * 获得商品匹配的的限时折扣信息 |
| 17 | * | 17 | * |
| 18 | - * @param skuIds 商品 SKU 编号数组 | 18 | + * @param spuIds 商品 spu 编号数组 |
| 19 | * @return 限时折扣信息 | 19 | * @return 限时折扣信息 |
| 20 | */ | 20 | */ |
| 21 | - List<DiscountProductRespDTO> getMatchDiscountProductList(Collection<Long> skuIds); | 21 | + List<DiscountProductRespDTO> getMatchDiscountProductList(Collection<Long> spuIds); |
| 22 | 22 | ||
| 23 | } | 23 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/DiscountActivityApiImpl.java
| @@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.promotion.api.discount; | @@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.promotion.api.discount; | ||
| 3 | import cn.iocoder.yudao.module.promotion.api.discount.dto.DiscountProductRespDTO; | 3 | import cn.iocoder.yudao.module.promotion.api.discount.dto.DiscountProductRespDTO; |
| 4 | import cn.iocoder.yudao.module.promotion.convert.discount.DiscountActivityConvert; | 4 | import cn.iocoder.yudao.module.promotion.convert.discount.DiscountActivityConvert; |
| 5 | import cn.iocoder.yudao.module.promotion.service.discount.DiscountActivityService; | 5 | import cn.iocoder.yudao.module.promotion.service.discount.DiscountActivityService; |
| 6 | +import jakarta.annotation.Resource; | ||
| 6 | import org.springframework.stereotype.Service; | 7 | import org.springframework.stereotype.Service; |
| 7 | import org.springframework.validation.annotation.Validated; | 8 | import org.springframework.validation.annotation.Validated; |
| 8 | 9 | ||
| 9 | -import jakarta.annotation.Resource; | ||
| 10 | import java.util.Collection; | 10 | import java.util.Collection; |
| 11 | import java.util.List; | 11 | import java.util.List; |
| 12 | 12 | ||
| @@ -23,8 +23,8 @@ public class DiscountActivityApiImpl implements DiscountActivityApi { | @@ -23,8 +23,8 @@ public class DiscountActivityApiImpl implements DiscountActivityApi { | ||
| 23 | private DiscountActivityService discountActivityService; | 23 | private DiscountActivityService discountActivityService; |
| 24 | 24 | ||
| 25 | @Override | 25 | @Override |
| 26 | - public List<DiscountProductRespDTO> getMatchDiscountProductList(Collection<Long> skuIds) { | ||
| 27 | - return DiscountActivityConvert.INSTANCE.convertList02(discountActivityService.getMatchDiscountProductList(skuIds)); | 26 | + public List<DiscountProductRespDTO> getMatchDiscountProductList(Collection<Long> spuIds) { |
| 27 | + return DiscountActivityConvert.INSTANCE.convertList02(discountActivityService.getMatchDiscountProductList(spuIds)); | ||
| 28 | } | 28 | } |
| 29 | 29 | ||
| 30 | } | 30 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/discount/DiscountProductMapper.java
| 1 | package cn.iocoder.yudao.module.promotion.dal.mysql.discount; | 1 | package cn.iocoder.yudao.module.promotion.dal.mysql.discount; |
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | 3 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| 4 | +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | ||
| 4 | import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO; | 5 | import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO; |
| 5 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | 6 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| 7 | +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; | ||
| 6 | import org.apache.ibatis.annotations.Mapper; | 8 | import org.apache.ibatis.annotations.Mapper; |
| 7 | -import org.apache.ibatis.annotations.Param; | ||
| 8 | 9 | ||
| 9 | import java.util.Collection; | 10 | import java.util.Collection; |
| 10 | import java.util.List; | 11 | import java.util.List; |
| @@ -27,9 +28,6 @@ public interface DiscountProductMapper extends BaseMapperX<DiscountProductDO> { | @@ -27,9 +28,6 @@ public interface DiscountProductMapper extends BaseMapperX<DiscountProductDO> { | ||
| 27 | return selectList(DiscountProductDO::getActivityId, activityIds); | 28 | return selectList(DiscountProductDO::getActivityId, activityIds); |
| 28 | } | 29 | } |
| 29 | 30 | ||
| 30 | - // TODO @zhangshuai:逻辑里,尽量避免写 join 语句哈,你可以看看这个查询,有什么办法优化?目前的一个思路,是分 2 次查询,性能也是 ok 的 | ||
| 31 | - List<DiscountProductDO> getMatchDiscountProductList(@Param("skuIds") Collection<Long> skuIds); | ||
| 32 | - | ||
| 33 | /** | 31 | /** |
| 34 | * 查询出指定 spuId 的 spu 参加的活动最接近现在的一条记录。多个的话,一个 spuId 对应一个最近的活动编号 | 32 | * 查询出指定 spuId 的 spu 参加的活动最接近现在的一条记录。多个的话,一个 spuId 对应一个最近的活动编号 |
| 35 | * | 33 | * |
| @@ -45,4 +43,19 @@ public interface DiscountProductMapper extends BaseMapperX<DiscountProductDO> { | @@ -45,4 +43,19 @@ public interface DiscountProductMapper extends BaseMapperX<DiscountProductDO> { | ||
| 45 | .groupBy("spu_id")); | 43 | .groupBy("spu_id")); |
| 46 | } | 44 | } |
| 47 | 45 | ||
| 46 | + default List<DiscountProductDO> selectListBySpuIdsAndStatus(Collection<Long> spuIds, Integer status) { | ||
| 47 | + return selectList(new LambdaQueryWrapperX<DiscountProductDO>() | ||
| 48 | + .in(DiscountProductDO::getSpuId, spuIds) | ||
| 49 | + .eq(DiscountProductDO::getActivityStatus, status)); | ||
| 50 | + } | ||
| 51 | + | ||
| 52 | + default void updateByActivityId(DiscountProductDO discountProductDO) { | ||
| 53 | + update(discountProductDO, new LambdaUpdateWrapper<DiscountProductDO>() | ||
| 54 | + .eq(DiscountProductDO::getActivityId, discountProductDO.getActivityId())); | ||
| 55 | + } | ||
| 56 | + | ||
| 57 | + default void deleteByActivityId(Long activityId) { | ||
| 58 | + delete(DiscountProductDO::getActivityId, activityId); | ||
| 59 | + } | ||
| 60 | + | ||
| 48 | } | 61 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityService.java
| @@ -24,10 +24,10 @@ public interface DiscountActivityService { | @@ -24,10 +24,10 @@ public interface DiscountActivityService { | ||
| 24 | * | 24 | * |
| 25 | * 注意,匹配的条件,仅仅是日期符合,并且处于开启状态 | 25 | * 注意,匹配的条件,仅仅是日期符合,并且处于开启状态 |
| 26 | * | 26 | * |
| 27 | - * @param skuIds SKU 编号数组 | 27 | + * @param spuIds SKU 编号数组 |
| 28 | * @return 匹配的限时折扣商品 | 28 | * @return 匹配的限时折扣商品 |
| 29 | */ | 29 | */ |
| 30 | - List<DiscountProductDO> getMatchDiscountProductList(Collection<Long> skuIds); | 30 | + List<DiscountProductDO> getMatchDiscountProductList(Collection<Long> spuIds); |
| 31 | 31 | ||
| 32 | /** | 32 | /** |
| 33 | * 创建限时折扣活动 | 33 | * 创建限时折扣活动 |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityServiceImpl.java
| @@ -18,7 +18,6 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountActivit | @@ -18,7 +18,6 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountActivit | ||
| 18 | import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO; | 18 | import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO; |
| 19 | import cn.iocoder.yudao.module.promotion.dal.mysql.discount.DiscountActivityMapper; | 19 | import cn.iocoder.yudao.module.promotion.dal.mysql.discount.DiscountActivityMapper; |
| 20 | import cn.iocoder.yudao.module.promotion.dal.mysql.discount.DiscountProductMapper; | 20 | import cn.iocoder.yudao.module.promotion.dal.mysql.discount.DiscountProductMapper; |
| 21 | -import cn.iocoder.yudao.module.promotion.enums.common.PromotionActivityStatusEnum; | ||
| 22 | import cn.iocoder.yudao.module.promotion.util.PromotionUtils; | 21 | import cn.iocoder.yudao.module.promotion.util.PromotionUtils; |
| 23 | import jakarta.annotation.Resource; | 22 | import jakarta.annotation.Resource; |
| 24 | import org.springframework.stereotype.Service; | 23 | import org.springframework.stereotype.Service; |
| @@ -55,8 +54,22 @@ public class DiscountActivityServiceImpl implements DiscountActivityService { | @@ -55,8 +54,22 @@ public class DiscountActivityServiceImpl implements DiscountActivityService { | ||
| 55 | private ProductSkuApi productSkuApi; | 54 | private ProductSkuApi productSkuApi; |
| 56 | 55 | ||
| 57 | @Override | 56 | @Override |
| 58 | - public List<DiscountProductDO> getMatchDiscountProductList(Collection<Long> skuIds) { | ||
| 59 | - return discountProductMapper.getMatchDiscountProductList(skuIds); | 57 | + public List<DiscountProductDO> getMatchDiscountProductList(Collection<Long> spuIds) { |
| 58 | + // 1.1 查询出 spu 对应的开启的限时折扣商品 | ||
| 59 | + List<DiscountProductDO> productList = discountProductMapper.selectListBySpuIdsAndStatus(spuIds, | ||
| 60 | + CommonStatusEnum.ENABLE.getStatus()); | ||
| 61 | + if (CollUtil.isEmpty(productList)) { | ||
| 62 | + return Collections.emptyList(); | ||
| 63 | + } | ||
| 64 | + // 1.2 查询出符合的限时折扣活动 | ||
| 65 | + List<DiscountActivityDO> activityList = discountActivityMapper.selectListByIdsAndDateTimeLt( | ||
| 66 | + convertSet(productList, DiscountProductDO::getActivityId), LocalDateTime.now()); | ||
| 67 | + if (CollUtil.isEmpty(productList)) { | ||
| 68 | + return Collections.emptyList(); | ||
| 69 | + } | ||
| 70 | + | ||
| 71 | + // 2. 获得这些活动的商品列表 | ||
| 72 | + return discountProductMapper.selectListByActivityId(convertList(activityList, DiscountActivityDO::getId)); | ||
| 60 | } | 73 | } |
| 61 | 74 | ||
| 62 | @Override | 75 | @Override |
| @@ -182,9 +195,11 @@ public class DiscountActivityServiceImpl implements DiscountActivityService { | @@ -182,9 +195,11 @@ public class DiscountActivityServiceImpl implements DiscountActivityService { | ||
| 182 | throw exception(DISCOUNT_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED); | 195 | throw exception(DISCOUNT_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED); |
| 183 | } | 196 | } |
| 184 | 197 | ||
| 185 | - // 更新 | ||
| 186 | - DiscountActivityDO updateObj = new DiscountActivityDO().setId(id).setStatus(PromotionActivityStatusEnum.CLOSE.getStatus()); | ||
| 187 | - discountActivityMapper.updateById(updateObj); | 198 | + // 更新活动状态 |
| 199 | + discountActivityMapper.updateById(new DiscountActivityDO().setId(id).setStatus(CommonStatusEnum.DISABLE.getStatus())); | ||
| 200 | + // 更新活动商品状态 | ||
| 201 | + discountProductMapper.updateByActivityId(new DiscountProductDO().setActivityId(id).setActivityStatus( | ||
| 202 | + CommonStatusEnum.DISABLE.getStatus())); | ||
| 188 | } | 203 | } |
| 189 | 204 | ||
| 190 | @Override | 205 | @Override |
| @@ -195,8 +210,10 @@ public class DiscountActivityServiceImpl implements DiscountActivityService { | @@ -195,8 +210,10 @@ public class DiscountActivityServiceImpl implements DiscountActivityService { | ||
| 195 | throw exception(DISCOUNT_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED); | 210 | throw exception(DISCOUNT_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED); |
| 196 | } | 211 | } |
| 197 | 212 | ||
| 198 | - // 删除 | 213 | + // 删除活动 |
| 199 | discountActivityMapper.deleteById(id); | 214 | discountActivityMapper.deleteById(id); |
| 215 | + // 删除活动商品 | ||
| 216 | + discountProductMapper.deleteByActivityId(id); | ||
| 200 | } | 217 | } |
| 201 | 218 | ||
| 202 | private DiscountActivityDO validateDiscountActivityExists(Long id) { | 219 | private DiscountActivityDO validateDiscountActivityExists(Long id) { |
| @@ -224,7 +241,7 @@ public class DiscountActivityServiceImpl implements DiscountActivityService { | @@ -224,7 +241,7 @@ public class DiscountActivityServiceImpl implements DiscountActivityService { | ||
| 224 | 241 | ||
| 225 | @Override | 242 | @Override |
| 226 | public List<DiscountProductDO> getDiscountProductsByActivityId(Collection<Long> activityIds) { | 243 | public List<DiscountProductDO> getDiscountProductsByActivityId(Collection<Long> activityIds) { |
| 227 | - return discountProductMapper.selectList("activity_id", activityIds); | 244 | + return discountProductMapper.selectList(DiscountProductDO::getActivityId, activityIds); |
| 228 | } | 245 | } |
| 229 | 246 | ||
| 230 | @Override | 247 | @Override |
yudao-module-mall/yudao-module-promotion-biz/src/main/resources/mapper/discount/DiscountProductMapper.xml
| @@ -2,23 +2,4 @@ | @@ -2,23 +2,4 @@ | ||
| 2 | <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | 2 | <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
| 3 | <mapper namespace="cn.iocoder.yudao.module.promotion.dal.mysql.discount.DiscountProductMapper"> | 3 | <mapper namespace="cn.iocoder.yudao.module.promotion.dal.mysql.discount.DiscountProductMapper"> |
| 4 | 4 | ||
| 5 | - | ||
| 6 | - <select id="getMatchDiscountProductList" resultType="cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO"> | ||
| 7 | - SELECT pdp.* | ||
| 8 | - FROM promotion_discount_product pdp | ||
| 9 | - LEFT JOIN promotion_discount_activity pda | ||
| 10 | - ON pdp.activity_id = pda.id | ||
| 11 | - <where> | ||
| 12 | - <if test="skuIds != null and skuIds.size > 0"> | ||
| 13 | - AND pdp.sku_id in | ||
| 14 | - <foreach collection="skuIds" item="skuId" index="index" open="(" close=")" separator=","> | ||
| 15 | - #{skuId} | ||
| 16 | - </foreach> | ||
| 17 | - </if> | ||
| 18 | - AND pda.start_time <= CURRENT_TIME AND pda.end_time >= CURRENT_TIME | ||
| 19 | - AND pda.`status` = 20 | ||
| 20 | - AND pda.deleted != 1 | ||
| 21 | - </where> | ||
| 22 | - </select> | ||
| 23 | - | ||
| 24 | </mapper> | 5 | </mapper> |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeDiscountActivityPriceCalculator.java
| @@ -10,15 +10,16 @@ import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum; | @@ -10,15 +10,16 @@ import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum; | ||
| 10 | import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; | 10 | import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; |
| 11 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; | 11 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; |
| 12 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; | 12 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; |
| 13 | +import jakarta.annotation.Resource; | ||
| 13 | import org.springframework.core.annotation.Order; | 14 | import org.springframework.core.annotation.Order; |
| 14 | import org.springframework.stereotype.Component; | 15 | import org.springframework.stereotype.Component; |
| 15 | 16 | ||
| 16 | -import jakarta.annotation.Resource; | ||
| 17 | import java.util.List; | 17 | import java.util.List; |
| 18 | import java.util.Map; | 18 | import java.util.Map; |
| 19 | 19 | ||
| 20 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; | 20 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; |
| 21 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; | 21 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; |
| 22 | +import static cn.iocoder.yudao.framework.common.util.number.MoneyUtils.calculateRatePrice; | ||
| 22 | import static cn.iocoder.yudao.module.trade.service.price.calculator.TradePriceCalculatorHelper.formatPrice; | 23 | import static cn.iocoder.yudao.module.trade.service.price.calculator.TradePriceCalculatorHelper.formatPrice; |
| 23 | 24 | ||
| 24 | /** | 25 | /** |
| @@ -41,7 +42,7 @@ public class TradeDiscountActivityPriceCalculator implements TradePriceCalculato | @@ -41,7 +42,7 @@ public class TradeDiscountActivityPriceCalculator implements TradePriceCalculato | ||
| 41 | } | 42 | } |
| 42 | // 获得 SKU 对应的限时折扣活动 | 43 | // 获得 SKU 对应的限时折扣活动 |
| 43 | List<DiscountProductRespDTO> discountProducts = discountActivityApi.getMatchDiscountProductList( | 44 | List<DiscountProductRespDTO> discountProducts = discountActivityApi.getMatchDiscountProductList( |
| 44 | - convertSet(result.getItems(), TradePriceCalculateRespBO.OrderItem::getSkuId)); | 45 | + convertSet(result.getItems(), TradePriceCalculateRespBO.OrderItem::getSpuId)); |
| 45 | if (CollUtil.isEmpty(discountProducts)) { | 46 | if (CollUtil.isEmpty(discountProducts)) { |
| 46 | return; | 47 | return; |
| 47 | } | 48 | } |
| @@ -79,7 +80,7 @@ public class TradeDiscountActivityPriceCalculator implements TradePriceCalculato | @@ -79,7 +80,7 @@ public class TradeDiscountActivityPriceCalculator implements TradePriceCalculato | ||
| 79 | if (PromotionDiscountTypeEnum.PRICE.getType().equals(discountProduct.getDiscountType())) { // 减价 | 80 | if (PromotionDiscountTypeEnum.PRICE.getType().equals(discountProduct.getDiscountType())) { // 减价 |
| 80 | price -= discountProduct.getDiscountPrice() * orderItem.getCount(); | 81 | price -= discountProduct.getDiscountPrice() * orderItem.getCount(); |
| 81 | } else if (PromotionDiscountTypeEnum.PERCENT.getType().equals(discountProduct.getDiscountType())) { // 打折 | 82 | } else if (PromotionDiscountTypeEnum.PERCENT.getType().equals(discountProduct.getDiscountType())) { // 打折 |
| 82 | - price = price * discountProduct.getDiscountPercent() / 100; | 83 | + price = calculateRatePrice(price, discountProduct.getDiscountPercent() / 100.0); |
| 83 | } else { | 84 | } else { |
| 84 | throw new IllegalArgumentException(String.format("优惠活动的商品(%s) 的优惠类型不正确", discountProduct)); | 85 | throw new IllegalArgumentException(String.format("优惠活动的商品(%s) 的优惠类型不正确", discountProduct)); |
| 85 | } | 86 | } |