【代码优化】商城: 满减送活动 CRUD 部分

This commit is contained in:
puhui999
2024-08-27 16:46:04 +08:00
parent 1e4cc953d3
commit 710f29d911
11 changed files with 220 additions and 175 deletions

View File

@@ -2,14 +2,19 @@ package cn.iocoder.yudao.module.promotion.controller.app.activity;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
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.controller.app.activity.vo.AppActivityRespVO;
import cn.iocoder.yudao.module.promotion.dal.dataobject.bargain.BargainActivityDO;
import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO;
import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountActivityDO;
import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO;
import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO;
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.SeckillActivityDO;
import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum;
import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum;
import cn.iocoder.yudao.module.promotion.service.bargain.BargainActivityService;
import cn.iocoder.yudao.module.promotion.service.combination.CombinationActivityService;
@@ -48,6 +53,8 @@ public class AppActivityController {
private DiscountActivityService discountActivityService;
@Resource
private RewardActivityService rewardActivityService;
@Resource
private ProductSpuApi productSpuApi;
@GetMapping("/list-by-spu-id")
@Operation(summary = "获得单个商品,近期参与的每个活动")
@@ -141,29 +148,52 @@ public class AppActivityController {
item.getName(), productMap.get(item.getId()), item.getStartTime(), item.getEndTime())));
}
private static void buildAppActivityRespVO(RewardActivityDO rewardActivity, Collection<Long> spuIds,
List<AppActivityRespVO> activityList) {
for (Long spuId : spuIds) {
// 校验商品是否已经加入过活动
if (anyMatch(activityList, appActivity -> ObjUtil.equal(appActivity.getId(), rewardActivity.getId()) &&
ObjUtil.equal(appActivity.getSpuId(), spuId))) {
continue;
}
activityList.add(new AppActivityRespVO(rewardActivity.getId(),
PromotionTypeEnum.REWARD_ACTIVITY.getType(), rewardActivity.getName(), spuId,
rewardActivity.getStartTime(), rewardActivity.getEndTime()));
}
}
private void getRewardActivities(Collection<Long> spuIds, LocalDateTime now, List<AppActivityRespVO> activityList) {
// TODO @puhui999有 3 范围,不只 spuId还有 categoryId全部下次 fix
//List<RewardActivityDO> rewardActivityList = rewardActivityService.getRewardActivityBySpuIdsAndStatusAndDateTimeLt(
// spuIds, PromotionActivityStatusEnum.RUN.getStatus(), now);
//if (CollUtil.isEmpty(rewardActivityList)) {
// return;
//}
//
//Map<Long, Optional<RewardActivityDO>> spuIdAndActivityMap = spuIds.stream()
// .collect(Collectors.toMap(
// spuId -> spuId,
// spuId -> rewardActivityList.stream()
// .filter(activity -> activity.getProductSpuIds().contains(spuId))
// .max(Comparator.comparing(RewardActivityDO::getCreateTime))));
//for (Long supId : spuIdAndActivityMap.keySet()) {
// if (spuIdAndActivityMap.get(supId).isEmpty()) {
// continue;
// }
//
// RewardActivityDO rewardActivityDO = spuIdAndActivityMap.get(supId).get();
// activityList.add(new AppActivityRespVO(rewardActivityDO.getId(), PromotionTypeEnum.REWARD_ACTIVITY.getType(),
// rewardActivityDO.getName(), supId, rewardActivityDO.getStartTime(), rewardActivityDO.getEndTime()));
//}
// 1.1 获得所有的活动
List<RewardActivityDO> rewardActivityList = rewardActivityService.getRewardActivityByStatusAndDateTimeLt(
CommonStatusEnum.ENABLE.getStatus(), now);
if (CollUtil.isEmpty(rewardActivityList)) {
return;
}
// 1.2 获得所有的商品信息
List<ProductSpuRespDTO> spuList = productSpuApi.getSpuList(spuIds);
if (CollUtil.isEmpty(spuList)) {
return;
}
// 2. 构建活动
for (RewardActivityDO rewardActivity : rewardActivityList) {
// 情况一:所有商品都能参加
if (PromotionProductScopeEnum.isAll(rewardActivity.getProductScope())) {
buildAppActivityRespVO(rewardActivity, spuIds, activityList);
}
// 情况二:指定商品参加
if (PromotionProductScopeEnum.isSpu(rewardActivity.getProductScope())) {
List<Long> fSpuIds = spuList.stream().map(ProductSpuRespDTO::getId).filter(id ->
rewardActivity.getProductScopeValues().contains(id)).toList();
buildAppActivityRespVO(rewardActivity, fSpuIds, activityList);
}
// 情况三:指定商品类型参加
if (PromotionProductScopeEnum.isCategory(rewardActivity.getProductScope())) {
List<Long> fSpuIds = spuList.stream().filter(spuItem -> rewardActivity.getProductScopeValues()
.contains(spuItem.getCategoryId())).map(ProductSpuRespDTO::getId).toList();
buildAppActivityRespVO(rewardActivity, fSpuIds, activityList);
}
}
}
}

View File

@@ -1,8 +1,8 @@
package cn.iocoder.yudao.module.promotion.dal.dataobject.reward;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.framework.mybatis.core.type.LongListTypeHandler;
import cn.iocoder.yudao.module.promotion.enums.common.PromotionActivityStatusEnum;
import cn.iocoder.yudao.module.promotion.enums.common.PromotionConditionTypeEnum;
import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum;
import com.baomidou.mybatisplus.annotation.KeySequence;
@@ -40,7 +40,7 @@ public class RewardActivityDO extends BaseDO {
/**
* 状态
*
* 枚举 {@link PromotionActivityStatusEnum}
* 枚举 {@link CommonStatusEnum}
*/
private Integer status;
/**

View File

@@ -30,10 +30,6 @@ public interface RewardActivityMapper extends BaseMapperX<RewardActivityDO> {
.orderByDesc(RewardActivityDO::getId));
}
default List<RewardActivityDO> selectListByStatus(Collection<Integer> statuses) {
return selectList(RewardActivityDO::getStatus, statuses);
}
default List<RewardActivityDO> selectListByProductScopeAndStatus(Integer productScope, Integer status) {
return selectList(new LambdaQueryWrapperX<RewardActivityDO>()
.eq(RewardActivityDO::getProductScope, productScope)
@@ -53,16 +49,16 @@ public interface RewardActivityMapper extends BaseMapperX<RewardActivityDO> {
* 获取指定活动编号的活动列表且
* 开始时间和结束时间小于给定时间 dateTime 的活动列表
*
* @param ids 活动编号
* @param status 状态
* @param dateTime 指定日期
* @return 活动列表
*/
default List<RewardActivityDO> selectListByIdsAndDateTimeLt(Collection<Long> ids, LocalDateTime dateTime) {
default List<RewardActivityDO> selectListByStatusAndDateTimeLt(Integer status, LocalDateTime dateTime) {
return selectList(new LambdaQueryWrapperX<RewardActivityDO>()
.in(RewardActivityDO::getId, ids)
.eq(RewardActivityDO::getStatus, status)
.lt(RewardActivityDO::getStartTime, dateTime)
.gt(RewardActivityDO::getEndTime, dateTime)// 开始时间 < 指定时间 < 结束时间,也就是说获取指定时间段的活动
.orderByDesc(RewardActivityDO::getCreateTime)
.orderByAsc(RewardActivityDO::getStartTime)
);
}

View File

@@ -75,11 +75,10 @@ public interface RewardActivityService {
/**
* 获取指定 spu 编号最近参加的活动,每个 spuId 只返回一条记录
*
* @param spuIds spu 编号
* @param status 状态
* @param dateTime 当前日期时间
* @return 满减送活动列表
*/
List<RewardActivityDO> getRewardActivityBySpuIdsAndStatusAndDateTimeLt(Collection<Long> spuIds, Integer status, LocalDateTime dateTime);
List<RewardActivityDO> getRewardActivityByStatusAndDateTimeLt(Integer status, LocalDateTime dateTime);
}

View File

@@ -1,17 +1,18 @@
package cn.iocoder.yudao.module.promotion.service.reward;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
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.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.convert.reward.RewardActivityConvert;
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.PromotionActivityStatusEnum;
import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum;
import cn.iocoder.yudao.module.promotion.util.PromotionUtils;
import jakarta.annotation.Resource;
@@ -20,14 +21,13 @@ import org.springframework.validation.annotation.Validated;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
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.anyMatch;
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
import static java.util.Arrays.asList;
/**
* 满减送活动 Service 实现类
@@ -51,7 +51,7 @@ public class RewardActivityServiceImpl implements RewardActivityService {
// 1.1 校验商品范围
validateProductScope(createReqVO.getProductScope(), createReqVO.getProductScopeValues());
// 1.2 校验商品是否冲突
//validateRewardActivitySpuConflicts(null, createReqVO.getProductSpuIds());
validateRewardActivitySpuConflicts(null, createReqVO);
// 2. 插入
RewardActivityDO rewardActivity = RewardActivityConvert.INSTANCE.convert(createReqVO)
@@ -65,13 +65,13 @@ public class RewardActivityServiceImpl implements RewardActivityService {
public void updateRewardActivity(RewardActivityUpdateReqVO updateReqVO) {
// 1.1 校验存在
RewardActivityDO dbRewardActivity = validateRewardActivityExists(updateReqVO.getId());
if (dbRewardActivity.getStatus().equals(PromotionActivityStatusEnum.CLOSE.getStatus())) { // 已关闭的活动,不能修改噢
if (dbRewardActivity.getStatus().equals(CommonStatusEnum.DISABLE.getStatus())) { // 已关闭的活动,不能修改噢
throw exception(REWARD_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED);
}
// 1.2 校验商品范围
validateProductScope(updateReqVO.getProductScope(), updateReqVO.getProductScopeValues());
// 1.3 校验商品是否冲突
//validateRewardActivitySpuConflicts(updateReqVO.getId(), updateReqVO.getProductSpuIds());
validateRewardActivitySpuConflicts(updateReqVO.getId(), updateReqVO);
// 2. 更新
RewardActivityDO updateObj = RewardActivityConvert.INSTANCE.convert(updateReqVO)
@@ -82,17 +82,13 @@ public class RewardActivityServiceImpl implements RewardActivityService {
@Override
public void closeRewardActivity(Long id) {
// 校验存在
// TODO @puhui999去掉 PromotionActivityStatusEnum使用 CommonStatus 作为状态哈。开启,关闭
RewardActivityDO dbRewardActivity = validateRewardActivityExists(id);
if (dbRewardActivity.getStatus().equals(PromotionActivityStatusEnum.CLOSE.getStatus())) { // 已关闭的活动,不能关闭噢
if (dbRewardActivity.getStatus().equals(CommonStatusEnum.DISABLE.getStatus())) { // 已关闭的活动,不能关闭噢
throw exception(REWARD_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED);
}
if (dbRewardActivity.getStatus().equals(PromotionActivityStatusEnum.END.getStatus())) { // 已关闭的活动,不能关闭噢
throw exception(REWARD_ACTIVITY_CLOSE_FAIL_STATUS_END);
}
// 更新
RewardActivityDO updateObj = new RewardActivityDO().setId(id).setStatus(PromotionActivityStatusEnum.CLOSE.getStatus());
RewardActivityDO updateObj = new RewardActivityDO().setId(id).setStatus(CommonStatusEnum.DISABLE.getStatus());
rewardActivityMapper.updateById(updateObj);
}
@@ -100,7 +96,7 @@ public class RewardActivityServiceImpl implements RewardActivityService {
public void deleteRewardActivity(Long id) {
// 校验存在
RewardActivityDO dbRewardActivity = validateRewardActivityExists(id);
if (!dbRewardActivity.getStatus().equals(PromotionActivityStatusEnum.CLOSE.getStatus())) { // 未关闭的活动,不能删除噢
if (dbRewardActivity.getStatus().equals(CommonStatusEnum.ENABLE.getStatus())) { // 未关闭的活动,不能删除噢
throw exception(REWARD_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED);
}
@@ -116,27 +112,30 @@ public class RewardActivityServiceImpl implements RewardActivityService {
return activity;
}
// TODO @芋艿:逻辑有问题,需要优化;要分成全场、和指定来校验;
// TODO @puhui999: 下次提交 fix
/**
* 校验商品参加的活动是否冲突
*
* @param id 活动编号
* @param spuIds 商品 SPU 编号数组
* @param id 活动编号
* @param rewardActivity 请求
*/
private void validateRewardActivitySpuConflicts(Long id, Collection<Long> spuIds) {
if (CollUtil.isEmpty(spuIds)) {
return;
}
// 查询商品参加的活动
List<RewardActivityDO> rewardActivityList = getRewardActivityListBySpuIds(spuIds,
asList(PromotionActivityStatusEnum.WAIT.getStatus(), PromotionActivityStatusEnum.RUN.getStatus()));
private void validateRewardActivitySpuConflicts(Long id, RewardActivityBaseVO rewardActivity) {
List<RewardActivityDO> list = rewardActivityMapper.selectList(RewardActivityDO::getProductScope,
rewardActivity.getProductScope(), RewardActivityDO::getStatus, CommonStatusEnum.ENABLE.getStatus());
if (id != null) { // 排除自己这个活动
rewardActivityList.removeIf(activity -> id.equals(activity.getId()));
list.removeIf(activity -> id.equals(activity.getId()));
}
// 如果非空,则说明冲突
if (CollUtil.isNotEmpty(rewardActivityList)) {
throw exception(REWARD_ACTIVITY_SPU_CONFLICTS);
// 情况一:全部商品参加
if (PromotionProductScopeEnum.isAll(rewardActivity.getProductScope()) && !list.isEmpty()) {
throw exception(REWARD_ACTIVITY_SCOPE_ALL_EXISTS);
}
if (PromotionProductScopeEnum.isSpu(rewardActivity.getProductScope()) || // 情况二:指定商品参加
PromotionProductScopeEnum.isCategory(rewardActivity.getProductScope())) { // 情况三:指定商品类型参加
if (anyMatch(list, item -> !intersectionDistinct(item.getProductScopeValues(),
rewardActivity.getProductScopeValues()).isEmpty())) {
throw exception(PromotionProductScopeEnum.isSpu(rewardActivity.getProductScope()) ?
REWARD_ACTIVITY_SPU_CONFLICTS : REWARD_ACTIVITY_SCOPE_CATEGORY_EXISTS);
}
}
}
@@ -148,21 +147,6 @@ public class RewardActivityServiceImpl implements RewardActivityService {
}
}
/**
* 获得商品参加的满减送活动的数组
*
* @param spuIds 商品 SPU 编号数组
* @param statuses 活动状态数组
* @return 商品参加的满减送活动的数组
*/
private List<RewardActivityDO> getRewardActivityListBySpuIds(Collection<Long> spuIds,
Collection<Integer> statuses) {
// TODO @puhui999: 下次 fix
//List<RewardActivityDO> list = rewardActivityMapper.selectListByStatus(statuses);
//return CollUtil.filter(list, activity -> CollUtil.containsAny(activity.getProductSpuIds(), spuIds));
return List.of();
}
@Override
public RewardActivityDO getRewardActivity(Long id) {
return rewardActivityMapper.selectById(id);
@@ -176,31 +160,13 @@ public class RewardActivityServiceImpl implements RewardActivityService {
@Override
public List<RewardActivityMatchRespDTO> getMatchRewardActivityList(Collection<Long> spuIds) {
// TODO 芋艿:待实现;先指定,然后再全局的;
// // 如果有全局活动,则直接选择它
// List<RewardActivityDO> allActivities = rewardActivityMapper.selectListByProductScopeAndStatus(
// PromotionProductScopeEnum.ALL.getScope(), PromotionActivityStatusEnum.RUN.getStatus());
// if (CollUtil.isNotEmpty(allActivities)) {
// return MapUtil.builder(allActivities.get(0), spuIds).build();
// }
//
// // 查询某个活动参加的活动
// List<RewardActivityDO> productActivityList = getRewardActivityListBySpuIds(spuIds,
// singleton(PromotionActivityStatusEnum.RUN.getStatus()));
// return convertMap(productActivityList, activity -> activity,
// rewardActivityDO -> intersectionDistinct(rewardActivityDO.getProductSpuIds(), spuIds)); // 求交集返回
return null;
List<RewardActivityDO> list = rewardActivityMapper.selectListBySpuIdsAndStatus(spuIds, CommonStatusEnum.ENABLE.getStatus());
return BeanUtils.toBean(list, RewardActivityMatchRespDTO.class);
}
@Override
public List<RewardActivityDO> getRewardActivityBySpuIdsAndStatusAndDateTimeLt(Collection<Long> spuIds, Integer status, LocalDateTime dateTime) {
// 1. 查询出指定 spuId 的 spu 参加的活动
List<RewardActivityDO> rewardActivityList = rewardActivityMapper.selectListBySpuIdsAndStatus(spuIds, status);
if (CollUtil.isEmpty(rewardActivityList)) {
return Collections.emptyList();
}
// 2. 查询活动详情
return rewardActivityMapper.selectListByIdsAndDateTimeLt(convertSet(rewardActivityList, RewardActivityDO::getId), dateTime);
public List<RewardActivityDO> getRewardActivityByStatusAndDateTimeLt(Integer status, LocalDateTime dateTime) {
return rewardActivityMapper.selectListByStatusAndDateTimeLt(status, dateTime);
}
}