Commit 4f7d6b4959dc97e3b541cee50d8b5b74cdaa1673

Authored by 芋道源码
Committed by Gitee
2 parents 00c2153f d3f03540

!643 订单:完善拼团活动和一些 TODO

Merge pull request !643 from puhui999/feature/mall_product
Showing 42 changed files with 605 additions and 283 deletions
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java
@@ -97,4 +97,44 @@ public class LocalDateTimeUtils { @@ -97,4 +97,44 @@ public class LocalDateTimeUtils {
97 LocalDateTime.of(nowDate, startTime2), LocalDateTime.of(nowDate, endTime2)); 97 LocalDateTime.of(nowDate, startTime2), LocalDateTime.of(nowDate, endTime2));
98 } 98 }
99 99
  100 + /**
  101 + * 构建日期时间 TODO 后面有需要的话再继续扩展
  102 + *
  103 + * @author HUIHUI
  104 + */
  105 + public static class BuilderDateTime {
  106 +
  107 + /**
  108 + * 日期;2023-10-01
  109 + */
  110 + private String localDate;
  111 + /**
  112 + * 时间;10:01:00
  113 + */
  114 + private String localTime;
  115 +
  116 + public BuilderDateTime() {
  117 + }
  118 +
  119 + public BuilderDateTime withDate(String date) {
  120 + this.localDate = date;
  121 + return this;
  122 + }
  123 +
  124 + public BuilderDateTime withDate(LocalDateTime date) {
  125 + this.localDate = LocalDateTimeUtil.format(date, "yyyy-MM-dd");
  126 + return this;
  127 + }
  128 +
  129 + public BuilderDateTime withTime(String time) {
  130 + this.localTime = time;
  131 + return this;
  132 + }
  133 +
  134 + public LocalDateTime build() {
  135 + return LocalDateTimeUtil.parse(this.localDate + " " + this.localTime, "yyyy-MM-dd HH:mm:ss");
  136 + }
  137 +
  138 + }
  139 +
100 } 140 }
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/bargain/BargainRecordApi.java
@@ -20,13 +20,4 @@ public interface BargainRecordApi { @@ -20,13 +20,4 @@ public interface BargainRecordApi {
20 */ 20 */
21 void createBargainRecord(@Valid BargainRecordCreateReqDTO reqDTO); 21 void createBargainRecord(@Valid BargainRecordCreateReqDTO reqDTO);
22 22
23 - /**  
24 - * 查询砍价是否成功  
25 - *  
26 - * @param userId 用户编号  
27 - * @param orderId 订单编号  
28 - * @return 砍价是否成功  
29 - */  
30 - boolean isBargainRecordSuccess(Long userId, Long orderId);  
31 -  
32 } 23 }
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationActivityApi.java
@@ -7,14 +7,4 @@ package cn.iocoder.yudao.module.promotion.api.combination; @@ -7,14 +7,4 @@ package cn.iocoder.yudao.module.promotion.api.combination;
7 */ 7 */
8 public interface CombinationActivityApi { 8 public interface CombinationActivityApi {
9 9
10 - /**  
11 - * 校验是否满足拼团条件  
12 - *  
13 - * @param activityId 活动编号  
14 - * @param userId 用户编号  
15 - * @param skuId sku 编号  
16 - * @param count 数量  
17 - */  
18 - void validateCombination(Long activityId, Long userId, Long skuId, Integer count);  
19 -  
20 } 10 }
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApi.java
@@ -15,6 +15,16 @@ import java.time.LocalDateTime; @@ -15,6 +15,16 @@ import java.time.LocalDateTime;
15 public interface CombinationRecordApi { 15 public interface CombinationRecordApi {
16 16
17 /** 17 /**
  18 + * 校验是否满足拼团条件
  19 + *
  20 + * @param activityId 活动编号
  21 + * @param userId 用户编号
  22 + * @param skuId sku 编号
  23 + * @param count 数量
  24 + */
  25 + void validateCombinationRecord(Long activityId, Long userId, Long skuId, Integer count);
  26 +
  27 + /**
18 * 创建开团记录 28 * 创建开团记录
19 * 29 *
20 * @param reqDTO 请求 DTO 30 * @param reqDTO 请求 DTO
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationRecordCreateReqDTO.java
@@ -29,6 +29,11 @@ public class CombinationRecordCreateReqDTO { @@ -29,6 +29,11 @@ public class CombinationRecordCreateReqDTO {
29 @NotNull(message = "sku 编号不能为空") 29 @NotNull(message = "sku 编号不能为空")
30 private Long skuId; 30 private Long skuId;
31 /** 31 /**
  32 + * 购买的商品数量
  33 + */
  34 + @NotNull(message = "购买数量不能为空")
  35 + private Integer count;
  36 + /**
32 * 订单编号 37 * 订单编号
33 */ 38 */
34 @NotNull(message = "订单编号不能为空") 39 @NotNull(message = "订单编号不能为空")
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApi.java
1 package cn.iocoder.yudao.module.promotion.api.seckill; 1 package cn.iocoder.yudao.module.promotion.api.seckill;
2 2
  3 +import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillActivityProductRespDTO;
  4 +
  5 +import java.util.Collection;
  6 +import java.util.List;
  7 +
3 /** 8 /**
4 * 秒杀活动 API 接口 9 * 秒杀活动 API 接口
5 * 10 *
@@ -16,4 +21,13 @@ public interface SeckillActivityApi { @@ -16,4 +21,13 @@ public interface SeckillActivityApi {
16 */ 21 */
17 void updateSeckillStock(Long id, Long skuId, Integer count); 22 void updateSeckillStock(Long id, Long skuId, Integer count);
18 23
  24 + /**
  25 + * 获取秒杀活动商品信息
  26 + *
  27 + * @param id 活动编号
  28 + * @param skuIds sku 编号
  29 + * @return 秒杀活动商品信息列表
  30 + */
  31 + List<SeckillActivityProductRespDTO> getSeckillActivityProductList(Long id, Collection<Long> skuIds);
  32 +
19 } 33 }
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/dto/SeckillActivityProductRespDTO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.promotion.api.seckill.dto;
  2 +
  3 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
  4 +import lombok.Data;
  5 +
  6 +import java.time.LocalDateTime;
  7 +import java.util.List;
  8 +
  9 +/**
  10 + * 秒杀活动商品 Response DTO
  11 + *
  12 + * @author HUIHUI
  13 + */
  14 +@Data
  15 +public class SeckillActivityProductRespDTO {
  16 +
  17 + /**
  18 + * 秒杀参与商品编号
  19 + */
  20 + private Long id;
  21 + /**
  22 + * 秒杀活动 id
  23 + *
  24 + * 关联 SeckillActivityDO#getId()
  25 + */
  26 + private Long activityId;
  27 + /**
  28 + * 秒杀时段 id
  29 + *
  30 + * 关联 SeckillConfigDO#getId()
  31 + */
  32 + private List<Long> configIds;
  33 + /**
  34 + * 商品 SPU 编号
  35 + */
  36 + private Long spuId;
  37 + /**
  38 + * 商品 SKU 编号
  39 + */
  40 + private Long skuId;
  41 + /**
  42 + * 秒杀金额,单位:分
  43 + */
  44 + private Integer seckillPrice;
  45 + /**
  46 + * 秒杀库存
  47 + */
  48 + private Integer stock;
  49 +
  50 + /**
  51 + * 秒杀商品状态
  52 + *
  53 + * 枚举 {@link CommonStatusEnum 对应的类}
  54 + */
  55 + private Integer activityStatus;
  56 + /**
  57 + * 活动开始时间点
  58 + */
  59 + private LocalDateTime activityStartTime;
  60 + /**
  61 + * 活动结束时间点
  62 + */
  63 + private LocalDateTime activityEndTime;
  64 +
  65 +}
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java
@@ -75,9 +75,11 @@ public interface ErrorCodeConstants { @@ -75,9 +75,11 @@ public interface ErrorCodeConstants {
75 ErrorCode COMBINATION_RECORD_HEAD_NOT_EXISTS = new ErrorCode(1_013_011_002, "拼团失败,父拼团不存在"); 75 ErrorCode COMBINATION_RECORD_HEAD_NOT_EXISTS = new ErrorCode(1_013_011_002, "拼团失败,父拼团不存在");
76 ErrorCode COMBINATION_RECORD_USER_FULL = new ErrorCode(1_013_011_003, "拼团失败,拼团人数已满"); 76 ErrorCode COMBINATION_RECORD_USER_FULL = new ErrorCode(1_013_011_003, "拼团失败,拼团人数已满");
77 ErrorCode COMBINATION_RECORD_FAILED_HAVE_JOINED = new ErrorCode(1_013_011_004, "拼团失败,已参与其它拼团"); 77 ErrorCode COMBINATION_RECORD_FAILED_HAVE_JOINED = new ErrorCode(1_013_011_004, "拼团失败,已参与其它拼团");
78 - ErrorCode COMBINATION_RECORD_FAILED_TIME_END = new ErrorCode(1_013_011_005, "拼团失败,活动已经结束");  
79 - ErrorCode COMBINATION_RECORD_FAILED_SINGLE_LIMIT_COUNT_EXCEED = new ErrorCode(1_013_011_006, "拼团失败,原因:单次限购超出");  
80 - ErrorCode COMBINATION_RECORD_FAILED_TOTAL_LIMIT_COUNT_EXCEED = new ErrorCode(1_013_011_007, "拼团失败,原因:超出总购买次数"); 78 + ErrorCode COMBINATION_RECORD_FAILED_TIME_NOT_START = new ErrorCode(1_013_011_005, "拼团失败,活动未开始");
  79 + ErrorCode COMBINATION_RECORD_FAILED_TIME_END = new ErrorCode(1_013_011_006, "拼团失败,活动已经结束");
  80 + ErrorCode COMBINATION_RECORD_FAILED_SINGLE_LIMIT_COUNT_EXCEED = new ErrorCode(1_013_011_007, "拼团失败,原因:单次限购超出");
  81 + ErrorCode COMBINATION_RECORD_FAILED_TOTAL_LIMIT_COUNT_EXCEED = new ErrorCode(1_013_011_008, "拼团失败,原因:超出总购买次数");
  82 + ErrorCode COMBINATION_RECORD_FAILED_ORDER_STATUS_UNPAID = new ErrorCode(1_013_011_009, "拼团失败,原因:存在未支付订单,请先支付");
81 83
82 // ========== 砍价活动 1-013-012-000 ========== 84 // ========== 砍价活动 1-013-012-000 ==========
83 ErrorCode BARGAIN_ACTIVITY_NOT_EXISTS = new ErrorCode(1_013_012_000, "砍价活动不存在"); 85 ErrorCode BARGAIN_ACTIVITY_NOT_EXISTS = new ErrorCode(1_013_012_000, "砍价活动不存在");
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/bargain/BargainRecordApiImpl.java
@@ -16,9 +16,4 @@ public class BargainRecordApiImpl implements BargainRecordApi { @@ -16,9 +16,4 @@ public class BargainRecordApiImpl implements BargainRecordApi {
16 16
17 } 17 }
18 18
19 - @Override  
20 - public boolean isBargainRecordSuccess(Long userId, Long orderId) {  
21 - return false;  
22 - }  
23 -  
24 } 19 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationActivityApiImpl.java
1 package cn.iocoder.yudao.module.promotion.api.combination; 1 package cn.iocoder.yudao.module.promotion.api.combination;
2 2
3 -import cn.iocoder.yudao.module.promotion.service.combination.CombinationActivityService;  
4 import org.springframework.stereotype.Service; 3 import org.springframework.stereotype.Service;
5 4
6 -import javax.annotation.Resource;  
7 -  
8 /** 5 /**
9 * 拼团活动 Api 接口实现类 6 * 拼团活动 Api 接口实现类
10 * 7 *
@@ -13,12 +10,4 @@ import javax.annotation.Resource; @@ -13,12 +10,4 @@ import javax.annotation.Resource;
13 @Service 10 @Service
14 public class CombinationActivityApiImpl implements CombinationActivityApi { 11 public class CombinationActivityApiImpl implements CombinationActivityApi {
15 12
16 - @Resource  
17 - private CombinationActivityService activityService;  
18 -  
19 - @Override  
20 - public void validateCombination(Long activityId, Long userId, Long skuId, Integer count) {  
21 - activityService.validateCombination(activityId, userId, skuId, count);  
22 - }  
23 -  
24 } 13 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApiImpl.java
@@ -20,6 +20,11 @@ public class CombinationRecordApiImpl implements CombinationRecordApi { @@ -20,6 +20,11 @@ public class CombinationRecordApiImpl implements CombinationRecordApi {
20 private CombinationRecordService recordService; 20 private CombinationRecordService recordService;
21 21
22 @Override 22 @Override
  23 + public void validateCombinationRecord(Long activityId, Long userId, Long skuId, Integer count) {
  24 + recordService.validateCombinationRecord(activityId, userId, skuId, count);
  25 + }
  26 +
  27 + @Override
23 public void createCombinationRecord(CombinationRecordCreateReqDTO reqDTO) { 28 public void createCombinationRecord(CombinationRecordCreateReqDTO reqDTO) {
24 recordService.createCombinationRecord(reqDTO); 29 recordService.createCombinationRecord(reqDTO);
25 } 30 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApiImpl.java
1 package cn.iocoder.yudao.module.promotion.api.seckill; 1 package cn.iocoder.yudao.module.promotion.api.seckill;
2 2
  3 +import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillActivityProductRespDTO;
  4 +import cn.iocoder.yudao.module.promotion.convert.seckill.seckillactivity.SeckillActivityConvert;
3 import cn.iocoder.yudao.module.promotion.service.seckill.SeckillActivityService; 5 import cn.iocoder.yudao.module.promotion.service.seckill.SeckillActivityService;
4 import org.springframework.stereotype.Service; 6 import org.springframework.stereotype.Service;
5 7
6 import javax.annotation.Resource; 8 import javax.annotation.Resource;
  9 +import java.util.Collection;
  10 +import java.util.List;
7 11
8 /** 12 /**
9 * 秒杀活动接口 Api 接口实现类 13 * 秒杀活动接口 Api 接口实现类
@@ -21,4 +25,9 @@ public class SeckillActivityApiImpl implements SeckillActivityApi { @@ -21,4 +25,9 @@ public class SeckillActivityApiImpl implements SeckillActivityApi {
21 activityService.updateSeckillStock(id, skuId, count); 25 activityService.updateSeckillStock(id, skuId, count);
22 } 26 }
23 27
  28 + @Override
  29 + public List<SeckillActivityProductRespDTO> getSeckillActivityProductList(Long id, Collection<Long> skuIds) {
  30 + return SeckillActivityConvert.INSTANCE.convertList4(activityService.getSeckillActivityProductList(id, skuIds));
  31 + }
  32 +
24 } 33 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/combination/CombinationActivityConvert.java
@@ -97,8 +97,8 @@ public interface CombinationActivityConvert { @@ -97,8 +97,8 @@ public interface CombinationActivityConvert {
97 default CombinationRecordDO convert(CombinationRecordCreateReqDTO reqDTO, 97 default CombinationRecordDO convert(CombinationRecordCreateReqDTO reqDTO,
98 CombinationActivityDO activity, MemberUserRespDTO user, 98 CombinationActivityDO activity, MemberUserRespDTO user,
99 ProductSpuRespDTO spu, ProductSkuRespDTO sku) { 99 ProductSpuRespDTO spu, ProductSkuRespDTO sku) {
100 - // TODO @puhui999:订单付款后需要设置开始时间和结束时间;  
101 return convert(reqDTO) 100 return convert(reqDTO)
  101 + .setCount(reqDTO.getCount())
102 .setVirtualGroup(false) 102 .setVirtualGroup(false)
103 .setExpireTime(activity.getStartTime().plusHours(activity.getLimitDuration())) 103 .setExpireTime(activity.getStartTime().plusHours(activity.getLimitDuration()))
104 .setUserSize(activity.getUserSize()) 104 .setUserSize(activity.getUserSize())
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckillactivity/SeckillActivityConvert.java
1 package cn.iocoder.yudao.module.promotion.convert.seckill.seckillactivity; 1 package cn.iocoder.yudao.module.promotion.convert.seckill.seckillactivity;
2 2
3 -import cn.hutool.core.date.LocalDateTimeUtil;  
4 import cn.iocoder.yudao.framework.common.pojo.PageResult; 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; 4 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
6 import cn.iocoder.yudao.framework.common.util.collection.MapUtils; 5 import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
  6 +import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils;
7 import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils; 7 import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils;
8 import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; 8 import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
9 import cn.iocoder.yudao.module.product.enums.DictTypeConstants; 9 import cn.iocoder.yudao.module.product.enums.DictTypeConstants;
  10 +import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillActivityProductRespDTO;
10 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityCreateReqVO; 11 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityCreateReqVO;
11 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityDetailRespVO; 12 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityDetailRespVO;
12 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityRespVO; 13 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityRespVO;
@@ -128,11 +129,16 @@ public interface SeckillActivityConvert { @@ -128,11 +129,16 @@ public interface SeckillActivityConvert {
128 default AppSeckillActivityDetailRespVO convert3(SeckillActivityDO seckillActivity, List<SeckillProductDO> products, SeckillConfigDO filteredConfig) { 129 default AppSeckillActivityDetailRespVO convert3(SeckillActivityDO seckillActivity, List<SeckillProductDO> products, SeckillConfigDO filteredConfig) {
129 return convert2(seckillActivity) 130 return convert2(seckillActivity)
130 .setProducts(convertList1(products)) 131 .setProducts(convertList1(products))
131 - // TODO @puhui999:要不要在里面 default 一个方法,处理这个事件;简洁一点;  
132 - .setStartTime(LocalDateTimeUtil.parse(LocalDateTimeUtil.format(seckillActivity.getStartTime(), "yyyy-MM-dd") + " " + filteredConfig.getStartTime(),  
133 - "yyyy-MM-dd HH:mm:ss")) // 活动开始日期和时段结合  
134 - .setEndTime(LocalDateTimeUtil.parse(LocalDateTimeUtil.format(seckillActivity.getEndTime(), "yyyy-MM-dd") + " " + filteredConfig.getEndTime(),  
135 - "yyyy-MM-dd HH:mm:ss")); // 活动结束日期和时段结合 132 + .setStartTime(new LocalDateTimeUtils.BuilderDateTime()
  133 + .withDate(seckillActivity.getStartTime())
  134 + .withTime(filteredConfig.getStartTime())
  135 + .build())// 活动开始日期和时段结合
  136 + .setEndTime(new LocalDateTimeUtils.BuilderDateTime()
  137 + .withDate(seckillActivity.getEndTime())
  138 + .withTime(filteredConfig.getEndTime())
  139 + .build()); // 活动结束日期和时段结合
136 } 140 }
137 141
  142 + List<SeckillActivityProductRespDTO> convertList4(List<SeckillProductDO> seckillActivityProductList);
  143 +
138 } 144 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/combination/CombinationRecordDO.java
@@ -62,6 +62,10 @@ public class CombinationRecordDO extends BaseDO { @@ -62,6 +62,10 @@ public class CombinationRecordDO extends BaseDO {
62 * SKU 编号 62 * SKU 编号
63 */ 63 */
64 private Long skuId; 64 private Long skuId;
  65 + /**
  66 + * 购买的商品数量
  67 + */
  68 + private Integer count;
65 69
66 /** 70 /**
67 * 用户编号 71 * 用户编号
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/CombinationRecordMapper.java
@@ -20,6 +20,10 @@ public interface CombinationRecordMapper extends BaseMapperX&lt;CombinationRecordDO @@ -20,6 +20,10 @@ public interface CombinationRecordMapper extends BaseMapperX&lt;CombinationRecordDO
20 CombinationRecordDO::getOrderId, orderId); 20 CombinationRecordDO::getOrderId, orderId);
21 } 21 }
22 22
  23 + default List<CombinationRecordDO> selectListByUserId(Long userId) {
  24 + return selectList(CombinationRecordDO::getUserId, userId);
  25 + }
  26 +
23 default List<CombinationRecordDO> selectListByUserIdAndStatus(Long userId, Integer status) { 27 default List<CombinationRecordDO> selectListByUserIdAndStatus(Long userId, Integer status) {
24 return selectList(new LambdaQueryWrapperX<CombinationRecordDO>() 28 return selectList(new LambdaQueryWrapperX<CombinationRecordDO>()
25 .eq(CombinationRecordDO::getUserId, userId) 29 .eq(CombinationRecordDO::getUserId, userId)
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/bargain/BargainActivityServiceImpl.java
@@ -116,10 +116,10 @@ public class BargainActivityServiceImpl implements BargainActivityService { @@ -116,10 +116,10 @@ public class BargainActivityServiceImpl implements BargainActivityService {
116 public void deleteBargainActivity(Long id) { 116 public void deleteBargainActivity(Long id) {
117 // 校验存在 117 // 校验存在
118 BargainActivityDO activityDO = validateBargainActivityExists(id); 118 BargainActivityDO activityDO = validateBargainActivityExists(id);
119 - // 校验状态 TODO puhui: 测试完成后需要恢复校验  
120 - //if (ObjectUtil.equal(activityDO.getStatus(), CommonStatusEnum.ENABLE.getStatus())) {  
121 - // throw exception(BARGAIN_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END);  
122 - //} 119 + // 校验状态
  120 + if (ObjectUtil.equal(activityDO.getStatus(), CommonStatusEnum.ENABLE.getStatus())) {
  121 + throw exception(BARGAIN_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END);
  122 + }
123 123
124 // 删除 124 // 删除
125 bargainActivityMapper.deleteById(id); 125 bargainActivityMapper.deleteById(id);
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityService.java
@@ -85,17 +85,6 @@ public interface CombinationActivityService { @@ -85,17 +85,6 @@ public interface CombinationActivityService {
85 List<CombinationProductDO> getCombinationProductsByActivityIds(Collection<Long> activityIds); 85 List<CombinationProductDO> getCombinationProductsByActivityIds(Collection<Long> activityIds);
86 86
87 /** 87 /**
88 - * 校验是否满足拼团条件  
89 - * 如果不满足,会抛出异常  
90 - *  
91 - * @param activityId 活动编号  
92 - * @param userId 用户编号  
93 - * @param skuId sku 编号  
94 - * @param count 数量  
95 - */  
96 - void validateCombination(Long activityId, Long userId, Long skuId, Integer count);  
97 -  
98 - /**  
99 * 获取正在进行的活动分页数据 88 * 获取正在进行的活动分页数据
100 * 89 *
101 * @param count 需要的数量 90 * @param count 需要的数量
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImpl.java
@@ -17,12 +17,8 @@ import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product @@ -17,12 +17,8 @@ import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product
17 import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert; 17 import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert;
18 import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO; 18 import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO;
19 import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationProductDO; 19 import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationProductDO;
20 -import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO;  
21 import cn.iocoder.yudao.module.promotion.dal.mysql.combination.CombinationActivityMapper; 20 import cn.iocoder.yudao.module.promotion.dal.mysql.combination.CombinationActivityMapper;
22 import cn.iocoder.yudao.module.promotion.dal.mysql.combination.CombinationProductMapper; 21 import cn.iocoder.yudao.module.promotion.dal.mysql.combination.CombinationProductMapper;
23 -import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum;  
24 -import cn.iocoder.yudao.module.trade.api.order.TradeOrderApi;  
25 -import org.springframework.context.annotation.Lazy;  
26 import org.springframework.stereotype.Service; 22 import org.springframework.stereotype.Service;
27 import org.springframework.transaction.annotation.Transactional; 23 import org.springframework.transaction.annotation.Transactional;
28 import org.springframework.validation.annotation.Validated; 24 import org.springframework.validation.annotation.Validated;
@@ -33,7 +29,8 @@ import java.util.List; @@ -33,7 +29,8 @@ import java.util.List;
33 import java.util.Map; 29 import java.util.Map;
34 30
35 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 31 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
36 -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; 32 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
  33 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList;
37 import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS; 34 import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS;
38 import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS; 35 import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS;
39 import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; 36 import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
@@ -54,15 +51,9 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic @@ -54,15 +51,9 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic
54 private CombinationProductMapper combinationProductMapper; 51 private CombinationProductMapper combinationProductMapper;
55 52
56 @Resource 53 @Resource
57 - @Lazy // TODO @puhui999:我感觉 validateCombination 可以挪到 CombinationRecordServiceImpl 中,因为它更偏向能不能创建拼团记录;  
58 - private CombinationRecordService combinationRecordService;  
59 -  
60 - @Resource  
61 private ProductSpuApi productSpuApi; 54 private ProductSpuApi productSpuApi;
62 @Resource 55 @Resource
63 private ProductSkuApi productSkuApi; 56 private ProductSkuApi productSkuApi;
64 - @Resource  
65 - private TradeOrderApi tradeOrderApi;  
66 57
67 @Override 58 @Override
68 @Transactional(rollbackFor = Exception.class) 59 @Transactional(rollbackFor = Exception.class)
@@ -216,36 +207,6 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic @@ -216,36 +207,6 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic
216 } 207 }
217 208
218 @Override 209 @Override
219 - public void validateCombination(Long activityId, Long userId, Long skuId, Integer count) {  
220 - // 1.1 校验拼团活动是否存在  
221 - CombinationActivityDO activity = validateCombinationActivityExists(activityId);  
222 - // 1.2 校验活动是否开启  
223 - if (ObjectUtil.equal(activity.getStatus(), CommonStatusEnum.DISABLE.getStatus())) {  
224 - throw exception(COMBINATION_ACTIVITY_STATUS_DISABLE);  
225 - }  
226 - // 1.3 校验是否超出单次限购数量  
227 - if (count > activity.getSingleLimitCount()) {  
228 - throw exception(COMBINATION_RECORD_FAILED_SINGLE_LIMIT_COUNT_EXCEED);  
229 - }  
230 -  
231 - // 2. 校验是否超出总限购数量  
232 - List<CombinationRecordDO> recordList = combinationRecordService.getRecordListByUserIdAndActivityId(userId, activityId);  
233 - if (CollUtil.isEmpty(recordList)) {  
234 - return;  
235 - }  
236 - // 过滤出拼团成功的  
237 - // TODO @puhui999:count 要不存一个在 record 里?  
238 - List<Long> skuIds = convertList(recordList, CombinationRecordDO::getSkuId,  
239 - item -> ObjectUtil.equals(item.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus()));  
240 - Integer countSum = tradeOrderApi.getOrderItemCountSumByOrderIdAndSkuId(convertList(recordList,  
241 - CombinationRecordDO::getOrderId,  
242 - item -> ObjectUtil.equals(item.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus())), skuIds);  
243 - if (activity.getTotalLimitCount() < countSum) {  
244 - throw exception(COMBINATION_RECORD_FAILED_TOTAL_LIMIT_COUNT_EXCEED);  
245 - }  
246 - }  
247 -  
248 - @Override  
249 public List<CombinationActivityDO> getCombinationActivityListByCount(Integer count) { 210 public List<CombinationActivityDO> getCombinationActivityListByCount(Integer count) {
250 return combinationActivityMapper.selectListByStatus(CommonStatusEnum.ENABLE.getStatus(), count); 211 return combinationActivityMapper.selectListByStatus(CommonStatusEnum.ENABLE.getStatus(), count);
251 } 212 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordService.java
@@ -23,6 +23,17 @@ public interface CombinationRecordService { @@ -23,6 +23,17 @@ public interface CombinationRecordService {
23 void updateCombinationRecordStatusByUserIdAndOrderId(Integer status, Long userId, Long orderId); 23 void updateCombinationRecordStatusByUserIdAndOrderId(Integer status, Long userId, Long orderId);
24 24
25 /** 25 /**
  26 + * 校验是否满足拼团条件
  27 + * 如果不满足,会抛出异常
  28 + *
  29 + * @param activityId 活动编号
  30 + * @param userId 用户编号
  31 + * @param skuId sku 编号
  32 + * @param count 数量
  33 + */
  34 + void validateCombinationRecord(Long activityId, Long userId, Long skuId, Integer count);
  35 +
  36 + /**
26 * 创建拼团记录 37 * 创建拼团记录
27 * 38 *
28 * @param reqDTO 创建信息 39 * @param reqDTO 创建信息
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordServiceImpl.java
@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.promotion.service.combination; @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.promotion.service.combination;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 import cn.hutool.core.util.ObjectUtil; 4 import cn.hutool.core.util.ObjectUtil;
  5 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
5 import cn.iocoder.yudao.module.member.api.user.MemberUserApi; 6 import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
6 import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; 7 import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
7 import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; 8 import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
@@ -14,6 +15,8 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationA @@ -14,6 +15,8 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationA
14 import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO; 15 import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO;
15 import cn.iocoder.yudao.module.promotion.dal.mysql.combination.CombinationRecordMapper; 16 import cn.iocoder.yudao.module.promotion.dal.mysql.combination.CombinationRecordMapper;
16 import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum; 17 import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum;
  18 +import cn.iocoder.yudao.module.trade.api.order.TradeOrderApi;
  19 +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum;
17 import org.springframework.context.annotation.Lazy; 20 import org.springframework.context.annotation.Lazy;
18 import org.springframework.stereotype.Service; 21 import org.springframework.stereotype.Service;
19 import org.springframework.transaction.annotation.Transactional; 22 import org.springframework.transaction.annotation.Transactional;
@@ -24,6 +27,7 @@ import java.time.LocalDateTime; @@ -24,6 +27,7 @@ import java.time.LocalDateTime;
24 import java.util.List; 27 import java.util.List;
25 28
26 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 29 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  30 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
27 import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; 31 import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
28 32
29 // TODO 芋艿:等拼团记录做完,完整 review 下 33 // TODO 芋艿:等拼团记录做完,完整 review 下
@@ -51,6 +55,8 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { @@ -51,6 +55,8 @@ public class CombinationRecordServiceImpl implements CombinationRecordService {
51 @Resource 55 @Resource
52 @Lazy 56 @Lazy
53 private ProductSkuApi productSkuApi; 57 private ProductSkuApi productSkuApi;
  58 + @Resource
  59 + private TradeOrderApi tradeOrderApi;
54 60
55 @Override 61 @Override
56 @Transactional(rollbackFor = Exception.class) 62 @Transactional(rollbackFor = Exception.class)
@@ -96,30 +102,77 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { @@ -96,30 +102,77 @@ public class CombinationRecordServiceImpl implements CombinationRecordService {
96 return recordDO; 102 return recordDO;
97 } 103 }
98 104
99 - // TODO @puhui999:有一个应该在创建那要做下;就是当前 activityId 已经有未支付的订单,不允许在发起新的;要么支付,要么去掉先; 105 + @Override
  106 + public void validateCombinationRecord(Long activityId, Long userId, Long skuId, Integer count) {
  107 + // 1.1 校验拼团活动是否存在
  108 + CombinationActivityDO activity = combinationActivityService.validateCombinationActivityExists(activityId);
  109 + // 1.2 校验活动是否开启
  110 + if (ObjectUtil.equal(activity.getStatus(), CommonStatusEnum.DISABLE.getStatus())) {
  111 + throw exception(COMBINATION_ACTIVITY_STATUS_DISABLE);
  112 + }
  113 + // 2 校验是否超出单次限购数量
  114 + if (count > activity.getSingleLimitCount()) {
  115 + throw exception(COMBINATION_RECORD_FAILED_SINGLE_LIMIT_COUNT_EXCEED);
  116 + }
  117 + // 3、校验是否有拼团记录
  118 + List<CombinationRecordDO> recordList = getRecordListByUserIdAndActivityId(userId, activityId);
  119 + if (CollUtil.isEmpty(recordList)) {
  120 + return;
  121 + }
  122 + // 4、校验是否超出总限购数量
  123 + Integer sumValue = getSumValue(convertList(recordList, CombinationRecordDO::getCount,
  124 + item -> ObjectUtil.equals(item.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus())), i -> i, Integer::sum);
  125 + if ((sumValue + count) > activity.getTotalLimitCount()) {
  126 + throw exception(COMBINATION_RECORD_FAILED_TOTAL_LIMIT_COUNT_EXCEED);
  127 + }
  128 + // 5、校验拼团记录是否存在未支付的订单(如果存在未支付的订单则不允许发起新的拼团)
  129 + CombinationRecordDO record = findFirst(recordList, item -> ObjectUtil.equals(item.getStatus(), null));
  130 + if (record == null) {
  131 + return;
  132 + }
  133 + // 5.1、查询关联的订单是否已经支付
  134 + // 当前 activityId 已经有未支付的订单,不允许在发起新的;要么支付,要么去掉先;
  135 + Integer orderStatus = tradeOrderApi.getOrderStatus(record.getOrderId());
  136 + if (ObjectUtil.equal(orderStatus, TradeOrderStatusEnum.UNPAID.getStatus())) {
  137 + throw exception(COMBINATION_RECORD_FAILED_ORDER_STATUS_UNPAID);
  138 + }
  139 + }
100 140
101 @Override 141 @Override
102 @Transactional(rollbackFor = Exception.class) 142 @Transactional(rollbackFor = Exception.class)
103 public void createCombinationRecord(CombinationRecordCreateReqDTO reqDTO) { 143 public void createCombinationRecord(CombinationRecordCreateReqDTO reqDTO) {
104 - // 1.1 校验拼团活动 144 +
  145 + // 1.1、 校验拼团活动
105 CombinationActivityDO activity = combinationActivityService.validateCombinationActivityExists(reqDTO.getActivityId()); 146 CombinationActivityDO activity = combinationActivityService.validateCombinationActivityExists(reqDTO.getActivityId());
106 - // 1.2 需要校验下,他当前是不是已经参加了该拼团;  
107 - // TODO @puhui999:拼团应该可以重复参加;应该去校验总共的上限哈,就是 activity.totalLimitCount  
108 - CombinationRecordDO recordDO = recordMapper.selectByUserIdAndOrderId(reqDTO.getUserId(), reqDTO.getOrderId());  
109 - if (recordDO != null) {  
110 - throw exception(COMBINATION_RECORD_EXISTS); 147 + // 1.2 校验是否超出单次限购数量
  148 + if (reqDTO.getCount() > activity.getSingleLimitCount()) {
  149 + throw exception(COMBINATION_RECORD_FAILED_SINGLE_LIMIT_COUNT_EXCEED);
  150 + }
  151 + // 1.3、校验是否有拼团记录
  152 + List<CombinationRecordDO> records = getRecordListByUserIdAndActivityId(reqDTO.getUserId(), reqDTO.getActivityId());
  153 + if (CollUtil.isEmpty(records)) {
  154 + return;
111 } 155 }
112 - // 1.3 校验用户是否参加了其它拼团 156 + // 1.4、校验是否超出总限购数量
  157 + Integer sumValue = getSumValue(convertList(records, CombinationRecordDO::getCount,
  158 + item -> ObjectUtil.equals(item.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus())), i -> i, Integer::sum);
  159 + if ((sumValue + reqDTO.getCount()) > activity.getTotalLimitCount()) {
  160 + throw exception(COMBINATION_RECORD_FAILED_TOTAL_LIMIT_COUNT_EXCEED);
  161 + }
  162 + // 2、 校验用户是否参加了其它拼团
113 List<CombinationRecordDO> recordDOList = recordMapper.selectListByUserIdAndStatus(reqDTO.getUserId(), CombinationRecordStatusEnum.IN_PROGRESS.getStatus()); 163 List<CombinationRecordDO> recordDOList = recordMapper.selectListByUserIdAndStatus(reqDTO.getUserId(), CombinationRecordStatusEnum.IN_PROGRESS.getStatus());
114 if (CollUtil.isNotEmpty(recordDOList)) { 164 if (CollUtil.isNotEmpty(recordDOList)) {
115 throw exception(COMBINATION_RECORD_FAILED_HAVE_JOINED); 165 throw exception(COMBINATION_RECORD_FAILED_HAVE_JOINED);
116 } 166 }
117 - // TODO @puhui999:有个开始时间未校验  
118 - // 1.4 校验当前活动是否过期 167 + // 3、 校验活动是否开启
  168 + if (LocalDateTime.now().isAfter(activity.getStartTime())) {
  169 + throw exception(COMBINATION_RECORD_FAILED_TIME_NOT_START);
  170 + }
  171 + // 4、 校验当前活动是否过期
119 if (LocalDateTime.now().isAfter(activity.getEndTime())) { 172 if (LocalDateTime.now().isAfter(activity.getEndTime())) {
120 throw exception(COMBINATION_RECORD_FAILED_TIME_END); 173 throw exception(COMBINATION_RECORD_FAILED_TIME_END);
121 } 174 }
122 - // 1.5 父拼团是否存在,是否已经满了 175 + // 5、 父拼团是否存在,是否已经满了
123 if (reqDTO.getHeadId() != null) { 176 if (reqDTO.getHeadId() != null) {
124 // 查询进行中的父拼团 177 // 查询进行中的父拼团
125 CombinationRecordDO record = recordMapper.selectOneByHeadId(reqDTO.getHeadId(), CombinationRecordStatusEnum.IN_PROGRESS.getStatus()); 178 CombinationRecordDO record = recordMapper.selectOneByHeadId(reqDTO.getHeadId(), CombinationRecordStatusEnum.IN_PROGRESS.getStatus());
@@ -132,8 +185,6 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { @@ -132,8 +185,6 @@ public class CombinationRecordServiceImpl implements CombinationRecordService {
132 } 185 }
133 } 186 }
134 187
135 - // TODO @puhui999:单次限购  
136 -  
137 // 2. 创建拼团记录 188 // 2. 创建拼团记录
138 MemberUserRespDTO user = memberUserApi.getUser(reqDTO.getUserId()); 189 MemberUserRespDTO user = memberUserApi.getUser(reqDTO.getUserId());
139 ProductSpuRespDTO spu = productSpuApi.getSpu(reqDTO.getSpuId()); 190 ProductSpuRespDTO spu = productSpuApi.getSpu(reqDTO.getSpuId());
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityService.java
@@ -37,9 +37,9 @@ public interface SeckillActivityService { @@ -37,9 +37,9 @@ public interface SeckillActivityService {
37 /** 37 /**
38 * 更新秒杀库存 38 * 更新秒杀库存
39 * 39 *
40 - * @param id 活动编号  
41 - * @param skuId sku 编号  
42 - * @param count 数量 40 + * @param id 活动编号
  41 + * @param skuId sku 编号
  42 + * @param count 数量
43 */ 43 */
44 void updateSeckillStock(Long id, Long skuId, Integer count); 44 void updateSeckillStock(Long id, Long skuId, Integer count);
45 45
@@ -114,4 +114,13 @@ public interface SeckillActivityService { @@ -114,4 +114,13 @@ public interface SeckillActivityService {
114 */ 114 */
115 PageResult<SeckillActivityDO> getSeckillActivityAppPageByConfigId(AppSeckillActivityPageReqVO pageReqVO); 115 PageResult<SeckillActivityDO> getSeckillActivityAppPageByConfigId(AppSeckillActivityPageReqVO pageReqVO);
116 116
  117 + /**
  118 + * 获取秒杀活动商品信息
  119 + *
  120 + * @param id 活动编号
  121 + * @param skuIds sku 编号
  122 + * @return 秒杀活动商品信息列表
  123 + */
  124 + List<SeckillProductDO> getSeckillActivityProductList(Long id, Collection<Long> skuIds);
  125 +
117 } 126 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java
1 package cn.iocoder.yudao.module.promotion.service.seckill; 1 package cn.iocoder.yudao.module.promotion.service.seckill;
2 2
  3 +import cn.hutool.core.collection.CollectionUtil;
3 import cn.hutool.core.util.ObjectUtil; 4 import cn.hutool.core.util.ObjectUtil;
4 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 5 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
5 import cn.iocoder.yudao.framework.common.pojo.PageResult; 6 import cn.iocoder.yudao.framework.common.pojo.PageResult;
@@ -278,4 +279,18 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { @@ -278,4 +279,18 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
278 return seckillActivityMapper.selectPage(pageReqVO, CommonStatusEnum.ENABLE.getStatus()); 279 return seckillActivityMapper.selectPage(pageReqVO, CommonStatusEnum.ENABLE.getStatus());
279 } 280 }
280 281
  282 + @Override
  283 + public List<SeckillProductDO> getSeckillActivityProductList(Long id, Collection<Long> skuIds) {
  284 + // 1、校验秒杀活动是否存在
  285 + validateSeckillActivityExists(id);
  286 + // 2、校验活动商品是否存在
  287 + List<SeckillProductDO> productList = filterList(seckillProductMapper.selectListByActivityId(id),
  288 + item -> skuIds.contains(item.getSkuId()));
  289 + if (CollectionUtil.isEmpty(productList)) {
  290 + throw exception(SKU_NOT_EXISTS);
  291 + }
  292 +
  293 + return productList;
  294 + }
  295 +
281 } 296 }
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/api/order/TradeOrderApi.java
1 package cn.iocoder.yudao.module.trade.api.order; 1 package cn.iocoder.yudao.module.trade.api.order;
2 2
3 -import java.util.Collection;  
4 -  
5 /** 3 /**
6 * 订单 API 接口 4 * 订单 API 接口
7 * 5 *
@@ -10,21 +8,11 @@ import java.util.Collection; @@ -10,21 +8,11 @@ import java.util.Collection;
10 public interface TradeOrderApi { 8 public interface TradeOrderApi {
11 9
12 /** 10 /**
13 - * 验证订单  
14 - *  
15 - * @param userId 用户 id  
16 - * @param orderItemId 订单项 id  
17 - * @return 校验通过返回订单 id  
18 - */  
19 - Long validateOrder(Long userId, Long orderItemId);  
20 -  
21 - /**  
22 - * 获取订单项商品购买数量总和 11 + * 获取订单状态
23 * 12 *
24 - * @param orderIds 订单编号  
25 - * @param skuIds sku 编号  
26 - * @return 订单项商品购买数量总和 13 + * @param id 订单编号
  14 + * @return 订单状态
27 */ 15 */
28 - Integer getOrderItemCountSumByOrderIdAndSkuId(Collection<Long> orderIds, Collection<Long> skuIds); 16 + Integer getOrderStatus(Long id);
29 17
30 } 18 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/api/order/TradeOrderApiImpl.java
1 package cn.iocoder.yudao.module.trade.api.order; 1 package cn.iocoder.yudao.module.trade.api.order;
2 2
3 -import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; 3 +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
4 import cn.iocoder.yudao.module.trade.service.order.TradeOrderQueryService; 4 import cn.iocoder.yudao.module.trade.service.order.TradeOrderQueryService;
5 import org.springframework.stereotype.Service; 5 import org.springframework.stereotype.Service;
6 import org.springframework.validation.annotation.Validated; 6 import org.springframework.validation.annotation.Validated;
7 7
8 import javax.annotation.Resource; 8 import javax.annotation.Resource;
9 -import java.util.Collection;  
10 9
11 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 10 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
12 -import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.ORDER_ITEM_NOT_FOUND; 11 +import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.ORDER_NOT_FOUND;
13 12
14 /** 13 /**
15 * 订单 API 接口实现类 14 * 订单 API 接口实现类
@@ -24,18 +23,12 @@ public class TradeOrderApiImpl implements TradeOrderApi { @@ -24,18 +23,12 @@ public class TradeOrderApiImpl implements TradeOrderApi {
24 private TradeOrderQueryService tradeOrderQueryService; 23 private TradeOrderQueryService tradeOrderQueryService;
25 24
26 @Override 25 @Override
27 - public Long validateOrder(Long userId, Long orderItemId) {  
28 - // 校验订单项,订单项存在订单就存在  
29 - TradeOrderItemDO item = tradeOrderQueryService.getOrderItem(userId, orderItemId);  
30 - if (item == null) {  
31 - throw exception(ORDER_ITEM_NOT_FOUND); 26 + public Integer getOrderStatus(Long id) {
  27 + TradeOrderDO order = tradeOrderQueryService.getOrder(id);
  28 + if (order == null) {
  29 + throw exception(ORDER_NOT_FOUND);
32 } 30 }
33 - return item.getOrderId();  
34 - }  
35 -  
36 - @Override  
37 - public Integer getOrderItemCountSumByOrderIdAndSkuId(Collection<Long> orderIds, Collection<Long> skuIds) {  
38 - return tradeOrderQueryService.getOrderItemCountSumByOrderIdAndSkuId(orderIds, skuIds); 31 + return order.getStatus();
39 } 32 }
40 33
41 } 34 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderSettlementReqVO.java
@@ -16,6 +16,7 @@ import java.util.List; @@ -16,6 +16,7 @@ import java.util.List;
16 16
17 @Schema(description = "用户 App - 交易订单结算 Request VO") 17 @Schema(description = "用户 App - 交易订单结算 Request VO")
18 @Data 18 @Data
  19 +@Valid
19 public class AppTradeOrderSettlementReqVO { 20 public class AppTradeOrderSettlementReqVO {
20 21
21 @Schema(description = "商品项数组", requiredMode = Schema.RequiredMode.REQUIRED) 22 @Schema(description = "商品项数组", requiredMode = Schema.RequiredMode.REQUIRED)
@@ -62,7 +63,16 @@ public class AppTradeOrderSettlementReqVO { @@ -62,7 +63,16 @@ public class AppTradeOrderSettlementReqVO {
62 @Schema(description = "砍价活动编号", example = "123") 63 @Schema(description = "砍价活动编号", example = "123")
63 private Long bargainActivityId; 64 private Long bargainActivityId;
64 65
65 - // TODO @puhui999:可以写个参数校验,如果 seckillActivityId 或 combinationActivityId 或 combinationHeadId 的情况,items 应该只有一个 66 + @AssertTrue(message = "活动商品每次只能购买一种规格")
  67 + @JsonIgnore
  68 + public boolean isValidActivityItems() {
  69 + // 校验是否是活动订单
  70 + if (seckillActivityId == null && combinationActivityId == null && combinationHeadId == null) {
  71 + return true;
  72 + }
  73 + // 校验订单项是否超出
  74 + return items.size() == 1;
  75 + }
66 76
67 @Data 77 @Data
68 @Schema(description = "用户 App - 商品项") 78 @Schema(description = "用户 App - 商品项")
@@ -70,7 +80,9 @@ public class AppTradeOrderSettlementReqVO { @@ -70,7 +80,9 @@ public class AppTradeOrderSettlementReqVO {
70 public static class Item { 80 public static class Item {
71 81
72 @Schema(description = "商品 SKU 编号", example = "2048") 82 @Schema(description = "商品 SKU 编号", example = "2048")
  83 + @NotNull(message = "商品 SKU 编号不能为空")
73 private Long skuId; 84 private Long skuId;
  85 +
74 @Schema(description = "购买数量", example = "1") 86 @Schema(description = "购买数量", example = "1")
75 @Min(value = 1, message = "购买数量最小值为 {value}") 87 @Min(value = 1, message = "购买数量最小值为 {value}")
76 private Integer count; 88 private Integer count;
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java
@@ -93,6 +93,7 @@ public interface TradeOrderConvert { @@ -93,6 +93,7 @@ public interface TradeOrderConvert {
93 new ProductSkuUpdateStockReqDTO.Item().setId(item.getSkuId()).setIncrCount(item.getCount())); 93 new ProductSkuUpdateStockReqDTO.Item().setId(item.getSkuId()).setIncrCount(item.getCount()));
94 return new ProductSkuUpdateStockReqDTO(items); 94 return new ProductSkuUpdateStockReqDTO(items);
95 } 95 }
  96 +
96 default ProductSkuUpdateStockReqDTO convertNegative(List<AppTradeOrderSettlementReqVO.Item> list) { 97 default ProductSkuUpdateStockReqDTO convertNegative(List<AppTradeOrderSettlementReqVO.Item> list) {
97 List<ProductSkuUpdateStockReqDTO.Item> items = CollectionUtils.convertList(list, item -> 98 List<ProductSkuUpdateStockReqDTO.Item> items = CollectionUtils.convertList(list, item ->
98 new ProductSkuUpdateStockReqDTO.Item().setId(item.getSkuId()).setIncrCount(-item.getCount())); 99 new ProductSkuUpdateStockReqDTO.Item().setId(item.getSkuId()).setIncrCount(-item.getCount()));
@@ -209,6 +210,8 @@ public interface TradeOrderConvert { @@ -209,6 +210,8 @@ public interface TradeOrderConvert {
209 }) 210 })
210 ProductCommentCreateReqDTO convert04(AppTradeOrderItemCommentCreateReqVO createReqVO, TradeOrderItemDO tradeOrderItemDO); 211 ProductCommentCreateReqDTO convert04(AppTradeOrderItemCommentCreateReqVO createReqVO, TradeOrderItemDO tradeOrderItemDO);
211 212
  213 + TradePriceCalculateReqBO convert(AppTradeOrderSettlementReqVO settlementReqVO);
  214 +
212 default TradePriceCalculateReqBO convert(Long userId, AppTradeOrderSettlementReqVO settlementReqVO, 215 default TradePriceCalculateReqBO convert(Long userId, AppTradeOrderSettlementReqVO settlementReqVO,
213 List<CartDO> cartList) { 216 List<CartDO> cartList) {
214 TradePriceCalculateReqBO reqBO = new TradePriceCalculateReqBO().setUserId(userId) 217 TradePriceCalculateReqBO reqBO = new TradePriceCalculateReqBO().setUserId(userId)
@@ -249,17 +252,6 @@ public interface TradeOrderConvert { @@ -249,17 +252,6 @@ public interface TradeOrderConvert {
249 252
250 AppTradeOrderSettlementRespVO convert0(TradePriceCalculateRespBO calculate, AddressRespDTO address); 253 AppTradeOrderSettlementRespVO convert0(TradePriceCalculateRespBO calculate, AddressRespDTO address);
251 254
252 - @Mappings({  
253 - @Mapping(target = "activityId", source = "afterOrderCreateReqBO.combinationActivityId"),  
254 - @Mapping(target = "spuId", source = "afterOrderCreateReqBO.spuId"),  
255 - @Mapping(target = "skuId", source = "afterOrderCreateReqBO.skuId"),  
256 - @Mapping(target = "orderId", source = "afterOrderCreateReqBO.orderId"),  
257 - @Mapping(target = "userId", source = "afterOrderCreateReqBO.userId"),  
258 - @Mapping(target = "headId", source = "afterOrderCreateReqBO.combinationHeadId"),  
259 - @Mapping(target = "combinationPrice", source = "afterOrderCreateReqBO.payPrice"),  
260 - })  
261 - CombinationRecordCreateReqDTO convert(TradeAfterOrderCreateReqBO afterOrderCreateReqBO);  
262 -  
263 List<AppOrderExpressTrackRespDTO> convertList02(List<ExpressTrackRespDTO> list); 255 List<AppOrderExpressTrackRespDTO> convertList02(List<ExpressTrackRespDTO> list);
264 256
265 TradeOrderDO convert(TradeOrderUpdateAddressReqVO reqVO); 257 TradeOrderDO convert(TradeOrderUpdateAddressReqVO reqVO);
@@ -280,18 +272,36 @@ public interface TradeOrderConvert { @@ -280,18 +272,36 @@ public interface TradeOrderConvert {
280 return bo; 272 return bo;
281 } 273 }
282 274
283 - TradeBeforeOrderCreateReqBO convert(AppTradeOrderCreateReqVO createReqVO); 275 + @Mappings({
  276 + @Mapping(target = "userId", source = "userId"),
  277 + @Mapping(target = "orderType", source = "calculateRespBO.type"),
  278 + @Mapping(target = "items", source = "createReqVO.items"),
  279 + })
  280 + TradeBeforeOrderCreateReqBO convert(Long userId, AppTradeOrderCreateReqVO createReqVO, TradePriceCalculateRespBO calculateRespBO);
  281 +
  282 +
  283 + List<TradeAfterOrderCreateReqBO.Item> convertList(List<TradeOrderItemDO> orderItems);
  284 +
284 285
285 @Mappings({ 286 @Mappings({
286 - @Mapping(target = "combinationActivityId", source = "createReqVO.combinationActivityId"),  
287 - @Mapping(target = "combinationHeadId", source = "createReqVO.combinationHeadId"),  
288 - @Mapping(target = "spuId", source = "orderItem.spuId"),  
289 - @Mapping(target = "skuId", source = "orderItem.skuId"),  
290 - @Mapping(target = "orderId", source = "tradeOrderDO.id"),  
291 @Mapping(target = "userId", source = "userId"), 287 @Mapping(target = "userId", source = "userId"),
  288 + @Mapping(target = "orderId", source = "tradeOrderDO.id"),
292 @Mapping(target = "payPrice", source = "tradeOrderDO.payPrice"), 289 @Mapping(target = "payPrice", source = "tradeOrderDO.payPrice"),
  290 + @Mapping(target = "items", source = "orderItems"),
293 }) 291 })
294 TradeAfterOrderCreateReqBO convert(Long userId, AppTradeOrderCreateReqVO createReqVO, 292 TradeAfterOrderCreateReqBO convert(Long userId, AppTradeOrderCreateReqVO createReqVO,
295 - TradeOrderDO tradeOrderDO, TradeOrderItemDO orderItem); 293 + TradeOrderDO tradeOrderDO, List<TradeOrderItemDO> orderItems);
  294 +
  295 + @Mappings({
  296 + @Mapping(target = "activityId", source = "combinationActivityId"),
  297 + @Mapping(target = "spuId", expression = "java(reqBO.getItems().get(0).getSpuId())"),
  298 + @Mapping(target = "skuId", expression = "java(reqBO.getItems().get(0).getSkuId())"),// TODO 艿艿看看这里
  299 + @Mapping(target = "count", expression = "java(reqBO.getItems().get(0).getCount())"),
  300 + @Mapping(target = "orderId", source = "orderId"),
  301 + @Mapping(target = "userId", source = "userId"),
  302 + @Mapping(target = "headId", source = "combinationHeadId"),
  303 + @Mapping(target = "combinationPrice", source = "payPrice")
  304 + })
  305 + CombinationRecordCreateReqDTO convert(TradeAfterOrderCreateReqBO reqBO);
296 306
297 } 307 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/TradeOrderItemMapper.java
@@ -26,12 +26,6 @@ public interface TradeOrderItemMapper extends BaseMapperX&lt;TradeOrderItemDO&gt; { @@ -26,12 +26,6 @@ public interface TradeOrderItemMapper extends BaseMapperX&lt;TradeOrderItemDO&gt; {
26 return selectList(TradeOrderItemDO::getOrderId, orderIds); 26 return selectList(TradeOrderItemDO::getOrderId, orderIds);
27 } 27 }
28 28
29 - default List<TradeOrderItemDO> selectListByOrderIdAnSkuId(Collection<Long> orderIds, Collection<Long> skuIds) {  
30 - return selectList(new LambdaQueryWrapperX<TradeOrderItemDO>()  
31 - .in(TradeOrderItemDO::getOrderId, orderIds)  
32 - .in(TradeOrderItemDO::getSkuId, skuIds));  
33 - }  
34 -  
35 default TradeOrderItemDO selectByIdAndUserId(Long orderItemId, Long loginUserId) { 29 default TradeOrderItemDO selectByIdAndUserId(Long orderItemId, Long loginUserId) {
36 return selectOne(new LambdaQueryWrapperX<TradeOrderItemDO>() 30 return selectOne(new LambdaQueryWrapperX<TradeOrderItemDO>()
37 .eq(TradeOrderItemDO::getId, orderItemId) 31 .eq(TradeOrderItemDO::getId, orderItemId)
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryService.java
@@ -119,13 +119,5 @@ public interface TradeOrderQueryService { @@ -119,13 +119,5 @@ public interface TradeOrderQueryService {
119 */ 119 */
120 List<TradeOrderItemDO> getOrderItemListByOrderId(Collection<Long> orderIds); 120 List<TradeOrderItemDO> getOrderItemListByOrderId(Collection<Long> orderIds);
121 121
122 - /**  
123 - * 获取订单项商品购买数量总和  
124 - *  
125 - * @param orderIds 订单编号  
126 - * @param skuIds sku 编号  
127 - * @return 订单项商品购买数量总和  
128 - */  
129 - Integer getOrderItemCountSumByOrderIdAndSkuId(Collection<Long> orderIds, Collection<Long> skuIds);  
130 122
131 } 123 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryServiceImpl.java
@@ -4,7 +4,6 @@ import cn.hutool.core.collection.CollUtil; @@ -4,7 +4,6 @@ import cn.hutool.core.collection.CollUtil;
4 import cn.hutool.core.util.ObjectUtil; 4 import cn.hutool.core.util.ObjectUtil;
5 import cn.hutool.core.util.StrUtil; 5 import cn.hutool.core.util.StrUtil;
6 import cn.iocoder.yudao.framework.common.pojo.PageResult; 6 import cn.iocoder.yudao.framework.common.pojo.PageResult;
7 -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;  
8 import cn.iocoder.yudao.module.member.api.user.MemberUserApi; 7 import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
9 import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; 8 import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
10 import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderPageReqVO; 9 import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderPageReqVO;
@@ -169,10 +168,4 @@ public class TradeOrderQueryServiceImpl implements TradeOrderQueryService { @@ -169,10 +168,4 @@ public class TradeOrderQueryServiceImpl implements TradeOrderQueryService {
169 return tradeOrderItemMapper.selectListByOrderId(orderIds); 168 return tradeOrderItemMapper.selectListByOrderId(orderIds);
170 } 169 }
171 170
172 - @Override  
173 - public Integer getOrderItemCountSumByOrderIdAndSkuId(Collection<Long> orderIds, Collection<Long> skuIds) {  
174 - List<TradeOrderItemDO> tradeOrderItems = tradeOrderItemMapper.selectListByOrderIdAnSkuId(orderIds, skuIds);  
175 - return CollectionUtils.getSumValue(tradeOrderItems, TradeOrderItemDO::getCount, Integer::sum);  
176 - }  
177 -  
178 } 171 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java
@@ -59,7 +59,7 @@ import cn.iocoder.yudao.module.trade.service.cart.CartService; @@ -59,7 +59,7 @@ import cn.iocoder.yudao.module.trade.service.cart.CartService;
59 import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressService; 59 import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressService;
60 import cn.iocoder.yudao.module.trade.service.message.TradeMessageService; 60 import cn.iocoder.yudao.module.trade.service.message.TradeMessageService;
61 import cn.iocoder.yudao.module.trade.service.message.bo.TradeOrderMessageWhenDeliveryOrderReqBO; 61 import cn.iocoder.yudao.module.trade.service.message.bo.TradeOrderMessageWhenDeliveryOrderReqBO;
62 -import cn.iocoder.yudao.module.trade.service.order.bo.TradeBeforeOrderCreateReqBO; 62 +import cn.iocoder.yudao.module.trade.service.order.bo.TradeAfterPayOrderReqBO;
63 import cn.iocoder.yudao.module.trade.service.order.handler.TradeOrderHandler; 63 import cn.iocoder.yudao.module.trade.service.order.handler.TradeOrderHandler;
64 import cn.iocoder.yudao.module.trade.service.price.TradePriceService; 64 import cn.iocoder.yudao.module.trade.service.price.TradePriceService;
65 import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; 65 import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO;
@@ -253,12 +253,9 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @@ -253,12 +253,9 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
253 private void beforeCreateTradeOrder(Long userId, AppTradeOrderCreateReqVO createReqVO, 253 private void beforeCreateTradeOrder(Long userId, AppTradeOrderCreateReqVO createReqVO,
254 TradePriceCalculateRespBO calculateRespBO) { 254 TradePriceCalculateRespBO calculateRespBO) {
255 // 1. 执行订单创建前置处理器 255 // 1. 执行订单创建前置处理器
256 - TradeBeforeOrderCreateReqBO beforeOrderCreateReqBO = TradeOrderConvert.INSTANCE.convert(createReqVO);  
257 - beforeOrderCreateReqBO.setOrderType(calculateRespBO.getType());  
258 - beforeOrderCreateReqBO.setUserId(userId);  
259 - beforeOrderCreateReqBO.setCount(getSumValue(createReqVO.getItems(), AppTradeOrderSettlementReqVO.Item::getCount, Integer::sum));  
260 // TODO @puhui999:这里有个纠结点;handler 的定义是只处理指定类型的订单的拓展逻辑;还是通用的 handler,类似可以处理优惠劵等等 256 // TODO @puhui999:这里有个纠结点;handler 的定义是只处理指定类型的订单的拓展逻辑;还是通用的 handler,类似可以处理优惠劵等等
261 - tradeOrderHandlers.forEach(handler -> handler.beforeOrderCreate(beforeOrderCreateReqBO)); 257 + tradeOrderHandlers.forEach(handler ->
  258 + handler.beforeOrderCreate(TradeOrderConvert.INSTANCE.convert(userId, createReqVO, calculateRespBO)));
262 259
263 // 2. 下单时扣减商品库存 260 // 2. 下单时扣减商品库存
264 productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convertNegative(createReqVO.getItems())); 261 productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convertNegative(createReqVO.getItems()));
@@ -278,9 +275,8 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @@ -278,9 +275,8 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
278 TradeOrderDO order, List<TradeOrderItemDO> orderItems, 275 TradeOrderDO order, List<TradeOrderItemDO> orderItems,
279 TradePriceCalculateRespBO calculateRespBO) { 276 TradePriceCalculateRespBO calculateRespBO) {
280 // 1. 执行订单创建后置处理器 277 // 1. 执行订单创建后置处理器
281 - // TODO @puhui999:从通用性来说,应该不用 orderItems.get(0)  
282 tradeOrderHandlers.forEach(handler -> handler.afterOrderCreate( 278 tradeOrderHandlers.forEach(handler -> handler.afterOrderCreate(
283 - TradeOrderConvert.INSTANCE.convert(userId, createReqVO, order, orderItems.get(0)))); 279 + TradeOrderConvert.INSTANCE.convert(userId, createReqVO, order, orderItems)));
284 280
285 // 2. 有使用优惠券时更新 281 // 2. 有使用优惠券时更新
286 // 不在前置扣减的原因,是因为优惠劵要记录使用的订单号 282 // 不在前置扣减的原因,是因为优惠劵要记录使用的订单号
@@ -337,13 +333,9 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @@ -337,13 +333,9 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
337 throw exception(ORDER_UPDATE_PAID_STATUS_NOT_UNPAID); 333 throw exception(ORDER_UPDATE_PAID_STATUS_NOT_UNPAID);
338 } 334 }
339 335
340 - // 3. 校验活动  
341 - // 1、拼团活动  
342 - // TODO @puhui999:这块也抽象到 handler 里  
343 - if (Objects.equals(TradeOrderTypeEnum.COMBINATION.getType(), order.getType())) {  
344 - // 更新拼团状态 TODO puhui999:订单支付失败或订单支付过期删除这条拼团记录  
345 - combinationRecordApi.updateRecordStatusToInProgress(order.getUserId(), order.getId(), LocalDateTime.now());  
346 - } 336 + // 3、订单支付成功后
  337 + tradeOrderHandlers.forEach(tradeOrderHandler -> tradeOrderHandler.afterPayOrder(new TradeAfterPayOrderReqBO()
  338 + .setOrderId(order.getId()).setOrderType(order.getType()).setUserId(order.getUserId()).setPayTime(LocalDateTime.now())));
347 339
348 // 4.1 增加用户积分(赠送) 340 // 4.1 增加用户积分(赠送)
349 addUserPoint(order.getUserId(), order.getGivePoint(), MemberPointBizTypeEnum.ORDER_GIVE, order.getId()); 341 addUserPoint(order.getUserId(), order.getGivePoint(), MemberPointBizTypeEnum.ORDER_GIVE, order.getId());
@@ -470,14 +462,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @@ -470,14 +462,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
470 throw exception(ORDER_DELIVERY_FAIL_COMBINATION_RECORD_STATUS_NOT_SUCCESS); 462 throw exception(ORDER_DELIVERY_FAIL_COMBINATION_RECORD_STATUS_NOT_SUCCESS);
471 } 463 }
472 } 464 }
473 - // 订单类类型:砍价  
474 - if (Objects.equals(TradeOrderTypeEnum.BARGAIN.getType(), order.getType())) {  
475 - // 校验订单砍价是否成功  
476 - // TODO @puhui999:砍价的话,应该不用校验。因为是砍价成功后,才可以下单  
477 - if (!bargainRecordApi.isBargainRecordSuccess(order.getUserId(), order.getId())) {  
478 - throw exception(ORDER_DELIVERY_FAIL_BARGAIN_RECORD_STATUS_NOT_SUCCESS);  
479 - }  
480 - } 465 +
481 return order; 466 return order;
482 } 467 }
483 468
@@ -644,7 +629,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @@ -644,7 +629,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
644 } 629 }
645 630
646 // 2. TODO 活动相关库存回滚需要活动 id,活动 id 怎么获取?app 端能否传过来;回复:从订单里拿呀 631 // 2. TODO 活动相关库存回滚需要活动 id,活动 id 怎么获取?app 端能否传过来;回复:从订单里拿呀
647 - tradeOrderHandlers.forEach(handler -> handler.rollback()); 632 + tradeOrderHandlers.forEach(handler -> handler.cancelOrder());
648 633
649 // 3. 回滚库存 634 // 3. 回滚库存
650 List<TradeOrderItemDO> orderItems = tradeOrderItemMapper.selectListByOrderId(id); 635 List<TradeOrderItemDO> orderItems = tradeOrderItemMapper.selectListByOrderId(id);
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/TradeAfterOrderCreateReqBO.java
1 package cn.iocoder.yudao.module.trade.service.order.bo; 1 package cn.iocoder.yudao.module.trade.service.order.bo;
2 2
3 -import io.swagger.v3.oas.annotations.media.Schema;  
4 import lombok.Data; 3 import lombok.Data;
5 4
  5 +import javax.validation.Valid;
6 import javax.validation.constraints.NotNull; 6 import javax.validation.constraints.NotNull;
  7 +import java.util.List;
7 8
8 // TODO 芋艿:在想想这些参数的定义 9 // TODO 芋艿:在想想这些参数的定义
9 /** 10 /**
@@ -16,25 +17,71 @@ public class TradeAfterOrderCreateReqBO { @@ -16,25 +17,71 @@ public class TradeAfterOrderCreateReqBO {
16 17
17 // ========== 拼团活动相关字段 ========== 18 // ========== 拼团活动相关字段 ==========
18 19
19 - @Schema(description = "拼团活动编号", example = "1024") 20 + /**
  21 + * 拼团活动编号
  22 + */
20 private Long combinationActivityId; 23 private Long combinationActivityId;
21 24
22 - @Schema(description = "拼团团长编号", example = "2048") 25 + /**
  26 + * 拼团团长编号
  27 + */
23 private Long combinationHeadId; 28 private Long combinationHeadId;
24 29
25 - @NotNull(message = "SPU 编号不能为空")  
26 - private Long spuId;  
27 -  
28 - @NotNull(message = "SKU 编号活动商品不能为空")  
29 - private Long skuId;  
30 - 30 + /**
  31 + * 订单编号
  32 + */
31 @NotNull(message = "订单编号不能为空") 33 @NotNull(message = "订单编号不能为空")
32 private Long orderId; 34 private Long orderId;
33 35
  36 + /**
  37 + * 用户编号
  38 + */
34 @NotNull(message = "用户编号不能为空") 39 @NotNull(message = "用户编号不能为空")
35 private Long userId; 40 private Long userId;
36 41
  42 + /**
  43 + * 支付金额
  44 + */
37 @NotNull(message = "支付金额不能为空") 45 @NotNull(message = "支付金额不能为空")
38 private Integer payPrice; 46 private Integer payPrice;
39 47
  48 + // ========== 购买商品相关字段 ==========
  49 +
  50 + /**
  51 + * 订单购买的商品信息
  52 + */
  53 + private List<Item> items;
  54 +
  55 + /**
  56 + * 订单商品信息
  57 + * 记录购买商品的简要核心信息
  58 + *
  59 + * @author HUIHUI
  60 + */
  61 + @Data
  62 + @Valid
  63 + public static class Item {
  64 +
  65 + /**
  66 + * SPU 编号
  67 + */
  68 + @NotNull(message = "SPU 编号不能为空")
  69 + private Long spuId;
  70 +
  71 + /**
  72 + * 商品 SKU 编号
  73 + *
  74 + * 关联 ProductSkuDO 的 id 编号
  75 + */
  76 + @NotNull(message = "SKU 编号活动商品不能为空")
  77 + private Long skuId;
  78 +
  79 + /**
  80 + * 购买的商品数量
  81 + */
  82 + @NotNull(message = "购买数量不能为空")
  83 + private Integer count;
  84 +
  85 + }
  86 +
40 } 87 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/TradeAfterPayOrderReqBO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.trade.service.order.bo;
  2 +
  3 +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum;
  4 +import io.swagger.v3.oas.annotations.media.Schema;
  5 +import lombok.Data;
  6 +
  7 +import java.time.LocalDateTime;
  8 +
  9 +/**
  10 + * 订单支付后 Request BO
  11 + *
  12 + * @author HUIHUI
  13 + */
  14 +@Data
  15 +public class TradeAfterPayOrderReqBO {
  16 +
  17 + /**
  18 + * 订单编号
  19 + */
  20 + @Schema(description = "订单编号", example = "6")
  21 + private Long orderId;
  22 +
  23 + /**
  24 + * 订单类型
  25 + *
  26 + * 枚举 {@link TradeOrderTypeEnum}
  27 + */
  28 + @Schema(description = "订单类型", example = "3")
  29 + private Integer orderType;
  30 +
  31 + /**
  32 + * 用户编号
  33 + */
  34 + @Schema(description = "用户编号", example = "11")
  35 + private Long userId;
  36 +
  37 + /**
  38 + * 订单支付时间
  39 + */
  40 + @Schema(description = "订单支付时间", example = "2023-08-15 10:00:00")
  41 + private LocalDateTime payTime;
  42 +
  43 +}
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/TradeBeforeOrderCreateReqBO.java
1 package cn.iocoder.yudao.module.trade.service.order.bo; 1 package cn.iocoder.yudao.module.trade.service.order.bo;
2 2
3 import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; 3 import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum;
4 -import io.swagger.v3.oas.annotations.media.Schema;  
5 import lombok.Data; 4 import lombok.Data;
6 5
  6 +import javax.validation.Valid;
7 import javax.validation.constraints.NotNull; 7 import javax.validation.constraints.NotNull;
8 - 8 +import java.util.List;
9 // TODO 芋艿:在想想这些参数的定义 9 // TODO 芋艿:在想想这些参数的定义
  10 +
10 /** 11 /**
11 * 订单创建之前 Request BO 12 * 订单创建之前 Request BO
12 * 13 *
@@ -34,9 +35,8 @@ public class TradeBeforeOrderCreateReqBO { @@ -34,9 +35,8 @@ public class TradeBeforeOrderCreateReqBO {
34 // ========== 秒杀活动相关字段 ========== 35 // ========== 秒杀活动相关字段 ==========
35 36
36 /** 37 /**
37 - * 38 + * 秒杀活动编号
38 */ 39 */
39 - @Schema(description = "秒杀活动编号", example = "1024")  
40 private Long seckillActivityId; 40 private Long seckillActivityId;
41 41
42 // ========== 拼团活动相关字段 ========== 42 // ========== 拼团活动相关字段 ==========
@@ -44,13 +44,11 @@ public class TradeBeforeOrderCreateReqBO { @@ -44,13 +44,11 @@ public class TradeBeforeOrderCreateReqBO {
44 /** 44 /**
45 * 拼团活动编号 45 * 拼团活动编号
46 */ 46 */
47 - @Schema(description = "拼团活动编号", example = "1024")  
48 private Long combinationActivityId; 47 private Long combinationActivityId;
49 48
50 /** 49 /**
51 * 拼团团长编号 50 * 拼团团长编号
52 */ 51 */
53 - @Schema(description = "拼团团长编号", example = "2048")  
54 private Long combinationHeadId; 52 private Long combinationHeadId;
55 53
56 // ========== 砍价活动相关字段 ========== 54 // ========== 砍价活动相关字段 ==========
@@ -58,31 +56,39 @@ public class TradeBeforeOrderCreateReqBO { @@ -58,31 +56,39 @@ public class TradeBeforeOrderCreateReqBO {
58 /** 56 /**
59 * 砍价活动编号 57 * 砍价活动编号
60 */ 58 */
61 - @Schema(description = "砍价活动编号", example = "123")  
62 private Long bargainActivityId; 59 private Long bargainActivityId;
63 60
64 - // ========== 活动购买商品相关字段 ========== 61 + // ========== 购买商品相关字段 ==========
65 62
66 /** 63 /**
67 - * 商品 SPU 编号  
68 - *  
69 - * 关联 ProductSkuDO 的 spuId 编号 64 + * 订单购买的商品信息
70 */ 65 */
71 - @NotNull(message = "SPU 编号不能为空")  
72 - private Long spuId; 66 + private List<Item> items;
73 67
74 /** 68 /**
75 - * 商品 SKU 编号 69 + * 订单商品信息
  70 + * 记录购买商品的简要核心信息
76 * 71 *
77 - * 关联 ProductSkuDO 的 id 编号  
78 - */  
79 - @NotNull(message = "SKU 编号活动商品不能为空")  
80 - private Long skuId;  
81 -  
82 - /**  
83 - * 购买的商品数量 72 + * @author HUIHUI
84 */ 73 */
85 - @NotNull(message = "购买数量不能为空")  
86 - private Integer count; 74 + @Data
  75 + @Valid
  76 + public static class Item {
  77 +
  78 + /**
  79 + * 商品 SKU 编号
  80 + *
  81 + * 关联 ProductSkuDO 的 id 编号
  82 + */
  83 + @NotNull(message = "SKU 编号活动商品不能为空")
  84 + private Long skuId;
  85 +
  86 + /**
  87 + * 购买的商品数量
  88 + */
  89 + @NotNull(message = "购买数量不能为空")
  90 + private Integer count;
  91 +
  92 + }
87 93
88 } 94 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeBargainHandler.java
@@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.trade.service.order.handler; @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.trade.service.order.handler;
3 import cn.hutool.core.util.ObjectUtil; 3 import cn.hutool.core.util.ObjectUtil;
4 import cn.iocoder.yudao.module.promotion.api.bargain.BargainActivityApi; 4 import cn.iocoder.yudao.module.promotion.api.bargain.BargainActivityApi;
5 import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; 5 import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum;
6 -import cn.iocoder.yudao.module.trade.service.order.bo.TradeAfterOrderCreateReqBO;  
7 import cn.iocoder.yudao.module.trade.service.order.bo.TradeBeforeOrderCreateReqBO; 6 import cn.iocoder.yudao.module.trade.service.order.bo.TradeBeforeOrderCreateReqBO;
8 import org.springframework.stereotype.Component; 7 import org.springframework.stereotype.Component;
9 8
@@ -15,7 +14,7 @@ import javax.annotation.Resource; @@ -15,7 +14,7 @@ import javax.annotation.Resource;
15 * @author HUIHUI 14 * @author HUIHUI
16 */ 15 */
17 @Component 16 @Component
18 -public class TradeBargainHandler implements TradeOrderHandler { 17 +public class TradeBargainHandler extends TradeOrderDefaultHandler {
19 18
20 @Resource 19 @Resource
21 private BargainActivityApi bargainActivityApi; 20 private BargainActivityApi bargainActivityApi;
@@ -30,18 +29,11 @@ public class TradeBargainHandler implements TradeOrderHandler { @@ -30,18 +29,11 @@ public class TradeBargainHandler implements TradeOrderHandler {
30 if (ObjectUtil.notEqual(TradeOrderTypeEnum.BARGAIN.getType(), reqBO.getOrderType())) { 29 if (ObjectUtil.notEqual(TradeOrderTypeEnum.BARGAIN.getType(), reqBO.getOrderType())) {
31 return; 30 return;
32 } 31 }
33 - // 扣减砍价活动的库存  
34 - bargainActivityApi.updateBargainActivityStock(reqBO.getBargainActivityId(), reqBO.getCount());  
35 - }  
36 -  
37 - @Override  
38 - public void afterOrderCreate(TradeAfterOrderCreateReqBO reqBO) {  
39 -  
40 - }  
41 -  
42 - @Override  
43 - public void rollback() {  
44 32
  33 + // 获取商品信息
  34 + TradeBeforeOrderCreateReqBO.Item item = reqBO.getItems().get(0);
  35 + // 扣减砍价活动的库存
  36 + bargainActivityApi.updateBargainActivityStock(reqBO.getBargainActivityId(), item.getCount());
45 } 37 }
46 38
47 } 39 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeCombinationHandler.java
1 package cn.iocoder.yudao.module.trade.service.order.handler; 1 package cn.iocoder.yudao.module.trade.service.order.handler;
2 2
3 import cn.hutool.core.util.ObjectUtil; 3 import cn.hutool.core.util.ObjectUtil;
4 -import cn.iocoder.yudao.module.promotion.api.combination.CombinationActivityApi;  
5 import cn.iocoder.yudao.module.promotion.api.combination.CombinationRecordApi; 4 import cn.iocoder.yudao.module.promotion.api.combination.CombinationRecordApi;
6 import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert; 5 import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert;
7 import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; 6 import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum;
8 import cn.iocoder.yudao.module.trade.service.order.bo.TradeAfterOrderCreateReqBO; 7 import cn.iocoder.yudao.module.trade.service.order.bo.TradeAfterOrderCreateReqBO;
  8 +import cn.iocoder.yudao.module.trade.service.order.bo.TradeAfterPayOrderReqBO;
9 import cn.iocoder.yudao.module.trade.service.order.bo.TradeBeforeOrderCreateReqBO; 9 import cn.iocoder.yudao.module.trade.service.order.bo.TradeBeforeOrderCreateReqBO;
10 import org.springframework.stereotype.Component; 10 import org.springframework.stereotype.Component;
11 11
@@ -17,28 +17,27 @@ import javax.annotation.Resource; @@ -17,28 +17,27 @@ import javax.annotation.Resource;
17 * @author HUIHUI 17 * @author HUIHUI
18 */ 18 */
19 @Component 19 @Component
20 -public class TradeCombinationHandler implements TradeOrderHandler { 20 +public class TradeCombinationHandler extends TradeOrderDefaultHandler {
21 21
22 @Resource 22 @Resource
23 - private CombinationActivityApi combinationActivityApi;  
24 - @Resource  
25 private CombinationRecordApi combinationRecordApi; 23 private CombinationRecordApi combinationRecordApi;
26 24
27 @Override 25 @Override
28 public void beforeOrderCreate(TradeBeforeOrderCreateReqBO reqBO) { 26 public void beforeOrderCreate(TradeBeforeOrderCreateReqBO reqBO) {
29 - // 如果是拼团订单; 27 + // 如果不是拼团订单则结束
30 if (ObjectUtil.notEqual(TradeOrderTypeEnum.COMBINATION.getType(), reqBO.getOrderType())) { 28 if (ObjectUtil.notEqual(TradeOrderTypeEnum.COMBINATION.getType(), reqBO.getOrderType())) {
31 return; 29 return;
32 } 30 }
33 31
  32 + // 获取商品信息
  33 + TradeBeforeOrderCreateReqBO.Item item = reqBO.getItems().get(0);
34 // 校验是否满足拼团活动相关限制 34 // 校验是否满足拼团活动相关限制
35 - combinationActivityApi.validateCombination(reqBO.getCombinationActivityId(), reqBO.getUserId(), reqBO.getSkuId(), reqBO.getCount()); 35 + combinationRecordApi.validateCombinationRecord(reqBO.getCombinationActivityId(), reqBO.getUserId(), item.getSkuId(), item.getCount());
36 } 36 }
37 37
38 @Override 38 @Override
39 public void afterOrderCreate(TradeAfterOrderCreateReqBO reqBO) { 39 public void afterOrderCreate(TradeAfterOrderCreateReqBO reqBO) {
40 - // TODO @puhui999:需要判断下;  
41 - if (true) { 40 + if (reqBO.getCombinationActivityId() == null) {
42 return; 41 return;
43 } 42 }
44 43
@@ -47,8 +46,14 @@ public class TradeCombinationHandler implements TradeOrderHandler { @@ -47,8 +46,14 @@ public class TradeCombinationHandler implements TradeOrderHandler {
47 } 46 }
48 47
49 @Override 48 @Override
50 - public void rollback() { 49 + public void afterPayOrder(TradeAfterPayOrderReqBO reqBO) {
  50 + // 如果不是拼团订单则结束
  51 + if (ObjectUtil.notEqual(TradeOrderTypeEnum.COMBINATION.getType(), reqBO.getOrderType())) {
  52 + return;
  53 + }
51 54
  55 + // 更新拼团状态 TODO puhui999:订单支付失败或订单支付过期删除这条拼团记录
  56 + combinationRecordApi.updateRecordStatusToInProgress(reqBO.getUserId(), reqBO.getOrderId(), reqBO.getPayTime());
52 } 57 }
53 58
54 } 59 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeOrderDefaultHandler.java 0 → 100644
  1 +package cn.iocoder.yudao.module.trade.service.order.handler;
  2 +
  3 +import cn.iocoder.yudao.module.trade.service.order.bo.TradeAfterOrderCreateReqBO;
  4 +import cn.iocoder.yudao.module.trade.service.order.bo.TradeAfterPayOrderReqBO;
  5 +import cn.iocoder.yudao.module.trade.service.order.bo.TradeBeforeOrderCreateReqBO;
  6 +
  7 +/**
  8 + * 订单活动特殊逻辑处理器 handler 默认抽象实现类
  9 + *
  10 + * @author HUIHUI
  11 + */
  12 +public abstract class TradeOrderDefaultHandler implements TradeOrderHandler {
  13 +
  14 + @Override
  15 + public void beforeOrderCreate(TradeBeforeOrderCreateReqBO reqBO) {
  16 +
  17 + }
  18 +
  19 + @Override
  20 + public void afterOrderCreate(TradeAfterOrderCreateReqBO reqBO) {
  21 +
  22 + }
  23 +
  24 + @Override
  25 + public void afterPayOrder(TradeAfterPayOrderReqBO reqBO) {
  26 +
  27 + }
  28 +
  29 + @Override
  30 + public void cancelOrder() {
  31 +
  32 + }
  33 +
  34 +}
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeOrderHandler.java
1 package cn.iocoder.yudao.module.trade.service.order.handler; 1 package cn.iocoder.yudao.module.trade.service.order.handler;
2 2
3 import cn.iocoder.yudao.module.trade.service.order.bo.TradeAfterOrderCreateReqBO; 3 import cn.iocoder.yudao.module.trade.service.order.bo.TradeAfterOrderCreateReqBO;
  4 +import cn.iocoder.yudao.module.trade.service.order.bo.TradeAfterPayOrderReqBO;
4 import cn.iocoder.yudao.module.trade.service.order.bo.TradeBeforeOrderCreateReqBO; 5 import cn.iocoder.yudao.module.trade.service.order.bo.TradeBeforeOrderCreateReqBO;
5 6
6 /** 7 /**
7 * 订单活动特殊逻辑处理器 handler 接口 8 * 订单活动特殊逻辑处理器 handler 接口
  9 + * 提供订单生命周期钩子接口;订单创建前、订单创建后、订单支付后、订单取消
8 * 10 *
9 * @author HUIHUI 11 * @author HUIHUI
10 */ 12 */
@@ -24,12 +26,16 @@ public interface TradeOrderHandler { @@ -24,12 +26,16 @@ public interface TradeOrderHandler {
24 */ 26 */
25 void afterOrderCreate(TradeAfterOrderCreateReqBO reqBO); 27 void afterOrderCreate(TradeAfterOrderCreateReqBO reqBO);
26 28
27 - // TODO @puhui999:这个搞成订单取消  
28 /** 29 /**
29 - * 回滚 30 + * 支付订单后
  31 + *
  32 + * @param reqBO 请求
30 */ 33 */
31 - void rollback(); 34 + void afterPayOrder(TradeAfterPayOrderReqBO reqBO);
32 35
33 - // TODO @puhui999:再搞个订单项取消哈 36 + /**
  37 + * 订单取消
  38 + */
  39 + void cancelOrder();
34 40
35 } 41 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeSeckillHandler.java
@@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.trade.service.order.handler; @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.trade.service.order.handler;
3 import cn.hutool.core.util.ObjectUtil; 3 import cn.hutool.core.util.ObjectUtil;
4 import cn.iocoder.yudao.module.promotion.api.seckill.SeckillActivityApi; 4 import cn.iocoder.yudao.module.promotion.api.seckill.SeckillActivityApi;
5 import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; 5 import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum;
6 -import cn.iocoder.yudao.module.trade.service.order.bo.TradeAfterOrderCreateReqBO;  
7 import cn.iocoder.yudao.module.trade.service.order.bo.TradeBeforeOrderCreateReqBO; 6 import cn.iocoder.yudao.module.trade.service.order.bo.TradeBeforeOrderCreateReqBO;
8 import org.springframework.stereotype.Component; 7 import org.springframework.stereotype.Component;
9 8
@@ -15,7 +14,7 @@ import javax.annotation.Resource; @@ -15,7 +14,7 @@ import javax.annotation.Resource;
15 * @author HUIHUI 14 * @author HUIHUI
16 */ 15 */
17 @Component 16 @Component
18 -public class TradeSeckillHandler implements TradeOrderHandler { 17 +public class TradeSeckillHandler extends TradeOrderDefaultHandler {
19 18
20 @Resource 19 @Resource
21 private SeckillActivityApi seckillActivityApi; 20 private SeckillActivityApi seckillActivityApi;
@@ -30,18 +29,11 @@ public class TradeSeckillHandler implements TradeOrderHandler { @@ -30,18 +29,11 @@ public class TradeSeckillHandler implements TradeOrderHandler {
30 if (ObjectUtil.notEqual(TradeOrderTypeEnum.SECKILL.getType(), reqBO.getOrderType())) { 29 if (ObjectUtil.notEqual(TradeOrderTypeEnum.SECKILL.getType(), reqBO.getOrderType())) {
31 return; 30 return;
32 } 31 }
33 - // 扣减秒杀活动的库存  
34 - seckillActivityApi.updateSeckillStock(reqBO.getSeckillActivityId(), reqBO.getSkuId(), reqBO.getCount());  
35 - }  
36 -  
37 - @Override  
38 - public void afterOrderCreate(TradeAfterOrderCreateReqBO reqBO) {  
39 -  
40 - }  
41 -  
42 - @Override  
43 - public void rollback() {  
44 32
  33 + // 获取商品信息
  34 + TradeBeforeOrderCreateReqBO.Item item = reqBO.getItems().get(0);
  35 + // 扣减秒杀活动的库存
  36 + seckillActivityApi.updateSeckillStock(reqBO.getSeckillActivityId(), item.getSkuId(), item.getCount());
45 } 37 }
46 38
47 } 39 }
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/bo/TradePriceCalculateRespBO.java
@@ -99,8 +99,18 @@ public class TradePriceCalculateRespBO { @@ -99,8 +99,18 @@ public class TradePriceCalculateRespBO {
99 */ 99 */
100 private Integer vipPrice; 100 private Integer vipPrice;
101 /** 101 /**
  102 + * 秒杀、拼团、砍价活动商品的总金额,单位:分
  103 + *
  104 + * 基于 {@link OrderItem#getActivityPrice()} ()} * {@link OrderItem#getCount()} 求和
  105 + */
  106 + private Integer activityPrice;
  107 + /**
102 * 最终购买金额(总),单位:分 108 * 最终购买金额(总),单位:分
103 * 109 *
  110 + * ==========活动情况===========
  111 + * = {@link #activityPrice}
  112 + * + {@link #deliveryPrice}
  113 + * ==========正常情况===========
104 * = {@link #totalPrice} 114 * = {@link #totalPrice}
105 * - {@link #couponPrice} 115 * - {@link #couponPrice}
106 * - {@link #pointPrice} 116 * - {@link #pointPrice}
@@ -177,8 +187,15 @@ public class TradePriceCalculateRespBO { @@ -177,8 +187,15 @@ public class TradePriceCalculateRespBO {
177 */ 187 */
178 private Integer vipPrice; 188 private Integer vipPrice;
179 /** 189 /**
  190 + * 秒杀、拼团、砍价活动商品的金额,单位:分
  191 + */
  192 + private Integer activityPrice;
  193 + /**
180 * 应付金额(总),单位:分 194 * 应付金额(总),单位:分
181 - * 195 + * ==========活动情况===========
  196 + * = {@link #activityPrice} * {@link #count}
  197 + * + {@link #deliveryPrice}
  198 + * ==========正常情况===========
182 * = {@link #price} * {@link #count} 199 * = {@link #price} * {@link #count}
183 * - {@link #couponPrice} 200 * - {@link #couponPrice}
184 * - {@link #pointPrice} 201 * - {@link #pointPrice}
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradePriceCalculatorHelper.java
@@ -105,6 +105,9 @@ public class TradePriceCalculatorHelper { @@ -105,6 +105,9 @@ public class TradePriceCalculatorHelper {
105 if (!item.getSelected()) { 105 if (!item.getSelected()) {
106 return; 106 return;
107 } 107 }
  108 + // TODO puhui: 需要在这里计算活动的价格
  109 + // ========== 一、活动情况 ==========
  110 + // ========== 二、正常情况 ==========
108 price.setTotalPrice(price.getTotalPrice() + item.getPrice() * item.getCount()); 111 price.setTotalPrice(price.getTotalPrice() + item.getPrice() * item.getCount());
109 price.setDiscountPrice(price.getDiscountPrice() + item.getDiscountPrice()); 112 price.setDiscountPrice(price.getDiscountPrice() + item.getDiscountPrice());
110 price.setDeliveryPrice(price.getDeliveryPrice() + item.getDeliveryPrice()); 113 price.setDeliveryPrice(price.getDeliveryPrice() + item.getDeliveryPrice());
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeSeckillActivityPriceCalculator.java 0 → 100644
  1 +package cn.iocoder.yudao.module.trade.service.price.calculator;
  2 +
  3 +import cn.iocoder.yudao.module.promotion.api.seckill.SeckillActivityApi;
  4 +import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillActivityProductRespDTO;
  5 +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO;
  6 +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO;
  7 +import org.springframework.core.annotation.Order;
  8 +import org.springframework.stereotype.Component;
  9 +
  10 +import javax.annotation.Resource;
  11 +import java.util.List;
  12 +import java.util.Map;
  13 +
  14 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
  15 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
  16 +
  17 +/**
  18 + * 秒杀活动的 {@link TradePriceCalculator} 实现类
  19 + *
  20 + * @author HUIHUI
  21 + */
  22 +@Component
  23 +@Order(TradePriceCalculator.ORDER_DISCOUNT_ACTIVITY)
  24 +public class TradeSeckillActivityPriceCalculator implements TradePriceCalculator {
  25 +
  26 + @Resource
  27 + private SeckillActivityApi activityApi;
  28 +
  29 + @Override
  30 + public void calculate(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result) {
  31 + // 1、判断订单类型和是否具有秒杀活动编号
  32 + if (param.getSeckillActivityId() == null) {
  33 + return;
  34 + }
  35 + // 2、获取秒杀活动商品信息
  36 + List<SeckillActivityProductRespDTO> productList = activityApi.getSeckillActivityProductList(param.getSeckillActivityId(), convertSet(param.getItems(),
  37 + TradePriceCalculateReqBO.Item::getSkuId));
  38 + Map<Long, SeckillActivityProductRespDTO> productMap = convertMap(productList, SeckillActivityProductRespDTO::getSkuId);
  39 + result.getItems().forEach(item -> {
  40 + SeckillActivityProductRespDTO product = productMap.get(item.getSkuId());
  41 + item.setActivityPrice(product.getSeckillPrice()); // 设置活动金额
  42 + });
  43 + }
  44 +
  45 +}