mall+order: 订单活动特殊逻辑的抽离
This commit is contained in:
parent
7fb455096c
commit
254d7828aa
@ -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);
|
||||
|
||||
}
|
@ -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;
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
|
||||
}
|
||||
|
@ -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 编号不能为空")
|
||||
|
@ -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, "砍价活动不存在");
|
||||
|
@ -29,6 +29,11 @@
|
||||
<artifactId>yudao-module-product-api</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-module-trade-api</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-module-member-api</artifactId>
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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<CombinationProductDO> getCombinationProductsByActivityIds(Collection<Long> activityIds);
|
||||
|
||||
/**
|
||||
* 更新拼图活动库存
|
||||
*
|
||||
* @param reqDTO 请求
|
||||
*/
|
||||
void validateCombination(CombinationActivityUpdateStockReqDTO reqDTO);
|
||||
|
||||
}
|
||||
|
@ -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<CombinationProductBaseVO> 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<CombinationRecordDO> recordList = combinationRecordService.getRecordListByUserIdAndActivityId(getLoginUserId(), reqDTO.getActivityId());
|
||||
if (CollUtil.isNotEmpty(recordList)) {
|
||||
// 过滤出拼团成功的
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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<Long> orderIds, Collection<Long> skuIds);
|
||||
|
||||
}
|
||||
|
@ -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<Long> orderIds, Collection<Long> skuIds) {
|
||||
return tradeOrderQueryService.getOrderItemCountSumByOrderIdAndSkuId(orderIds, skuIds);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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<AppOrderExpressTrackRespDTO> convertList02(List<ExpressTrackRespDTO> 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);
|
||||
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ public interface TradeOrderItemMapper extends BaseMapperX<TradeOrderItemDO> {
|
||||
default List<TradeOrderItemDO> selectListByOrderIdAnSkuId(Collection<Long> orderIds, Collection<Long> skuIds) {
|
||||
return selectList(new LambdaQueryWrapperX<TradeOrderItemDO>()
|
||||
.in(TradeOrderItemDO::getOrderId, orderIds)
|
||||
.eq(TradeOrderItemDO::getSkuId, skuIds));
|
||||
.in(TradeOrderItemDO::getSkuId, skuIds));
|
||||
}
|
||||
|
||||
default TradeOrderItemDO selectByIdAndUserId(Long orderItemId, Long loginUserId) {
|
||||
|
@ -119,4 +119,13 @@ public interface TradeOrderQueryService {
|
||||
*/
|
||||
List<TradeOrderItemDO> getOrderItemListByOrderId(Collection<Long> orderIds);
|
||||
|
||||
/**
|
||||
* 获取订单项商品购买数量总和
|
||||
*
|
||||
* @param orderIds 订单编号
|
||||
* @param skuIds sku 编号
|
||||
* @return 订单项商品购买数量总和
|
||||
*/
|
||||
Integer getOrderItemCountSumByOrderIdAndSkuId(Collection<Long> orderIds, Collection<Long> skuIds);
|
||||
|
||||
}
|
||||
|
@ -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<Long> orderIds, Collection<Long> skuIds) {
|
||||
List<TradeOrderItemDO> tradeOrderItems = tradeOrderItemMapper.selectListByOrderIdAnSkuId(orderIds, skuIds);
|
||||
return CollectionUtils.getSumValue(tradeOrderItems, TradeOrderItemDO::getCount, Integer::sum);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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<TradeOrderHandler> 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<TradeOrderItemDO> orderItems, TradeOrderDO order) {
|
||||
MemberUserRespDTO user = memberUserApi.getUser(userId);
|
||||
List<CombinationRecordRespDTO> recordRespDTOS = combinationRecordApi.getRecordListByUserIdAndActivityId(userId, createReqVO.getCombinationActivityId());
|
||||
// TODO 拼团一次应该只能选择一种规格的商品
|
||||
TradeOrderItemDO orderItemDO = orderItems.get(0);
|
||||
if (CollUtil.isNotEmpty(recordRespDTOS)) {
|
||||
List<Long> skuIds = convertList(recordRespDTOS, CombinationRecordRespDTO::getSkuId, item -> ObjectUtil.equals(item.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus()));
|
||||
List<TradeOrderItemDO> 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<TradeOrderItemDO> 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<TradeOrderItemDO> 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<TradeOrderItemDO> 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<TradeOrderItemDO> orderItems = tradeOrderItemMapper.selectListByOrderId(id);
|
||||
productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convert(orderItems));
|
||||
|
@ -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;
|
||||
|
||||
}
|
@ -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;
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -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() {
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -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() {
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -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();
|
||||
|
||||
}
|
@ -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() {
|
||||
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user