Browse Source

订单:完善拼团活动部分 TODO

puhui999 1 year ago
parent
commit
0b35d4a7e3
16 changed files with 179 additions and 102 deletions
  1. 40 0
      yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java
  2. 0 3
      yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImplTest.java
  3. 0 10
      yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationActivityApi.java
  4. 10 0
      yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApi.java
  5. 4 3
      yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java
  6. 0 11
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationActivityApiImpl.java
  7. 5 0
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApiImpl.java
  8. 9 6
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckillactivity/SeckillActivityConvert.java
  9. 4 0
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/CombinationRecordMapper.java
  10. 0 11
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityService.java
  11. 2 41
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImpl.java
  12. 11 0
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordService.java
  13. 45 6
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordServiceImpl.java
  14. 5 8
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java
  15. 43 0
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/TradeAfterPayOrderReqBO.java
  16. 1 3
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeSeckillActivityPriceCalculator.java

+ 40 - 0
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java

@@ -93,4 +93,44 @@ public class LocalDateTimeUtils {
                 LocalDateTime.of(nowDate, startTime2), LocalDateTime.of(nowDate, endTime2));
     }
 
+    /**
+     * 构建日期时间 TODO 后面有需要的话再继续扩展
+     *
+     * @author HUIHUI
+     */
+    public static class BuilderDateTime {
+
+        /**
+         * 日期;2023-10-01
+         */
+        private String localDate;
+        /**
+         * 时间;10:01:00
+         */
+        private String localTime;
+
+        public BuilderDateTime() {
+        }
+
+        public BuilderDateTime withDate(String date) {
+            this.localDate = date;
+            return this;
+        }
+
+        public BuilderDateTime withDate(LocalDateTime date) {
+            this.localDate = LocalDateTimeUtil.format(date, "yyyy-MM-dd");
+            return this;
+        }
+
+        public BuilderDateTime withTime(String time) {
+            this.localTime = time;
+            return this;
+        }
+
+        public LocalDateTime build() {
+            return LocalDateTimeUtil.parse(this.localDate + " " + this.localTime, "yyyy-MM-dd HH:mm:ss");
+        }
+
+    }
+
 }

+ 0 - 3
yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImplTest.java

@@ -16,7 +16,6 @@ import cn.iocoder.yudao.module.product.dal.mysql.comment.ProductCommentMapper;
 import cn.iocoder.yudao.module.product.enums.comment.ProductCommentScoresEnum;
 import cn.iocoder.yudao.module.product.service.sku.ProductSkuService;
 import cn.iocoder.yudao.module.product.service.spu.ProductSpuService;
-import cn.iocoder.yudao.module.trade.api.order.TradeOrderApi;
 import org.junit.jupiter.api.Test;
 import org.springframework.boot.test.mock.mockito.MockBean;
 import org.springframework.context.annotation.Import;
@@ -48,8 +47,6 @@ public class ProductCommentServiceImplTest extends BaseDbUnitTest {
     @Lazy
     private ProductCommentServiceImpl productCommentService;
 
-    @MockBean
-    private TradeOrderApi tradeOrderApi;
     @MockBean
     private ProductSpuService productSpuService;
     @MockBean

+ 0 - 10
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;
  */
 public interface CombinationActivityApi {
 
-    /**
-     * 校验是否满足拼团条件
-     *
-     * @param activityId 活动编号
-     * @param userId 用户编号
-     * @param skuId sku 编号
-     * @param count 数量
-     */
-    void validateCombination(Long activityId, Long userId, Long skuId, Integer count);
-
 }

+ 10 - 0
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApi.java

@@ -14,6 +14,16 @@ import java.time.LocalDateTime;
  */
 public interface CombinationRecordApi {
 
+    /**
+     * 校验是否满足拼团条件
+     *
+     * @param activityId 活动编号
+     * @param userId     用户编号
+     * @param skuId      sku 编号
+     * @param count      数量
+     */
+    void validateCombinationRecord(Long activityId, Long userId, Long skuId, Integer count);
+
     /**
      * 创建开团记录
      *

+ 4 - 3
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java

@@ -75,9 +75,10 @@ public interface ErrorCodeConstants {
     ErrorCode COMBINATION_RECORD_HEAD_NOT_EXISTS = new ErrorCode(1013011002, "拼团失败,父拼团不存在");
     ErrorCode COMBINATION_RECORD_USER_FULL = new ErrorCode(1013011003, "拼团失败,拼团人数已满");
     ErrorCode COMBINATION_RECORD_FAILED_HAVE_JOINED = new ErrorCode(1013011004, "拼团失败,已参与其它拼团");
-    ErrorCode COMBINATION_RECORD_FAILED_TIME_END = new ErrorCode(1013011005, "拼团失败,活动已经结束");
-    ErrorCode COMBINATION_RECORD_FAILED_SINGLE_LIMIT_COUNT_EXCEED = new ErrorCode(1013011006, "拼团失败,原因:单次限购超出");
-    ErrorCode COMBINATION_RECORD_FAILED_TOTAL_LIMIT_COUNT_EXCEED = new ErrorCode(1013011007, "拼团失败,原因:超出总购买次数");
+    ErrorCode COMBINATION_RECORD_FAILED_TIME_NOT_START = new ErrorCode(1013011005, "拼团失败,活动未开始");
+    ErrorCode COMBINATION_RECORD_FAILED_TIME_END = new ErrorCode(1013011006, "拼团失败,活动已经结束");
+    ErrorCode COMBINATION_RECORD_FAILED_SINGLE_LIMIT_COUNT_EXCEED = new ErrorCode(1013011007, "拼团失败,原因:单次限购超出");
+    ErrorCode COMBINATION_RECORD_FAILED_TOTAL_LIMIT_COUNT_EXCEED = new ErrorCode(1013011008, "拼团失败,原因:超出总购买次数");
 
     // ========== 砍价活动 1013012000 ==========
     ErrorCode BARGAIN_ACTIVITY_NOT_EXISTS = new ErrorCode(1013012000, "砍价活动不存在");

+ 0 - 11
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationActivityApiImpl.java

@@ -1,10 +1,7 @@
 package cn.iocoder.yudao.module.promotion.api.combination;
 
-import cn.iocoder.yudao.module.promotion.service.combination.CombinationActivityService;
 import org.springframework.stereotype.Service;
 
-import javax.annotation.Resource;
-
 /**
  * 拼团活动 Api 接口实现类
  *
@@ -13,12 +10,4 @@ import javax.annotation.Resource;
 @Service
 public class CombinationActivityApiImpl implements CombinationActivityApi {
 
-    @Resource
-    private CombinationActivityService activityService;
-
-    @Override
-    public void validateCombination(Long activityId, Long userId, Long skuId, Integer count) {
-        activityService.validateCombination(activityId, userId, skuId, count);
-    }
-
 }

+ 5 - 0
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApiImpl.java

@@ -19,6 +19,11 @@ public class CombinationRecordApiImpl implements CombinationRecordApi {
     @Resource
     private CombinationRecordService recordService;
 
+    @Override
+    public void validateCombinationRecord(Long activityId, Long userId, Long skuId, Integer count) {
+        recordService.validateCombinationRecord(activityId, userId, skuId, count);
+    }
+
     @Override
     public void createCombinationRecord(CombinationRecordCreateReqDTO reqDTO) {
         recordService.createCombinationRecord(reqDTO);

+ 9 - 6
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckillactivity/SeckillActivityConvert.java

@@ -1,9 +1,9 @@
 package cn.iocoder.yudao.module.promotion.convert.seckill.seckillactivity;
 
-import cn.hutool.core.date.LocalDateTimeUtil;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
 import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
+import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils;
 import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils;
 import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
 import cn.iocoder.yudao.module.product.enums.DictTypeConstants;
@@ -129,11 +129,14 @@ public interface SeckillActivityConvert {
     default AppSeckillActivityDetailRespVO convert3(SeckillActivityDO seckillActivity, List<SeckillProductDO> products, SeckillConfigDO filteredConfig) {
         return convert2(seckillActivity)
                 .setProducts(convertList1(products))
-                // TODO @puhui999:要不要在里面 default 一个方法,处理这个事件;简洁一点;
-                .setStartTime(LocalDateTimeUtil.parse(LocalDateTimeUtil.format(seckillActivity.getStartTime(), "yyyy-MM-dd") + " " + filteredConfig.getStartTime(),
-                        "yyyy-MM-dd HH:mm:ss")) // 活动开始日期和时段结合
-                .setEndTime(LocalDateTimeUtil.parse(LocalDateTimeUtil.format(seckillActivity.getEndTime(), "yyyy-MM-dd") + " " + filteredConfig.getEndTime(),
-                        "yyyy-MM-dd HH:mm:ss")); // 活动结束日期和时段结合
+                .setStartTime(new LocalDateTimeUtils.BuilderDateTime()
+                        .withDate(seckillActivity.getStartTime())
+                        .withTime(filteredConfig.getStartTime())
+                        .build())// 活动开始日期和时段结合
+                .setEndTime(new LocalDateTimeUtils.BuilderDateTime()
+                        .withDate(seckillActivity.getEndTime())
+                        .withTime(filteredConfig.getEndTime())
+                        .build()); // 活动结束日期和时段结合
     }
 
     List<SeckillActivityProductRespDTO> convertList4(List<SeckillProductDO> seckillActivityProductList);

+ 4 - 0
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<CombinationRecordDO
                 CombinationRecordDO::getOrderId, orderId);
     }
 
+    default List<CombinationRecordDO> selectListByUserId(Long userId) {
+        return selectList(CombinationRecordDO::getUserId, userId);
+    }
+
     default List<CombinationRecordDO> selectListByUserIdAndStatus(Long userId, Integer status) {
         return selectList(new LambdaQueryWrapperX<CombinationRecordDO>()
                 .eq(CombinationRecordDO::getUserId, userId)

+ 0 - 11
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityService.java

@@ -84,17 +84,6 @@ public interface CombinationActivityService {
      */
     List<CombinationProductDO> getCombinationProductsByActivityIds(Collection<Long> activityIds);
 
-    /**
-     * 校验是否满足拼团条件
-     * 如果不满足,会抛出异常
-     *
-     * @param activityId 活动编号
-     * @param userId     用户编号
-     * @param skuId      sku 编号
-     * @param count      数量
-     */
-    void validateCombination(Long activityId, Long userId, Long skuId, Integer count);
-
     /**
      * 获取正在进行的活动分页数据
      *

+ 2 - 41
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
 import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert;
 import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO;
 import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationProductDO;
-import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO;
 import cn.iocoder.yudao.module.promotion.dal.mysql.combination.CombinationActivityMapper;
 import cn.iocoder.yudao.module.promotion.dal.mysql.combination.CombinationProductMapper;
-import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum;
-import cn.iocoder.yudao.module.trade.api.order.TradeOrderApi;
-import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;
@@ -33,7 +29,8 @@ import java.util.List;
 import java.util.Map;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
-import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList;
 import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS;
 import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS;
 import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
@@ -53,16 +50,10 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic
     @Resource
     private CombinationProductMapper combinationProductMapper;
 
-    @Resource
-    @Lazy // TODO @puhui999:我感觉 validateCombination 可以挪到 CombinationRecordServiceImpl 中,因为它更偏向能不能创建拼团记录;
-    private CombinationRecordService combinationRecordService;
-
     @Resource
     private ProductSpuApi productSpuApi;
     @Resource
     private ProductSkuApi productSkuApi;
-    @Resource
-    private TradeOrderApi tradeOrderApi;
 
     @Override
     @Transactional(rollbackFor = Exception.class)
@@ -215,36 +206,6 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic
         return combinationProductMapper.selectListByActivityIds(activityIds);
     }
 
-    @Override
-    public void validateCombination(Long activityId, Long userId, Long skuId, Integer count) {
-        // 1.1 校验拼团活动是否存在
-        CombinationActivityDO activity = validateCombinationActivityExists(activityId);
-        // 1.2 校验活动是否开启
-        if (ObjectUtil.equal(activity.getStatus(), CommonStatusEnum.DISABLE.getStatus())) {
-            throw exception(COMBINATION_ACTIVITY_STATUS_DISABLE);
-        }
-        // 1.3 校验是否超出单次限购数量
-        if (count > activity.getSingleLimitCount()) {
-            throw exception(COMBINATION_RECORD_FAILED_SINGLE_LIMIT_COUNT_EXCEED);
-        }
-
-        // 2. 校验是否超出总限购数量
-        List<CombinationRecordDO> recordList = combinationRecordService.getRecordListByUserIdAndActivityId(userId, activityId);
-        if (CollUtil.isEmpty(recordList)) {
-            return;
-        }
-        // 过滤出拼团成功的
-        // TODO @puhui999:count 要不存一个在 record 里?
-        List<Long> skuIds = convertList(recordList, CombinationRecordDO::getSkuId,
-                item -> ObjectUtil.equals(item.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus()));
-        Integer countSum = tradeOrderApi.getOrderItemCountSumByOrderIdAndSkuId(convertList(recordList,
-                CombinationRecordDO::getOrderId,
-                item -> ObjectUtil.equals(item.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus())), skuIds);
-        if (activity.getTotalLimitCount() < countSum) {
-            throw exception(COMBINATION_RECORD_FAILED_TOTAL_LIMIT_COUNT_EXCEED);
-        }
-    }
-
     @Override
     public List<CombinationActivityDO> getCombinationActivityListByCount(Integer count) {
         return combinationActivityMapper.selectListByStatus(CommonStatusEnum.ENABLE.getStatus(), count);

+ 11 - 0
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordService.java

@@ -22,6 +22,17 @@ public interface CombinationRecordService {
      */
     void updateCombinationRecordStatusByUserIdAndOrderId(Integer status, Long userId, Long orderId);
 
+    /**
+     * 校验是否满足拼团条件
+     * 如果不满足,会抛出异常
+     *
+     * @param activityId 活动编号
+     * @param userId     用户编号
+     * @param skuId      sku 编号
+     * @param count      数量
+     */
+    void validateCombinationRecord(Long activityId, Long userId, Long skuId, Integer count);
+
     /**
      * 创建拼团记录
      *

+ 45 - 6
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;
 
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.ObjectUtil;
+import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
 import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
 import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
@@ -14,6 +15,7 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationA
 import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO;
 import cn.iocoder.yudao.module.promotion.dal.mysql.combination.CombinationRecordMapper;
 import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum;
+import cn.iocoder.yudao.module.trade.api.order.TradeOrderApi;
 import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -24,6 +26,7 @@ import java.time.LocalDateTime;
 import java.util.List;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
 import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
 
 // TODO 芋艿:等拼团记录做完,完整 review 下
@@ -51,6 +54,8 @@ public class CombinationRecordServiceImpl implements CombinationRecordService {
     @Resource
     @Lazy
     private ProductSkuApi productSkuApi;
+    @Resource
+    private TradeOrderApi tradeOrderApi;
 
     @Override
     @Transactional(rollbackFor = Exception.class)
@@ -97,6 +102,35 @@ public class CombinationRecordServiceImpl implements CombinationRecordService {
     }
 
     // TODO @puhui999:有一个应该在创建那要做下;就是当前 activityId 已经有未支付的订单,不允许在发起新的;要么支付,要么去掉先;
+    @Override
+    public void validateCombinationRecord(Long activityId, Long userId, Long skuId, Integer count) {
+        // 1.1 校验拼团活动是否存在
+        CombinationActivityDO activity = combinationActivityService.validateCombinationActivityExists(activityId);
+        // 1.2 校验活动是否开启
+        if (ObjectUtil.equal(activity.getStatus(), CommonStatusEnum.DISABLE.getStatus())) {
+            throw exception(COMBINATION_ACTIVITY_STATUS_DISABLE);
+        }
+        // 1.3 校验是否超出单次限购数量
+        if (count > activity.getSingleLimitCount()) {
+            throw exception(COMBINATION_RECORD_FAILED_SINGLE_LIMIT_COUNT_EXCEED);
+        }
+
+        // 2. 校验是否超出总限购数量
+        List<CombinationRecordDO> recordList = getRecordListByUserIdAndActivityId(userId, activityId);
+        if (CollUtil.isEmpty(recordList)) {
+            return;
+        }
+        // 过滤出拼团成功的
+        // TODO @puhui999:count 要不存一个在 record 里?
+        List<Long> skuIds = convertList(recordList, CombinationRecordDO::getSkuId,
+                item -> ObjectUtil.equals(item.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus()));
+        Integer countSum = tradeOrderApi.getOrderItemCountSumByOrderIdAndSkuId(convertList(recordList,
+                CombinationRecordDO::getOrderId,
+                item -> ObjectUtil.equals(item.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus())), skuIds);
+        if (activity.getTotalLimitCount() < countSum) {
+            throw exception(COMBINATION_RECORD_FAILED_TOTAL_LIMIT_COUNT_EXCEED);
+        }
+    }
 
     @Override
     @Transactional(rollbackFor = Exception.class)
@@ -105,21 +139,26 @@ public class CombinationRecordServiceImpl implements CombinationRecordService {
         CombinationActivityDO activity = combinationActivityService.validateCombinationActivityExists(reqDTO.getActivityId());
         // 1.2 需要校验下,他当前是不是已经参加了该拼团;
         // TODO @puhui999:拼团应该可以重复参加;应该去校验总共的上限哈,就是 activity.totalLimitCount
-        CombinationRecordDO recordDO = recordMapper.selectByUserIdAndOrderId(reqDTO.getUserId(), reqDTO.getOrderId());
-        if (recordDO != null) {
-            throw exception(COMBINATION_RECORD_EXISTS);
+        List<CombinationRecordDO> records = recordMapper.selectListByUserId(reqDTO.getUserId());
+        List<Long> orderIds = convertList(records, CombinationRecordDO::getOrderId);
+        // 1.2.1 如果存在订单才去校验
+        if (CollUtil.isNotEmpty(orderIds)) {
+
         }
         // 1.3 校验用户是否参加了其它拼团
         List<CombinationRecordDO> recordDOList = recordMapper.selectListByUserIdAndStatus(reqDTO.getUserId(), CombinationRecordStatusEnum.IN_PROGRESS.getStatus());
         if (CollUtil.isNotEmpty(recordDOList)) {
             throw exception(COMBINATION_RECORD_FAILED_HAVE_JOINED);
         }
-        // TODO @puhui999:有个开始时间未校验
-        // 1.4 校验当前活动是否过期
+        // 1、4 校验活动是否开启
+        if (LocalDateTime.now().isAfter(activity.getStartTime())) {
+            throw exception(COMBINATION_RECORD_FAILED_TIME_NOT_START);
+        }
+        // 1.5 校验当前活动是否过期
         if (LocalDateTime.now().isAfter(activity.getEndTime())) {
             throw exception(COMBINATION_RECORD_FAILED_TIME_END);
         }
-        // 1.5 父拼团是否存在,是否已经满了
+        // 1.6 父拼团是否存在,是否已经满了
         if (reqDTO.getHeadId() != null) {
             // 查询进行中的父拼团
             CombinationRecordDO record = recordMapper.selectOneByHeadId(reqDTO.getHeadId(), CombinationRecordStatusEnum.IN_PROGRESS.getStatus());

+ 5 - 8
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java

@@ -56,6 +56,7 @@ import cn.iocoder.yudao.module.trade.service.cart.CartService;
 import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressService;
 import cn.iocoder.yudao.module.trade.service.message.TradeMessageService;
 import cn.iocoder.yudao.module.trade.service.message.bo.TradeOrderMessageWhenDeliveryOrderReqBO;
+import cn.iocoder.yudao.module.trade.service.order.bo.TradeAfterPayOrderReqBO;
 import cn.iocoder.yudao.module.trade.service.order.bo.TradeBeforeOrderCreateReqBO;
 import cn.iocoder.yudao.module.trade.service.order.handler.TradeOrderHandler;
 import cn.iocoder.yudao.module.trade.service.price.TradePriceService;
@@ -333,13 +334,9 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
         if (updateCount == 0) {
             throw exception(ORDER_UPDATE_PAID_STATUS_NOT_UNPAID);
         }
-        // 校验活动
-        // 1、拼团活动
-        // TODO @puhui999:这块也抽象到 handler 里
-        if (Objects.equals(TradeOrderTypeEnum.COMBINATION.getType(), order.getType())) {
-            // 更新拼团状态 TODO puhui999:订单支付失败或订单支付过期删除这条拼团记录
-            combinationRecordApi.updateRecordStatusToInProgress(order.getUserId(), order.getId(), LocalDateTime.now());
-        }
+        // 订单支付成功后
+        tradeOrderHandlers.forEach(tradeOrderHandler -> tradeOrderHandler.afterPayOrder(new TradeAfterPayOrderReqBO()
+                .setOrderId(order.getId()).setOrderType(order.getType()).setUserId(order.getUserId()).setPayTime(LocalDateTime.now())));
         // TODO 芋艿:发送订单变化的消息
 
         // TODO 芋艿:发送站内信
@@ -742,7 +739,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
         }
 
         // 3. TODO 活动相关库存回滚需要活动 id,活动 id 怎么获取?app 端能否传过来;回复:从订单里拿呀
-        tradeOrderHandlers.forEach(handler -> handler.rollback());
+        tradeOrderHandlers.forEach(handler -> handler.cancelOrder());
 
         // 4. 回滚库存
         List<TradeOrderItemDO> orderItems = tradeOrderItemMapper.selectListByOrderId(id);

+ 43 - 0
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/TradeAfterPayOrderReqBO.java

@@ -0,0 +1,43 @@
+package cn.iocoder.yudao.module.trade.service.order.bo;
+
+import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+/**
+ * 订单支付后 Request BO
+ *
+ * @author HUIHUI
+ */
+@Data
+public class TradeAfterPayOrderReqBO {
+
+    /**
+     * 订单编号
+     */
+    @Schema(description = "订单编号", example = "6")
+    private Long orderId;
+
+    /**
+     * 订单类型
+     *
+     * 枚举 {@link TradeOrderTypeEnum}
+     */
+    @Schema(description = "订单类型", example = "3")
+    private Integer orderType;
+
+    /**
+     * 用户编号
+     */
+    @Schema(description = "用户编号", example = "11")
+    private Long userId;
+
+    /**
+     * 订单支付时间
+     */
+    @Schema(description = "订单支付时间", example = "2023-08-15 10:00:00")
+    private LocalDateTime payTime;
+
+}

+ 1 - 3
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeSeckillActivityPriceCalculator.java

@@ -1,9 +1,7 @@
 package cn.iocoder.yudao.module.trade.service.price.calculator;
 
-import cn.hutool.core.util.ObjectUtil;
 import cn.iocoder.yudao.module.promotion.api.seckill.SeckillActivityApi;
 import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillActivityProductRespDTO;
-import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum;
 import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO;
 import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO;
 import org.springframework.core.annotation.Order;
@@ -31,7 +29,7 @@ public class TradeSeckillActivityPriceCalculator implements TradePriceCalculator
     @Override
     public void calculate(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result) {
         // 1、判断订单类型和是否具有秒杀活动编号
-        if (ObjectUtil.notEqual(param.getType(), TradeOrderTypeEnum.SECKILL.getType()) && param.getSeckillActivityId() == null) {
+        if (param.getSeckillActivityId() == null) {
             return;
         }
         // 2、获取秒杀活动商品信息