【代码优化】商城: 限时折扣活动

This commit is contained in:
puhui999 2024-09-15 14:01:37 +08:00
parent ad1ceaaf1c
commit 71c40cf5ad
7 changed files with 53 additions and 41 deletions

View File

@ -15,9 +15,9 @@ public interface DiscountActivityApi {
/** /**
* 获得商品匹配的的限时折扣信息 * 获得商品匹配的的限时折扣信息
* *
* @param skuIds 商品 SKU 编号数组 * @param spuIds 商品 spu 编号数组
* @return 限时折扣信息 * @return 限时折扣信息
*/ */
List<DiscountProductRespDTO> getMatchDiscountProductList(Collection<Long> skuIds); List<DiscountProductRespDTO> getMatchDiscountProductList(Collection<Long> spuIds);
} }

View File

@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.promotion.api.discount;
import cn.iocoder.yudao.module.promotion.api.discount.dto.DiscountProductRespDTO; import cn.iocoder.yudao.module.promotion.api.discount.dto.DiscountProductRespDTO;
import cn.iocoder.yudao.module.promotion.convert.discount.DiscountActivityConvert; import cn.iocoder.yudao.module.promotion.convert.discount.DiscountActivityConvert;
import cn.iocoder.yudao.module.promotion.service.discount.DiscountActivityService; import cn.iocoder.yudao.module.promotion.service.discount.DiscountActivityService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import jakarta.annotation.Resource;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
@ -23,8 +23,8 @@ public class DiscountActivityApiImpl implements DiscountActivityApi {
private DiscountActivityService discountActivityService; private DiscountActivityService discountActivityService;
@Override @Override
public List<DiscountProductRespDTO> getMatchDiscountProductList(Collection<Long> skuIds) { public List<DiscountProductRespDTO> getMatchDiscountProductList(Collection<Long> spuIds) {
return DiscountActivityConvert.INSTANCE.convertList02(discountActivityService.getMatchDiscountProductList(skuIds)); return DiscountActivityConvert.INSTANCE.convertList02(discountActivityService.getMatchDiscountProductList(spuIds));
} }
} }

View File

@ -1,10 +1,11 @@
package cn.iocoder.yudao.module.promotion.dal.mysql.discount; package cn.iocoder.yudao.module.promotion.dal.mysql.discount;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
@ -27,9 +28,6 @@ public interface DiscountProductMapper extends BaseMapperX<DiscountProductDO> {
return selectList(DiscountProductDO::getActivityId, activityIds); return selectList(DiscountProductDO::getActivityId, activityIds);
} }
// TODO @zhangshuai逻辑里尽量避免写 join 语句哈你可以看看这个查询有什么办法优化目前的一个思路是分 2 次查询性能也是 ok
List<DiscountProductDO> getMatchDiscountProductList(@Param("skuIds") Collection<Long> skuIds);
/** /**
* 查询出指定 spuId spu 参加的活动最接近现在的一条记录多个的话一个 spuId 对应一个最近的活动编号 * 查询出指定 spuId spu 参加的活动最接近现在的一条记录多个的话一个 spuId 对应一个最近的活动编号
* *
@ -45,4 +43,19 @@ public interface DiscountProductMapper extends BaseMapperX<DiscountProductDO> {
.groupBy("spu_id")); .groupBy("spu_id"));
} }
default List<DiscountProductDO> selectListBySpuIdsAndStatus(Collection<Long> spuIds, Integer status) {
return selectList(new LambdaQueryWrapperX<DiscountProductDO>()
.in(DiscountProductDO::getSpuId, spuIds)
.eq(DiscountProductDO::getActivityStatus, status));
}
default void updateByActivityId(DiscountProductDO discountProductDO) {
update(discountProductDO, new LambdaUpdateWrapper<DiscountProductDO>()
.eq(DiscountProductDO::getActivityId, discountProductDO.getActivityId()));
}
default void deleteByActivityId(Long activityId) {
delete(DiscountProductDO::getActivityId, activityId);
}
} }

View File

@ -24,10 +24,10 @@ public interface DiscountActivityService {
* *
* 注意匹配的条件仅仅是日期符合并且处于开启状态 * 注意匹配的条件仅仅是日期符合并且处于开启状态
* *
* @param skuIds SKU 编号数组 * @param spuIds SKU 编号数组
* @return 匹配的限时折扣商品 * @return 匹配的限时折扣商品
*/ */
List<DiscountProductDO> getMatchDiscountProductList(Collection<Long> skuIds); List<DiscountProductDO> getMatchDiscountProductList(Collection<Long> spuIds);
/** /**
* 创建限时折扣活动 * 创建限时折扣活动

View File

@ -18,7 +18,6 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountActivit
import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO;
import cn.iocoder.yudao.module.promotion.dal.mysql.discount.DiscountActivityMapper; import cn.iocoder.yudao.module.promotion.dal.mysql.discount.DiscountActivityMapper;
import cn.iocoder.yudao.module.promotion.dal.mysql.discount.DiscountProductMapper; import cn.iocoder.yudao.module.promotion.dal.mysql.discount.DiscountProductMapper;
import cn.iocoder.yudao.module.promotion.enums.common.PromotionActivityStatusEnum;
import cn.iocoder.yudao.module.promotion.util.PromotionUtils; import cn.iocoder.yudao.module.promotion.util.PromotionUtils;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -55,8 +54,22 @@ public class DiscountActivityServiceImpl implements DiscountActivityService {
private ProductSkuApi productSkuApi; private ProductSkuApi productSkuApi;
@Override @Override
public List<DiscountProductDO> getMatchDiscountProductList(Collection<Long> skuIds) { public List<DiscountProductDO> getMatchDiscountProductList(Collection<Long> spuIds) {
return discountProductMapper.getMatchDiscountProductList(skuIds); // 1.1 查询出 spu 对应的开启的限时折扣商品
List<DiscountProductDO> productList = discountProductMapper.selectListBySpuIdsAndStatus(spuIds,
CommonStatusEnum.ENABLE.getStatus());
if (CollUtil.isEmpty(productList)) {
return Collections.emptyList();
}
// 1.2 查询出符合的限时折扣活动
List<DiscountActivityDO> activityList = discountActivityMapper.selectListByIdsAndDateTimeLt(
convertSet(productList, DiscountProductDO::getActivityId), LocalDateTime.now());
if (CollUtil.isEmpty(productList)) {
return Collections.emptyList();
}
// 2. 获得这些活动的商品列表
return discountProductMapper.selectListByActivityId(convertList(activityList, DiscountActivityDO::getId));
} }
@Override @Override
@ -182,9 +195,11 @@ public class DiscountActivityServiceImpl implements DiscountActivityService {
throw exception(DISCOUNT_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED); throw exception(DISCOUNT_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED);
} }
// 更新 // 更新活动状态
DiscountActivityDO updateObj = new DiscountActivityDO().setId(id).setStatus(PromotionActivityStatusEnum.CLOSE.getStatus()); discountActivityMapper.updateById(new DiscountActivityDO().setId(id).setStatus(CommonStatusEnum.DISABLE.getStatus()));
discountActivityMapper.updateById(updateObj); // 更新活动商品状态
discountProductMapper.updateByActivityId(new DiscountProductDO().setActivityId(id).setActivityStatus(
CommonStatusEnum.DISABLE.getStatus()));
} }
@Override @Override
@ -195,8 +210,10 @@ public class DiscountActivityServiceImpl implements DiscountActivityService {
throw exception(DISCOUNT_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED); throw exception(DISCOUNT_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED);
} }
// 删除 // 删除活动
discountActivityMapper.deleteById(id); discountActivityMapper.deleteById(id);
// 删除活动商品
discountProductMapper.deleteByActivityId(id);
} }
private DiscountActivityDO validateDiscountActivityExists(Long id) { private DiscountActivityDO validateDiscountActivityExists(Long id) {
@ -224,7 +241,7 @@ public class DiscountActivityServiceImpl implements DiscountActivityService {
@Override @Override
public List<DiscountProductDO> getDiscountProductsByActivityId(Collection<Long> activityIds) { public List<DiscountProductDO> getDiscountProductsByActivityId(Collection<Long> activityIds) {
return discountProductMapper.selectList("activity_id", activityIds); return discountProductMapper.selectList(DiscountProductDO::getActivityId, activityIds);
} }
@Override @Override

View File

@ -2,23 +2,4 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.iocoder.yudao.module.promotion.dal.mysql.discount.DiscountProductMapper"> <mapper namespace="cn.iocoder.yudao.module.promotion.dal.mysql.discount.DiscountProductMapper">
<select id="getMatchDiscountProductList" resultType="cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO">
SELECT pdp.*
FROM promotion_discount_product pdp
LEFT JOIN promotion_discount_activity pda
ON pdp.activity_id = pda.id
<where>
<if test="skuIds != null and skuIds.size > 0">
AND pdp.sku_id in
<foreach collection="skuIds" item="skuId" index="index" open="(" close=")" separator=",">
#{skuId}
</foreach>
</if>
AND pda.start_time &lt;= CURRENT_TIME AND pda.end_time &gt;= CURRENT_TIME
AND pda.`status` = 20
AND pda.deleted != 1
</where>
</select>
</mapper> </mapper>

View File

@ -10,15 +10,16 @@ import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum;
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum;
import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO;
import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO;
import jakarta.annotation.Resource;
import org.springframework.core.annotation.Order; import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import jakarta.annotation.Resource;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.framework.common.util.number.MoneyUtils.calculateRatePrice;
import static cn.iocoder.yudao.module.trade.service.price.calculator.TradePriceCalculatorHelper.formatPrice; import static cn.iocoder.yudao.module.trade.service.price.calculator.TradePriceCalculatorHelper.formatPrice;
/** /**
@ -41,7 +42,7 @@ public class TradeDiscountActivityPriceCalculator implements TradePriceCalculato
} }
// 获得 SKU 对应的限时折扣活动 // 获得 SKU 对应的限时折扣活动
List<DiscountProductRespDTO> discountProducts = discountActivityApi.getMatchDiscountProductList( List<DiscountProductRespDTO> discountProducts = discountActivityApi.getMatchDiscountProductList(
convertSet(result.getItems(), TradePriceCalculateRespBO.OrderItem::getSkuId)); convertSet(result.getItems(), TradePriceCalculateRespBO.OrderItem::getSpuId));
if (CollUtil.isEmpty(discountProducts)) { if (CollUtil.isEmpty(discountProducts)) {
return; return;
} }
@ -79,7 +80,7 @@ public class TradeDiscountActivityPriceCalculator implements TradePriceCalculato
if (PromotionDiscountTypeEnum.PRICE.getType().equals(discountProduct.getDiscountType())) { // 减价 if (PromotionDiscountTypeEnum.PRICE.getType().equals(discountProduct.getDiscountType())) { // 减价
price -= discountProduct.getDiscountPrice() * orderItem.getCount(); price -= discountProduct.getDiscountPrice() * orderItem.getCount();
} else if (PromotionDiscountTypeEnum.PERCENT.getType().equals(discountProduct.getDiscountType())) { // 打折 } else if (PromotionDiscountTypeEnum.PERCENT.getType().equals(discountProduct.getDiscountType())) { // 打折
price = price * discountProduct.getDiscountPercent() / 100; price = calculateRatePrice(price, discountProduct.getDiscountPercent() / 100.0);
} else { } else {
throw new IllegalArgumentException(String.format("优惠活动的商品(%s) 的优惠类型不正确", discountProduct)); throw new IllegalArgumentException(String.format("优惠活动的商品(%s) 的优惠类型不正确", discountProduct));
} }