mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-11-04 20:28:44 +08:00 
			
		
		
		
	mall+order: 订单活动特殊逻辑的抽离
This commit is contained in:
		@@ -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 lombok.Data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import javax.validation.constraints.NotEmpty;
 | 
					 | 
				
			||||||
import javax.validation.constraints.NotNull;
 | 
					import javax.validation.constraints.NotNull;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TODO @芋艿:这块要在看看
 | 
					// TODO @芋艿:这块要在看看
 | 
				
			||||||
@@ -14,65 +13,25 @@ import javax.validation.constraints.NotNull;
 | 
				
			|||||||
@Data
 | 
					@Data
 | 
				
			||||||
public class CombinationRecordCreateReqDTO {
 | 
					public class CombinationRecordCreateReqDTO {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * 拼团活动编号
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    @NotNull(message = "拼团活动编号不能为空")
 | 
					    @NotNull(message = "拼团活动编号不能为空")
 | 
				
			||||||
    private Long activityId;
 | 
					    private Long activityId;
 | 
				
			||||||
    /**
 | 
					
 | 
				
			||||||
     * spu 编号
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    @NotNull(message = "spu 编号不能为空")
 | 
					    @NotNull(message = "spu 编号不能为空")
 | 
				
			||||||
    private Long spuId;
 | 
					    private Long spuId;
 | 
				
			||||||
    /**
 | 
					
 | 
				
			||||||
     * sku 编号
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    @NotNull(message = "sku 编号不能为空")
 | 
					    @NotNull(message = "sku 编号不能为空")
 | 
				
			||||||
    private Long skuId;
 | 
					    private Long skuId;
 | 
				
			||||||
    /**
 | 
					
 | 
				
			||||||
     * 用户编号
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    @NotNull(message = "用户编号不能为空")
 | 
					 | 
				
			||||||
    private Long userId;
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * 订单编号
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    @NotNull(message = "订单编号不能为空")
 | 
					    @NotNull(message = "订单编号不能为空")
 | 
				
			||||||
    private Long orderId;
 | 
					    private Long orderId;
 | 
				
			||||||
    /**
 | 
					
 | 
				
			||||||
     * 团长编号
 | 
					    @NotNull(message = "用户编号不能为空")
 | 
				
			||||||
     */
 | 
					    private Long userId;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @NotNull(message = "团长编号不能为空")
 | 
					    @NotNull(message = "团长编号不能为空")
 | 
				
			||||||
    private Long headId;
 | 
					    private Long headId;
 | 
				
			||||||
    /**
 | 
					
 | 
				
			||||||
     * 商品名字
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    @NotEmpty(message = "商品名字不能为空")
 | 
					 | 
				
			||||||
    private String spuName;
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * 商品图片
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    @NotEmpty(message = "商品图片不能为空")
 | 
					 | 
				
			||||||
    private String picUrl;
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * 拼团商品单价
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    @NotNull(message = "拼团商品单价不能为空")
 | 
					    @NotNull(message = "拼团商品单价不能为空")
 | 
				
			||||||
    private Integer combinationPrice;
 | 
					    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 lombok.Data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import javax.validation.Valid;
 | 
				
			||||||
import javax.validation.constraints.NotNull;
 | 
					import javax.validation.constraints.NotNull;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@@ -22,6 +23,7 @@ public class SeckillActivityUpdateStockReqDTO {
 | 
				
			|||||||
    private Item item;
 | 
					    private Item item;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Data
 | 
					    @Data
 | 
				
			||||||
 | 
					    @Valid
 | 
				
			||||||
    public static class Item {
 | 
					    public static class Item {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        @NotNull(message = "SPU 编号不能为空")
 | 
					        @NotNull(message = "SPU 编号不能为空")
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -65,18 +65,19 @@ public interface ErrorCodeConstants {
 | 
				
			|||||||
    // ========== 拼团活动 1013010000 ==========
 | 
					    // ========== 拼团活动 1013010000 ==========
 | 
				
			||||||
    ErrorCode COMBINATION_ACTIVITY_NOT_EXISTS = new ErrorCode(1013010000, "拼团活动不存在");
 | 
					    ErrorCode COMBINATION_ACTIVITY_NOT_EXISTS = new ErrorCode(1013010000, "拼团活动不存在");
 | 
				
			||||||
    ErrorCode COMBINATION_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1013010001, "存在商品参加了其它拼团活动");
 | 
					    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_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 ==========
 | 
					    // ========== 拼团记录 1013011000 ==========
 | 
				
			||||||
    ErrorCode COMBINATION_RECORD_EXISTS = new ErrorCode(1013011000, "拼团失败,已参与过该拼团");
 | 
					    ErrorCode COMBINATION_RECORD_NOT_EXISTS = new ErrorCode(1013011000, "拼团不存在");
 | 
				
			||||||
    ErrorCode COMBINATION_RECORD_HEAD_NOT_EXISTS = new ErrorCode(1013011001, "拼团失败,父拼团不存在");
 | 
					    ErrorCode COMBINATION_RECORD_EXISTS = new ErrorCode(1013011001, "拼团失败,已参与过该拼团");
 | 
				
			||||||
    ErrorCode COMBINATION_RECORD_USER_FULL = new ErrorCode(1013011002, "拼团失败,拼团人数已满");
 | 
					    ErrorCode COMBINATION_RECORD_HEAD_NOT_EXISTS = new ErrorCode(1013011002, "拼团失败,父拼团不存在");
 | 
				
			||||||
    ErrorCode COMBINATION_RECORD_FAILED_HAVE_JOINED = new ErrorCode(1013011003, "拼团失败,已参与其它拼团");
 | 
					    ErrorCode COMBINATION_RECORD_USER_FULL = new ErrorCode(1013011003, "拼团失败,拼团人数已满");
 | 
				
			||||||
    ErrorCode COMBINATION_RECORD_FAILED_TIME_END = new ErrorCode(1013011004, "拼团失败,活动已经结束");
 | 
					    ErrorCode COMBINATION_RECORD_FAILED_HAVE_JOINED = new ErrorCode(1013011004, "拼团失败,已参与其它拼团");
 | 
				
			||||||
    ErrorCode COMBINATION_RECORD_FAILED_SINGLE_LIMIT_COUNT_EXCEED = new ErrorCode(1013011005, "拼团失败,单次限购超出");
 | 
					    ErrorCode COMBINATION_RECORD_FAILED_TIME_END = new ErrorCode(1013011005, "拼团失败,活动已经结束");
 | 
				
			||||||
    ErrorCode COMBINATION_RECORD_FAILED_TOTAL_LIMIT_COUNT_EXCEED = new ErrorCode(1013011006, "拼团失败,单次限购超出");
 | 
					    ErrorCode COMBINATION_RECORD_FAILED_SINGLE_LIMIT_COUNT_EXCEED = new ErrorCode(1013011006, "拼团失败,原因:单次限购超出");
 | 
				
			||||||
 | 
					    ErrorCode COMBINATION_RECORD_FAILED_TOTAL_LIMIT_COUNT_EXCEED = new ErrorCode(1013011007, "拼团失败,原因:超出总购买次数");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // ========== 砍价活动 1013012000 ==========
 | 
					    // ========== 砍价活动 1013012000 ==========
 | 
				
			||||||
    ErrorCode BARGAIN_ACTIVITY_NOT_EXISTS = new ErrorCode(1013012000, "砍价活动不存在");
 | 
					    ErrorCode BARGAIN_ACTIVITY_NOT_EXISTS = new ErrorCode(1013012000, "砍价活动不存在");
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,6 +29,11 @@
 | 
				
			|||||||
            <artifactId>yudao-module-product-api</artifactId>
 | 
					            <artifactId>yudao-module-product-api</artifactId>
 | 
				
			||||||
            <version>${revision}</version>
 | 
					            <version>${revision}</version>
 | 
				
			||||||
        </dependency>
 | 
					        </dependency>
 | 
				
			||||||
 | 
					        <dependency>
 | 
				
			||||||
 | 
					            <groupId>cn.iocoder.boot</groupId>
 | 
				
			||||||
 | 
					            <artifactId>yudao-module-trade-api</artifactId>
 | 
				
			||||||
 | 
					            <version>${revision}</version>
 | 
				
			||||||
 | 
					        </dependency>
 | 
				
			||||||
        <dependency>
 | 
					        <dependency>
 | 
				
			||||||
            <groupId>cn.iocoder.boot</groupId>
 | 
					            <groupId>cn.iocoder.boot</groupId>
 | 
				
			||||||
            <artifactId>yudao-module-member-api</artifactId>
 | 
					            <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;
 | 
					package cn.iocoder.yudao.module.promotion.service.combination;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
 | 
					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.CombinationActivityCreateReqVO;
 | 
				
			||||||
import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityPageReqVO;
 | 
					import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityPageReqVO;
 | 
				
			||||||
import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityUpdateReqVO;
 | 
					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);
 | 
					    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.sku.dto.ProductSkuRespDTO;
 | 
				
			||||||
import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
 | 
					import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
 | 
				
			||||||
import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
 | 
					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.CombinationActivityCreateReqVO;
 | 
				
			||||||
import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityPageReqVO;
 | 
					import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityPageReqVO;
 | 
				
			||||||
import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityUpdateReqVO;
 | 
					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.convert.combination.CombinationActivityConvert;
 | 
				
			||||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO;
 | 
					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.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.CombinationActivityMapper;
 | 
				
			||||||
import cn.iocoder.yudao.module.promotion.dal.mysql.combination.CombinationProductMapper;
 | 
					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.stereotype.Service;
 | 
				
			||||||
import org.springframework.transaction.annotation.Transactional;
 | 
					import org.springframework.transaction.annotation.Transactional;
 | 
				
			||||||
import org.springframework.validation.annotation.Validated;
 | 
					import org.springframework.validation.annotation.Validated;
 | 
				
			||||||
@@ -28,8 +32,8 @@ import java.util.List;
 | 
				
			|||||||
import java.util.Map;
 | 
					import java.util.Map;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 | 
					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.*;
 | 
				
			||||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList;
 | 
					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.SKU_NOT_EXISTS;
 | 
				
			||||||
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS;
 | 
					import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS;
 | 
				
			||||||
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
 | 
					import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
 | 
				
			||||||
@@ -48,11 +52,15 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic
 | 
				
			|||||||
    private CombinationActivityMapper combinationActivityMapper;
 | 
					    private CombinationActivityMapper combinationActivityMapper;
 | 
				
			||||||
    @Resource
 | 
					    @Resource
 | 
				
			||||||
    private CombinationProductMapper combinationProductMapper;
 | 
					    private CombinationProductMapper combinationProductMapper;
 | 
				
			||||||
 | 
					    @Resource
 | 
				
			||||||
 | 
					    private CombinationRecordService combinationRecordService;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Resource
 | 
					    @Resource
 | 
				
			||||||
    private ProductSpuApi productSpuApi;
 | 
					    private ProductSpuApi productSpuApi;
 | 
				
			||||||
    @Resource
 | 
					    @Resource
 | 
				
			||||||
    private ProductSkuApi productSkuApi;
 | 
					    private ProductSkuApi productSkuApi;
 | 
				
			||||||
 | 
					    @Resource
 | 
				
			||||||
 | 
					    private TradeOrderApi tradeOrderApi;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    @Transactional(rollbackFor = Exception.class)
 | 
					    @Transactional(rollbackFor = Exception.class)
 | 
				
			||||||
@@ -97,7 +105,7 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic
 | 
				
			|||||||
     * 校验拼团商品是否都存在
 | 
					     * 校验拼团商品是否都存在
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param spuId 商品 SPU 编号
 | 
					     * @param spuId 商品 SPU 编号
 | 
				
			||||||
     * @param products 秒杀商品
 | 
					     * @param products 拼团商品
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    private void validateProductExists(Long spuId, List<CombinationProductBaseVO> products) {
 | 
					    private void validateProductExists(Long spuId, List<CombinationProductBaseVO> products) {
 | 
				
			||||||
        // 1. 校验商品 spu 是否存在
 | 
					        // 1. 校验商品 spu 是否存在
 | 
				
			||||||
@@ -123,7 +131,7 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic
 | 
				
			|||||||
        CombinationActivityDO activityDO = validateCombinationActivityExists(updateReqVO.getId());
 | 
					        CombinationActivityDO activityDO = validateCombinationActivityExists(updateReqVO.getId());
 | 
				
			||||||
        // 校验状态
 | 
					        // 校验状态
 | 
				
			||||||
        if (ObjectUtil.equal(activityDO.getStatus(), CommonStatusEnum.DISABLE.getStatus())) {
 | 
					        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());
 | 
					        validateProductConflict(updateReqVO.getSpuId(), updateReqVO.getId());
 | 
				
			||||||
@@ -205,4 +213,30 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic
 | 
				
			|||||||
        return combinationProductMapper.selectListByActivityIds(activityIds);
 | 
					        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.collection.CollUtil;
 | 
				
			||||||
import cn.hutool.core.util.ObjectUtil;
 | 
					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.api.combination.dto.CombinationRecordCreateReqDTO;
 | 
				
			||||||
import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert;
 | 
					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.CombinationActivityDO;
 | 
				
			||||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO;
 | 
					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.dal.mysql.combination.CombinationRecordMapper;
 | 
				
			||||||
import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum;
 | 
					import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum;
 | 
				
			||||||
 | 
					import org.springframework.context.annotation.Lazy;
 | 
				
			||||||
import org.springframework.stereotype.Service;
 | 
					import org.springframework.stereotype.Service;
 | 
				
			||||||
import org.springframework.transaction.annotation.Transactional;
 | 
					import org.springframework.transaction.annotation.Transactional;
 | 
				
			||||||
import org.springframework.validation.annotation.Validated;
 | 
					import org.springframework.validation.annotation.Validated;
 | 
				
			||||||
@@ -32,10 +39,18 @@ public class CombinationRecordServiceImpl implements CombinationRecordService {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    @Resource
 | 
					    @Resource
 | 
				
			||||||
    private CombinationActivityService combinationActivityService;
 | 
					    private CombinationActivityService combinationActivityService;
 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Resource
 | 
					    @Resource
 | 
				
			||||||
    private CombinationRecordMapper recordMapper;
 | 
					    private CombinationRecordMapper recordMapper;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Resource
 | 
				
			||||||
 | 
					    private MemberUserApi memberUserApi;
 | 
				
			||||||
 | 
					    @Resource
 | 
				
			||||||
 | 
					    @Lazy
 | 
				
			||||||
 | 
					    private ProductSpuApi productSpuApi;
 | 
				
			||||||
 | 
					    @Resource
 | 
				
			||||||
 | 
					    @Lazy
 | 
				
			||||||
 | 
					    private ProductSkuApi productSkuApi;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    @Transactional(rollbackFor = Exception.class)
 | 
					    @Transactional(rollbackFor = Exception.class)
 | 
				
			||||||
    public void updateCombinationRecordStatusByUserIdAndOrderId(Integer status, Long userId, Long orderId) {
 | 
					    public void updateCombinationRecordStatusByUserIdAndOrderId(Integer status, Long userId, Long orderId) {
 | 
				
			||||||
@@ -102,12 +117,12 @@ public class CombinationRecordServiceImpl implements CombinationRecordService {
 | 
				
			|||||||
        // 1.5 父拼团是否存在,是否已经满了
 | 
					        // 1.5 父拼团是否存在,是否已经满了
 | 
				
			||||||
        if (reqDTO.getHeadId() != null) {
 | 
					        if (reqDTO.getHeadId() != null) {
 | 
				
			||||||
            // 查询进行中的父拼团
 | 
					            // 查询进行中的父拼团
 | 
				
			||||||
            CombinationRecordDO recordDO1 = recordMapper.selectOneByHeadId(reqDTO.getHeadId(), CombinationRecordStatusEnum.IN_PROGRESS.getStatus());
 | 
					            CombinationRecordDO record = recordMapper.selectOneByHeadId(reqDTO.getHeadId(), CombinationRecordStatusEnum.IN_PROGRESS.getStatus());
 | 
				
			||||||
            if (recordDO1 == null) {
 | 
					            if (record == null) {
 | 
				
			||||||
                throw exception(COMBINATION_RECORD_HEAD_NOT_EXISTS);
 | 
					                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);
 | 
					                throw exception(COMBINATION_RECORD_USER_FULL);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -117,6 +132,13 @@ public class CombinationRecordServiceImpl implements CombinationRecordService {
 | 
				
			|||||||
        record.setVirtualGroup(false);
 | 
					        record.setVirtualGroup(false);
 | 
				
			||||||
        record.setExpireTime(record.getStartTime().plusHours(activity.getLimitDuration()));
 | 
					        record.setExpireTime(record.getStartTime().plusHours(activity.getLimitDuration()));
 | 
				
			||||||
        record.setUserSize(activity.getUserSize());
 | 
					        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);
 | 
					        recordMapper.insert(record);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,7 @@
 | 
				
			|||||||
package cn.iocoder.yudao.module.trade.api.order;
 | 
					package cn.iocoder.yudao.module.trade.api.order;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.Collection;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * 订单 API 接口
 | 
					 * 订单 API 接口
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -16,4 +18,13 @@ public interface TradeOrderApi {
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    Long validateOrder(Long userId, Long orderItemId);
 | 
					    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 org.springframework.validation.annotation.Validated;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import javax.annotation.Resource;
 | 
					import javax.annotation.Resource;
 | 
				
			||||||
 | 
					import java.util.Collection;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 | 
					import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 | 
				
			||||||
import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.ORDER_ITEM_NOT_FOUND;
 | 
					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();
 | 
					        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.property.dto.ProductPropertyValueDetailRespDTO;
 | 
				
			||||||
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
 | 
					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.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.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.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.member.user.MemberUserRespVO;
 | 
				
			||||||
import cn.iocoder.yudao.module.trade.controller.admin.base.product.property.ProductPropertyValueDetailRespVO;
 | 
					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.delivery.core.client.dto.ExpressTrackRespDTO;
 | 
				
			||||||
import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties;
 | 
					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.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.TradePriceCalculateReqBO;
 | 
				
			||||||
import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO;
 | 
					import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO;
 | 
				
			||||||
import org.mapstruct.Mapper;
 | 
					import org.mapstruct.Mapper;
 | 
				
			||||||
@@ -253,21 +257,15 @@ public interface TradeOrderConvert {
 | 
				
			|||||||
    AppTradeOrderSettlementRespVO convert0(TradePriceCalculateRespBO calculate, AddressRespDTO address);
 | 
					    AppTradeOrderSettlementRespVO convert0(TradePriceCalculateRespBO calculate, AddressRespDTO address);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Mappings({
 | 
					    @Mappings({
 | 
				
			||||||
            @Mapping(target = "activityId", source = "createReqVO.combinationActivityId"),
 | 
					            @Mapping(target = "activityId", source = "afterOrderCreateReqBO.combinationActivityId"),
 | 
				
			||||||
            @Mapping(target = "spuId", source = "orderItem.spuId"),
 | 
					            @Mapping(target = "spuId", source = "afterOrderCreateReqBO.spuId"),
 | 
				
			||||||
            @Mapping(target = "skuId", source = "orderItem.skuId"),
 | 
					            @Mapping(target = "skuId", source = "afterOrderCreateReqBO.skuId"),
 | 
				
			||||||
            @Mapping(target = "userId", source = "order.userId"),
 | 
					            @Mapping(target = "orderId", source = "afterOrderCreateReqBO.orderId"),
 | 
				
			||||||
            @Mapping(target = "orderId", source = "order.id"),
 | 
					            @Mapping(target = "userId", source = "afterOrderCreateReqBO.userId"),
 | 
				
			||||||
            @Mapping(target = "headId", source = "createReqVO.combinationHeadId"),
 | 
					            @Mapping(target = "headId", source = "afterOrderCreateReqBO.combinationHeadId"),
 | 
				
			||||||
            @Mapping(target = "spuName", source = "orderItem.spuName"),
 | 
					            @Mapping(target = "combinationPrice", source = "afterOrderCreateReqBO.payPrice"),
 | 
				
			||||||
            @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)
 | 
					 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
    CombinationRecordCreateReqDTO convert(TradeOrderDO order, TradeOrderItemDO orderItem,
 | 
					    CombinationRecordCreateReqDTO convert(TradeAfterOrderCreateReqBO afterOrderCreateReqBO);
 | 
				
			||||||
                                          AppTradeOrderCreateReqVO createReqVO, MemberUserRespDTO user);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    List<AppOrderExpressTrackRespDTO> convertList02(List<ExpressTrackRespDTO> list);
 | 
					    List<AppOrderExpressTrackRespDTO> convertList02(List<ExpressTrackRespDTO> list);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -283,4 +281,24 @@ public interface TradeOrderConvert {
 | 
				
			|||||||
                .setFirstFixedPrice(sku.getFirstBrokerageRecord())
 | 
					                .setFirstFixedPrice(sku.getFirstBrokerageRecord())
 | 
				
			||||||
                .setSecondFixedPrice(sku.getSecondBrokerageRecord());
 | 
					                .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) {
 | 
					    default List<TradeOrderItemDO> selectListByOrderIdAnSkuId(Collection<Long> orderIds, Collection<Long> skuIds) {
 | 
				
			||||||
        return selectList(new LambdaQueryWrapperX<TradeOrderItemDO>()
 | 
					        return selectList(new LambdaQueryWrapperX<TradeOrderItemDO>()
 | 
				
			||||||
                .in(TradeOrderItemDO::getOrderId, orderIds)
 | 
					                .in(TradeOrderItemDO::getOrderId, orderIds)
 | 
				
			||||||
                .eq(TradeOrderItemDO::getSkuId, skuIds));
 | 
					                .in(TradeOrderItemDO::getSkuId, skuIds));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    default TradeOrderItemDO selectByIdAndUserId(Long orderItemId, Long loginUserId) {
 | 
					    default TradeOrderItemDO selectByIdAndUserId(Long orderItemId, Long loginUserId) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -119,4 +119,13 @@ public interface TradeOrderQueryService {
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    List<TradeOrderItemDO> getOrderItemListByOrderId(Collection<Long> orderIds);
 | 
					    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.ObjectUtil;
 | 
				
			||||||
import cn.hutool.core.util.StrUtil;
 | 
					import cn.hutool.core.util.StrUtil;
 | 
				
			||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
 | 
					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.MemberUserApi;
 | 
				
			||||||
import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
 | 
					import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
 | 
				
			||||||
import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderPageReqVO;
 | 
					import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderPageReqVO;
 | 
				
			||||||
@@ -167,4 +168,10 @@ public class TradeOrderQueryServiceImpl implements TradeOrderQueryService {
 | 
				
			|||||||
        return tradeOrderItemMapper.selectListByOrderId(orderIds);
 | 
					        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.address.dto.AddressRespDTO;
 | 
				
			||||||
import cn.iocoder.yudao.module.member.api.level.MemberLevelApi;
 | 
					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.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.MemberExperienceBizTypeEnum;
 | 
				
			||||||
import cn.iocoder.yudao.module.member.enums.point.MemberPointBizTypeEnum;
 | 
					import cn.iocoder.yudao.module.member.enums.point.MemberPointBizTypeEnum;
 | 
				
			||||||
import cn.iocoder.yudao.module.pay.api.order.PayOrderApi;
 | 
					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.ProductCommentApi;
 | 
				
			||||||
import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO;
 | 
					import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO;
 | 
				
			||||||
import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
 | 
					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.bargain.BargainRecordApi;
 | 
				
			||||||
import cn.iocoder.yudao.module.promotion.api.combination.CombinationRecordApi;
 | 
					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.CouponApi;
 | 
				
			||||||
import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponUseReqDTO;
 | 
					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.TradeOrderDeliveryReqVO;
 | 
				
			||||||
import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderRemarkReqVO;
 | 
					import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderRemarkReqVO;
 | 
				
			||||||
import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderUpdateAddressReqVO;
 | 
					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.delivery.DeliveryExpressService;
 | 
				
			||||||
import cn.iocoder.yudao.module.trade.service.message.TradeMessageService;
 | 
					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.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.TradePriceService;
 | 
				
			||||||
import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO;
 | 
					import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO;
 | 
				
			||||||
import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO;
 | 
					import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO;
 | 
				
			||||||
@@ -95,6 +90,8 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
 | 
				
			|||||||
    private TradeOrderItemMapper tradeOrderItemMapper;
 | 
					    private TradeOrderItemMapper tradeOrderItemMapper;
 | 
				
			||||||
    @Resource
 | 
					    @Resource
 | 
				
			||||||
    private TradeOrderNoRedisDAO orderNoRedisDAO;
 | 
					    private TradeOrderNoRedisDAO orderNoRedisDAO;
 | 
				
			||||||
 | 
					    @Resource
 | 
				
			||||||
 | 
					    private List<TradeOrderHandler> orderHandlers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Resource
 | 
					    @Resource
 | 
				
			||||||
    private CartService cartService;
 | 
					    private CartService cartService;
 | 
				
			||||||
@@ -118,12 +115,6 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
 | 
				
			|||||||
    @Resource
 | 
					    @Resource
 | 
				
			||||||
    private BargainRecordApi bargainRecordApi;
 | 
					    private BargainRecordApi bargainRecordApi;
 | 
				
			||||||
    @Resource
 | 
					    @Resource
 | 
				
			||||||
    private SeckillActivityApi seckillActivityApi;
 | 
					 | 
				
			||||||
    @Resource
 | 
					 | 
				
			||||||
    private BargainActivityApi bargainActivityApi;
 | 
					 | 
				
			||||||
    @Resource
 | 
					 | 
				
			||||||
    private MemberUserApi memberUserApi;
 | 
					 | 
				
			||||||
    @Resource
 | 
					 | 
				
			||||||
    private MemberLevelApi memberLevelApi;
 | 
					    private MemberLevelApi memberLevelApi;
 | 
				
			||||||
    @Resource
 | 
					    @Resource
 | 
				
			||||||
    private MemberPointApi memberPointApi;
 | 
					    private MemberPointApi memberPointApi;
 | 
				
			||||||
@@ -188,7 +179,13 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
 | 
				
			|||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    @Transactional(rollbackFor = Exception.class)
 | 
					    @Transactional(rollbackFor = Exception.class)
 | 
				
			||||||
    public TradeOrderDO createOrder(Long userId, String userIp, AppTradeOrderCreateReqVO createReqVO) {
 | 
					    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);
 | 
					        TradePriceCalculateRespBO calculateRespBO = calculatePrice(userId, createReqVO);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // 2.1 插入 TradeOrderDO 订单
 | 
					        // 2.1 插入 TradeOrderDO 订单
 | 
				
			||||||
@@ -198,37 +195,11 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        // 3. 订单创建完后的逻辑
 | 
					        // 3. 订单创建完后的逻辑
 | 
				
			||||||
        afterCreateTradeOrder(userId, createReqVO, order, orderItems, calculateRespBO);
 | 
					        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: 是可以思考下, 订单的营销优惠记录, 应该记录在哪里, 微信讨论起来!
 | 
					        // TODO @LeeYan9: 是可以思考下, 订单的营销优惠记录, 应该记录在哪里, 微信讨论起来!
 | 
				
			||||||
        return order;
 | 
					        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:订单超时,自动取消;
 | 
					    // TODO @puhui999:订单超时,自动取消;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -310,13 +281,8 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
 | 
				
			|||||||
    private void afterCreateTradeOrder(Long userId, AppTradeOrderCreateReqVO createReqVO,
 | 
					    private void afterCreateTradeOrder(Long userId, AppTradeOrderCreateReqVO createReqVO,
 | 
				
			||||||
                                       TradeOrderDO tradeOrderDO, List<TradeOrderItemDO> orderItems,
 | 
					                                       TradeOrderDO tradeOrderDO, List<TradeOrderItemDO> orderItems,
 | 
				
			||||||
                                       TradePriceCalculateRespBO calculateRespBO) {
 | 
					                                       TradePriceCalculateRespBO calculateRespBO) {
 | 
				
			||||||
        Integer count = getSumValue(orderItems, TradeOrderItemDO::getCount, Integer::sum);
 | 
					        // 执行订单创建后置处理器
 | 
				
			||||||
        // 1)如果是秒杀商品:额外扣减秒杀的库存;
 | 
					        orderHandlers.forEach(handler -> handler.afterOrderCreate(TradeOrderConvert.INSTANCE.convert(userId, createReqVO, tradeOrderDO, orderItems.get(0))));
 | 
				
			||||||
        if (Objects.equals(TradeOrderTypeEnum.SECKILL.getType(), tradeOrderDO.getType())) {
 | 
					 | 
				
			||||||
            seckillActivityApi.updateSeckillStock(getSeckillActivityUpdateStockReqDTO(createReqVO, orderItems, count));
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        // 2)如果是砍价活动:额外扣减砍价的库存;
 | 
					 | 
				
			||||||
        bargainActivityApi.updateBargainActivityStock(createReqVO.getBargainActivityId(), count);
 | 
					 | 
				
			||||||
        // 扣减积分 TODO 芋艿:待实现,需要前置;
 | 
					        // 扣减积分 TODO 芋艿:待实现,需要前置;
 | 
				
			||||||
        // 这个是不是应该放到支付成功之后?如果支付后的话,可能积分可以重复使用哈。资源类,都要预扣
 | 
					        // 这个是不是应该放到支付成功之后?如果支付后的话,可能积分可以重复使用哈。资源类,都要预扣
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -341,19 +307,6 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
 | 
				
			|||||||
        // 增加订单日志 TODO 芋艿:待实现
 | 
					        // 增加订单日志 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) {
 | 
					    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);
 | 
					            throw exception(ORDER_CANCEL_FAIL_STATUS_NOT_UNPAID);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // TODO 活动相关库存回滚需要活动 id,活动 id 怎么获取?app 端能否传过来
 | 
				
			||||||
 | 
					        orderHandlers.forEach(handler -> handler.rollbackStock());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // 2.回滚库存
 | 
					        // 2.回滚库存
 | 
				
			||||||
        List<TradeOrderItemDO> orderItems = tradeOrderItemMapper.selectListByOrderId(id);
 | 
					        List<TradeOrderItemDO> orderItems = tradeOrderItemMapper.selectListByOrderId(id);
 | 
				
			||||||
        productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convert(orderItems));
 | 
					        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() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user