【代码优化】商城:完善满减送的计算逻辑

This commit is contained in:
YunaiV
2024-09-15 20:04:40 +08:00
parent 65c6184450
commit 222aa33f3e
20 changed files with 312 additions and 324 deletions

View File

@@ -24,8 +24,8 @@ public class DiscountActivityApiImpl implements DiscountActivityApi {
private DiscountActivityService discountActivityService;
@Override
public List<DiscountProductRespDTO> getMatchDiscountProductList(Collection<Long> skuIds) {
List<DiscountProductDO> list = discountActivityService.getMatchDiscountProductList(skuIds);
public List<DiscountProductRespDTO> getMatchDiscountProductListBySkuIds(Collection<Long> skuIds) {
List<DiscountProductDO> list = discountActivityService.getMatchDiscountProductListBySkuIds(skuIds);
return BeanUtils.toBean(list, DiscountProductRespDTO.class);
}

View File

@@ -1,14 +1,11 @@
package cn.iocoder.yudao.module.promotion.api.reward;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.promotion.api.reward.dto.RewardActivityMatchRespDTO;
import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO;
import cn.iocoder.yudao.module.promotion.service.reward.RewardActivityService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.List;
@@ -25,9 +22,8 @@ public class RewardActivityApiImpl implements RewardActivityApi {
private RewardActivityService rewardActivityService;
@Override
public List<RewardActivityMatchRespDTO> getRewardActivityBySpuIdsAndStatusAndDateTimeLt(Collection<Long> spuIds, Integer status, LocalDateTime dateTime) {
List<RewardActivityDO> list = rewardActivityService.getRewardActivityBySpuIdsAndStatusAndDateTimeLt(spuIds, status, dateTime);
return BeanUtils.toBean(list, RewardActivityMatchRespDTO.class);
public List<RewardActivityMatchRespDTO> getMatchRewardActivityListBySpuIds(Collection<Long> spuIds) {
return rewardActivityService.getMatchRewardActivityListBySpuIds(spuIds);
}
}

View File

@@ -27,12 +27,13 @@ public interface DiscountProductMapper extends BaseMapperX<DiscountProductDO> {
return selectList(DiscountProductDO::getSkuId, skuIds);
}
default List<DiscountProductDO> selectListByStatusAndDateTimeLt(Collection<Long> skuIds, Integer status, LocalDateTime dateTime) {
default List<DiscountProductDO> selectListBySkuIdsAndStatusAndNow(Collection<Long> skuIds, Integer status) {
LocalDateTime now = LocalDateTime.now();
return selectList(new LambdaQueryWrapperX<DiscountProductDO>()
.in(DiscountProductDO::getSkuId, skuIds)
.eq(DiscountProductDO::getActivityStatus,status)
.lt(DiscountProductDO::getActivityStartTime, dateTime)
.gt(DiscountProductDO::getActivityEndTime, dateTime));
.lt(DiscountProductDO::getActivityStartTime, now)
.gt(DiscountProductDO::getActivityEndTime, now));
}
/**

View File

@@ -30,14 +30,17 @@ public interface RewardActivityMapper extends BaseMapperX<RewardActivityDO> {
.orderByDesc(RewardActivityDO::getId));
}
default List<RewardActivityDO> selectListByStatusAndDateTimeLt(Collection<Long> spuIds, Collection<Long> categoryIds, Integer status, LocalDateTime dateTime) {
default List<RewardActivityDO> selectListBySpuIdAndStatusAndNow(Collection<Long> spuIds,
Collection<Long> categoryIds,
Integer status) {
LocalDateTime now = LocalDateTime.now();
Function<Collection<Long>, String> productScopeValuesFindInSetFunc = ids -> ids.stream()
.map(id -> StrUtil.format("FIND_IN_SET({}, product_scope_values) ", id))
.collect(Collectors.joining(" OR "));
return selectList(new LambdaQueryWrapperX<RewardActivityDO>()
.eq(RewardActivityDO::getStatus,status)
.lt(RewardActivityDO::getStartTime, dateTime)
.gt(RewardActivityDO::getEndTime, dateTime)
.eq(RewardActivityDO::getStatus, status)
.lt(RewardActivityDO::getStartTime, now)
.gt(RewardActivityDO::getEndTime, now)
.and(i -> i.eq(RewardActivityDO::getProductScope, PromotionProductScopeEnum.SPU.getScope())
.and(i1 -> i1.apply(productScopeValuesFindInSetFunc.apply(spuIds)))
.or(i1 -> i1.eq(RewardActivityDO::getProductScope, PromotionProductScopeEnum.ALL.getScope()))

View File

@@ -26,7 +26,7 @@ public interface DiscountActivityService {
* @param skuIds SKU 编号数组
* @return 匹配的限时折扣商品
*/
List<DiscountProductDO> getMatchDiscountProductList(Collection<Long> skuIds);
List<DiscountProductDO> getMatchDiscountProductListBySkuIds(Collection<Long> skuIds);
/**
* 创建限时折扣活动

View File

@@ -46,8 +46,8 @@ public class DiscountActivityServiceImpl implements DiscountActivityService {
private DiscountProductMapper discountProductMapper;
@Override
public List<DiscountProductDO> getMatchDiscountProductList(Collection<Long> skuIds) {
return discountProductMapper.selectListByStatusAndDateTimeLt(skuIds, CommonStatusEnum.ENABLE.getStatus(), LocalDateTime.now());
public List<DiscountProductDO> getMatchDiscountProductListBySkuIds(Collection<Long> skuIds) {
return discountProductMapper.selectListBySkuIdsAndStatusAndNow(skuIds, CommonStatusEnum.ENABLE.getStatus());
}
@Override

View File

@@ -1,13 +1,13 @@
package cn.iocoder.yudao.module.promotion.service.reward;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.promotion.api.reward.dto.RewardActivityMatchRespDTO;
import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityCreateReqVO;
import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityPageReqVO;
import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityUpdateReqVO;
import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO;
import jakarta.validation.Valid;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.List;
@@ -64,15 +64,11 @@ public interface RewardActivityService {
PageResult<RewardActivityDO> getRewardActivityPage(RewardActivityPageReqVO pageReqVO);
/**
* 获取指定 spu 编号最近参加的活动,每个 spuId 只返回一条记录
* 获 spuId 商品匹配的的满减送活动列表
*
* @param spuIds SPU 编号数组
* @param status 状态
* @param dateTime 当前日期时间
* @return 满减送活动列表
*/
List<RewardActivityDO> getRewardActivityBySpuIdsAndStatusAndDateTimeLt(Collection<Long> spuIds,
Integer status,
LocalDateTime dateTime);
List<RewardActivityMatchRespDTO> getMatchRewardActivityListBySpuIds(Collection<Long> spuIds);
}

View File

@@ -2,29 +2,32 @@ package cn.iocoder.yudao.module.promotion.service.reward;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.number.MoneyUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.product.api.category.ProductCategoryApi;
import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
import cn.iocoder.yudao.module.promotion.api.reward.dto.RewardActivityMatchRespDTO;
import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityBaseVO;
import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityCreateReqVO;
import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityPageReqVO;
import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityUpdateReqVO;
import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO;
import cn.iocoder.yudao.module.promotion.dal.mysql.reward.RewardActivityMapper;
import cn.iocoder.yudao.module.promotion.enums.common.PromotionConditionTypeEnum;
import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import java.time.LocalDateTime;
import java.util.*;
import static cn.hutool.core.collection.CollUtil.intersectionDistinct;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
/**
@@ -193,16 +196,61 @@ public class RewardActivityServiceImpl implements RewardActivityService {
}
@Override
public List<RewardActivityDO> getRewardActivityBySpuIdsAndStatusAndDateTimeLt(Collection<Long> spuIds, Integer status, LocalDateTime dateTime) {
public List<RewardActivityMatchRespDTO> getMatchRewardActivityListBySpuIds(Collection<Long> spuIds) {
// 1. 查询商品分类
List<ProductSpuRespDTO> spuList = productSpuApi.getSpuList(spuIds);
if (CollUtil.isEmpty(spuList)) {
return Collections.emptyList();
}
Set<Long> categoryIds = convertSet(spuList, ProductSpuRespDTO::getCategoryId);
Map<Long, ProductSpuRespDTO> spuMap = convertMap(spuList, ProductSpuRespDTO::getId);
// 2. 查询出指定 spuId 的 spu 参加的活动
return rewardActivityMapper.selectListByStatusAndDateTimeLt(spuIds, categoryIds, status, dateTime);
List<RewardActivityDO> activityList = rewardActivityMapper.selectListBySpuIdAndStatusAndNow(
spuIds, convertSet(spuList, ProductSpuRespDTO::getCategoryId), CommonStatusEnum.ENABLE.getStatus());
if (CollUtil.isEmpty(activityList)) {
return Collections.emptyList();
}
// 3. 转换成 Response DTO
return BeanUtils.toBean(activityList, RewardActivityMatchRespDTO.class, activityDTO -> {
// 3.1 设置对应匹配的 spuIds
activityDTO.setSpuIds(new ArrayList<>());
for (Long spuId : spuIds) {
if (PromotionProductScopeEnum.isAll(activityDTO.getProductScope())) {
activityDTO.getSpuIds().add(spuId);
} else if (PromotionProductScopeEnum.isSpu(activityDTO.getProductScope())) {
if (CollUtil.contains(activityDTO.getProductScopeValues(), spuId)) {
activityDTO.getSpuIds().add(spuId);
}
} else if (PromotionProductScopeEnum.isCategory(activityDTO.getProductScope())) {
ProductSpuRespDTO spu = spuMap.get(spuId);
if (spu != null && CollUtil.contains(activityDTO.getProductScopeValues(), spu.getCategoryId())) {
activityDTO.getSpuIds().add(spuId);
}
}
}
// 3.2 设置每个 Rule 的描述
activityDTO.getRules().forEach(rule -> {
String description = "";
if (PromotionConditionTypeEnum.PRICE.getType().equals(activityDTO.getConditionType())) {
description += StrUtil.format("满 {} 元", rule.getLimit());
} else {
description += StrUtil.format("满 {} 件", rule.getLimit());
}
if (rule.getDiscountPrice() != null) {
description += StrUtil.format("减 {}", MoneyUtils.fenToYuanStr(rule.getDiscountPrice()));
} else if (Boolean.TRUE.equals(rule.getFreeDelivery())) {
description += "包邮";
} else if (rule.getPoint() != null && rule.getPoint() > 0) {
description += StrUtil.format("增 {} 积分", rule.getPoint());
} else if (CollUtil.isNotEmpty(rule.getGiveCouponTemplateCounts())) {
description += StrUtil.format("送 {} 张优惠券",
getSumValue(rule.getGiveCouponTemplateCounts().values(), count -> count, Integer::sum));
}
rule.setDescription(description);
});
});
}
}