Commit c4943e97c7b447d75776cd6c1d50023236d243f2

Authored by 芋道源码
Committed by Gitee
2 parents 1e4cc953 63fcc699

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

Merge pull request !1057 from puhui999/develop
Showing 17 changed files with 248 additions and 193 deletions
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/dto/RewardActivityMatchRespDTO.java
1 1 package cn.iocoder.yudao.module.promotion.api.reward.dto;
2 2  
  3 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
3 4 import cn.iocoder.yudao.module.promotion.enums.common.PromotionConditionTypeEnum;
  5 +import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum;
4 6 import lombok.Data;
5 7  
  8 +import java.io.Serializable;
  9 +import java.time.LocalDateTime;
6 10 import java.util.List;
7 11  
8 12 /**
... ... @@ -22,27 +26,49 @@ public class RewardActivityMatchRespDTO {
22 26 */
23 27 private String name;
24 28 /**
  29 + * 状态
  30 + *
  31 + * 枚举 {@link CommonStatusEnum}
  32 + */
  33 + private Integer status;
  34 + /**
  35 + * 开始时间
  36 + */
  37 + private LocalDateTime startTime;
  38 + /**
  39 + * 结束时间
  40 + */
  41 + private LocalDateTime endTime;
  42 + /**
  43 + * 备注
  44 + */
  45 + private String remark;
  46 + /**
25 47 * 条件类型
26 48 *
27 49 * 枚举 {@link PromotionConditionTypeEnum}
28 50 */
29 51 private Integer conditionType;
30 52 /**
31   - * 优惠规则的数组
  53 + * 商品范围
  54 + *
  55 + * 枚举 {@link PromotionProductScopeEnum}
32 56 */
33   - private List<Rule> rules;
34   -
  57 + private Integer productScope;
35 58 /**
36 59 * 商品 SPU 编号的数组
37 60 */
38   - private List<Long> spuIds;
  61 + private List<Long> productScopeValues;
  62 + /**
  63 + * 优惠规则的数组
  64 + */
  65 + private List<Rule> rules;
39 66  
40   - // TODO 芋艿:后面 RewardActivityRespDTO 有了之后,Rule 可以放过去
41 67 /**
42 68 * 优惠规则
43 69 */
44 70 @Data
45   - public static class Rule {
  71 + public static class Rule implements Serializable {
46 72  
47 73 /**
48 74 * 优惠门槛
... ... @@ -60,10 +86,18 @@ public class RewardActivityMatchRespDTO {
60 86 */
61 87 private Boolean freeDelivery;
62 88 /**
  89 + * 是否赠送积分
  90 + */
  91 + private Boolean givePoint;
  92 + /**
63 93 * 赠送的积分
64 94 */
65 95 private Integer point;
66 96 /**
  97 + * 是否赠送优惠券
  98 + */
  99 + private Boolean giveCoupon;
  100 + /**
67 101 * 赠送的优惠劵编号的数组
68 102 */
69 103 private List<Long> couponIds;
... ...
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java
... ... @@ -44,7 +44,8 @@ public interface ErrorCodeConstants {
44 44 ErrorCode REWARD_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED = new ErrorCode(1_013_006_002, "满减送活动已关闭,不能修改");
45 45 ErrorCode REWARD_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED = new ErrorCode(1_013_006_003, "满减送活动未关闭,不能删除");
46 46 ErrorCode REWARD_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1_013_006_004, "满减送活动已关闭,不能重复关闭");
47   - ErrorCode REWARD_ACTIVITY_CLOSE_FAIL_STATUS_END = new ErrorCode(1_013_006_005, "满减送活动已结束,不能关闭");
  47 + ErrorCode REWARD_ACTIVITY_SCOPE_ALL_EXISTS = new ErrorCode(1_013_006_005, "已存在商品范围为全场的满减送活动");
  48 + ErrorCode REWARD_ACTIVITY_SCOPE_CATEGORY_EXISTS = new ErrorCode(1_013_006_006, "存在商品类型参加了其它满减送活动");
48 49  
49 50 // ========== TODO 空着 1-013-007-000 ============
50 51  
... ...
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/common/PromotionProductScopeEnum.java
1 1 package cn.iocoder.yudao.module.promotion.enums.common;
2 2  
  3 +import cn.hutool.core.util.ObjUtil;
3 4 import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
4 5 import lombok.AllArgsConstructor;
5 6 import lombok.Getter;
... ... @@ -35,4 +36,16 @@ public enum PromotionProductScopeEnum implements IntArrayValuable {
35 36 return ARRAYS;
36 37 }
37 38  
  39 + public static boolean isAll(Integer scope) {
  40 + return ObjUtil.equal(scope, ALL.scope);
  41 + }
  42 +
  43 + public static boolean isSpu(Integer scope) {
  44 + return ObjUtil.equal(scope, SPU.scope);
  45 + }
  46 +
  47 + public static boolean isCategory(Integer scope) {
  48 + return ObjUtil.equal(scope, CATEGORY.scope);
  49 + }
  50 +
38 51 }
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/activity/AppActivityController.java
... ... @@ -2,14 +2,19 @@ package cn.iocoder.yudao.module.promotion.controller.app.activity;
2 2  
3 3 import cn.hutool.core.collection.CollUtil;
4 4 import cn.hutool.core.map.MapUtil;
  5 +import cn.hutool.core.util.ObjUtil;
5 6 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
6 7 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  8 +import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
  9 +import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
7 10 import cn.iocoder.yudao.module.promotion.controller.app.activity.vo.AppActivityRespVO;
8 11 import cn.iocoder.yudao.module.promotion.dal.dataobject.bargain.BargainActivityDO;
9 12 import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO;
10 13 import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountActivityDO;
11 14 import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO;
  15 +import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO;
12 16 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.SeckillActivityDO;
  17 +import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum;
13 18 import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum;
14 19 import cn.iocoder.yudao.module.promotion.service.bargain.BargainActivityService;
15 20 import cn.iocoder.yudao.module.promotion.service.combination.CombinationActivityService;
... ... @@ -48,6 +53,8 @@ public class AppActivityController {
48 53 private DiscountActivityService discountActivityService;
49 54 @Resource
50 55 private RewardActivityService rewardActivityService;
  56 + @Resource
  57 + private ProductSpuApi productSpuApi;
51 58  
52 59 @GetMapping("/list-by-spu-id")
53 60 @Operation(summary = "获得单个商品,近期参与的每个活动")
... ... @@ -141,29 +148,52 @@ public class AppActivityController {
141 148 item.getName(), productMap.get(item.getId()), item.getStartTime(), item.getEndTime())));
142 149 }
143 150  
  151 + private static void buildAppActivityRespVO(RewardActivityDO rewardActivity, Collection<Long> spuIds,
  152 + List<AppActivityRespVO> activityList) {
  153 + for (Long spuId : spuIds) {
  154 + // 校验商品是否已经加入过活动
  155 + if (anyMatch(activityList, appActivity -> ObjUtil.equal(appActivity.getId(), rewardActivity.getId()) &&
  156 + ObjUtil.equal(appActivity.getSpuId(), spuId))) {
  157 + continue;
  158 + }
  159 + activityList.add(new AppActivityRespVO(rewardActivity.getId(),
  160 + PromotionTypeEnum.REWARD_ACTIVITY.getType(), rewardActivity.getName(), spuId,
  161 + rewardActivity.getStartTime(), rewardActivity.getEndTime()));
  162 + }
  163 + }
  164 +
144 165 private void getRewardActivities(Collection<Long> spuIds, LocalDateTime now, List<AppActivityRespVO> activityList) {
145   - // TODO @puhui999:有 3 范围,不只 spuId,还有 categoryId,全部,下次 fix
146   - //List<RewardActivityDO> rewardActivityList = rewardActivityService.getRewardActivityBySpuIdsAndStatusAndDateTimeLt(
147   - // spuIds, PromotionActivityStatusEnum.RUN.getStatus(), now);
148   - //if (CollUtil.isEmpty(rewardActivityList)) {
149   - // return;
150   - //}
151   - //
152   - //Map<Long, Optional<RewardActivityDO>> spuIdAndActivityMap = spuIds.stream()
153   - // .collect(Collectors.toMap(
154   - // spuId -> spuId,
155   - // spuId -> rewardActivityList.stream()
156   - // .filter(activity -> activity.getProductSpuIds().contains(spuId))
157   - // .max(Comparator.comparing(RewardActivityDO::getCreateTime))));
158   - //for (Long supId : spuIdAndActivityMap.keySet()) {
159   - // if (spuIdAndActivityMap.get(supId).isEmpty()) {
160   - // continue;
161   - // }
162   - //
163   - // RewardActivityDO rewardActivityDO = spuIdAndActivityMap.get(supId).get();
164   - // activityList.add(new AppActivityRespVO(rewardActivityDO.getId(), PromotionTypeEnum.REWARD_ACTIVITY.getType(),
165   - // rewardActivityDO.getName(), supId, rewardActivityDO.getStartTime(), rewardActivityDO.getEndTime()));
166   - //}
  166 + // 1.1 获得所有的活动
  167 + List<RewardActivityDO> rewardActivityList = rewardActivityService.getRewardActivityByStatusAndDateTimeLt(
  168 + CommonStatusEnum.ENABLE.getStatus(), now);
  169 + if (CollUtil.isEmpty(rewardActivityList)) {
  170 + return;
  171 + }
  172 + // 1.2 获得所有的商品信息
  173 + List<ProductSpuRespDTO> spuList = productSpuApi.getSpuList(spuIds);
  174 + if (CollUtil.isEmpty(spuList)) {
  175 + return;
  176 + }
  177 +
  178 + // 2. 构建活动
  179 + for (RewardActivityDO rewardActivity : rewardActivityList) {
  180 + // 情况一:所有商品都能参加
  181 + if (PromotionProductScopeEnum.isAll(rewardActivity.getProductScope())) {
  182 + buildAppActivityRespVO(rewardActivity, spuIds, activityList);
  183 + }
  184 + // 情况二:指定商品参加
  185 + if (PromotionProductScopeEnum.isSpu(rewardActivity.getProductScope())) {
  186 + List<Long> fSpuIds = spuList.stream().map(ProductSpuRespDTO::getId).filter(id ->
  187 + rewardActivity.getProductScopeValues().contains(id)).toList();
  188 + buildAppActivityRespVO(rewardActivity, fSpuIds, activityList);
  189 + }
  190 + // 情况三:指定商品类型参加
  191 + if (PromotionProductScopeEnum.isCategory(rewardActivity.getProductScope())) {
  192 + List<Long> fSpuIds = spuList.stream().filter(spuItem -> rewardActivity.getProductScopeValues()
  193 + .contains(spuItem.getCategoryId())).map(ProductSpuRespDTO::getId).toList();
  194 + buildAppActivityRespVO(rewardActivity, fSpuIds, activityList);
  195 + }
  196 + }
167 197 }
168 198  
169 199 }
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/reward/RewardActivityDO.java
1 1 package cn.iocoder.yudao.module.promotion.dal.dataobject.reward;
2 2  
  3 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
3 4 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
4 5 import cn.iocoder.yudao.framework.mybatis.core.type.LongListTypeHandler;
5   -import cn.iocoder.yudao.module.promotion.enums.common.PromotionActivityStatusEnum;
6 6 import cn.iocoder.yudao.module.promotion.enums.common.PromotionConditionTypeEnum;
7 7 import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum;
8 8 import com.baomidou.mybatisplus.annotation.KeySequence;
... ... @@ -40,7 +40,7 @@ public class RewardActivityDO extends BaseDO {
40 40 /**
41 41 * 状态
42 42 *
43   - * 枚举 {@link PromotionActivityStatusEnum}
  43 + * 枚举 {@link CommonStatusEnum}
44 44 */
45 45 private Integer status;
46 46 /**
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/reward/RewardActivityMapper.java
... ... @@ -30,10 +30,6 @@ public interface RewardActivityMapper extends BaseMapperX&lt;RewardActivityDO&gt; {
30 30 .orderByDesc(RewardActivityDO::getId));
31 31 }
32 32  
33   - default List<RewardActivityDO> selectListByStatus(Collection<Integer> statuses) {
34   - return selectList(RewardActivityDO::getStatus, statuses);
35   - }
36   -
37 33 default List<RewardActivityDO> selectListByProductScopeAndStatus(Integer productScope, Integer status) {
38 34 return selectList(new LambdaQueryWrapperX<RewardActivityDO>()
39 35 .eq(RewardActivityDO::getProductScope, productScope)
... ... @@ -53,16 +49,16 @@ public interface RewardActivityMapper extends BaseMapperX&lt;RewardActivityDO&gt; {
53 49 * 获取指定活动编号的活动列表且
54 50 * 开始时间和结束时间小于给定时间 dateTime 的活动列表
55 51 *
56   - * @param ids 活动编号
  52 + * @param status 状态
57 53 * @param dateTime 指定日期
58 54 * @return 活动列表
59 55 */
60   - default List<RewardActivityDO> selectListByIdsAndDateTimeLt(Collection<Long> ids, LocalDateTime dateTime) {
  56 + default List<RewardActivityDO> selectListByStatusAndDateTimeLt(Integer status, LocalDateTime dateTime) {
61 57 return selectList(new LambdaQueryWrapperX<RewardActivityDO>()
62   - .in(RewardActivityDO::getId, ids)
  58 + .eq(RewardActivityDO::getStatus, status)
63 59 .lt(RewardActivityDO::getStartTime, dateTime)
64 60 .gt(RewardActivityDO::getEndTime, dateTime)// 开始时间 < 指定时间 < 结束时间,也就是说获取指定时间段的活动
65   - .orderByDesc(RewardActivityDO::getCreateTime)
  61 + .orderByAsc(RewardActivityDO::getStartTime)
66 62 );
67 63 }
68 64  
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordServiceImpl.java
... ... @@ -27,6 +27,7 @@ import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStat
27 27 import cn.iocoder.yudao.module.system.api.social.SocialClientApi;
28 28 import cn.iocoder.yudao.module.system.api.social.dto.SocialWxaSubscribeMessageSendReqDTO;
29 29 import cn.iocoder.yudao.module.trade.api.order.TradeOrderApi;
  30 +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderCancelTypeEnum;
30 31 import jakarta.annotation.Nullable;
31 32 import jakarta.annotation.Resource;
32 33 import lombok.extern.slf4j.Slf4j;
... ... @@ -37,7 +38,10 @@ import org.springframework.transaction.annotation.Transactional;
37 38 import org.springframework.validation.annotation.Validated;
38 39  
39 40 import java.time.LocalDateTime;
40   -import java.util.*;
  41 +import java.util.ArrayList;
  42 +import java.util.Collection;
  43 +import java.util.List;
  44 +import java.util.Map;
41 45  
42 46 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
43 47 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
... ... @@ -335,7 +339,8 @@ public class CombinationRecordServiceImpl implements CombinationRecordService {
335 339 List<CombinationRecordDO> headAndRecords = updateBatchCombinationRecords(headRecord,
336 340 CombinationRecordStatusEnum.FAILED);
337 341 // 2. 订单取消
338   - headAndRecords.forEach(item -> tradeOrderApi.cancelPaidOrder(item.getUserId(), item.getOrderId()));
  342 + headAndRecords.forEach(item -> tradeOrderApi.cancelPaidOrder(item.getUserId(), item.getOrderId(),
  343 + TradeOrderCancelTypeEnum.COMBINATION_CLOSE));
339 344 }
340 345  
341 346 /**
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityService.java
... ... @@ -75,11 +75,10 @@ public interface RewardActivityService {
75 75 /**
76 76 * 获取指定 spu 编号最近参加的活动,每个 spuId 只返回一条记录
77 77 *
78   - * @param spuIds spu 编号
79 78 * @param status 状态
80 79 * @param dateTime 当前日期时间
81 80 * @return 满减送活动列表
82 81 */
83   - List<RewardActivityDO> getRewardActivityBySpuIdsAndStatusAndDateTimeLt(Collection<Long> spuIds, Integer status, LocalDateTime dateTime);
  82 + List<RewardActivityDO> getRewardActivityByStatusAndDateTimeLt(Integer status, LocalDateTime dateTime);
84 83  
85 84 }
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImpl.java
1 1 package cn.iocoder.yudao.module.promotion.service.reward;
2 2  
3   -import cn.hutool.core.collection.CollUtil;
  3 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
4 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  5 +import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
5 6 import cn.iocoder.yudao.module.product.api.category.ProductCategoryApi;
6 7 import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
7 8 import cn.iocoder.yudao.module.promotion.api.reward.dto.RewardActivityMatchRespDTO;
  9 +import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityBaseVO;
8 10 import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityCreateReqVO;
9 11 import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityPageReqVO;
10 12 import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityUpdateReqVO;
11 13 import cn.iocoder.yudao.module.promotion.convert.reward.RewardActivityConvert;
12 14 import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO;
13 15 import cn.iocoder.yudao.module.promotion.dal.mysql.reward.RewardActivityMapper;
14   -import cn.iocoder.yudao.module.promotion.enums.common.PromotionActivityStatusEnum;
15 16 import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum;
16 17 import cn.iocoder.yudao.module.promotion.util.PromotionUtils;
17 18 import jakarta.annotation.Resource;
... ... @@ -20,14 +21,13 @@ import org.springframework.validation.annotation.Validated;
20 21  
21 22 import java.time.LocalDateTime;
22 23 import java.util.Collection;
23   -import java.util.Collections;
24 24 import java.util.List;
25 25 import java.util.Objects;
26 26  
  27 +import static cn.hutool.core.collection.CollUtil.intersectionDistinct;
27 28 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
28   -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
  29 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.anyMatch;
29 30 import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
30   -import static java.util.Arrays.asList;
31 31  
32 32 /**
33 33 * 满减送活动 Service 实现类
... ... @@ -51,7 +51,7 @@ public class RewardActivityServiceImpl implements RewardActivityService {
51 51 // 1.1 校验商品范围
52 52 validateProductScope(createReqVO.getProductScope(), createReqVO.getProductScopeValues());
53 53 // 1.2 校验商品是否冲突
54   - //validateRewardActivitySpuConflicts(null, createReqVO.getProductSpuIds());
  54 + validateRewardActivitySpuConflicts(null, createReqVO);
55 55  
56 56 // 2. 插入
57 57 RewardActivityDO rewardActivity = RewardActivityConvert.INSTANCE.convert(createReqVO)
... ... @@ -65,13 +65,13 @@ public class RewardActivityServiceImpl implements RewardActivityService {
65 65 public void updateRewardActivity(RewardActivityUpdateReqVO updateReqVO) {
66 66 // 1.1 校验存在
67 67 RewardActivityDO dbRewardActivity = validateRewardActivityExists(updateReqVO.getId());
68   - if (dbRewardActivity.getStatus().equals(PromotionActivityStatusEnum.CLOSE.getStatus())) { // 已关闭的活动,不能修改噢
  68 + if (dbRewardActivity.getStatus().equals(CommonStatusEnum.DISABLE.getStatus())) { // 已关闭的活动,不能修改噢
69 69 throw exception(REWARD_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED);
70 70 }
71 71 // 1.2 校验商品范围
72 72 validateProductScope(updateReqVO.getProductScope(), updateReqVO.getProductScopeValues());
73 73 // 1.3 校验商品是否冲突
74   - //validateRewardActivitySpuConflicts(updateReqVO.getId(), updateReqVO.getProductSpuIds());
  74 + validateRewardActivitySpuConflicts(updateReqVO.getId(), updateReqVO);
75 75  
76 76 // 2. 更新
77 77 RewardActivityDO updateObj = RewardActivityConvert.INSTANCE.convert(updateReqVO)
... ... @@ -82,17 +82,13 @@ public class RewardActivityServiceImpl implements RewardActivityService {
82 82 @Override
83 83 public void closeRewardActivity(Long id) {
84 84 // 校验存在
85   - // TODO @puhui999:去掉 PromotionActivityStatusEnum,使用 CommonStatus 作为状态哈。开启,关闭
86 85 RewardActivityDO dbRewardActivity = validateRewardActivityExists(id);
87   - if (dbRewardActivity.getStatus().equals(PromotionActivityStatusEnum.CLOSE.getStatus())) { // 已关闭的活动,不能关闭噢
  86 + if (dbRewardActivity.getStatus().equals(CommonStatusEnum.DISABLE.getStatus())) { // 已关闭的活动,不能关闭噢
88 87 throw exception(REWARD_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED);
89 88 }
90   - if (dbRewardActivity.getStatus().equals(PromotionActivityStatusEnum.END.getStatus())) { // 已关闭的活动,不能关闭噢
91   - throw exception(REWARD_ACTIVITY_CLOSE_FAIL_STATUS_END);
92   - }
93 89  
94 90 // 更新
95   - RewardActivityDO updateObj = new RewardActivityDO().setId(id).setStatus(PromotionActivityStatusEnum.CLOSE.getStatus());
  91 + RewardActivityDO updateObj = new RewardActivityDO().setId(id).setStatus(CommonStatusEnum.DISABLE.getStatus());
96 92 rewardActivityMapper.updateById(updateObj);
97 93 }
98 94  
... ... @@ -100,7 +96,7 @@ public class RewardActivityServiceImpl implements RewardActivityService {
100 96 public void deleteRewardActivity(Long id) {
101 97 // 校验存在
102 98 RewardActivityDO dbRewardActivity = validateRewardActivityExists(id);
103   - if (!dbRewardActivity.getStatus().equals(PromotionActivityStatusEnum.CLOSE.getStatus())) { // 未关闭的活动,不能删除噢
  99 + if (dbRewardActivity.getStatus().equals(CommonStatusEnum.ENABLE.getStatus())) { // 未关闭的活动,不能删除噢
104 100 throw exception(REWARD_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED);
105 101 }
106 102  
... ... @@ -116,27 +112,30 @@ public class RewardActivityServiceImpl implements RewardActivityService {
116 112 return activity;
117 113 }
118 114  
119   - // TODO @芋艿:逻辑有问题,需要优化;要分成全场、和指定来校验;
120   - // TODO @puhui999: 下次提交 fix
121 115 /**
122 116 * 校验商品参加的活动是否冲突
123 117 *
124   - * @param id 活动编号
125   - * @param spuIds 商品 SPU 编号数组
  118 + * @param id 活动编号
  119 + * @param rewardActivity 请求
126 120 */
127   - private void validateRewardActivitySpuConflicts(Long id, Collection<Long> spuIds) {
128   - if (CollUtil.isEmpty(spuIds)) {
129   - return;
130   - }
131   - // 查询商品参加的活动
132   - List<RewardActivityDO> rewardActivityList = getRewardActivityListBySpuIds(spuIds,
133   - asList(PromotionActivityStatusEnum.WAIT.getStatus(), PromotionActivityStatusEnum.RUN.getStatus()));
  121 + private void validateRewardActivitySpuConflicts(Long id, RewardActivityBaseVO rewardActivity) {
  122 + List<RewardActivityDO> list = rewardActivityMapper.selectList(RewardActivityDO::getProductScope,
  123 + rewardActivity.getProductScope(), RewardActivityDO::getStatus, CommonStatusEnum.ENABLE.getStatus());
134 124 if (id != null) { // 排除自己这个活动
135   - rewardActivityList.removeIf(activity -> id.equals(activity.getId()));
  125 + list.removeIf(activity -> id.equals(activity.getId()));
  126 + }
  127 +
  128 + // 情况一:全部商品参加
  129 + if (PromotionProductScopeEnum.isAll(rewardActivity.getProductScope()) && !list.isEmpty()) {
  130 + throw exception(REWARD_ACTIVITY_SCOPE_ALL_EXISTS);
136 131 }
137   - // 如果非空,则说明冲突
138   - if (CollUtil.isNotEmpty(rewardActivityList)) {
139   - throw exception(REWARD_ACTIVITY_SPU_CONFLICTS);
  132 + if (PromotionProductScopeEnum.isSpu(rewardActivity.getProductScope()) || // 情况二:指定商品参加
  133 + PromotionProductScopeEnum.isCategory(rewardActivity.getProductScope())) { // 情况三:指定商品类型参加
  134 + if (anyMatch(list, item -> !intersectionDistinct(item.getProductScopeValues(),
  135 + rewardActivity.getProductScopeValues()).isEmpty())) {
  136 + throw exception(PromotionProductScopeEnum.isSpu(rewardActivity.getProductScope()) ?
  137 + REWARD_ACTIVITY_SPU_CONFLICTS : REWARD_ACTIVITY_SCOPE_CATEGORY_EXISTS);
  138 + }
140 139 }
141 140 }
142 141  
... ... @@ -148,21 +147,6 @@ public class RewardActivityServiceImpl implements RewardActivityService {
148 147 }
149 148 }
150 149  
151   - /**
152   - * 获得商品参加的满减送活动的数组
153   - *
154   - * @param spuIds 商品 SPU 编号数组
155   - * @param statuses 活动状态数组
156   - * @return 商品参加的满减送活动的数组
157   - */
158   - private List<RewardActivityDO> getRewardActivityListBySpuIds(Collection<Long> spuIds,
159   - Collection<Integer> statuses) {
160   - // TODO @puhui999: 下次 fix
161   - //List<RewardActivityDO> list = rewardActivityMapper.selectListByStatus(statuses);
162   - //return CollUtil.filter(list, activity -> CollUtil.containsAny(activity.getProductSpuIds(), spuIds));
163   - return List.of();
164   - }
165   -
166 150 @Override
167 151 public RewardActivityDO getRewardActivity(Long id) {
168 152 return rewardActivityMapper.selectById(id);
... ... @@ -176,31 +160,13 @@ public class RewardActivityServiceImpl implements RewardActivityService {
176 160 @Override
177 161 public List<RewardActivityMatchRespDTO> getMatchRewardActivityList(Collection<Long> spuIds) {
178 162 // TODO 芋艿:待实现;先指定,然后再全局的;
179   -// // 如果有全局活动,则直接选择它
180   -// List<RewardActivityDO> allActivities = rewardActivityMapper.selectListByProductScopeAndStatus(
181   -// PromotionProductScopeEnum.ALL.getScope(), PromotionActivityStatusEnum.RUN.getStatus());
182   -// if (CollUtil.isNotEmpty(allActivities)) {
183   -// return MapUtil.builder(allActivities.get(0), spuIds).build();
184   -// }
185   -//
186   -// // 查询某个活动参加的活动
187   -// List<RewardActivityDO> productActivityList = getRewardActivityListBySpuIds(spuIds,
188   -// singleton(PromotionActivityStatusEnum.RUN.getStatus()));
189   -// return convertMap(productActivityList, activity -> activity,
190   -// rewardActivityDO -> intersectionDistinct(rewardActivityDO.getProductSpuIds(), spuIds)); // 求交集返回
191   - return null;
  163 + List<RewardActivityDO> list = rewardActivityMapper.selectListBySpuIdsAndStatus(spuIds, CommonStatusEnum.ENABLE.getStatus());
  164 + return BeanUtils.toBean(list, RewardActivityMatchRespDTO.class);
192 165 }
193 166  
194 167 @Override
195   - public List<RewardActivityDO> getRewardActivityBySpuIdsAndStatusAndDateTimeLt(Collection<Long> spuIds, Integer status, LocalDateTime dateTime) {
196   - // 1. 查询出指定 spuId 的 spu 参加的活动
197   - List<RewardActivityDO> rewardActivityList = rewardActivityMapper.selectListBySpuIdsAndStatus(spuIds, status);
198   - if (CollUtil.isEmpty(rewardActivityList)) {
199   - return Collections.emptyList();
200   - }
201   -
202   - // 2. 查询活动详情
203   - return rewardActivityMapper.selectListByIdsAndDateTimeLt(convertSet(rewardActivityList, RewardActivityDO::getId), dateTime);
  168 + public List<RewardActivityDO> getRewardActivityByStatusAndDateTimeLt(Integer status, LocalDateTime dateTime) {
  169 + return rewardActivityMapper.selectListByStatusAndDateTimeLt(status, dateTime);
204 170 }
205 171  
206 172 }
... ...
yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImplTest.java
1 1 package cn.iocoder.yudao.module.promotion.service.reward;
2 2  
  3 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
3 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 5 import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
  6 +import cn.iocoder.yudao.module.promotion.api.reward.dto.RewardActivityMatchRespDTO;
5 7 import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityCreateReqVO;
6 8 import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityPageReqVO;
7 9 import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityUpdateReqVO;
8 10 import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO;
9 11 import cn.iocoder.yudao.module.promotion.dal.mysql.reward.RewardActivityMapper;
10   -import cn.iocoder.yudao.module.promotion.enums.common.PromotionActivityStatusEnum;
11 12 import cn.iocoder.yudao.module.promotion.enums.common.PromotionConditionTypeEnum;
12 13 import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum;
  14 +import jakarta.annotation.Resource;
13 15 import org.junit.jupiter.api.Disabled;
14 16 import org.junit.jupiter.api.Test;
15 17 import org.springframework.context.annotation.Import;
16 18  
17   -import jakarta.annotation.Resource;
18 19 import java.time.Duration;
  20 +import java.util.List;
19 21 import java.util.Set;
20 22  
21 23 import static cn.hutool.core.util.RandomUtil.randomEle;
... ... @@ -27,15 +29,15 @@ import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServic
27 29 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
28 30 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
29 31 import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.REWARD_ACTIVITY_NOT_EXISTS;
30   -import static java.util.Arrays.asList;
  32 +import static com.google.common.primitives.Longs.asList;
31 33 import static java.util.Collections.singletonList;
32 34 import static org.junit.jupiter.api.Assertions.*;
33 35  
34 36 /**
35   -* {@link RewardActivityServiceImpl} 的单元测试类
36   -*
37   -* @author 芋道源码
38   -*/
  37 + * {@link RewardActivityServiceImpl} 的单元测试类
  38 + *
  39 + * @author 芋道源码
  40 + */
39 41 @Disabled // TODO 芋艿:后续 fix 补充的单测
40 42 @Import(RewardActivityServiceImpl.class)
41 43 public class RewardActivityServiceImplTest extends BaseDbUnitTest {
... ... @@ -63,7 +65,7 @@ public class RewardActivityServiceImplTest extends BaseDbUnitTest {
63 65 // 校验记录的属性是否正确
64 66 RewardActivityDO rewardActivity = rewardActivityMapper.selectById(rewardActivityId);
65 67 assertPojoEquals(reqVO, rewardActivity, "rules");
66   - assertEquals(rewardActivity.getStatus(), PromotionActivityStatusEnum.WAIT.getStatus());
  68 + assertEquals(rewardActivity.getStatus(), CommonStatusEnum.DISABLE.getStatus());
67 69 for (int i = 0; i < reqVO.getRules().size(); i++) {
68 70 assertPojoEquals(reqVO.getRules().get(i), rewardActivity.getRules().get(i));
69 71 }
... ... @@ -72,7 +74,7 @@ public class RewardActivityServiceImplTest extends BaseDbUnitTest {
72 74 @Test
73 75 public void testUpdateRewardActivity_success() {
74 76 // mock 数据
75   - RewardActivityDO dbRewardActivity = randomPojo(RewardActivityDO.class, o -> o.setStatus(PromotionActivityStatusEnum.WAIT.getStatus()));
  77 + RewardActivityDO dbRewardActivity = randomPojo(RewardActivityDO.class, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()));
76 78 rewardActivityMapper.insert(dbRewardActivity);// @Sql: 先插入出一条存在的数据
77 79 // 准备参数
78 80 RewardActivityUpdateReqVO reqVO = randomPojo(RewardActivityUpdateReqVO.class, o -> {
... ... @@ -88,7 +90,7 @@ public class RewardActivityServiceImplTest extends BaseDbUnitTest {
88 90 // 校验是否更新正确
89 91 RewardActivityDO rewardActivity = rewardActivityMapper.selectById(reqVO.getId()); // 获取最新的
90 92 assertPojoEquals(reqVO, rewardActivity, "rules");
91   - assertEquals(rewardActivity.getStatus(), PromotionActivityStatusEnum.WAIT.getStatus());
  93 + assertEquals(rewardActivity.getStatus(), CommonStatusEnum.DISABLE.getStatus());
92 94 for (int i = 0; i < reqVO.getRules().size(); i++) {
93 95 assertPojoEquals(reqVO.getRules().get(i), rewardActivity.getRules().get(i));
94 96 }
... ... @@ -97,7 +99,7 @@ public class RewardActivityServiceImplTest extends BaseDbUnitTest {
97 99 @Test
98 100 public void testCloseRewardActivity() {
99 101 // mock 数据
100   - RewardActivityDO dbRewardActivity = randomPojo(RewardActivityDO.class, o -> o.setStatus(PromotionActivityStatusEnum.WAIT.getStatus()));
  102 + RewardActivityDO dbRewardActivity = randomPojo(RewardActivityDO.class, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()));
101 103 rewardActivityMapper.insert(dbRewardActivity);// @Sql: 先插入出一条存在的数据
102 104 // 准备参数
103 105 Long id = dbRewardActivity.getId();
... ... @@ -106,7 +108,7 @@ public class RewardActivityServiceImplTest extends BaseDbUnitTest {
106 108 rewardActivityService.closeRewardActivity(id);
107 109 // 校验状态
108 110 RewardActivityDO rewardActivity = rewardActivityMapper.selectById(id);
109   - assertEquals(rewardActivity.getStatus(), PromotionActivityStatusEnum.CLOSE.getStatus());
  111 + assertEquals(rewardActivity.getStatus(), CommonStatusEnum.DISABLE.getStatus());
110 112 }
111 113  
112 114 @Test
... ... @@ -121,15 +123,15 @@ public class RewardActivityServiceImplTest extends BaseDbUnitTest {
121 123 @Test
122 124 public void testDeleteRewardActivity_success() {
123 125 // mock 数据
124   - RewardActivityDO dbRewardActivity = randomPojo(RewardActivityDO.class, o -> o.setStatus(PromotionActivityStatusEnum.CLOSE.getStatus()));
  126 + RewardActivityDO dbRewardActivity = randomPojo(RewardActivityDO.class, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()));
125 127 rewardActivityMapper.insert(dbRewardActivity);// @Sql: 先插入出一条存在的数据
126 128 // 准备参数
127 129 Long id = dbRewardActivity.getId();
128 130  
129 131 // 调用
130 132 rewardActivityService.deleteRewardActivity(id);
131   - // 校验数据不存在了
132   - assertNull(rewardActivityMapper.selectById(id));
  133 + // 校验数据不存在了
  134 + assertNull(rewardActivityMapper.selectById(id));
133 135 }
134 136  
135 137 @Test
... ... @@ -143,78 +145,82 @@ public class RewardActivityServiceImplTest extends BaseDbUnitTest {
143 145  
144 146 @Test
145 147 public void testGetRewardActivityPage() {
146   - // mock 数据
147   - RewardActivityDO dbRewardActivity = randomPojo(RewardActivityDO.class, o -> { // 等会查询到
148   - o.setName("芋艿");
149   - o.setStatus(PromotionActivityStatusEnum.CLOSE.getStatus());
150   - });
151   - rewardActivityMapper.insert(dbRewardActivity);
152   - // 测试 name 不匹配
153   - rewardActivityMapper.insert(cloneIgnoreId(dbRewardActivity, o -> o.setName("土豆")));
154   - // 测试 status 不匹配
155   - rewardActivityMapper.insert(cloneIgnoreId(dbRewardActivity, o -> o.setStatus(PromotionActivityStatusEnum.RUN.getStatus())));
156   - // 准备参数
157   - RewardActivityPageReqVO reqVO = new RewardActivityPageReqVO();
158   - reqVO.setName("芋艿");
159   - reqVO.setStatus(PromotionActivityStatusEnum.CLOSE.getStatus());
160   -
161   - // 调用
162   - PageResult<RewardActivityDO> pageResult = rewardActivityService.getRewardActivityPage(reqVO);
163   - // 断言
164   - assertEquals(1, pageResult.getTotal());
165   - assertEquals(1, pageResult.getList().size());
166   - assertPojoEquals(dbRewardActivity, pageResult.getList().get(0), "rules");
  148 + // mock 数据
  149 + RewardActivityDO dbRewardActivity = randomPojo(RewardActivityDO.class, o -> { // 等会查询到
  150 + o.setName("芋艿");
  151 + o.setStatus(CommonStatusEnum.DISABLE.getStatus());
  152 + });
  153 + rewardActivityMapper.insert(dbRewardActivity);
  154 + // 测试 name 不匹配
  155 + rewardActivityMapper.insert(cloneIgnoreId(dbRewardActivity, o -> o.setName("土豆")));
  156 + // 测试 status 不匹配
  157 + rewardActivityMapper.insert(cloneIgnoreId(dbRewardActivity, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus())));
  158 + // 准备参数
  159 + RewardActivityPageReqVO reqVO = new RewardActivityPageReqVO();
  160 + reqVO.setName("芋艿");
  161 + reqVO.setStatus(CommonStatusEnum.DISABLE.getStatus());
  162 +
  163 + // 调用
  164 + PageResult<RewardActivityDO> pageResult = rewardActivityService.getRewardActivityPage(reqVO);
  165 + // 断言
  166 + assertEquals(1, pageResult.getTotal());
  167 + assertEquals(1, pageResult.getList().size());
  168 + assertPojoEquals(dbRewardActivity, pageResult.getList().get(0), "rules");
167 169 }
168 170  
169 171 @Test
170 172 public void testGetRewardActivities_all() {
171 173 // mock 数据
172   - RewardActivityDO allActivity = randomPojo(RewardActivityDO.class, o -> o.setStatus(PromotionActivityStatusEnum.RUN.getStatus())
  174 + RewardActivityDO allActivity = randomPojo(RewardActivityDO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus())
173 175 .setProductScope(PromotionProductScopeEnum.ALL.getScope()));
174 176 rewardActivityMapper.insert(allActivity);
175   - RewardActivityDO productActivity = randomPojo(RewardActivityDO.class, o -> o.setStatus(PromotionActivityStatusEnum.RUN.getStatus())
176   - .setProductScope(PromotionProductScopeEnum.SPU.getScope()).setProductSpuIds(asList(1L, 2L)));
  177 + RewardActivityDO productActivity = randomPojo(RewardActivityDO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus())
  178 + .setProductScope(PromotionProductScopeEnum.SPU.getScope()).setProductScopeValues(asList(1L, 2L)));
177 179 rewardActivityMapper.insert(productActivity);
178 180 // 准备参数
179 181 Set<Long> spuIds = asSet(1L, 2L);
180 182  
181 183 // 调用 TODO getMatchRewardActivities 没有这个方法,但是找到了 getMatchRewardActivityList
182   - //Map<RewardActivityDO, Set<Long>> matchRewardActivities = rewardActivityService.getMatchRewardActivities(spuIds);
  184 + List<RewardActivityMatchRespDTO> matchRewardActivityList = rewardActivityService.getMatchRewardActivityList(spuIds);
183 185 // 断言
184   - //assertEquals(matchRewardActivities.size(), 1);
185   - //Map.Entry<RewardActivityDO, Set<Long>> next = matchRewardActivities.entrySet().iterator().next();
186   - //assertPojoEquals(next.getKey(), allActivity);
187   - //assertEquals(next.getValue(), spuIds);
  186 + assertEquals(matchRewardActivityList.size(), 1);
  187 + matchRewardActivityList.forEach((activity) -> {
  188 + if (activity.getId().equals(productActivity.getId())) {
  189 + assertPojoEquals(activity, productActivity);
  190 + assertEquals(activity.getProductScopeValues(), asList(1L, 2L));
  191 + } else {
  192 + fail();
  193 + }
  194 + });
188 195 }
189 196  
190 197 @Test
191 198 public void testGetRewardActivities_product() {
192 199 // mock 数据
193   - // TODO @puhui999:有单测的问题,也一起瞅瞅
194   - RewardActivityDO productActivity01 = randomPojo(RewardActivityDO.class, o -> o.setStatus(PromotionActivityStatusEnum.RUN.getStatus())
195   - .setProductScope(PromotionProductScopeEnum.SPU.getScope()).setProductSpuIds(asList(1L, 2L)));
  200 + RewardActivityDO productActivity01 = randomPojo(RewardActivityDO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus())
  201 + .setProductScope(PromotionProductScopeEnum.SPU.getScope()).setProductScopeValues(asList(1L, 2L)));
196 202 rewardActivityMapper.insert(productActivity01);
197   - RewardActivityDO productActivity02 = randomPojo(RewardActivityDO.class, o -> o.setStatus(PromotionActivityStatusEnum.RUN.getStatus())
198   - .setProductScope(PromotionProductScopeEnum.SPU.getScope()).setProductSpuIds(singletonList(3L)));
  203 + RewardActivityDO productActivity02 = randomPojo(RewardActivityDO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus())
  204 + .setProductScope(PromotionProductScopeEnum.SPU.getScope()).setProductScopeValues(singletonList(3L)));
199 205 rewardActivityMapper.insert(productActivity02);
200 206 // 准备参数
201 207 Set<Long> spuIds = asSet(1L, 2L, 3L);
202 208  
203 209 // 调用 TODO getMatchRewardActivities 没有这个方法,但是找到了 getMatchRewardActivityList
204   - //Map<RewardActivityDO, Set<Long>> matchRewardActivities = rewardActivityService.getMatchRewardActivities(spuIds);
  210 + List<RewardActivityMatchRespDTO> matchRewardActivityList = rewardActivityService.getMatchRewardActivityList(spuIds);
205 211 // 断言
206   - //assertEquals(matchRewardActivities.size(), 2);
207   - //matchRewardActivities.forEach((activity, activitySpuIds) -> {
208   - // if (activity.getId().equals(productActivity01.getId())) {
209   - // assertPojoEquals(activity, productActivity01);
210   - // assertEquals(activitySpuIds, asSet(1L, 2L));
211   - // } else if (activity.getId().equals(productActivity02.getId())) {
212   - // assertPojoEquals(activity, productActivity02);
213   - // assertEquals(activitySpuIds, asSet(3L));
214   - // } else {
215   - // fail();
216   - // }
217   - //});
  212 + assertEquals(matchRewardActivityList.size(), 2);
  213 + matchRewardActivityList.forEach((activity) -> {
  214 + if (activity.getId().equals(productActivity01.getId())) {
  215 + assertPojoEquals(activity, productActivity01);
  216 + assertEquals(activity.getProductScopeValues(), asList(1L, 2L));
  217 + } else if (activity.getId().equals(productActivity02.getId())) {
  218 + assertPojoEquals(activity, productActivity02);
  219 + assertEquals(activity.getProductScopeValues(), singletonList(3L));
  220 + } else {
  221 + fail();
  222 + }
  223 + });
218 224 }
219 225  
220 226 }
... ...
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/api/order/TradeOrderApi.java
1 1 package cn.iocoder.yudao.module.trade.api.order;
2 2  
3 3 import cn.iocoder.yudao.module.trade.api.order.dto.TradeOrderRespDTO;
  4 +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderCancelTypeEnum;
4 5  
5 6 import java.util.Collection;
6 7 import java.util.List;
... ... @@ -31,9 +32,10 @@ public interface TradeOrderApi {
31 32 /**
32 33 * 取消支付订单
33 34 *
34   - * @param userId 用户编号
35   - * @param orderId 订单编号
  35 + * @param userId 用户编号
  36 + * @param orderId 订单编号
  37 + * @param cancelTypeEnum 取消类型
36 38 */
37   - void cancelPaidOrder(Long userId, Long orderId);
  39 + void cancelPaidOrder(Long userId, Long orderId, TradeOrderCancelTypeEnum cancelTypeEnum);
38 40  
39 41 }
... ...
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderCancelTypeEnum.java
... ... @@ -17,7 +17,8 @@ public enum TradeOrderCancelTypeEnum implements IntArrayValuable {
17 17  
18 18 PAY_TIMEOUT(10, "超时未支付"),
19 19 AFTER_SALE_CLOSE(20, "退款关闭"),
20   - MEMBER_CANCEL(30, "买家取消");
  20 + MEMBER_CANCEL(30, "买家取消"),
  21 + COMBINATION_CLOSE(40, "拼团关闭");
21 22  
22 23 public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(TradeOrderCancelTypeEnum::getType).toArray();
23 24  
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/api/order/TradeOrderApiImpl.java
... ... @@ -2,12 +2,13 @@ package cn.iocoder.yudao.module.trade.api.order;
2 2  
3 3 import cn.iocoder.yudao.module.trade.api.order.dto.TradeOrderRespDTO;
4 4 import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert;
  5 +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderCancelTypeEnum;
5 6 import cn.iocoder.yudao.module.trade.service.order.TradeOrderQueryService;
6 7 import cn.iocoder.yudao.module.trade.service.order.TradeOrderUpdateService;
  8 +import jakarta.annotation.Resource;
7 9 import org.springframework.stereotype.Service;
8 10 import org.springframework.validation.annotation.Validated;
9 11  
10   -import jakarta.annotation.Resource;
11 12 import java.util.Collection;
12 13 import java.util.List;
13 14  
... ... @@ -36,8 +37,8 @@ public class TradeOrderApiImpl implements TradeOrderApi {
36 37 }
37 38  
38 39 @Override
39   - public void cancelPaidOrder(Long userId, Long orderId) {
40   - tradeOrderUpdateService.cancelPaidOrder(userId, orderId);
  40 + public void cancelPaidOrder(Long userId, Long orderId, TradeOrderCancelTypeEnum cancelTypeEnum) {
  41 + tradeOrderUpdateService.cancelPaidOrder(userId, orderId, cancelTypeEnum);
41 42 }
42 43  
43 44 }
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateService.java
1 1 package cn.iocoder.yudao.module.trade.service.order;
2 2  
3   -import cn.iocoder.yudao.framework.common.enums.TerminalEnum;
4 3 import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDeliveryReqVO;
5 4 import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderRemarkReqVO;
6 5 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
10 9 import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettlementRespVO;
11 10 import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemCommentCreateReqVO;
12 11 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
13   -
  12 +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderCancelTypeEnum;
14 13 import jakarta.validation.constraints.NotNull;
15 14  
16 15 /**
... ... @@ -188,12 +187,14 @@ public interface TradeOrderUpdateService {
188 187 void updateOrderCombinationInfo(Long orderId, Long activityId, Long combinationRecordId, Long headId);
189 188  
190 189 // TODO 芋艿:拼团取消,不调这个接口哈;
  190 +
191 191 /**
192 192 * 取消支付订单
193 193 *
194   - * @param userId 用户编号
195   - * @param orderId 订单编号
  194 + * @param userId 用户编号
  195 + * @param orderId 订单编号
  196 + * @param cancelTypeEnum 取消类型
196 197 */
197   - void cancelPaidOrder(Long userId, Long orderId);
  198 + void cancelPaidOrder(Long userId, Long orderId, TradeOrderCancelTypeEnum cancelTypeEnum);
198 199  
199 200 }
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java
... ... @@ -858,13 +858,13 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
858 858  
859 859 @Override
860 860 @Transactional(rollbackFor = Exception.class)
861   - public void cancelPaidOrder(Long userId, Long orderId) {
862   - // TODO @puhui999:可能要加一个拼团取消;TradeOrderCancelTypeEnum.AFTER_SALE_CLOSE;然后参数传入下;
  861 + public void cancelPaidOrder(Long userId, Long orderId, TradeOrderCancelTypeEnum cancelTypeEnum) {
863 862 // 1.1 检验订单存在
864 863 TradeOrderDO order = tradeOrderMapper.selectOrderByIdAndUserId(orderId, userId);
865 864 if (order == null) {
866 865 throw exception(ORDER_NOT_FOUND);
867 866 }
  867 +
868 868 // 1.2 校验订单是否支付
869 869 if (!order.getPayStatus()) {
870 870 throw exception(ORDER_CANCEL_PAID_FAIL, "已支付");
... ... @@ -875,13 +875,13 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
875 875 }
876 876  
877 877 // 2.1 取消订单
878   - cancelOrder0(order, TradeOrderCancelTypeEnum.AFTER_SALE_CLOSE);
  878 + cancelOrder0(order, cancelTypeEnum);
879 879 // 2.2 创建退款单
880 880 payRefundApi.createRefund(new PayRefundCreateReqDTO()
881 881 .setAppKey(tradeOrderProperties.getPayAppKey()).setUserIp(getClientIP()) // 支付应用
882 882 .setMerchantOrderId(String.valueOf(order.getId())) // 支付单号
883 883 .setMerchantRefundId(String.valueOf(order.getId()))
884   - .setReason("取消支付订单").setPrice(order.getPayPrice()));// 价格信息
  884 + .setReason(cancelTypeEnum.getName()).setPrice(order.getPayPrice()));// 价格信息
885 885 }
886 886  
887 887 /**
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeRewardActivityPriceCalculator.java
... ... @@ -10,10 +10,10 @@ import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum;
10 10 import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum;
11 11 import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO;
12 12 import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO;
  13 +import jakarta.annotation.Resource;
13 14 import org.springframework.core.annotation.Order;
14 15 import org.springframework.stereotype.Component;
15 16  
16   -import jakarta.annotation.Resource;
17 17 import java.util.List;
18 18  
19 19 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
... ... @@ -96,7 +96,7 @@ public class TradeRewardActivityPriceCalculator implements TradePriceCalculator
96 96 private List<TradePriceCalculateRespBO.OrderItem> filterMatchCouponOrderItems(TradePriceCalculateRespBO result,
97 97 RewardActivityMatchRespDTO rewardActivity) {
98 98 return filterList(result.getItems(),
99   - orderItem -> CollUtil.contains(rewardActivity.getSpuIds(), orderItem.getSpuId()));
  99 + orderItem -> CollUtil.contains(rewardActivity.getProductScopeValues(), orderItem.getSpuId()));
100 100 }
101 101  
102 102 /**
... ...
yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeRewardActivityPriceCalculatorTest.java
... ... @@ -63,10 +63,10 @@ public class TradeRewardActivityPriceCalculatorTest extends BaseMockitoUnitTest
63 63 // mock 方法(限时折扣 DiscountActivity 信息)
64 64 when(rewardActivityApi.getMatchRewardActivityList(eq(asSet(1L, 2L, 3L)))).thenReturn(asList(
65 65 randomPojo(RewardActivityMatchRespDTO.class, o -> o.setId(1000L).setName("活动 1000 号")
66   - .setSpuIds(asList(1L, 2L)).setConditionType(PromotionConditionTypeEnum.PRICE.getType())
  66 + .setProductScopeValues(asList(1L, 2L)).setConditionType(PromotionConditionTypeEnum.PRICE.getType())
67 67 .setRules(singletonList(new RewardActivityMatchRespDTO.Rule().setLimit(200).setDiscountPrice(70)))),
68 68 randomPojo(RewardActivityMatchRespDTO.class, o -> o.setId(2000L).setName("活动 2000 号")
69   - .setSpuIds(singletonList(3L)).setConditionType(PromotionConditionTypeEnum.COUNT.getType())
  69 + .setProductScopeValues(singletonList(3L)).setConditionType(PromotionConditionTypeEnum.COUNT.getType())
70 70 .setRules(asList(new RewardActivityMatchRespDTO.Rule().setLimit(1).setDiscountPrice(10),
71 71 new RewardActivityMatchRespDTO.Rule().setLimit(2).setDiscountPrice(60), // 最大可满足,因为是 4 个
72 72 new RewardActivityMatchRespDTO.Rule().setLimit(10).setDiscountPrice(100))))
... ... @@ -175,7 +175,7 @@ public class TradeRewardActivityPriceCalculatorTest extends BaseMockitoUnitTest
175 175 // mock 方法(限时折扣 DiscountActivity 信息)
176 176 when(rewardActivityApi.getMatchRewardActivityList(eq(asSet(1L, 2L)))).thenReturn(singletonList(
177 177 randomPojo(RewardActivityMatchRespDTO.class, o -> o.setId(1000L).setName("活动 1000 号")
178   - .setSpuIds(asList(1L, 2L)).setConditionType(PromotionConditionTypeEnum.PRICE.getType())
  178 + .setProductScopeValues(asList(1L, 2L)).setConditionType(PromotionConditionTypeEnum.PRICE.getType())
179 179 .setRules(singletonList(new RewardActivityMatchRespDTO.Rule().setLimit(351).setDiscountPrice(70))))
180 180 ));
181 181  
... ...