diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationApi.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationApi.java
new file mode 100644
index 000000000..ec8d5c714
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationApi.java
@@ -0,0 +1,19 @@
+package cn.iocoder.yudao.module.promotion.api.combination;
+
+import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationActivityUpdateStockReqDTO;
+
+/**
+ * 拼团活动 Api 接口
+ *
+ * @author HUIHUI
+ */
+public interface CombinationApi {
+
+ /**
+ * 更新活动库存
+ *
+ * @param reqDTO 请求
+ */
+ void validateCombination(CombinationActivityUpdateStockReqDTO reqDTO);
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationActivityUpdateStockReqDTO.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationActivityUpdateStockReqDTO.java
new file mode 100644
index 000000000..a1d0ebce7
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationActivityUpdateStockReqDTO.java
@@ -0,0 +1,40 @@
+package cn.iocoder.yudao.module.promotion.api.combination.dto;
+
+import lombok.Data;
+
+import javax.validation.Valid;
+import javax.validation.constraints.NotNull;
+
+/**
+ * 拼团活动更新活动库存 Request DTO
+ *
+ * @author HUIHUI
+ */
+@Data
+public class CombinationActivityUpdateStockReqDTO {
+
+ @NotNull(message = "活动编号不能为空")
+ private Long activityId;
+
+ @NotNull(message = "购买数量不能为空")
+ private Integer count;
+
+ @NotNull(message = "活动商品不能为空")
+ private Item item;
+
+ @Data
+ @Valid
+ public static class Item {
+
+ @NotNull(message = "SPU 编号不能为空")
+ private Long spuId;
+
+ @NotNull(message = "SKU 编号活动商品不能为空")
+ private Long skuId;
+
+ @NotNull(message = "购买数量不能为空")
+ private Integer count;
+
+ }
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationRecordCreateReqDTO.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationRecordCreateReqDTO.java
index 4d4c0dafd..288a83d4c 100644
--- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationRecordCreateReqDTO.java
+++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationRecordCreateReqDTO.java
@@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.promotion.api.combination.dto;
import lombok.Data;
-import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
// TODO @芋艿:这块要在看看
@@ -14,65 +13,25 @@ import javax.validation.constraints.NotNull;
@Data
public class CombinationRecordCreateReqDTO {
- /**
- * 拼团活动编号
- */
@NotNull(message = "拼团活动编号不能为空")
private Long activityId;
- /**
- * spu 编号
- */
+
@NotNull(message = "spu 编号不能为空")
private Long spuId;
- /**
- * sku 编号
- */
+
@NotNull(message = "sku 编号不能为空")
private Long skuId;
- /**
- * 用户编号
- */
- @NotNull(message = "用户编号不能为空")
- private Long userId;
- /**
- * 订单编号
- */
+
@NotNull(message = "订单编号不能为空")
private Long orderId;
- /**
- * 团长编号
- */
+
+ @NotNull(message = "用户编号不能为空")
+ private Long userId;
+
@NotNull(message = "团长编号不能为空")
private Long headId;
- /**
- * 商品名字
- */
- @NotEmpty(message = "商品名字不能为空")
- private String spuName;
- /**
- * 商品图片
- */
- @NotEmpty(message = "商品图片不能为空")
- private String picUrl;
- /**
- * 拼团商品单价
- */
+
@NotNull(message = "拼团商品单价不能为空")
private Integer combinationPrice;
- /**
- * 用户昵称
- */
- @NotEmpty(message = "用户昵称不能为空")
- private String nickname;
- /**
- * 用户头像
- */
- @NotEmpty(message = "用户头像不能为空")
- private String avatar;
- /**
- * 开团状态:正在开团 拼团成功 拼团失败
- */
- @NotNull(message = "开团状态不能为空")
- private Integer status;
}
diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/dto/SeckillActivityUpdateStockReqDTO.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/dto/SeckillActivityUpdateStockReqDTO.java
index 07a25b3d6..f3cf1d2b2 100644
--- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/dto/SeckillActivityUpdateStockReqDTO.java
+++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/dto/SeckillActivityUpdateStockReqDTO.java
@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.promotion.api.seckill.dto;
import lombok.Data;
+import javax.validation.Valid;
import javax.validation.constraints.NotNull;
/**
@@ -22,6 +23,7 @@ public class SeckillActivityUpdateStockReqDTO {
private Item item;
@Data
+ @Valid
public static class Item {
@NotNull(message = "SPU 编号不能为空")
diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java
index baca6c273..4fc58004a 100644
--- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java
+++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java
@@ -65,18 +65,19 @@ public interface ErrorCodeConstants {
// ========== 拼团活动 1013010000 ==========
ErrorCode COMBINATION_ACTIVITY_NOT_EXISTS = new ErrorCode(1013010000, "拼团活动不存在");
ErrorCode COMBINATION_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1013010001, "存在商品参加了其它拼团活动");
- ErrorCode COMBINATION_ACTIVITY_STATUS_DISABLE = new ErrorCode(1013010002, "拼团活动已关闭不能修改");
+ ErrorCode COMBINATION_ACTIVITY_STATUS_DISABLE_NOT_UPDATE = new ErrorCode(1013010002, "拼团活动已关闭不能修改");
ErrorCode COMBINATION_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1013010003, "拼团活动未关闭或未结束,不能删除");
- ErrorCode COMBINATION_RECORD_NOT_EXISTS = new ErrorCode(1013010004, "拼团不存在");
+ ErrorCode COMBINATION_ACTIVITY_STATUS_DISABLE = new ErrorCode(1013010004, "拼团失败,原因:拼团活动已关闭");
// ========== 拼团记录 1013011000 ==========
- ErrorCode COMBINATION_RECORD_EXISTS = new ErrorCode(1013011000, "拼团失败,已参与过该拼团");
- ErrorCode COMBINATION_RECORD_HEAD_NOT_EXISTS = new ErrorCode(1013011001, "拼团失败,父拼团不存在");
- ErrorCode COMBINATION_RECORD_USER_FULL = new ErrorCode(1013011002, "拼团失败,拼团人数已满");
- ErrorCode COMBINATION_RECORD_FAILED_HAVE_JOINED = new ErrorCode(1013011003, "拼团失败,已参与其它拼团");
- ErrorCode COMBINATION_RECORD_FAILED_TIME_END = new ErrorCode(1013011004, "拼团失败,活动已经结束");
- ErrorCode COMBINATION_RECORD_FAILED_SINGLE_LIMIT_COUNT_EXCEED = new ErrorCode(1013011005, "拼团失败,单次限购超出");
- ErrorCode COMBINATION_RECORD_FAILED_TOTAL_LIMIT_COUNT_EXCEED = new ErrorCode(1013011006, "拼团失败,单次限购超出");
+ ErrorCode COMBINATION_RECORD_NOT_EXISTS = new ErrorCode(1013011000, "拼团不存在");
+ ErrorCode COMBINATION_RECORD_EXISTS = new ErrorCode(1013011001, "拼团失败,已参与过该拼团");
+ 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, "拼团失败,原因:超出总购买次数");
// ========== 砍价活动 1013012000 ==========
ErrorCode BARGAIN_ACTIVITY_NOT_EXISTS = new ErrorCode(1013012000, "砍价活动不存在");
diff --git a/yudao-module-mall/yudao-module-promotion-biz/pom.xml b/yudao-module-mall/yudao-module-promotion-biz/pom.xml
index 266cb1511..bad2c8a35 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/pom.xml
+++ b/yudao-module-mall/yudao-module-promotion-biz/pom.xml
@@ -29,6 +29,11 @@
yudao-module-product-api
${revision}
+
+ cn.iocoder.boot
+ yudao-module-trade-api
+ ${revision}
+
cn.iocoder.boot
yudao-module-member-api
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationApiImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationApiImpl.java
new file mode 100644
index 000000000..767b2e680
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationApiImpl.java
@@ -0,0 +1,23 @@
+package cn.iocoder.yudao.module.promotion.api.combination;
+
+import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationActivityUpdateStockReqDTO;
+import cn.iocoder.yudao.module.promotion.service.combination.CombinationActivityService;
+
+import javax.annotation.Resource;
+
+/**
+ * 拼团活动 Api 接口实现类
+ *
+ * @author HUIHUI
+ */
+public class CombinationApiImpl implements CombinationApi {
+
+ @Resource
+ private CombinationActivityService activityService;
+
+ @Override
+ public void validateCombination(CombinationActivityUpdateStockReqDTO reqDTO) {
+ activityService.validateCombination(reqDTO);
+ }
+
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityService.java
index 99b87df6c..c3ee01fcc 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityService.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityService.java
@@ -1,6 +1,7 @@
package cn.iocoder.yudao.module.promotion.service.combination;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationActivityUpdateStockReqDTO;
import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityCreateReqVO;
import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityPageReqVO;
import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityUpdateReqVO;
@@ -72,4 +73,11 @@ public interface CombinationActivityService {
*/
List getCombinationProductsByActivityIds(Collection activityIds);
+ /**
+ * 更新拼图活动库存
+ *
+ * @param reqDTO 请求
+ */
+ void validateCombination(CombinationActivityUpdateStockReqDTO reqDTO);
+
}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImpl.java
index c6a7c8c49..026c1a0ff 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImpl.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImpl.java
@@ -9,6 +9,7 @@ import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
+import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationActivityUpdateStockReqDTO;
import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityCreateReqVO;
import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityPageReqVO;
import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityUpdateReqVO;
@@ -16,8 +17,11 @@ 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.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
@@ -28,8 +32,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.convertMap;
-import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
+import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
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.*;
@@ -48,11 +52,15 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic
private CombinationActivityMapper combinationActivityMapper;
@Resource
private CombinationProductMapper combinationProductMapper;
+ @Resource
+ private CombinationRecordService combinationRecordService;
@Resource
private ProductSpuApi productSpuApi;
@Resource
private ProductSkuApi productSkuApi;
+ @Resource
+ private TradeOrderApi tradeOrderApi;
@Override
@Transactional(rollbackFor = Exception.class)
@@ -97,7 +105,7 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic
* 校验拼团商品是否都存在
*
* @param spuId 商品 SPU 编号
- * @param products 秒杀商品
+ * @param products 拼团商品
*/
private void validateProductExists(Long spuId, List products) {
// 1. 校验商品 spu 是否存在
@@ -123,7 +131,7 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic
CombinationActivityDO activityDO = validateCombinationActivityExists(updateReqVO.getId());
// 校验状态
if (ObjectUtil.equal(activityDO.getStatus(), CommonStatusEnum.DISABLE.getStatus())) {
- throw exception(COMBINATION_ACTIVITY_STATUS_DISABLE);
+ throw exception(COMBINATION_ACTIVITY_STATUS_DISABLE_NOT_UPDATE);
}
// 校验商品冲突
validateProductConflict(updateReqVO.getSpuId(), updateReqVO.getId());
@@ -205,4 +213,30 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic
return combinationProductMapper.selectListByActivityIds(activityIds);
}
+ @Override
+ public void validateCombination(CombinationActivityUpdateStockReqDTO reqDTO) {
+ // 1、校验拼团活动是否存在
+ CombinationActivityDO activity = validateCombinationActivityExists(reqDTO.getActivityId());
+ // 1.1、校验活动是否开启
+ if (ObjectUtil.equal(activity.getStatus(), CommonStatusEnum.DISABLE.getStatus())) {
+ throw exception(COMBINATION_ACTIVITY_STATUS_DISABLE);
+ }
+ // 1.2、校验是否超出单次限购数量
+ if (activity.getSingleLimitCount() < reqDTO.getCount()) {
+ throw exception(COMBINATION_RECORD_FAILED_SINGLE_LIMIT_COUNT_EXCEED);
+ }
+ // 1.3、校验是否超出总限购数量
+ List recordList = combinationRecordService.getRecordListByUserIdAndActivityId(getLoginUserId(), reqDTO.getActivityId());
+ if (CollUtil.isNotEmpty(recordList)) {
+ // 过滤出拼团成功的
+ List 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);
+ }
+ }
+ }
+
}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordServiceImpl.java
index bc9c1df4c..63df4ad0d 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordServiceImpl.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordServiceImpl.java
@@ -2,12 +2,19 @@ package cn.iocoder.yudao.module.promotion.service.combination;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
+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;
+import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
+import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
+import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO;
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.CombinationRecordDO;
import cn.iocoder.yudao.module.promotion.dal.mysql.combination.CombinationRecordMapper;
import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum;
+import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
@@ -32,10 +39,18 @@ public class CombinationRecordServiceImpl implements CombinationRecordService {
@Resource
private CombinationActivityService combinationActivityService;
-
@Resource
private CombinationRecordMapper recordMapper;
+ @Resource
+ private MemberUserApi memberUserApi;
+ @Resource
+ @Lazy
+ private ProductSpuApi productSpuApi;
+ @Resource
+ @Lazy
+ private ProductSkuApi productSkuApi;
+
@Override
@Transactional(rollbackFor = Exception.class)
public void updateCombinationRecordStatusByUserIdAndOrderId(Integer status, Long userId, Long orderId) {
@@ -102,12 +117,12 @@ public class CombinationRecordServiceImpl implements CombinationRecordService {
// 1.5 父拼团是否存在,是否已经满了
if (reqDTO.getHeadId() != null) {
// 查询进行中的父拼团
- CombinationRecordDO recordDO1 = recordMapper.selectOneByHeadId(reqDTO.getHeadId(), CombinationRecordStatusEnum.IN_PROGRESS.getStatus());
- if (recordDO1 == null) {
+ CombinationRecordDO record = recordMapper.selectOneByHeadId(reqDTO.getHeadId(), CombinationRecordStatusEnum.IN_PROGRESS.getStatus());
+ if (record == null) {
throw exception(COMBINATION_RECORD_HEAD_NOT_EXISTS);
}
// 校验拼团是否满足要求
- if (ObjectUtil.equal(recordDO1.getUserCount(), recordDO1.getUserSize())) {
+ if (ObjectUtil.equal(record.getUserCount(), record.getUserSize())) {
throw exception(COMBINATION_RECORD_USER_FULL);
}
}
@@ -117,6 +132,13 @@ public class CombinationRecordServiceImpl implements CombinationRecordService {
record.setVirtualGroup(false);
record.setExpireTime(record.getStartTime().plusHours(activity.getLimitDuration()));
record.setUserSize(activity.getUserSize());
+ MemberUserRespDTO user = memberUserApi.getUser(reqDTO.getUserId());
+ record.setNickname(user.getNickname());
+ record.setAvatar(user.getAvatar());
+ ProductSpuRespDTO spu = productSpuApi.getSpu(record.getSpuId());
+ record.setSpuName(spu.getName());
+ ProductSkuRespDTO sku = productSkuApi.getSku(record.getSkuId());
+ record.setPicUrl(sku.getPicUrl());
recordMapper.insert(record);
}
diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/api/order/TradeOrderApi.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/api/order/TradeOrderApi.java
index 5f98073d1..8f33fff28 100644
--- a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/api/order/TradeOrderApi.java
+++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/api/order/TradeOrderApi.java
@@ -1,5 +1,7 @@
package cn.iocoder.yudao.module.trade.api.order;
+import java.util.Collection;
+
/**
* 订单 API 接口
*
@@ -16,4 +18,13 @@ public interface TradeOrderApi {
*/
Long validateOrder(Long userId, Long orderItemId);
+ /**
+ * 获取订单项商品购买数量总和
+ *
+ * @param orderIds 订单编号
+ * @param skuIds sku 编号
+ * @return 订单项商品购买数量总和
+ */
+ Integer getOrderItemCountSumByOrderIdAndSkuId(Collection orderIds, Collection skuIds);
+
}
diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/api/order/TradeOrderApiImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/api/order/TradeOrderApiImpl.java
index 7895386cf..3ee315ccb 100644
--- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/api/order/TradeOrderApiImpl.java
+++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/api/order/TradeOrderApiImpl.java
@@ -6,6 +6,7 @@ import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
+import java.util.Collection;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.ORDER_ITEM_NOT_FOUND;
@@ -32,4 +33,9 @@ public class TradeOrderApiImpl implements TradeOrderApi {
return item.getOrderId();
}
+ @Override
+ public Integer getOrderItemCountSumByOrderIdAndSkuId(Collection orderIds, Collection skuIds) {
+ return tradeOrderQueryService.getOrderItemCountSumByOrderIdAndSkuId(orderIds, skuIds);
+ }
+
}
diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java
index feaa1bab0..72fe9ff59 100644
--- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java
+++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java
@@ -14,7 +14,9 @@ import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDT
import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO;
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO;
+import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationActivityUpdateStockReqDTO;
import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO;
+import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillActivityUpdateStockReqDTO;
import cn.iocoder.yudao.module.trade.api.order.dto.TradeOrderRespDTO;
import cn.iocoder.yudao.module.trade.controller.admin.base.member.user.MemberUserRespVO;
import cn.iocoder.yudao.module.trade.controller.admin.base.product.property.ProductPropertyValueDetailRespVO;
@@ -31,6 +33,8 @@ import cn.iocoder.yudao.module.trade.enums.order.TradeOrderItemAfterSaleStatusEn
import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.ExpressTrackRespDTO;
import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties;
import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageAddReqBO;
+import cn.iocoder.yudao.module.trade.service.order.bo.TradeAfterOrderCreateReqBO;
+import cn.iocoder.yudao.module.trade.service.order.bo.TradeBeforeOrderCreateReqBO;
import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO;
import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO;
import org.mapstruct.Mapper;
@@ -253,21 +257,15 @@ public interface TradeOrderConvert {
AppTradeOrderSettlementRespVO convert0(TradePriceCalculateRespBO calculate, AddressRespDTO address);
@Mappings({
- @Mapping(target = "activityId", source = "createReqVO.combinationActivityId"),
- @Mapping(target = "spuId", source = "orderItem.spuId"),
- @Mapping(target = "skuId", source = "orderItem.skuId"),
- @Mapping(target = "userId", source = "order.userId"),
- @Mapping(target = "orderId", source = "order.id"),
- @Mapping(target = "headId", source = "createReqVO.combinationHeadId"),
- @Mapping(target = "spuName", source = "orderItem.spuName"),
- @Mapping(target = "picUrl", source = "orderItem.picUrl"),
- @Mapping(target = "combinationPrice", source = "orderItem.payPrice"),
- @Mapping(target = "nickname", source = "user.nickname"),
- @Mapping(target = "avatar", source = "user.avatar"),
- @Mapping(target = "status", ignore = true)
+ @Mapping(target = "activityId", source = "afterOrderCreateReqBO.combinationActivityId"),
+ @Mapping(target = "spuId", source = "afterOrderCreateReqBO.spuId"),
+ @Mapping(target = "skuId", source = "afterOrderCreateReqBO.skuId"),
+ @Mapping(target = "orderId", source = "afterOrderCreateReqBO.orderId"),
+ @Mapping(target = "userId", source = "afterOrderCreateReqBO.userId"),
+ @Mapping(target = "headId", source = "afterOrderCreateReqBO.combinationHeadId"),
+ @Mapping(target = "combinationPrice", source = "afterOrderCreateReqBO.payPrice"),
})
- CombinationRecordCreateReqDTO convert(TradeOrderDO order, TradeOrderItemDO orderItem,
- AppTradeOrderCreateReqVO createReqVO, MemberUserRespDTO user);
+ CombinationRecordCreateReqDTO convert(TradeAfterOrderCreateReqBO afterOrderCreateReqBO);
List convertList02(List list);
@@ -283,4 +281,24 @@ public interface TradeOrderConvert {
.setFirstFixedPrice(sku.getFirstBrokerageRecord())
.setSecondFixedPrice(sku.getSecondBrokerageRecord());
}
+
+ @Mapping(target = "activityId", source = "reqBO.seckillActivityId")
+ SeckillActivityUpdateStockReqDTO convert(TradeBeforeOrderCreateReqBO reqBO);
+
+ @Mapping(target = "activityId", source = "reqBO.combinationActivityId")
+ CombinationActivityUpdateStockReqDTO convert1(TradeBeforeOrderCreateReqBO reqBO);
+
+ TradeBeforeOrderCreateReqBO convert(AppTradeOrderCreateReqVO createReqVO);
+
+ @Mappings({
+ @Mapping(target = "combinationActivityId", source = "createReqVO.combinationActivityId"),
+ @Mapping(target = "combinationHeadId", source = "createReqVO.combinationHeadId"),
+ @Mapping(target = "spuId", source = "orderItem.spuId"),
+ @Mapping(target = "skuId", source = "orderItem.skuId"),
+ @Mapping(target = "orderId", source = "tradeOrderDO.id"),
+ @Mapping(target = "userId", source = "userId"),
+ @Mapping(target = "payPrice", source = "tradeOrderDO.payPrice"),
+ })
+ TradeAfterOrderCreateReqBO convert(Long userId, AppTradeOrderCreateReqVO createReqVO, TradeOrderDO tradeOrderDO, TradeOrderItemDO orderItem);
+
}
diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/TradeOrderItemMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/TradeOrderItemMapper.java
index a9538cc91..e7121077b 100644
--- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/TradeOrderItemMapper.java
+++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/TradeOrderItemMapper.java
@@ -29,7 +29,7 @@ public interface TradeOrderItemMapper extends BaseMapperX {
default List selectListByOrderIdAnSkuId(Collection orderIds, Collection skuIds) {
return selectList(new LambdaQueryWrapperX()
.in(TradeOrderItemDO::getOrderId, orderIds)
- .eq(TradeOrderItemDO::getSkuId, skuIds));
+ .in(TradeOrderItemDO::getSkuId, skuIds));
}
default TradeOrderItemDO selectByIdAndUserId(Long orderItemId, Long loginUserId) {
diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryService.java
index 0cd5240bd..c64de4a58 100644
--- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryService.java
+++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryService.java
@@ -119,4 +119,13 @@ public interface TradeOrderQueryService {
*/
List getOrderItemListByOrderId(Collection orderIds);
+ /**
+ * 获取订单项商品购买数量总和
+ *
+ * @param orderIds 订单编号
+ * @param skuIds sku 编号
+ * @return 订单项商品购买数量总和
+ */
+ Integer getOrderItemCountSumByOrderIdAndSkuId(Collection orderIds, Collection skuIds);
+
}
diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryServiceImpl.java
index 657c6f0f8..733ec9780 100644
--- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryServiceImpl.java
+++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryServiceImpl.java
@@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderPageReqVO;
@@ -167,4 +168,10 @@ public class TradeOrderQueryServiceImpl implements TradeOrderQueryService {
return tradeOrderItemMapper.selectListByOrderId(orderIds);
}
+ @Override
+ public Integer getOrderItemCountSumByOrderIdAndSkuId(Collection orderIds, Collection skuIds) {
+ List tradeOrderItems = tradeOrderItemMapper.selectListByOrderIdAnSkuId(orderIds, skuIds);
+ return CollectionUtils.getSumValue(tradeOrderItems, TradeOrderItemDO::getCount, Integer::sum);
+ }
+
}
diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java
index 3ea5a76c1..a90c505e3 100644
--- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java
+++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java
@@ -13,8 +13,6 @@ import cn.iocoder.yudao.module.member.api.address.AddressApi;
import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO;
import cn.iocoder.yudao.module.member.api.level.MemberLevelApi;
import cn.iocoder.yudao.module.member.api.point.MemberPointApi;
-import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
-import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
import cn.iocoder.yudao.module.member.enums.MemberExperienceBizTypeEnum;
import cn.iocoder.yudao.module.member.enums.point.MemberPointBizTypeEnum;
import cn.iocoder.yudao.module.pay.api.order.PayOrderApi;
@@ -24,15 +22,10 @@ import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
import cn.iocoder.yudao.module.product.api.comment.ProductCommentApi;
import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO;
import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
-import cn.iocoder.yudao.module.promotion.api.bargain.BargainActivityApi;
import cn.iocoder.yudao.module.promotion.api.bargain.BargainRecordApi;
import cn.iocoder.yudao.module.promotion.api.combination.CombinationRecordApi;
-import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordRespDTO;
import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi;
import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponUseReqDTO;
-import cn.iocoder.yudao.module.promotion.api.seckill.SeckillActivityApi;
-import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillActivityUpdateStockReqDTO;
-import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum;
import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDeliveryReqVO;
import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderRemarkReqVO;
import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderUpdateAddressReqVO;
@@ -59,6 +52,8 @@ 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.TradeBeforeOrderCreateReqBO;
+import cn.iocoder.yudao.module.trade.service.order.handler.TradeOrderHandler;
import cn.iocoder.yudao.module.trade.service.price.TradePriceService;
import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO;
import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO;
@@ -95,6 +90,8 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
private TradeOrderItemMapper tradeOrderItemMapper;
@Resource
private TradeOrderNoRedisDAO orderNoRedisDAO;
+ @Resource
+ private List orderHandlers;
@Resource
private CartService cartService;
@@ -118,12 +115,6 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
@Resource
private BargainRecordApi bargainRecordApi;
@Resource
- private SeckillActivityApi seckillActivityApi;
- @Resource
- private BargainActivityApi bargainActivityApi;
- @Resource
- private MemberUserApi memberUserApi;
- @Resource
private MemberLevelApi memberLevelApi;
@Resource
private MemberPointApi memberPointApi;
@@ -188,7 +179,13 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
@Override
@Transactional(rollbackFor = Exception.class)
public TradeOrderDO createOrder(Long userId, String userIp, AppTradeOrderCreateReqVO createReqVO) {
- // 1. 价格计算
+ // 1、执行订单创建前置处理器
+ TradeBeforeOrderCreateReqBO beforeOrderCreateReqBO = TradeOrderConvert.INSTANCE.convert(createReqVO);
+ beforeOrderCreateReqBO.setOrderType(validateActivity(createReqVO));
+ beforeOrderCreateReqBO.setCount(CollectionUtils.getSumValue(createReqVO.getItems(), AppTradeOrderSettlementReqVO.Item::getCount, Integer::sum));
+ orderHandlers.forEach(handler -> handler.beforeOrderCreate(beforeOrderCreateReqBO));
+
+ // 2. 价格计算
TradePriceCalculateRespBO calculateRespBO = calculatePrice(userId, createReqVO);
// 2.1 插入 TradeOrderDO 订单
@@ -198,37 +195,11 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
// 3. 订单创建完后的逻辑
afterCreateTradeOrder(userId, createReqVO, order, orderItems, calculateRespBO);
- // 3.1 拼团的特殊逻辑
- // TODO @puhui999:这个逻辑,先抽个小方法;未来要通过设计模式,把这些拼团之类的逻辑,抽象出去
- // 拼团
- if (Objects.equals(TradeOrderTypeEnum.COMBINATION.getType(), order.getType())) {
- createCombinationRecord(userId, createReqVO, orderItems, order);
- }
- // 3.2 秒杀的特殊逻辑
- if (Objects.equals(TradeOrderTypeEnum.SECKILL.getType(), order.getType())) {
-
- }
- // 3.3 砍价的特殊逻辑
// TODO @LeeYan9: 是可以思考下, 订单的营销优惠记录, 应该记录在哪里, 微信讨论起来!
return order;
}
- private void createCombinationRecord(Long userId, AppTradeOrderCreateReqVO createReqVO, List orderItems, TradeOrderDO order) {
- MemberUserRespDTO user = memberUserApi.getUser(userId);
- List recordRespDTOS = combinationRecordApi.getRecordListByUserIdAndActivityId(userId, createReqVO.getCombinationActivityId());
- // TODO 拼团一次应该只能选择一种规格的商品
- TradeOrderItemDO orderItemDO = orderItems.get(0);
- if (CollUtil.isNotEmpty(recordRespDTOS)) {
- List skuIds = convertList(recordRespDTOS, CombinationRecordRespDTO::getSkuId, item -> ObjectUtil.equals(item.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus()));
- List tradeOrderItemDOS = tradeOrderItemMapper.selectListByOrderIdAnSkuId(convertList(recordRespDTOS,
- CombinationRecordRespDTO::getOrderId, item -> ObjectUtil.equals(item.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus())), skuIds);
- combinationRecordApi.validateCombinationLimitCount(createReqVO.getCombinationActivityId(),
- CollectionUtils.getSumValue(tradeOrderItemDOS, TradeOrderItemDO::getCount, Integer::sum), orderItemDO.getCount());
- }
-
- combinationRecordApi.createCombinationRecord(TradeOrderConvert.INSTANCE.convert(order, orderItemDO, createReqVO, user));
- }
// TODO @puhui999:订单超时,自动取消;
@@ -310,13 +281,8 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
private void afterCreateTradeOrder(Long userId, AppTradeOrderCreateReqVO createReqVO,
TradeOrderDO tradeOrderDO, List orderItems,
TradePriceCalculateRespBO calculateRespBO) {
- Integer count = getSumValue(orderItems, TradeOrderItemDO::getCount, Integer::sum);
- // 1)如果是秒杀商品:额外扣减秒杀的库存;
- if (Objects.equals(TradeOrderTypeEnum.SECKILL.getType(), tradeOrderDO.getType())) {
- seckillActivityApi.updateSeckillStock(getSeckillActivityUpdateStockReqDTO(createReqVO, orderItems, count));
- }
- // 2)如果是砍价活动:额外扣减砍价的库存;
- bargainActivityApi.updateBargainActivityStock(createReqVO.getBargainActivityId(), count);
+ // 执行订单创建后置处理器
+ orderHandlers.forEach(handler -> handler.afterOrderCreate(TradeOrderConvert.INSTANCE.convert(userId, createReqVO, tradeOrderDO, orderItems.get(0))));
// 扣减积分 TODO 芋艿:待实现,需要前置;
// 这个是不是应该放到支付成功之后?如果支付后的话,可能积分可以重复使用哈。资源类,都要预扣
@@ -341,19 +307,6 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
// 增加订单日志 TODO 芋艿:待实现
}
- private SeckillActivityUpdateStockReqDTO getSeckillActivityUpdateStockReqDTO(AppTradeOrderCreateReqVO createReqVO, List orderItems, Integer count) {
- SeckillActivityUpdateStockReqDTO updateStockReqDTO = new SeckillActivityUpdateStockReqDTO();
- updateStockReqDTO.setActivityId(createReqVO.getSeckillActivityId());
- updateStockReqDTO.setCount(count);
- // 秒杀活动只能选择一个商品
- TradeOrderItemDO item = orderItems.get(0);
- SeckillActivityUpdateStockReqDTO.Item item1 = new SeckillActivityUpdateStockReqDTO.Item();
- item1.setSpuId(item.getSpuId());
- item1.setSkuId(item.getSkuId());
- item1.setCount(item.getCount());
- updateStockReqDTO.setItem(item1);
- return updateStockReqDTO;
- }
private void createPayOrder(TradeOrderDO order, List orderItems, TradePriceCalculateRespBO calculateRespBO) {
// 创建支付单,用于后续的支付
@@ -768,6 +721,9 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
throw exception(ORDER_CANCEL_FAIL_STATUS_NOT_UNPAID);
}
+ // TODO 活动相关库存回滚需要活动 id,活动 id 怎么获取?app 端能否传过来
+ orderHandlers.forEach(handler -> handler.rollbackStock());
+
// 2.回滚库存
List orderItems = tradeOrderItemMapper.selectListByOrderId(id);
productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convert(orderItems));
diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/TradeAfterOrderCreateReqBO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/TradeAfterOrderCreateReqBO.java
new file mode 100644
index 000000000..8a33e3eaf
--- /dev/null
+++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/TradeAfterOrderCreateReqBO.java
@@ -0,0 +1,39 @@
+package cn.iocoder.yudao.module.trade.service.order.bo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import javax.validation.constraints.NotNull;
+
+/**
+ * 订单创建之后 Request BO
+ *
+ * @author HUIHUI
+ */
+@Data
+public class TradeAfterOrderCreateReqBO {
+
+ // ========== 拼团活动相关字段 ==========
+
+ @Schema(description = "拼团活动编号", example = "1024")
+ private Long combinationActivityId;
+
+ @Schema(description = "拼团团长编号", example = "2048")
+ private Long combinationHeadId;
+
+ @NotNull(message = "SPU 编号不能为空")
+ private Long spuId;
+
+ @NotNull(message = "SKU 编号活动商品不能为空")
+ private Long skuId;
+
+ @NotNull(message = "订单编号不能为空")
+ private Long orderId;
+
+ @NotNull(message = "用户编号不能为空")
+ private Long userId;
+
+ @NotNull(message = "支付金额不能为空")
+ private Integer payPrice;
+
+}
diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/TradeBeforeOrderCreateReqBO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/TradeBeforeOrderCreateReqBO.java
new file mode 100644
index 000000000..e1b7faa35
--- /dev/null
+++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/TradeBeforeOrderCreateReqBO.java
@@ -0,0 +1,57 @@
+package cn.iocoder.yudao.module.trade.service.order.bo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import javax.validation.Valid;
+import javax.validation.constraints.NotNull;
+
+/**
+ * 订单创建之前 Request BO
+ *
+ * @author HUIHUI
+ */
+@Data
+public class TradeBeforeOrderCreateReqBO {
+
+ @NotNull(message = "订单类型不能为空")
+ private Integer orderType;
+
+ // ========== 秒杀活动相关字段 ==========
+
+ @Schema(description = "秒杀活动编号", example = "1024")
+ private Long seckillActivityId;
+
+ // ========== 拼团活动相关字段 ==========
+
+ @Schema(description = "拼团活动编号", example = "1024")
+ private Long combinationActivityId;
+
+ @Schema(description = "拼团团长编号", example = "2048")
+ private Long combinationHeadId;
+
+ @Schema(description = "砍价活动编号", example = "123")
+ private Long bargainActivityId;
+
+ @NotNull(message = "购买数量不能为空")
+ private Integer count;
+
+ @NotNull(message = "活动商品不能为空")
+ private Item item;
+
+ @Data
+ @Valid
+ public static class Item {
+
+ @NotNull(message = "SPU 编号不能为空")
+ private Long spuId;
+
+ @NotNull(message = "SKU 编号活动商品不能为空")
+ private Long skuId;
+
+ @NotNull(message = "购买数量不能为空")
+ private Integer count;
+
+ }
+
+}
diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeBargainHandler.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeBargainHandler.java
new file mode 100644
index 000000000..fc410963a
--- /dev/null
+++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeBargainHandler.java
@@ -0,0 +1,44 @@
+package cn.iocoder.yudao.module.trade.service.order.handler;
+
+import cn.hutool.core.util.ObjectUtil;
+import cn.iocoder.yudao.module.promotion.api.bargain.BargainActivityApi;
+import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum;
+import cn.iocoder.yudao.module.trade.service.order.bo.TradeAfterOrderCreateReqBO;
+import cn.iocoder.yudao.module.trade.service.order.bo.TradeBeforeOrderCreateReqBO;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+
+/**
+ * 砍价订单 handler 实现类
+ *
+ * @author HUIHUI
+ */
+@Component
+public class TradeBargainHandler implements TradeOrderHandler {
+
+ @Resource
+ private BargainActivityApi bargainActivityApi;
+
+ @Override
+ public void beforeOrderCreate(TradeBeforeOrderCreateReqBO reqBO) {
+ // 如果是秒杀订单
+ if (ObjectUtil.notEqual(TradeOrderTypeEnum.BARGAIN.getType(), reqBO.getOrderType())) {
+ return;
+ }
+
+ // 额外扣减砍价的库存
+ bargainActivityApi.updateBargainActivityStock(reqBO.getBargainActivityId(), reqBO.getCount());
+ }
+
+ @Override
+ public void afterOrderCreate(TradeAfterOrderCreateReqBO reqBO) {
+
+ }
+
+ @Override
+ public void rollbackStock() {
+
+ }
+
+}
diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeCombinationHandler.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeCombinationHandler.java
new file mode 100644
index 000000000..f9fce744b
--- /dev/null
+++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeCombinationHandler.java
@@ -0,0 +1,49 @@
+package cn.iocoder.yudao.module.trade.service.order.handler;
+
+import cn.hutool.core.util.ObjectUtil;
+import cn.iocoder.yudao.module.promotion.api.combination.CombinationApi;
+import cn.iocoder.yudao.module.promotion.api.combination.CombinationRecordApi;
+import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert;
+import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum;
+import cn.iocoder.yudao.module.trade.service.order.bo.TradeAfterOrderCreateReqBO;
+import cn.iocoder.yudao.module.trade.service.order.bo.TradeBeforeOrderCreateReqBO;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+
+/**
+ * 拼团订单 handler 接口实现类
+ *
+ * @author HUIHUI
+ */
+@Component
+public class TradeCombinationHandler implements TradeOrderHandler {
+
+ @Resource
+ private CombinationApi combinationApi;
+ @Resource
+ private CombinationRecordApi combinationRecordApi;
+
+ @Override
+ public void beforeOrderCreate(TradeBeforeOrderCreateReqBO reqBO) {
+ // 如果是拼团订单;
+ if (ObjectUtil.notEqual(TradeOrderTypeEnum.COMBINATION.getType(), reqBO.getOrderType())) {
+ return;
+ }
+
+ // 校验是否满足拼团活动相关限制
+ combinationApi.validateCombination(TradeOrderConvert.INSTANCE.convert1(reqBO));
+ }
+
+ @Override
+ public void afterOrderCreate(TradeAfterOrderCreateReqBO reqBO) {
+ // 创建砍价记录
+ combinationRecordApi.createCombinationRecord(TradeOrderConvert.INSTANCE.convert(reqBO));
+ }
+
+ @Override
+ public void rollbackStock() {
+
+ }
+
+}
diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeOrderHandler.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeOrderHandler.java
new file mode 100644
index 000000000..37dda82ce
--- /dev/null
+++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeOrderHandler.java
@@ -0,0 +1,32 @@
+package cn.iocoder.yudao.module.trade.service.order.handler;
+
+import cn.iocoder.yudao.module.trade.service.order.bo.TradeAfterOrderCreateReqBO;
+import cn.iocoder.yudao.module.trade.service.order.bo.TradeBeforeOrderCreateReqBO;
+
+/**
+ * 订单活动特殊逻辑处理器 handler 接口
+ *
+ * @author HUIHUI
+ */
+public interface TradeOrderHandler {
+
+ /**
+ * 订单创建前
+ *
+ * @param reqBO 请求
+ */
+ void beforeOrderCreate(TradeBeforeOrderCreateReqBO reqBO);
+
+ /**
+ * 订单创建后
+ *
+ * @param reqBO 请求
+ */
+ void afterOrderCreate(TradeAfterOrderCreateReqBO reqBO);
+
+ /**
+ * 回滚活动相关库存
+ */
+ void rollbackStock();
+
+}
diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeSeckillHandler.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeSeckillHandler.java
new file mode 100644
index 000000000..0774543a5
--- /dev/null
+++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeSeckillHandler.java
@@ -0,0 +1,44 @@
+package cn.iocoder.yudao.module.trade.service.order.handler;
+
+import cn.hutool.core.util.ObjectUtil;
+import cn.iocoder.yudao.module.promotion.api.seckill.SeckillActivityApi;
+import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert;
+import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum;
+import cn.iocoder.yudao.module.trade.service.order.bo.TradeAfterOrderCreateReqBO;
+import cn.iocoder.yudao.module.trade.service.order.bo.TradeBeforeOrderCreateReqBO;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+
+/**
+ * 秒杀订单 handler 实现类
+ *
+ * @author HUIHUI
+ */
+@Component
+public class TradeSeckillHandler implements TradeOrderHandler {
+
+ @Resource
+ private SeckillActivityApi seckillActivityApi;
+
+ @Override
+ public void beforeOrderCreate(TradeBeforeOrderCreateReqBO reqBO) {
+ // 如果是秒杀订单:额外扣减秒杀的库存;
+ if (ObjectUtil.notEqual(TradeOrderTypeEnum.SECKILL.getType(), reqBO.getOrderType())) {
+ return;
+ }
+
+ seckillActivityApi.updateSeckillStock(TradeOrderConvert.INSTANCE.convert(reqBO));
+ }
+
+ @Override
+ public void afterOrderCreate(TradeAfterOrderCreateReqBO reqBO) {
+
+ }
+
+ @Override
+ public void rollbackStock() {
+
+ }
+
+}