!1057 完善满减送活动 CRUD 部分

Merge pull request !1057 from puhui999/develop
This commit is contained in:
芋道源码 2024-08-28 05:06:29 +00:00 committed by Gitee
commit c4943e97c7
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
17 changed files with 248 additions and 193 deletions

View File

@ -1,8 +1,12 @@
package cn.iocoder.yudao.module.promotion.api.reward.dto; package cn.iocoder.yudao.module.promotion.api.reward.dto;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.module.promotion.enums.common.PromotionConditionTypeEnum; import cn.iocoder.yudao.module.promotion.enums.common.PromotionConditionTypeEnum;
import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum;
import lombok.Data; import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.List; import java.util.List;
/** /**
@ -21,28 +25,50 @@ public class RewardActivityMatchRespDTO {
* 活动标题 * 活动标题
*/ */
private String name; private String name;
/**
* 状态
*
* 枚举 {@link CommonStatusEnum}
*/
private Integer status;
/**
* 开始时间
*/
private LocalDateTime startTime;
/**
* 结束时间
*/
private LocalDateTime endTime;
/**
* 备注
*/
private String remark;
/** /**
* 条件类型 * 条件类型
* *
* 枚举 {@link PromotionConditionTypeEnum} * 枚举 {@link PromotionConditionTypeEnum}
*/ */
private Integer conditionType; private Integer conditionType;
/**
* 商品范围
*
* 枚举 {@link PromotionProductScopeEnum}
*/
private Integer productScope;
/**
* 商品 SPU 编号的数组
*/
private List<Long> productScopeValues;
/** /**
* 优惠规则的数组 * 优惠规则的数组
*/ */
private List<Rule> rules; private List<Rule> rules;
/**
* 商品 SPU 编号的数组
*/
private List<Long> spuIds;
// TODO 芋艿后面 RewardActivityRespDTO 有了之后Rule 可以放过去
/** /**
* 优惠规则 * 优惠规则
*/ */
@Data @Data
public static class Rule { public static class Rule implements Serializable {
/** /**
* 优惠门槛 * 优惠门槛
@ -59,10 +85,18 @@ public class RewardActivityMatchRespDTO {
* 是否包邮 * 是否包邮
*/ */
private Boolean freeDelivery; private Boolean freeDelivery;
/**
* 是否赠送积分
*/
private Boolean givePoint;
/** /**
* 赠送的积分 * 赠送的积分
*/ */
private Integer point; private Integer point;
/**
* 是否赠送优惠券
*/
private Boolean giveCoupon;
/** /**
* 赠送的优惠劵编号的数组 * 赠送的优惠劵编号的数组
*/ */

View File

@ -44,7 +44,8 @@ public interface ErrorCodeConstants {
ErrorCode REWARD_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED = new ErrorCode(1_013_006_002, "满减送活动已关闭,不能修改"); ErrorCode REWARD_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED = new ErrorCode(1_013_006_002, "满减送活动已关闭,不能修改");
ErrorCode REWARD_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED = new ErrorCode(1_013_006_003, "满减送活动未关闭,不能删除"); ErrorCode REWARD_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED = new ErrorCode(1_013_006_003, "满减送活动未关闭,不能删除");
ErrorCode REWARD_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1_013_006_004, "满减送活动已关闭,不能重复关闭"); ErrorCode REWARD_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1_013_006_004, "满减送活动已关闭,不能重复关闭");
ErrorCode REWARD_ACTIVITY_CLOSE_FAIL_STATUS_END = new ErrorCode(1_013_006_005, "满减送活动已结束,不能关闭"); ErrorCode REWARD_ACTIVITY_SCOPE_ALL_EXISTS = new ErrorCode(1_013_006_005, "已存在商品范围为全场的满减送活动");
ErrorCode REWARD_ACTIVITY_SCOPE_CATEGORY_EXISTS = new ErrorCode(1_013_006_006, "存在商品类型参加了其它满减送活动");
// ========== TODO 空着 1-013-007-000 ============ // ========== TODO 空着 1-013-007-000 ============

View File

@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.promotion.enums.common; package cn.iocoder.yudao.module.promotion.enums.common;
import cn.hutool.core.util.ObjUtil;
import cn.iocoder.yudao.framework.common.core.IntArrayValuable; import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
@ -35,4 +36,16 @@ public enum PromotionProductScopeEnum implements IntArrayValuable {
return ARRAYS; return ARRAYS;
} }
public static boolean isAll(Integer scope) {
return ObjUtil.equal(scope, ALL.scope);
}
public static boolean isSpu(Integer scope) {
return ObjUtil.equal(scope, SPU.scope);
}
public static boolean isCategory(Integer scope) {
return ObjUtil.equal(scope, CATEGORY.scope);
}
} }

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.collection.CollUtil;
import cn.hutool.core.map.MapUtil; 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.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.CommonResult; 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.controller.app.activity.vo.AppActivityRespVO;
import cn.iocoder.yudao.module.promotion.dal.dataobject.bargain.BargainActivityDO; 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.combination.CombinationActivityDO;
import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountActivityDO; 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.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.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.enums.common.PromotionTypeEnum;
import cn.iocoder.yudao.module.promotion.service.bargain.BargainActivityService; import cn.iocoder.yudao.module.promotion.service.bargain.BargainActivityService;
import cn.iocoder.yudao.module.promotion.service.combination.CombinationActivityService; import cn.iocoder.yudao.module.promotion.service.combination.CombinationActivityService;
@ -48,6 +53,8 @@ public class AppActivityController {
private DiscountActivityService discountActivityService; private DiscountActivityService discountActivityService;
@Resource @Resource
private RewardActivityService rewardActivityService; private RewardActivityService rewardActivityService;
@Resource
private ProductSpuApi productSpuApi;
@GetMapping("/list-by-spu-id") @GetMapping("/list-by-spu-id")
@Operation(summary = "获得单个商品,近期参与的每个活动") @Operation(summary = "获得单个商品,近期参与的每个活动")
@ -141,29 +148,52 @@ public class AppActivityController {
item.getName(), productMap.get(item.getId()), item.getStartTime(), item.getEndTime()))); 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) { private void getRewardActivities(Collection<Long> spuIds, LocalDateTime now, List<AppActivityRespVO> activityList) {
// TODO @puhui999 3 范围不只 spuId还有 categoryId全部下次 fix // 1.1 获得所有的活动
//List<RewardActivityDO> rewardActivityList = rewardActivityService.getRewardActivityBySpuIdsAndStatusAndDateTimeLt( List<RewardActivityDO> rewardActivityList = rewardActivityService.getRewardActivityByStatusAndDateTimeLt(
// spuIds, PromotionActivityStatusEnum.RUN.getStatus(), now); CommonStatusEnum.ENABLE.getStatus(), now);
//if (CollUtil.isEmpty(rewardActivityList)) { if (CollUtil.isEmpty(rewardActivityList)) {
// return; return;
//} }
// // 1.2 获得所有的商品信息
//Map<Long, Optional<RewardActivityDO>> spuIdAndActivityMap = spuIds.stream() List<ProductSpuRespDTO> spuList = productSpuApi.getSpuList(spuIds);
// .collect(Collectors.toMap( if (CollUtil.isEmpty(spuList)) {
// spuId -> spuId, return;
// spuId -> rewardActivityList.stream() }
// .filter(activity -> activity.getProductSpuIds().contains(spuId))
// .max(Comparator.comparing(RewardActivityDO::getCreateTime)))); // 2. 构建活动
//for (Long supId : spuIdAndActivityMap.keySet()) { for (RewardActivityDO rewardActivity : rewardActivityList) {
// if (spuIdAndActivityMap.get(supId).isEmpty()) { // 情况一所有商品都能参加
// continue; if (PromotionProductScopeEnum.isAll(rewardActivity.getProductScope())) {
// } buildAppActivityRespVO(rewardActivity, spuIds, activityList);
// }
// RewardActivityDO rewardActivityDO = spuIdAndActivityMap.get(supId).get(); // 情况二指定商品参加
// activityList.add(new AppActivityRespVO(rewardActivityDO.getId(), PromotionTypeEnum.REWARD_ACTIVITY.getType(), if (PromotionProductScopeEnum.isSpu(rewardActivity.getProductScope())) {
// rewardActivityDO.getName(), supId, rewardActivityDO.getStartTime(), rewardActivityDO.getEndTime())); 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; 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.dataobject.BaseDO;
import cn.iocoder.yudao.framework.mybatis.core.type.LongListTypeHandler; 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.PromotionConditionTypeEnum;
import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum; import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum;
import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.KeySequence;
@ -40,7 +40,7 @@ public class RewardActivityDO extends BaseDO {
/** /**
* 状态 * 状态
* *
* 枚举 {@link PromotionActivityStatusEnum} * 枚举 {@link CommonStatusEnum}
*/ */
private Integer status; private Integer status;
/** /**

View File

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

View File

@ -27,6 +27,7 @@ import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStat
import cn.iocoder.yudao.module.system.api.social.SocialClientApi; import cn.iocoder.yudao.module.system.api.social.SocialClientApi;
import cn.iocoder.yudao.module.system.api.social.dto.SocialWxaSubscribeMessageSendReqDTO; import cn.iocoder.yudao.module.system.api.social.dto.SocialWxaSubscribeMessageSendReqDTO;
import cn.iocoder.yudao.module.trade.api.order.TradeOrderApi; import cn.iocoder.yudao.module.trade.api.order.TradeOrderApi;
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderCancelTypeEnum;
import jakarta.annotation.Nullable; import jakarta.annotation.Nullable;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -37,7 +38,10 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.*; import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
@ -335,7 +339,8 @@ public class CombinationRecordServiceImpl implements CombinationRecordService {
List<CombinationRecordDO> headAndRecords = updateBatchCombinationRecords(headRecord, List<CombinationRecordDO> headAndRecords = updateBatchCombinationRecords(headRecord,
CombinationRecordStatusEnum.FAILED); CombinationRecordStatusEnum.FAILED);
// 2. 订单取消 // 2. 订单取消
headAndRecords.forEach(item -> tradeOrderApi.cancelPaidOrder(item.getUserId(), item.getOrderId())); headAndRecords.forEach(item -> tradeOrderApi.cancelPaidOrder(item.getUserId(), item.getOrderId(),
TradeOrderCancelTypeEnum.COMBINATION_CLOSE));
} }
/** /**

View File

@ -75,11 +75,10 @@ public interface RewardActivityService {
/** /**
* 获取指定 spu 编号最近参加的活动每个 spuId 只返回一条记录 * 获取指定 spu 编号最近参加的活动每个 spuId 只返回一条记录
* *
* @param spuIds spu 编号
* @param status 状态 * @param status 状态
* @param dateTime 当前日期时间 * @param dateTime 当前日期时间
* @return 满减送活动列表 * @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; 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.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.category.ProductCategoryApi;
import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi; 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.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.RewardActivityCreateReqVO;
import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityPageReqVO; 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.controller.admin.reward.vo.RewardActivityUpdateReqVO;
import cn.iocoder.yudao.module.promotion.convert.reward.RewardActivityConvert; 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.dataobject.reward.RewardActivityDO;
import cn.iocoder.yudao.module.promotion.dal.mysql.reward.RewardActivityMapper; 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.enums.common.PromotionProductScopeEnum;
import cn.iocoder.yudao.module.promotion.util.PromotionUtils; import cn.iocoder.yudao.module.promotion.util.PromotionUtils;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
@ -20,14 +21,13 @@ import org.springframework.validation.annotation.Validated;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Objects; 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.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 cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
import static java.util.Arrays.asList;
/** /**
* 满减送活动 Service 实现类 * 满减送活动 Service 实现类
@ -51,7 +51,7 @@ public class RewardActivityServiceImpl implements RewardActivityService {
// 1.1 校验商品范围 // 1.1 校验商品范围
validateProductScope(createReqVO.getProductScope(), createReqVO.getProductScopeValues()); validateProductScope(createReqVO.getProductScope(), createReqVO.getProductScopeValues());
// 1.2 校验商品是否冲突 // 1.2 校验商品是否冲突
//validateRewardActivitySpuConflicts(null, createReqVO.getProductSpuIds()); validateRewardActivitySpuConflicts(null, createReqVO);
// 2. 插入 // 2. 插入
RewardActivityDO rewardActivity = RewardActivityConvert.INSTANCE.convert(createReqVO) RewardActivityDO rewardActivity = RewardActivityConvert.INSTANCE.convert(createReqVO)
@ -65,13 +65,13 @@ public class RewardActivityServiceImpl implements RewardActivityService {
public void updateRewardActivity(RewardActivityUpdateReqVO updateReqVO) { public void updateRewardActivity(RewardActivityUpdateReqVO updateReqVO) {
// 1.1 校验存在 // 1.1 校验存在
RewardActivityDO dbRewardActivity = validateRewardActivityExists(updateReqVO.getId()); 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); throw exception(REWARD_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED);
} }
// 1.2 校验商品范围 // 1.2 校验商品范围
validateProductScope(updateReqVO.getProductScope(), updateReqVO.getProductScopeValues()); validateProductScope(updateReqVO.getProductScope(), updateReqVO.getProductScopeValues());
// 1.3 校验商品是否冲突 // 1.3 校验商品是否冲突
//validateRewardActivitySpuConflicts(updateReqVO.getId(), updateReqVO.getProductSpuIds()); validateRewardActivitySpuConflicts(updateReqVO.getId(), updateReqVO);
// 2. 更新 // 2. 更新
RewardActivityDO updateObj = RewardActivityConvert.INSTANCE.convert(updateReqVO) RewardActivityDO updateObj = RewardActivityConvert.INSTANCE.convert(updateReqVO)
@ -82,17 +82,13 @@ public class RewardActivityServiceImpl implements RewardActivityService {
@Override @Override
public void closeRewardActivity(Long id) { public void closeRewardActivity(Long id) {
// 校验存在 // 校验存在
// TODO @puhui999去掉 PromotionActivityStatusEnum使用 CommonStatus 作为状态哈开启关闭
RewardActivityDO dbRewardActivity = validateRewardActivityExists(id); 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); 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); rewardActivityMapper.updateById(updateObj);
} }
@ -100,7 +96,7 @@ public class RewardActivityServiceImpl implements RewardActivityService {
public void deleteRewardActivity(Long id) { public void deleteRewardActivity(Long id) {
// 校验存在 // 校验存在
RewardActivityDO dbRewardActivity = validateRewardActivityExists(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); throw exception(REWARD_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED);
} }
@ -116,27 +112,30 @@ public class RewardActivityServiceImpl implements RewardActivityService {
return activity; return activity;
} }
// TODO @芋艿逻辑有问题需要优化要分成全场和指定来校验
// TODO @puhui999: 下次提交 fix
/** /**
* 校验商品参加的活动是否冲突 * 校验商品参加的活动是否冲突
* *
* @param id 活动编号 * @param id 活动编号
* @param spuIds 商品 SPU 编号数组 * @param rewardActivity 请求
*/ */
private void validateRewardActivitySpuConflicts(Long id, Collection<Long> spuIds) { private void validateRewardActivitySpuConflicts(Long id, RewardActivityBaseVO rewardActivity) {
if (CollUtil.isEmpty(spuIds)) { List<RewardActivityDO> list = rewardActivityMapper.selectList(RewardActivityDO::getProductScope,
return; rewardActivity.getProductScope(), RewardActivityDO::getStatus, CommonStatusEnum.ENABLE.getStatus());
}
// 查询商品参加的活动
List<RewardActivityDO> rewardActivityList = getRewardActivityListBySpuIds(spuIds,
asList(PromotionActivityStatusEnum.WAIT.getStatus(), PromotionActivityStatusEnum.RUN.getStatus()));
if (id != null) { // 排除自己这个活动 if (id != null) { // 排除自己这个活动
rewardActivityList.removeIf(activity -> id.equals(activity.getId())); list.removeIf(activity -> id.equals(activity.getId()));
}
// 情况一全部商品参加
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);
} }
// 如果非空则说明冲突
if (CollUtil.isNotEmpty(rewardActivityList)) {
throw exception(REWARD_ACTIVITY_SPU_CONFLICTS);
} }
} }
@ -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 @Override
public RewardActivityDO getRewardActivity(Long id) { public RewardActivityDO getRewardActivity(Long id) {
return rewardActivityMapper.selectById(id); return rewardActivityMapper.selectById(id);
@ -176,31 +160,13 @@ public class RewardActivityServiceImpl implements RewardActivityService {
@Override @Override
public List<RewardActivityMatchRespDTO> getMatchRewardActivityList(Collection<Long> spuIds) { public List<RewardActivityMatchRespDTO> getMatchRewardActivityList(Collection<Long> spuIds) {
// TODO 芋艿待实现先指定然后再全局的 // TODO 芋艿待实现先指定然后再全局的
// // 如果有全局活动则直接选择它 List<RewardActivityDO> list = rewardActivityMapper.selectListBySpuIdsAndStatus(spuIds, CommonStatusEnum.ENABLE.getStatus());
// List<RewardActivityDO> allActivities = rewardActivityMapper.selectListByProductScopeAndStatus( return BeanUtils.toBean(list, RewardActivityMatchRespDTO.class);
// 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;
} }
@Override @Override
public List<RewardActivityDO> getRewardActivityBySpuIdsAndStatusAndDateTimeLt(Collection<Long> spuIds, Integer status, LocalDateTime dateTime) { public List<RewardActivityDO> getRewardActivityByStatusAndDateTimeLt(Integer status, LocalDateTime dateTime) {
// 1. 查询出指定 spuId spu 参加的活动 return rewardActivityMapper.selectListByStatusAndDateTimeLt(status, dateTime);
List<RewardActivityDO> rewardActivityList = rewardActivityMapper.selectListBySpuIdsAndStatus(spuIds, status);
if (CollUtil.isEmpty(rewardActivityList)) {
return Collections.emptyList();
}
// 2. 查询活动详情
return rewardActivityMapper.selectListByIdsAndDateTimeLt(convertSet(rewardActivityList, RewardActivityDO::getId), dateTime);
} }
} }

View File

@ -1,21 +1,23 @@
package cn.iocoder.yudao.module.promotion.service.reward; package cn.iocoder.yudao.module.promotion.service.reward;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
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.RewardActivityCreateReqVO;
import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityPageReqVO; 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.controller.admin.reward.vo.RewardActivityUpdateReqVO;
import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO; 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.dal.mysql.reward.RewardActivityMapper;
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.PromotionConditionTypeEnum;
import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum; import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Import;
import jakarta.annotation.Resource;
import java.time.Duration; import java.time.Duration;
import java.util.List;
import java.util.Set; import java.util.Set;
import static cn.hutool.core.util.RandomUtil.randomEle; import static cn.hutool.core.util.RandomUtil.randomEle;
@ -27,15 +29,15 @@ import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServic
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.REWARD_ACTIVITY_NOT_EXISTS; import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.REWARD_ACTIVITY_NOT_EXISTS;
import static java.util.Arrays.asList; import static com.google.common.primitives.Longs.asList;
import static java.util.Collections.singletonList; import static java.util.Collections.singletonList;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
/** /**
* {@link RewardActivityServiceImpl} 的单元测试类 * {@link RewardActivityServiceImpl} 的单元测试类
* *
* @author 芋道源码 * @author 芋道源码
*/ */
@Disabled // TODO 芋艿后续 fix 补充的单测 @Disabled // TODO 芋艿后续 fix 补充的单测
@Import(RewardActivityServiceImpl.class) @Import(RewardActivityServiceImpl.class)
public class RewardActivityServiceImplTest extends BaseDbUnitTest { public class RewardActivityServiceImplTest extends BaseDbUnitTest {
@ -63,7 +65,7 @@ public class RewardActivityServiceImplTest extends BaseDbUnitTest {
// 校验记录的属性是否正确 // 校验记录的属性是否正确
RewardActivityDO rewardActivity = rewardActivityMapper.selectById(rewardActivityId); RewardActivityDO rewardActivity = rewardActivityMapper.selectById(rewardActivityId);
assertPojoEquals(reqVO, rewardActivity, "rules"); assertPojoEquals(reqVO, rewardActivity, "rules");
assertEquals(rewardActivity.getStatus(), PromotionActivityStatusEnum.WAIT.getStatus()); assertEquals(rewardActivity.getStatus(), CommonStatusEnum.DISABLE.getStatus());
for (int i = 0; i < reqVO.getRules().size(); i++) { for (int i = 0; i < reqVO.getRules().size(); i++) {
assertPojoEquals(reqVO.getRules().get(i), rewardActivity.getRules().get(i)); assertPojoEquals(reqVO.getRules().get(i), rewardActivity.getRules().get(i));
} }
@ -72,7 +74,7 @@ public class RewardActivityServiceImplTest extends BaseDbUnitTest {
@Test @Test
public void testUpdateRewardActivity_success() { public void testUpdateRewardActivity_success() {
// mock 数据 // mock 数据
RewardActivityDO dbRewardActivity = randomPojo(RewardActivityDO.class, o -> o.setStatus(PromotionActivityStatusEnum.WAIT.getStatus())); RewardActivityDO dbRewardActivity = randomPojo(RewardActivityDO.class, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()));
rewardActivityMapper.insert(dbRewardActivity);// @Sql: 先插入出一条存在的数据 rewardActivityMapper.insert(dbRewardActivity);// @Sql: 先插入出一条存在的数据
// 准备参数 // 准备参数
RewardActivityUpdateReqVO reqVO = randomPojo(RewardActivityUpdateReqVO.class, o -> { RewardActivityUpdateReqVO reqVO = randomPojo(RewardActivityUpdateReqVO.class, o -> {
@ -88,7 +90,7 @@ public class RewardActivityServiceImplTest extends BaseDbUnitTest {
// 校验是否更新正确 // 校验是否更新正确
RewardActivityDO rewardActivity = rewardActivityMapper.selectById(reqVO.getId()); // 获取最新的 RewardActivityDO rewardActivity = rewardActivityMapper.selectById(reqVO.getId()); // 获取最新的
assertPojoEquals(reqVO, rewardActivity, "rules"); assertPojoEquals(reqVO, rewardActivity, "rules");
assertEquals(rewardActivity.getStatus(), PromotionActivityStatusEnum.WAIT.getStatus()); assertEquals(rewardActivity.getStatus(), CommonStatusEnum.DISABLE.getStatus());
for (int i = 0; i < reqVO.getRules().size(); i++) { for (int i = 0; i < reqVO.getRules().size(); i++) {
assertPojoEquals(reqVO.getRules().get(i), rewardActivity.getRules().get(i)); assertPojoEquals(reqVO.getRules().get(i), rewardActivity.getRules().get(i));
} }
@ -97,7 +99,7 @@ public class RewardActivityServiceImplTest extends BaseDbUnitTest {
@Test @Test
public void testCloseRewardActivity() { public void testCloseRewardActivity() {
// mock 数据 // mock 数据
RewardActivityDO dbRewardActivity = randomPojo(RewardActivityDO.class, o -> o.setStatus(PromotionActivityStatusEnum.WAIT.getStatus())); RewardActivityDO dbRewardActivity = randomPojo(RewardActivityDO.class, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()));
rewardActivityMapper.insert(dbRewardActivity);// @Sql: 先插入出一条存在的数据 rewardActivityMapper.insert(dbRewardActivity);// @Sql: 先插入出一条存在的数据
// 准备参数 // 准备参数
Long id = dbRewardActivity.getId(); Long id = dbRewardActivity.getId();
@ -106,7 +108,7 @@ public class RewardActivityServiceImplTest extends BaseDbUnitTest {
rewardActivityService.closeRewardActivity(id); rewardActivityService.closeRewardActivity(id);
// 校验状态 // 校验状态
RewardActivityDO rewardActivity = rewardActivityMapper.selectById(id); RewardActivityDO rewardActivity = rewardActivityMapper.selectById(id);
assertEquals(rewardActivity.getStatus(), PromotionActivityStatusEnum.CLOSE.getStatus()); assertEquals(rewardActivity.getStatus(), CommonStatusEnum.DISABLE.getStatus());
} }
@Test @Test
@ -121,7 +123,7 @@ public class RewardActivityServiceImplTest extends BaseDbUnitTest {
@Test @Test
public void testDeleteRewardActivity_success() { public void testDeleteRewardActivity_success() {
// mock 数据 // mock 数据
RewardActivityDO dbRewardActivity = randomPojo(RewardActivityDO.class, o -> o.setStatus(PromotionActivityStatusEnum.CLOSE.getStatus())); RewardActivityDO dbRewardActivity = randomPojo(RewardActivityDO.class, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()));
rewardActivityMapper.insert(dbRewardActivity);// @Sql: 先插入出一条存在的数据 rewardActivityMapper.insert(dbRewardActivity);// @Sql: 先插入出一条存在的数据
// 准备参数 // 准备参数
Long id = dbRewardActivity.getId(); Long id = dbRewardActivity.getId();
@ -146,17 +148,17 @@ public class RewardActivityServiceImplTest extends BaseDbUnitTest {
// mock 数据 // mock 数据
RewardActivityDO dbRewardActivity = randomPojo(RewardActivityDO.class, o -> { // 等会查询到 RewardActivityDO dbRewardActivity = randomPojo(RewardActivityDO.class, o -> { // 等会查询到
o.setName("芋艿"); o.setName("芋艿");
o.setStatus(PromotionActivityStatusEnum.CLOSE.getStatus()); o.setStatus(CommonStatusEnum.DISABLE.getStatus());
}); });
rewardActivityMapper.insert(dbRewardActivity); rewardActivityMapper.insert(dbRewardActivity);
// 测试 name 不匹配 // 测试 name 不匹配
rewardActivityMapper.insert(cloneIgnoreId(dbRewardActivity, o -> o.setName("土豆"))); rewardActivityMapper.insert(cloneIgnoreId(dbRewardActivity, o -> o.setName("土豆")));
// 测试 status 不匹配 // 测试 status 不匹配
rewardActivityMapper.insert(cloneIgnoreId(dbRewardActivity, o -> o.setStatus(PromotionActivityStatusEnum.RUN.getStatus()))); rewardActivityMapper.insert(cloneIgnoreId(dbRewardActivity, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus())));
// 准备参数 // 准备参数
RewardActivityPageReqVO reqVO = new RewardActivityPageReqVO(); RewardActivityPageReqVO reqVO = new RewardActivityPageReqVO();
reqVO.setName("芋艿"); reqVO.setName("芋艿");
reqVO.setStatus(PromotionActivityStatusEnum.CLOSE.getStatus()); reqVO.setStatus(CommonStatusEnum.DISABLE.getStatus());
// 调用 // 调用
PageResult<RewardActivityDO> pageResult = rewardActivityService.getRewardActivityPage(reqVO); PageResult<RewardActivityDO> pageResult = rewardActivityService.getRewardActivityPage(reqVO);
@ -169,52 +171,56 @@ public class RewardActivityServiceImplTest extends BaseDbUnitTest {
@Test @Test
public void testGetRewardActivities_all() { public void testGetRewardActivities_all() {
// mock 数据 // mock 数据
RewardActivityDO allActivity = randomPojo(RewardActivityDO.class, o -> o.setStatus(PromotionActivityStatusEnum.RUN.getStatus()) RewardActivityDO allActivity = randomPojo(RewardActivityDO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus())
.setProductScope(PromotionProductScopeEnum.ALL.getScope())); .setProductScope(PromotionProductScopeEnum.ALL.getScope()));
rewardActivityMapper.insert(allActivity); rewardActivityMapper.insert(allActivity);
RewardActivityDO productActivity = randomPojo(RewardActivityDO.class, o -> o.setStatus(PromotionActivityStatusEnum.RUN.getStatus()) RewardActivityDO productActivity = randomPojo(RewardActivityDO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus())
.setProductScope(PromotionProductScopeEnum.SPU.getScope()).setProductSpuIds(asList(1L, 2L))); .setProductScope(PromotionProductScopeEnum.SPU.getScope()).setProductScopeValues(asList(1L, 2L)));
rewardActivityMapper.insert(productActivity); rewardActivityMapper.insert(productActivity);
// 准备参数 // 准备参数
Set<Long> spuIds = asSet(1L, 2L); Set<Long> spuIds = asSet(1L, 2L);
// 调用 TODO getMatchRewardActivities 没有这个方法但是找到了 getMatchRewardActivityList // 调用 TODO getMatchRewardActivities 没有这个方法但是找到了 getMatchRewardActivityList
//Map<RewardActivityDO, Set<Long>> matchRewardActivities = rewardActivityService.getMatchRewardActivities(spuIds); List<RewardActivityMatchRespDTO> matchRewardActivityList = rewardActivityService.getMatchRewardActivityList(spuIds);
// 断言 // 断言
//assertEquals(matchRewardActivities.size(), 1); assertEquals(matchRewardActivityList.size(), 1);
//Map.Entry<RewardActivityDO, Set<Long>> next = matchRewardActivities.entrySet().iterator().next(); matchRewardActivityList.forEach((activity) -> {
//assertPojoEquals(next.getKey(), allActivity); if (activity.getId().equals(productActivity.getId())) {
//assertEquals(next.getValue(), spuIds); assertPojoEquals(activity, productActivity);
assertEquals(activity.getProductScopeValues(), asList(1L, 2L));
} else {
fail();
}
});
} }
@Test @Test
public void testGetRewardActivities_product() { public void testGetRewardActivities_product() {
// mock 数据 // mock 数据
// TODO @puhui999有单测的问题也一起瞅瞅 RewardActivityDO productActivity01 = randomPojo(RewardActivityDO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus())
RewardActivityDO productActivity01 = randomPojo(RewardActivityDO.class, o -> o.setStatus(PromotionActivityStatusEnum.RUN.getStatus()) .setProductScope(PromotionProductScopeEnum.SPU.getScope()).setProductScopeValues(asList(1L, 2L)));
.setProductScope(PromotionProductScopeEnum.SPU.getScope()).setProductSpuIds(asList(1L, 2L)));
rewardActivityMapper.insert(productActivity01); rewardActivityMapper.insert(productActivity01);
RewardActivityDO productActivity02 = randomPojo(RewardActivityDO.class, o -> o.setStatus(PromotionActivityStatusEnum.RUN.getStatus()) RewardActivityDO productActivity02 = randomPojo(RewardActivityDO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus())
.setProductScope(PromotionProductScopeEnum.SPU.getScope()).setProductSpuIds(singletonList(3L))); .setProductScope(PromotionProductScopeEnum.SPU.getScope()).setProductScopeValues(singletonList(3L)));
rewardActivityMapper.insert(productActivity02); rewardActivityMapper.insert(productActivity02);
// 准备参数 // 准备参数
Set<Long> spuIds = asSet(1L, 2L, 3L); Set<Long> spuIds = asSet(1L, 2L, 3L);
// 调用 TODO getMatchRewardActivities 没有这个方法但是找到了 getMatchRewardActivityList // 调用 TODO getMatchRewardActivities 没有这个方法但是找到了 getMatchRewardActivityList
//Map<RewardActivityDO, Set<Long>> matchRewardActivities = rewardActivityService.getMatchRewardActivities(spuIds); List<RewardActivityMatchRespDTO> matchRewardActivityList = rewardActivityService.getMatchRewardActivityList(spuIds);
// 断言 // 断言
//assertEquals(matchRewardActivities.size(), 2); assertEquals(matchRewardActivityList.size(), 2);
//matchRewardActivities.forEach((activity, activitySpuIds) -> { matchRewardActivityList.forEach((activity) -> {
// if (activity.getId().equals(productActivity01.getId())) { if (activity.getId().equals(productActivity01.getId())) {
// assertPojoEquals(activity, productActivity01); assertPojoEquals(activity, productActivity01);
// assertEquals(activitySpuIds, asSet(1L, 2L)); assertEquals(activity.getProductScopeValues(), asList(1L, 2L));
// } else if (activity.getId().equals(productActivity02.getId())) { } else if (activity.getId().equals(productActivity02.getId())) {
// assertPojoEquals(activity, productActivity02); assertPojoEquals(activity, productActivity02);
// assertEquals(activitySpuIds, asSet(3L)); assertEquals(activity.getProductScopeValues(), singletonList(3L));
// } else { } else {
// fail(); fail();
// } }
//}); });
} }
} }

View File

@ -1,6 +1,7 @@
package cn.iocoder.yudao.module.trade.api.order; package cn.iocoder.yudao.module.trade.api.order;
import cn.iocoder.yudao.module.trade.api.order.dto.TradeOrderRespDTO; import cn.iocoder.yudao.module.trade.api.order.dto.TradeOrderRespDTO;
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderCancelTypeEnum;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
@ -33,7 +34,8 @@ public interface TradeOrderApi {
* *
* @param userId 用户编号 * @param userId 用户编号
* @param orderId 订单编号 * @param orderId 订单编号
* @param cancelTypeEnum 取消类型
*/ */
void cancelPaidOrder(Long userId, Long orderId); void cancelPaidOrder(Long userId, Long orderId, TradeOrderCancelTypeEnum cancelTypeEnum);
} }

View File

@ -17,7 +17,8 @@ public enum TradeOrderCancelTypeEnum implements IntArrayValuable {
PAY_TIMEOUT(10, "超时未支付"), PAY_TIMEOUT(10, "超时未支付"),
AFTER_SALE_CLOSE(20, "退款关闭"), AFTER_SALE_CLOSE(20, "退款关闭"),
MEMBER_CANCEL(30, "买家取消"); MEMBER_CANCEL(30, "买家取消"),
COMBINATION_CLOSE(40, "拼团关闭");
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(TradeOrderCancelTypeEnum::getType).toArray(); public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(TradeOrderCancelTypeEnum::getType).toArray();

View File

@ -2,12 +2,13 @@ package cn.iocoder.yudao.module.trade.api.order;
import cn.iocoder.yudao.module.trade.api.order.dto.TradeOrderRespDTO; import cn.iocoder.yudao.module.trade.api.order.dto.TradeOrderRespDTO;
import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert; import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert;
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderCancelTypeEnum;
import cn.iocoder.yudao.module.trade.service.order.TradeOrderQueryService; import cn.iocoder.yudao.module.trade.service.order.TradeOrderQueryService;
import cn.iocoder.yudao.module.trade.service.order.TradeOrderUpdateService; import cn.iocoder.yudao.module.trade.service.order.TradeOrderUpdateService;
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;
@ -36,8 +37,8 @@ public class TradeOrderApiImpl implements TradeOrderApi {
} }
@Override @Override
public void cancelPaidOrder(Long userId, Long orderId) { public void cancelPaidOrder(Long userId, Long orderId, TradeOrderCancelTypeEnum cancelTypeEnum) {
tradeOrderUpdateService.cancelPaidOrder(userId, orderId); tradeOrderUpdateService.cancelPaidOrder(userId, orderId, cancelTypeEnum);
} }
} }

View File

@ -1,6 +1,5 @@
package cn.iocoder.yudao.module.trade.service.order; package cn.iocoder.yudao.module.trade.service.order;
import cn.iocoder.yudao.framework.common.enums.TerminalEnum;
import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDeliveryReqVO; import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDeliveryReqVO;
import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderRemarkReqVO; import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderRemarkReqVO;
import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderUpdateAddressReqVO; import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderUpdateAddressReqVO;
@ -10,7 +9,7 @@ import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettle
import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettlementRespVO; import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettlementRespVO;
import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemCommentCreateReqVO; import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemCommentCreateReqVO;
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderCancelTypeEnum;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
/** /**
@ -188,12 +187,14 @@ public interface TradeOrderUpdateService {
void updateOrderCombinationInfo(Long orderId, Long activityId, Long combinationRecordId, Long headId); void updateOrderCombinationInfo(Long orderId, Long activityId, Long combinationRecordId, Long headId);
// TODO 芋艿拼团取消不调这个接口哈 // TODO 芋艿拼团取消不调这个接口哈
/** /**
* 取消支付订单 * 取消支付订单
* *
* @param userId 用户编号 * @param userId 用户编号
* @param orderId 订单编号 * @param orderId 订单编号
* @param cancelTypeEnum 取消类型
*/ */
void cancelPaidOrder(Long userId, Long orderId); void cancelPaidOrder(Long userId, Long orderId, TradeOrderCancelTypeEnum cancelTypeEnum);
} }

View File

@ -858,13 +858,13 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void cancelPaidOrder(Long userId, Long orderId) { public void cancelPaidOrder(Long userId, Long orderId, TradeOrderCancelTypeEnum cancelTypeEnum) {
// TODO @puhui999可能要加一个拼团取消TradeOrderCancelTypeEnum.AFTER_SALE_CLOSE然后参数传入下
// 1.1 检验订单存在 // 1.1 检验订单存在
TradeOrderDO order = tradeOrderMapper.selectOrderByIdAndUserId(orderId, userId); TradeOrderDO order = tradeOrderMapper.selectOrderByIdAndUserId(orderId, userId);
if (order == null) { if (order == null) {
throw exception(ORDER_NOT_FOUND); throw exception(ORDER_NOT_FOUND);
} }
// 1.2 校验订单是否支付 // 1.2 校验订单是否支付
if (!order.getPayStatus()) { if (!order.getPayStatus()) {
throw exception(ORDER_CANCEL_PAID_FAIL, "已支付"); throw exception(ORDER_CANCEL_PAID_FAIL, "已支付");
@ -875,13 +875,13 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
} }
// 2.1 取消订单 // 2.1 取消订单
cancelOrder0(order, TradeOrderCancelTypeEnum.AFTER_SALE_CLOSE); cancelOrder0(order, cancelTypeEnum);
// 2.2 创建退款单 // 2.2 创建退款单
payRefundApi.createRefund(new PayRefundCreateReqDTO() payRefundApi.createRefund(new PayRefundCreateReqDTO()
.setAppKey(tradeOrderProperties.getPayAppKey()).setUserIp(getClientIP()) // 支付应用 .setAppKey(tradeOrderProperties.getPayAppKey()).setUserIp(getClientIP()) // 支付应用
.setMerchantOrderId(String.valueOf(order.getId())) // 支付单号 .setMerchantOrderId(String.valueOf(order.getId())) // 支付单号
.setMerchantRefundId(String.valueOf(order.getId())) .setMerchantRefundId(String.valueOf(order.getId()))
.setReason("取消支付订单").setPrice(order.getPayPrice()));// 价格信息 .setReason(cancelTypeEnum.getName()).setPrice(order.getPayPrice()));// 价格信息
} }
/** /**

View File

@ -10,10 +10,10 @@ 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 static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
@ -96,7 +96,7 @@ public class TradeRewardActivityPriceCalculator implements TradePriceCalculator
private List<TradePriceCalculateRespBO.OrderItem> filterMatchCouponOrderItems(TradePriceCalculateRespBO result, private List<TradePriceCalculateRespBO.OrderItem> filterMatchCouponOrderItems(TradePriceCalculateRespBO result,
RewardActivityMatchRespDTO rewardActivity) { RewardActivityMatchRespDTO rewardActivity) {
return filterList(result.getItems(), return filterList(result.getItems(),
orderItem -> CollUtil.contains(rewardActivity.getSpuIds(), orderItem.getSpuId())); orderItem -> CollUtil.contains(rewardActivity.getProductScopeValues(), orderItem.getSpuId()));
} }
/** /**

View File

@ -63,10 +63,10 @@ public class TradeRewardActivityPriceCalculatorTest extends BaseMockitoUnitTest
// mock 方法限时折扣 DiscountActivity 信息 // mock 方法限时折扣 DiscountActivity 信息
when(rewardActivityApi.getMatchRewardActivityList(eq(asSet(1L, 2L, 3L)))).thenReturn(asList( when(rewardActivityApi.getMatchRewardActivityList(eq(asSet(1L, 2L, 3L)))).thenReturn(asList(
randomPojo(RewardActivityMatchRespDTO.class, o -> o.setId(1000L).setName("活动 1000 号") randomPojo(RewardActivityMatchRespDTO.class, o -> o.setId(1000L).setName("活动 1000 号")
.setSpuIds(asList(1L, 2L)).setConditionType(PromotionConditionTypeEnum.PRICE.getType()) .setProductScopeValues(asList(1L, 2L)).setConditionType(PromotionConditionTypeEnum.PRICE.getType())
.setRules(singletonList(new RewardActivityMatchRespDTO.Rule().setLimit(200).setDiscountPrice(70)))), .setRules(singletonList(new RewardActivityMatchRespDTO.Rule().setLimit(200).setDiscountPrice(70)))),
randomPojo(RewardActivityMatchRespDTO.class, o -> o.setId(2000L).setName("活动 2000 号") randomPojo(RewardActivityMatchRespDTO.class, o -> o.setId(2000L).setName("活动 2000 号")
.setSpuIds(singletonList(3L)).setConditionType(PromotionConditionTypeEnum.COUNT.getType()) .setProductScopeValues(singletonList(3L)).setConditionType(PromotionConditionTypeEnum.COUNT.getType())
.setRules(asList(new RewardActivityMatchRespDTO.Rule().setLimit(1).setDiscountPrice(10), .setRules(asList(new RewardActivityMatchRespDTO.Rule().setLimit(1).setDiscountPrice(10),
new RewardActivityMatchRespDTO.Rule().setLimit(2).setDiscountPrice(60), // 最大可满足因为是 4 new RewardActivityMatchRespDTO.Rule().setLimit(2).setDiscountPrice(60), // 最大可满足因为是 4
new RewardActivityMatchRespDTO.Rule().setLimit(10).setDiscountPrice(100)))) new RewardActivityMatchRespDTO.Rule().setLimit(10).setDiscountPrice(100))))
@ -175,7 +175,7 @@ public class TradeRewardActivityPriceCalculatorTest extends BaseMockitoUnitTest
// mock 方法限时折扣 DiscountActivity 信息 // mock 方法限时折扣 DiscountActivity 信息
when(rewardActivityApi.getMatchRewardActivityList(eq(asSet(1L, 2L)))).thenReturn(singletonList( when(rewardActivityApi.getMatchRewardActivityList(eq(asSet(1L, 2L)))).thenReturn(singletonList(
randomPojo(RewardActivityMatchRespDTO.class, o -> o.setId(1000L).setName("活动 1000 号") randomPojo(RewardActivityMatchRespDTO.class, o -> o.setId(1000L).setName("活动 1000 号")
.setSpuIds(asList(1L, 2L)).setConditionType(PromotionConditionTypeEnum.PRICE.getType()) .setProductScopeValues(asList(1L, 2L)).setConditionType(PromotionConditionTypeEnum.PRICE.getType())
.setRules(singletonList(new RewardActivityMatchRespDTO.Rule().setLimit(351).setDiscountPrice(70)))) .setRules(singletonList(new RewardActivityMatchRespDTO.Rule().setLimit(351).setDiscountPrice(70))))
)); ));