Commit f40bd23f6a168ef63d7169af0148a597d4cb9627

Authored by puhui999
1 parent c7b5df93

拼团记录:完善拼团记录创建前的条件校验规则

yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApi.java
@@ -18,12 +18,13 @@ public interface CombinationRecordApi { @@ -18,12 +18,13 @@ public interface CombinationRecordApi {
18 /** 18 /**
19 * 校验是否满足拼团条件 19 * 校验是否满足拼团条件
20 * 20 *
21 - * @param activityId 活动编号  
22 * @param userId 用户编号 21 * @param userId 用户编号
  22 + * @param activityId 活动编号
  23 + * @param headId 团长编号
23 * @param skuId sku 编号 24 * @param skuId sku 编号
24 * @param count 数量 25 * @param count 数量
25 */ 26 */
26 - void validateCombinationRecord(Long activityId, Long userId, Long skuId, Integer count); 27 + void validateCombinationRecord(Long userId, Long activityId, Long headId, Long skuId, Integer count);
27 28
28 /** 29 /**
29 * 创建开团记录 30 * 创建开团记录
@@ -71,13 +72,13 @@ public interface CombinationRecordApi { @@ -71,13 +72,13 @@ public interface CombinationRecordApi {
71 * 72 *
72 * 如果校验失败,则抛出业务异常 73 * 如果校验失败,则抛出业务异常
73 * 74 *
74 - * @param activityId 活动编号  
75 * @param userId 用户编号 75 * @param userId 用户编号
  76 + * @param activityId 活动编号
  77 + * @param headId 团长编号
76 * @param skuId sku 编号 78 * @param skuId sku 编号
77 * @param count 数量 79 * @param count 数量
78 * @return 拼团信息 80 * @return 拼团信息
79 */ 81 */
80 - // TODO @puhui:userId 放最前面;然后应该还有个 headId 参数;  
81 - CombinationValidateJoinRespDTO validateJoinCombination(Long activityId, Long userId, Long skuId, Integer count); 82 + CombinationValidateJoinRespDTO validateJoinCombination(Long userId, Long activityId, Long headId, Long skuId, Integer count);
82 83
83 } 84 }
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java
@@ -80,7 +80,7 @@ public interface ErrorCodeConstants { @@ -80,7 +80,7 @@ public interface ErrorCodeConstants {
80 ErrorCode COMBINATION_RECORD_EXISTS = new ErrorCode(1_013_011_001, "拼团失败,已参与过该拼团"); 80 ErrorCode COMBINATION_RECORD_EXISTS = new ErrorCode(1_013_011_001, "拼团失败,已参与过该拼团");
81 ErrorCode COMBINATION_RECORD_HEAD_NOT_EXISTS = new ErrorCode(1_013_011_002, "拼团失败,父拼团不存在"); 81 ErrorCode COMBINATION_RECORD_HEAD_NOT_EXISTS = new ErrorCode(1_013_011_002, "拼团失败,父拼团不存在");
82 ErrorCode COMBINATION_RECORD_USER_FULL = new ErrorCode(1_013_011_003, "拼团失败,拼团人数已满"); 82 ErrorCode COMBINATION_RECORD_USER_FULL = new ErrorCode(1_013_011_003, "拼团失败,拼团人数已满");
83 - ErrorCode COMBINATION_RECORD_FAILED_HAVE_JOINED = new ErrorCode(1_013_011_004, "拼团失败,已参与其它拼团"); 83 + ErrorCode COMBINATION_RECORD_FAILED_HAVE_JOINED = new ErrorCode(1_013_011_004, "拼团失败,原因:存在该活动正在进行的拼团记录");
84 ErrorCode COMBINATION_RECORD_FAILED_TIME_NOT_START = new ErrorCode(1_013_011_005, "拼团失败,活动未开始"); 84 ErrorCode COMBINATION_RECORD_FAILED_TIME_NOT_START = new ErrorCode(1_013_011_005, "拼团失败,活动未开始");
85 ErrorCode COMBINATION_RECORD_FAILED_TIME_END = new ErrorCode(1_013_011_006, "拼团失败,活动已经结束"); 85 ErrorCode COMBINATION_RECORD_FAILED_TIME_END = new ErrorCode(1_013_011_006, "拼团失败,活动已经结束");
86 ErrorCode COMBINATION_RECORD_FAILED_SINGLE_LIMIT_COUNT_EXCEED = new ErrorCode(1_013_011_007, "拼团失败,原因:单次限购超出"); 86 ErrorCode COMBINATION_RECORD_FAILED_SINGLE_LIMIT_COUNT_EXCEED = new ErrorCode(1_013_011_007, "拼团失败,原因:单次限购超出");
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/combination/CombinationRecordStatusEnum.java
@@ -40,4 +40,8 @@ public enum CombinationRecordStatusEnum implements IntArrayValuable { @@ -40,4 +40,8 @@ public enum CombinationRecordStatusEnum implements IntArrayValuable {
40 return ObjectUtil.equal(status, SUCCESS.getStatus()); 40 return ObjectUtil.equal(status, SUCCESS.getStatus());
41 } 41 }
42 42
  43 + public static boolean isInProgress(Integer status) {
  44 + return ObjectUtil.equal(status, IN_PROGRESS.getStatus());
  45 + }
  46 +
43 } 47 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApiImpl.java
@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.promotion.api.combination; @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.promotion.api.combination;
2 2
3 import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO; 3 import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO;
4 import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationValidateJoinRespDTO; 4 import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationValidateJoinRespDTO;
  5 +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO;
5 import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum; 6 import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum;
6 import cn.iocoder.yudao.module.promotion.service.combination.CombinationRecordService; 7 import cn.iocoder.yudao.module.promotion.service.combination.CombinationRecordService;
7 import org.springframework.stereotype.Service; 8 import org.springframework.stereotype.Service;
@@ -9,6 +10,9 @@ import org.springframework.stereotype.Service; @@ -9,6 +10,9 @@ import org.springframework.stereotype.Service;
9 import javax.annotation.Resource; 10 import javax.annotation.Resource;
10 import java.time.LocalDateTime; 11 import java.time.LocalDateTime;
11 12
  13 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  14 +import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COMBINATION_RECORD_NOT_EXISTS;
  15 +
12 /** 16 /**
13 * 拼团活动 API 实现类 17 * 拼团活动 API 实现类
14 * 18 *
@@ -21,8 +25,8 @@ public class CombinationRecordApiImpl implements CombinationRecordApi { @@ -21,8 +25,8 @@ public class CombinationRecordApiImpl implements CombinationRecordApi {
21 private CombinationRecordService recordService; 25 private CombinationRecordService recordService;
22 26
23 @Override 27 @Override
24 - public void validateCombinationRecord(Long activityId, Long userId, Long skuId, Integer count) {  
25 - recordService.validateCombinationRecord(activityId, userId, skuId, count); 28 + public void validateCombinationRecord(Long userId, Long activityId, Long headId, Long skuId, Integer count) {
  29 + recordService.validateCombinationRecord(userId, activityId, headId, skuId, count);
26 } 30 }
27 31
28 @Override 32 @Override
@@ -32,7 +36,12 @@ public class CombinationRecordApiImpl implements CombinationRecordApi { @@ -32,7 +36,12 @@ public class CombinationRecordApiImpl implements CombinationRecordApi {
32 36
33 @Override 37 @Override
34 public boolean isCombinationRecordSuccess(Long userId, Long orderId) { 38 public boolean isCombinationRecordSuccess(Long userId, Long orderId) {
35 - return CombinationRecordStatusEnum.isSuccess(recordService.getCombinationRecord(userId, orderId).getStatus()); 39 + CombinationRecordDO combinationRecord = recordService.getCombinationRecord(userId, orderId);
  40 + if (combinationRecord == null) {
  41 + throw exception(COMBINATION_RECORD_NOT_EXISTS);
  42 + }
  43 +
  44 + return CombinationRecordStatusEnum.isSuccess(combinationRecord.getStatus());
36 } 45 }
37 46
38 @Override 47 @Override
@@ -52,8 +61,8 @@ public class CombinationRecordApiImpl implements CombinationRecordApi { @@ -52,8 +61,8 @@ public class CombinationRecordApiImpl implements CombinationRecordApi {
52 } 61 }
53 62
54 @Override 63 @Override
55 - public CombinationValidateJoinRespDTO validateJoinCombination(Long activityId, Long userId, Long skuId, Integer count) {  
56 - return recordService.validateJoinCombination(activityId, userId, skuId, count); 64 + public CombinationValidateJoinRespDTO validateJoinCombination(Long userId, Long activityId, Long headId, Long skuId, Integer count) {
  65 + return recordService.validateJoinCombination(userId, activityId, headId, skuId, count);
57 } 66 }
58 67
59 } 68 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityBaseVO.java
@@ -48,8 +48,9 @@ public class CombinationActivityBaseVO { @@ -48,8 +48,9 @@ public class CombinationActivityBaseVO {
48 @NotNull(message = "开团人数不能为空") 48 @NotNull(message = "开团人数不能为空")
49 private Integer userSize; 49 private Integer userSize;
50 50
51 - @Schema(description = "虚拟成团", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")  
52 - private Boolean virtualGroup = false; // TODO @puhui999:这个字段界面没做呀。 51 + @Schema(description = "虚拟成团", requiredMode = Schema.RequiredMode.REQUIRED, example = "false")
  52 + @NotNull(message = "虚拟成团不能为空")
  53 + private Boolean virtualGroup;
53 54
54 @Schema(description = "限制时长(小时)", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") 55 @Schema(description = "限制时长(小时)", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
55 @NotNull(message = "限制时长不能为空") 56 @NotNull(message = "限制时长不能为空")
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/CombinationRecordMapper.java
@@ -113,7 +113,7 @@ public interface CombinationRecordMapper extends BaseMapperX<CombinationRecordDO @@ -113,7 +113,7 @@ public interface CombinationRecordMapper extends BaseMapperX<CombinationRecordDO
113 // 转换数据 113 // 转换数据
114 return CollectionUtils.convertMap(result, 114 return CollectionUtils.convertMap(result,
115 record -> MapUtil.getLong(record, "activityId"), 115 record -> MapUtil.getLong(record, "activityId"),
116 - record -> MapUtil.getInt(record, "recordCount" )); 116 + record -> MapUtil.getInt(record, "recordCount"));
117 } 117 }
118 118
119 static LocalDateTime[] builderQueryTime(Integer dateType) { 119 static LocalDateTime[] builderQueryTime(Integer dateType) {
@@ -172,4 +172,20 @@ public interface CombinationRecordMapper extends BaseMapperX<CombinationRecordDO @@ -172,4 +172,20 @@ public interface CombinationRecordMapper extends BaseMapperX<CombinationRecordDO
172 .betweenIfPresent(CombinationRecordDO::getCreateTime, builderQueryTime(dateType))); 172 .betweenIfPresent(CombinationRecordDO::getCreateTime, builderQueryTime(dateType)));
173 } 173 }
174 174
  175 + /**
  176 + * 查询指定团长的拼团记录(包括团长)
  177 + *
  178 + * @param activityId 活动编号
  179 + * @param headId 团长编号
  180 + * @return 拼团记录
  181 + */
  182 + default List<CombinationRecordDO> selectList(Long activityId, Long headId) {
  183 + return selectList(new LambdaQueryWrapperX<CombinationRecordDO>()
  184 + .eq(CombinationRecordDO::getActivityId, activityId)
  185 + .eq(CombinationRecordDO::getHeadId, headId)
  186 + .or()
  187 + .eq(CombinationRecordDO::getId, headId));
  188 +
  189 + }
  190 +
175 } 191 }
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordService.java
@@ -32,16 +32,18 @@ public interface CombinationRecordService { @@ -32,16 +32,18 @@ public interface CombinationRecordService {
32 void updateCombinationRecordStatusByUserIdAndOrderId(Integer status, Long userId, Long orderId); 32 void updateCombinationRecordStatusByUserIdAndOrderId(Integer status, Long userId, Long orderId);
33 33
34 /** 34 /**
35 - * 校验是否满足拼团条件  
36 - * 如果不满足,会抛出异常 35 + * 【下单前】校验是否满足拼团活动条件
  36 + *
  37 + * 如果校验失败,则抛出业务异常
37 * 38 *
38 - * @param activityId 活动编号  
39 * @param userId 用户编号 39 * @param userId 用户编号
  40 + * @param activityId 活动编号
  41 + * @param headId 团长编号
40 * @param skuId sku 编号 42 * @param skuId sku 编号
41 * @param count 数量 43 * @param count 数量
42 - * @return 返回拼团活动和拼团活动商品 44 + * @return 拼团信息
43 */ 45 */
44 - KeyValue<CombinationActivityDO, CombinationProductDO> validateCombinationRecord(Long activityId, Long userId, Long skuId, Integer count); 46 + KeyValue<CombinationActivityDO, CombinationProductDO> validateCombinationRecord(Long userId, Long activityId, Long headId, Long skuId, Integer count);
45 47
46 /** 48 /**
47 * 创建拼团记录 49 * 创建拼团记录
@@ -83,13 +85,14 @@ public interface CombinationRecordService { @@ -83,13 +85,14 @@ public interface CombinationRecordService {
83 * 85 *
84 * 如果校验失败,则抛出业务异常 86 * 如果校验失败,则抛出业务异常
85 * 87 *
86 - * @param activityId 活动编号  
87 * @param userId 用户编号 88 * @param userId 用户编号
  89 + * @param activityId 活动编号
  90 + * @param headId 团长编号
88 * @param skuId sku 编号 91 * @param skuId sku 编号
89 * @param count 数量 92 * @param count 数量
90 * @return 拼团信息 93 * @return 拼团信息
91 */ 94 */
92 - CombinationValidateJoinRespDTO validateJoinCombination(Long activityId, Long userId, Long skuId, Integer count); 95 + CombinationValidateJoinRespDTO validateJoinCombination(Long userId, Long activityId, Long headId, Long skuId, Integer count);
93 96
94 /** 97 /**
95 * 获取所有拼团记录数 98 * 获取所有拼团记录数
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordServiceImpl.java
1 package cn.iocoder.yudao.module.promotion.service.combination; 1 package cn.iocoder.yudao.module.promotion.service.combination;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.util.ObjUtil;
4 import cn.hutool.core.util.ObjectUtil; 5 import cn.hutool.core.util.ObjectUtil;
5 import cn.iocoder.yudao.framework.common.core.KeyValue; 6 import cn.iocoder.yudao.framework.common.core.KeyValue;
6 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 7 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
7 import cn.iocoder.yudao.framework.common.pojo.PageResult; 8 import cn.iocoder.yudao.framework.common.pojo.PageResult;
8 -import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils;  
9 import cn.iocoder.yudao.module.member.api.user.MemberUserApi; 9 import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
10 import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; 10 import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
11 import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; 11 import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
@@ -37,6 +37,8 @@ import java.util.Map; @@ -37,6 +37,8 @@ import java.util.Map;
37 37
38 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 38 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
39 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; 39 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
  40 +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.afterNow;
  41 +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.beforeNow;
40 import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; 42 import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
41 43
42 // TODO 芋艿:等拼团记录做完,完整 review 下 44 // TODO 芋艿:等拼团记录做完,完整 review 下
@@ -114,48 +116,83 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { @@ -114,48 +116,83 @@ public class CombinationRecordServiceImpl implements CombinationRecordService {
114 // TODO @芋艿:在详细预览下; 116 // TODO @芋艿:在详细预览下;
115 @Override 117 @Override
116 public KeyValue<CombinationActivityDO, CombinationProductDO> validateCombinationRecord( 118 public KeyValue<CombinationActivityDO, CombinationProductDO> validateCombinationRecord(
117 - Long activityId, Long userId, Long skuId, Integer count) {  
118 - // 1.1 校验拼团活动是否存在 119 + Long userId, Long activityId, Long headId, Long skuId, Integer count) {
  120 + // 1 校验拼团活动是否存在
119 CombinationActivityDO activity = combinationActivityService.validateCombinationActivityExists(activityId); 121 CombinationActivityDO activity = combinationActivityService.validateCombinationActivityExists(activityId);
120 - // 1.2 校验活动是否开启  
121 - if (ObjectUtil.equal(activity.getStatus(), CommonStatusEnum.DISABLE.getStatus())) { 122 + // 1.1 校验活动是否开启
  123 + if (ObjUtil.equal(activity.getStatus(), CommonStatusEnum.DISABLE.getStatus())) {
122 throw exception(COMBINATION_ACTIVITY_STATUS_DISABLE); 124 throw exception(COMBINATION_ACTIVITY_STATUS_DISABLE);
123 } 125 }
124 - // 2 校验是否超出单次限购数量 126 + // 1.2、校验活动开始时间
  127 + if (afterNow(activity.getStartTime())) {
  128 + throw exception(COMBINATION_RECORD_FAILED_TIME_NOT_START);
  129 + }
  130 + // 1.3 校验是否超出单次限购数量
125 if (count > activity.getSingleLimitCount()) { 131 if (count > activity.getSingleLimitCount()) {
126 throw exception(COMBINATION_RECORD_FAILED_SINGLE_LIMIT_COUNT_EXCEED); 132 throw exception(COMBINATION_RECORD_FAILED_SINGLE_LIMIT_COUNT_EXCEED);
127 } 133 }
128 - // 2.1、校验活动商品是否存在 134 +
  135 + // 2、父拼团是否存在,是否已经满了
  136 + if (headId != null) {
  137 + // 2.1、查询进行中的父拼团
  138 + CombinationRecordDO record = recordMapper.selectOneByHeadId(headId, CombinationRecordStatusEnum.IN_PROGRESS.getStatus());
  139 + if (record == null) {
  140 + throw exception(COMBINATION_RECORD_HEAD_NOT_EXISTS);
  141 + }
  142 + // 2.2、校验拼团是否满足要求
  143 + if (ObjUtil.equal(record.getUserCount(), record.getUserSize())) {
  144 + throw exception(COMBINATION_RECORD_USER_FULL);
  145 + }
  146 + // 2.3、校验拼团是否过期
  147 + if (beforeNow(record.getExpireTime())) {
  148 + throw exception(COMBINATION_RECORD_FAILED_TIME_END);
  149 + }
  150 + }
  151 +
  152 + // 3、校验当前活动是否结束
  153 + if (beforeNow(activity.getEndTime())) {
  154 + throw exception(COMBINATION_RECORD_FAILED_TIME_END);
  155 + }
  156 +
  157 + // 4、校验活动商品是否存在
129 CombinationProductDO product = combinationActivityService.selectByActivityIdAndSkuId(activityId, skuId); 158 CombinationProductDO product = combinationActivityService.selectByActivityIdAndSkuId(activityId, skuId);
130 if (product == null) { 159 if (product == null) {
131 throw exception(COMBINATION_JOIN_ACTIVITY_PRODUCT_NOT_EXISTS); 160 throw exception(COMBINATION_JOIN_ACTIVITY_PRODUCT_NOT_EXISTS);
132 } 161 }
133 - // 2.2、校验 sku 是否存在 162 +
  163 + // 5、校验 sku 是否存在
134 ProductSkuRespDTO sku = productSkuApi.getSku(skuId); 164 ProductSkuRespDTO sku = productSkuApi.getSku(skuId);
135 if (sku == null) { 165 if (sku == null) {
136 throw exception(COMBINATION_JOIN_ACTIVITY_PRODUCT_NOT_EXISTS); 166 throw exception(COMBINATION_JOIN_ACTIVITY_PRODUCT_NOT_EXISTS);
137 } 167 }
138 - // 2.3、 校验库存是否充足 168 + // 5.1、校验库存是否充足
139 if (count > sku.getStock()) { 169 if (count > sku.getStock()) {
140 throw exception(COMBINATION_ACTIVITY_UPDATE_STOCK_FAIL); 170 throw exception(COMBINATION_ACTIVITY_UPDATE_STOCK_FAIL);
141 } 171 }
142 - // 3、校验是否有拼团记录 172 +
  173 + // 6、校验是否有拼团记录
143 List<CombinationRecordDO> recordList = getCombinationRecordListByUserIdAndActivityId(userId, activityId); 174 List<CombinationRecordDO> recordList = getCombinationRecordListByUserIdAndActivityId(userId, activityId);
144 if (CollUtil.isEmpty(recordList)) { 175 if (CollUtil.isEmpty(recordList)) {
145 return new KeyValue<>(activity, product); 176 return new KeyValue<>(activity, product);
146 } 177 }
147 - // 4、校验是否超出总限购数量 178 + // 6.1、校验用户是否有该活动正在进行的拼团
  179 + List<CombinationRecordDO> filtered = filterList(recordList, record -> CombinationRecordStatusEnum.isInProgress(record.getStatus()));
  180 + if (CollUtil.isNotEmpty(filtered)) {
  181 + throw exception(COMBINATION_RECORD_FAILED_HAVE_JOINED);
  182 + }
  183 + // 6.2、校验是否超出总限购数量
148 Integer sumValue = getSumValue(convertList(recordList, CombinationRecordDO::getCount, 184 Integer sumValue = getSumValue(convertList(recordList, CombinationRecordDO::getCount,
149 - item -> ObjectUtil.equals(item.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus())), i -> i, Integer::sum); 185 + item -> CombinationRecordStatusEnum.isSuccess(item.getStatus())), i -> i, Integer::sum);
150 if ((sumValue + count) > activity.getTotalLimitCount()) { 186 if ((sumValue + count) > activity.getTotalLimitCount()) {
151 throw exception(COMBINATION_RECORD_FAILED_TOTAL_LIMIT_COUNT_EXCEED); 187 throw exception(COMBINATION_RECORD_FAILED_TOTAL_LIMIT_COUNT_EXCEED);
152 } 188 }
153 - // 5、校验拼团记录是否存在未支付的订单(如果存在未支付的订单则不允许发起新的拼团) 189 +
  190 + // 7、校验拼团记录是否存在未支付的订单(如果存在未支付的订单则不允许发起新的拼团)
154 CombinationRecordDO record = findFirst(recordList, item -> ObjectUtil.equals(item.getStatus(), null)); 191 CombinationRecordDO record = findFirst(recordList, item -> ObjectUtil.equals(item.getStatus(), null));
155 if (record == null) { 192 if (record == null) {
156 return new KeyValue<>(activity, product); 193 return new KeyValue<>(activity, product);
157 } 194 }
158 - // 5.1、查询关联的订单是否已经支付 195 + // 7.1、查询关联的订单是否已经支付
159 // 当前 activityId 已经有未支付的订单,不允许在发起新的;要么支付,要么去掉先; 196 // 当前 activityId 已经有未支付的订单,不允许在发起新的;要么支付,要么去掉先;
160 // TODO 芋艿:看看是不是可以删除掉; 197 // TODO 芋艿:看看是不是可以删除掉;
161 Integer orderStatus = tradeOrderApi.getOrderStatus(record.getOrderId()); 198 Integer orderStatus = tradeOrderApi.getOrderStatus(record.getOrderId());
@@ -171,46 +208,19 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { @@ -171,46 +208,19 @@ public class CombinationRecordServiceImpl implements CombinationRecordService {
171 @Transactional(rollbackFor = Exception.class) 208 @Transactional(rollbackFor = Exception.class)
172 public void createCombinationRecord(CombinationRecordCreateReqDTO reqDTO) { 209 public void createCombinationRecord(CombinationRecordCreateReqDTO reqDTO) {
173 // 1、校验拼团活动 210 // 1、校验拼团活动
174 - KeyValue<CombinationActivityDO, CombinationProductDO> keyValue = validateCombinationRecord(  
175 - reqDTO.getActivityId(), reqDTO.getUserId(), reqDTO.getSkuId(), reqDTO.getCount());  
176 - CombinationActivityDO activity = keyValue.getKey();  
177 - // 2、校验用户是否参加了其它拼团  
178 - List<CombinationRecordDO> recordDOList = recordMapper.selectListByUserIdAndStatus(reqDTO.getUserId(), CombinationRecordStatusEnum.IN_PROGRESS.getStatus());  
179 - if (CollUtil.isNotEmpty(recordDOList)) {  
180 - throw exception(COMBINATION_RECORD_FAILED_HAVE_JOINED);  
181 - }  
182 - // 3、校验活动是否开启  
183 - if (!LocalDateTimeUtils.beforeNow(activity.getStartTime())) {  
184 - throw exception(COMBINATION_RECORD_FAILED_TIME_NOT_START);  
185 - }  
186 - // 4、校验当前活动是否过期  
187 - if (LocalDateTime.now().isAfter(activity.getEndTime())) {  
188 - throw exception(COMBINATION_RECORD_FAILED_TIME_END);  
189 - }  
190 - // 5、父拼团是否存在,是否已经满了  
191 - if (reqDTO.getHeadId() != null) {  
192 - // 5.1、查询进行中的父拼团  
193 - CombinationRecordDO record = recordMapper.selectOneByHeadId(reqDTO.getHeadId(), CombinationRecordStatusEnum.IN_PROGRESS.getStatus());  
194 - if (record == null) {  
195 - throw exception(COMBINATION_RECORD_HEAD_NOT_EXISTS);  
196 - }  
197 - // 5.2、校验拼团是否满足要求  
198 - if (ObjectUtil.equal(record.getUserCount(), record.getUserSize())) {  
199 - throw exception(COMBINATION_RECORD_USER_FULL);  
200 - }  
201 - } 211 + KeyValue<CombinationActivityDO, CombinationProductDO> keyValue = validateCombinationRecord(reqDTO.getUserId(),
  212 + reqDTO.getActivityId(), reqDTO.getHeadId(), reqDTO.getSkuId(), reqDTO.getCount());
202 213
203 - // 6. 创建拼团记录 214 + // 2. 组合数据创建拼团记录
204 MemberUserRespDTO user = memberUserApi.getUser(reqDTO.getUserId()); 215 MemberUserRespDTO user = memberUserApi.getUser(reqDTO.getUserId());
205 ProductSpuRespDTO spu = productSpuApi.getSpu(reqDTO.getSpuId()); 216 ProductSpuRespDTO spu = productSpuApi.getSpu(reqDTO.getSpuId());
206 ProductSkuRespDTO sku = productSkuApi.getSku(reqDTO.getSkuId()); 217 ProductSkuRespDTO sku = productSkuApi.getSku(reqDTO.getSkuId());
207 - recordMapper.insert(CombinationActivityConvert.INSTANCE.convert(reqDTO, activity, user, spu, sku)); 218 + recordMapper.insert(CombinationActivityConvert.INSTANCE.convert(reqDTO, keyValue.getKey(), user, spu, sku));
208 } 219 }
209 220
210 @Override 221 @Override
211 public CombinationRecordDO getCombinationRecord(Long userId, Long orderId) { 222 public CombinationRecordDO getCombinationRecord(Long userId, Long orderId) {
212 - // TODO puhui999:这里直接获得,不适合调用校验的接口;  
213 - return validateCombinationRecord(userId, orderId); 223 + return recordMapper.selectByUserIdAndOrderId(userId, orderId);
214 } 224 }
215 225
216 @Override 226 @Override
@@ -219,8 +229,8 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { @@ -219,8 +229,8 @@ public class CombinationRecordServiceImpl implements CombinationRecordService {
219 } 229 }
220 230
221 @Override 231 @Override
222 - public CombinationValidateJoinRespDTO validateJoinCombination(Long activityId, Long userId, Long skuId, Integer count) {  
223 - KeyValue<CombinationActivityDO, CombinationProductDO> keyValue = validateCombinationRecord(activityId, userId, skuId, count); 232 + public CombinationValidateJoinRespDTO validateJoinCombination(Long userId, Long activityId, Long headId, Long skuId, Integer count) {
  233 + KeyValue<CombinationActivityDO, CombinationProductDO> keyValue = validateCombinationRecord(userId, activityId, headId, skuId, count);
224 return new CombinationValidateJoinRespDTO() 234 return new CombinationValidateJoinRespDTO()
225 .setActivityId(keyValue.getKey().getId()) 235 .setActivityId(keyValue.getKey().getId())
226 .setName(keyValue.getKey().getName()) 236 .setName(keyValue.getKey().getName())
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeCombinationHandler.java
@@ -34,7 +34,8 @@ public class TradeCombinationHandler implements TradeOrderHandler { @@ -34,7 +34,8 @@ public class TradeCombinationHandler implements TradeOrderHandler {
34 // 获取商品信息 34 // 获取商品信息
35 TradeOrderItemDO item = orderItems.get(0); 35 TradeOrderItemDO item = orderItems.get(0);
36 // 校验是否满足拼团活动相关限制 36 // 校验是否满足拼团活动相关限制
37 - combinationRecordApi.validateCombinationRecord(order.getCombinationActivityId(), order.getUserId(), item.getSkuId(), item.getCount()); 37 + combinationRecordApi.validateCombinationRecord(order.getUserId(), order.getCombinationActivityId(),
  38 + order.getCombinationHeadId(), item.getSkuId(), item.getCount());
38 } 39 }
39 40
40 @Override 41 @Override
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeCombinationActivityPriceCalculator.java
@@ -13,6 +13,7 @@ import org.springframework.stereotype.Component; @@ -13,6 +13,7 @@ import org.springframework.stereotype.Component;
13 import javax.annotation.Resource; 13 import javax.annotation.Resource;
14 14
15 // TODO @puhui999:单测可以后补下 15 // TODO @puhui999:单测可以后补下
  16 +
16 /** 17 /**
17 * 拼团活动的 {@link TradePriceCalculator} 实现类 18 * 拼团活动的 {@link TradePriceCalculator} 实现类
18 * 19 *
@@ -35,7 +36,7 @@ public class TradeCombinationActivityPriceCalculator implements TradePriceCalcul @@ -35,7 +36,7 @@ public class TradeCombinationActivityPriceCalculator implements TradePriceCalcul
35 // 2. 校验是否可以参与拼团 36 // 2. 校验是否可以参与拼团
36 TradePriceCalculateRespBO.OrderItem orderItem = result.getItems().get(0); 37 TradePriceCalculateRespBO.OrderItem orderItem = result.getItems().get(0);
37 CombinationValidateJoinRespDTO combinationActivity = combinationRecordApi.validateJoinCombination( 38 CombinationValidateJoinRespDTO combinationActivity = combinationRecordApi.validateJoinCombination(
38 - param.getCombinationActivityId(), param.getUserId(), 39 + param.getUserId(), param.getCombinationActivityId(), param.getCombinationHeadId(),
39 orderItem.getSkuId(), orderItem.getCount()); 40 orderItem.getSkuId(), orderItem.getCount());
40 41
41 // 3.1 记录优惠明细 42 // 3.1 记录优惠明细