diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java index 414c0af7d..92604e94c 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java @@ -93,4 +93,44 @@ public class LocalDateTimeUtils { LocalDateTime.of(nowDate, startTime2), LocalDateTime.of(nowDate, endTime2)); } + /** + * 构建日期时间 TODO 后面有需要的话再继续扩展 + * + * @author HUIHUI + */ + public static class BuilderDateTime { + + /** + * 日期;2023-10-01 + */ + private String localDate; + /** + * 时间;10:01:00 + */ + private String localTime; + + public BuilderDateTime() { + } + + public BuilderDateTime withDate(String date) { + this.localDate = date; + return this; + } + + public BuilderDateTime withDate(LocalDateTime date) { + this.localDate = LocalDateTimeUtil.format(date, "yyyy-MM-dd"); + return this; + } + + public BuilderDateTime withTime(String time) { + this.localTime = time; + return this; + } + + public LocalDateTime build() { + return LocalDateTimeUtil.parse(this.localDate + " " + this.localTime, "yyyy-MM-dd HH:mm:ss"); + } + + } + } diff --git a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImplTest.java b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImplTest.java index 2f55af837..fb6bc3649 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImplTest.java +++ b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImplTest.java @@ -16,7 +16,6 @@ import cn.iocoder.yudao.module.product.dal.mysql.comment.ProductCommentMapper; import cn.iocoder.yudao.module.product.enums.comment.ProductCommentScoresEnum; import cn.iocoder.yudao.module.product.service.sku.ProductSkuService; import cn.iocoder.yudao.module.product.service.spu.ProductSpuService; -import cn.iocoder.yudao.module.trade.api.order.TradeOrderApi; import org.junit.jupiter.api.Test; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Import; @@ -48,8 +47,6 @@ public class ProductCommentServiceImplTest extends BaseDbUnitTest { @Lazy private ProductCommentServiceImpl productCommentService; - @MockBean - private TradeOrderApi tradeOrderApi; @MockBean private ProductSpuService productSpuService; @MockBean diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationActivityApi.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationActivityApi.java index ad78aaa0d..a5163cdf1 100644 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationActivityApi.java +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationActivityApi.java @@ -7,14 +7,4 @@ package cn.iocoder.yudao.module.promotion.api.combination; */ public interface CombinationActivityApi { - /** - * 校验是否满足拼团条件 - * - * @param activityId 活动编号 - * @param userId 用户编号 - * @param skuId sku 编号 - * @param count 数量 - */ - void validateCombination(Long activityId, Long userId, Long skuId, Integer count); - } diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApi.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApi.java index bf70bb29c..5a144a75a 100644 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApi.java +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApi.java @@ -14,6 +14,16 @@ import java.time.LocalDateTime; */ public interface CombinationRecordApi { + /** + * 校验是否满足拼团条件 + * + * @param activityId 活动编号 + * @param userId 用户编号 + * @param skuId sku 编号 + * @param count 数量 + */ + void validateCombinationRecord(Long activityId, Long userId, Long skuId, Integer count); + /** * 创建开团记录 * diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java index 4fc58004a..c63928fbd 100644 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java @@ -75,9 +75,10 @@ public interface ErrorCodeConstants { ErrorCode COMBINATION_RECORD_HEAD_NOT_EXISTS = new ErrorCode(1013011002, "拼团失败,父拼团不存在"); ErrorCode COMBINATION_RECORD_USER_FULL = new ErrorCode(1013011003, "拼团失败,拼团人数已满"); ErrorCode COMBINATION_RECORD_FAILED_HAVE_JOINED = new ErrorCode(1013011004, "拼团失败,已参与其它拼团"); - ErrorCode COMBINATION_RECORD_FAILED_TIME_END = new ErrorCode(1013011005, "拼团失败,活动已经结束"); - ErrorCode COMBINATION_RECORD_FAILED_SINGLE_LIMIT_COUNT_EXCEED = new ErrorCode(1013011006, "拼团失败,原因:单次限购超出"); - ErrorCode COMBINATION_RECORD_FAILED_TOTAL_LIMIT_COUNT_EXCEED = new ErrorCode(1013011007, "拼团失败,原因:超出总购买次数"); + ErrorCode COMBINATION_RECORD_FAILED_TIME_NOT_START = new ErrorCode(1013011005, "拼团失败,活动未开始"); + ErrorCode COMBINATION_RECORD_FAILED_TIME_END = new ErrorCode(1013011006, "拼团失败,活动已经结束"); + ErrorCode COMBINATION_RECORD_FAILED_SINGLE_LIMIT_COUNT_EXCEED = new ErrorCode(1013011007, "拼团失败,原因:单次限购超出"); + ErrorCode COMBINATION_RECORD_FAILED_TOTAL_LIMIT_COUNT_EXCEED = new ErrorCode(1013011008, "拼团失败,原因:超出总购买次数"); // ========== 砍价活动 1013012000 ========== ErrorCode BARGAIN_ACTIVITY_NOT_EXISTS = new ErrorCode(1013012000, "砍价活动不存在"); diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationActivityApiImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationActivityApiImpl.java index 14eb9dd41..967ce6101 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationActivityApiImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationActivityApiImpl.java @@ -1,10 +1,7 @@ package cn.iocoder.yudao.module.promotion.api.combination; -import cn.iocoder.yudao.module.promotion.service.combination.CombinationActivityService; import org.springframework.stereotype.Service; -import javax.annotation.Resource; - /** * 拼团活动 Api 接口实现类 * @@ -13,12 +10,4 @@ import javax.annotation.Resource; @Service public class CombinationActivityApiImpl implements CombinationActivityApi { - @Resource - private CombinationActivityService activityService; - - @Override - public void validateCombination(Long activityId, Long userId, Long skuId, Integer count) { - activityService.validateCombination(activityId, userId, skuId, count); - } - } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApiImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApiImpl.java index 24d42482a..8f7ce2e24 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApiImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApiImpl.java @@ -19,6 +19,11 @@ public class CombinationRecordApiImpl implements CombinationRecordApi { @Resource private CombinationRecordService recordService; + @Override + public void validateCombinationRecord(Long activityId, Long userId, Long skuId, Integer count) { + recordService.validateCombinationRecord(activityId, userId, skuId, count); + } + @Override public void createCombinationRecord(CombinationRecordCreateReqDTO reqDTO) { recordService.createCombinationRecord(reqDTO); diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckillactivity/SeckillActivityConvert.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckillactivity/SeckillActivityConvert.java index f2e5ff50a..7c7457155 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckillactivity/SeckillActivityConvert.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckillactivity/SeckillActivityConvert.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.promotion.convert.seckill.seckillactivity; -import cn.hutool.core.date.LocalDateTimeUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils; import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; import cn.iocoder.yudao.module.product.enums.DictTypeConstants; @@ -129,11 +129,14 @@ public interface SeckillActivityConvert { default AppSeckillActivityDetailRespVO convert3(SeckillActivityDO seckillActivity, List products, SeckillConfigDO filteredConfig) { return convert2(seckillActivity) .setProducts(convertList1(products)) - // TODO @puhui999:要不要在里面 default 一个方法,处理这个事件;简洁一点; - .setStartTime(LocalDateTimeUtil.parse(LocalDateTimeUtil.format(seckillActivity.getStartTime(), "yyyy-MM-dd") + " " + filteredConfig.getStartTime(), - "yyyy-MM-dd HH:mm:ss")) // 活动开始日期和时段结合 - .setEndTime(LocalDateTimeUtil.parse(LocalDateTimeUtil.format(seckillActivity.getEndTime(), "yyyy-MM-dd") + " " + filteredConfig.getEndTime(), - "yyyy-MM-dd HH:mm:ss")); // 活动结束日期和时段结合 + .setStartTime(new LocalDateTimeUtils.BuilderDateTime() + .withDate(seckillActivity.getStartTime()) + .withTime(filteredConfig.getStartTime()) + .build())// 活动开始日期和时段结合 + .setEndTime(new LocalDateTimeUtils.BuilderDateTime() + .withDate(seckillActivity.getEndTime()) + .withTime(filteredConfig.getEndTime()) + .build()); // 活动结束日期和时段结合 } List convertList4(List seckillActivityProductList); diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/CombinationRecordMapper.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/CombinationRecordMapper.java index 218a24897..b1ccfc858 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/CombinationRecordMapper.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/CombinationRecordMapper.java @@ -20,6 +20,10 @@ public interface CombinationRecordMapper extends BaseMapperX selectListByUserId(Long userId) { + return selectList(CombinationRecordDO::getUserId, userId); + } + default List selectListByUserIdAndStatus(Long userId, Integer status) { return selectList(new LambdaQueryWrapperX() .eq(CombinationRecordDO::getUserId, userId) diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityService.java index c5f72e6a6..e3efbfaa5 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityService.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityService.java @@ -84,17 +84,6 @@ public interface CombinationActivityService { */ List getCombinationProductsByActivityIds(Collection activityIds); - /** - * 校验是否满足拼团条件 - * 如果不满足,会抛出异常 - * - * @param activityId 活动编号 - * @param userId 用户编号 - * @param skuId sku 编号 - * @param count 数量 - */ - void validateCombination(Long activityId, Long userId, Long skuId, Integer count); - /** * 获取正在进行的活动分页数据 * diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImpl.java index 2dc715039..41b72233a 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImpl.java @@ -17,12 +17,8 @@ import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert; import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationProductDO; -import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO; import cn.iocoder.yudao.module.promotion.dal.mysql.combination.CombinationActivityMapper; import cn.iocoder.yudao.module.promotion.dal.mysql.combination.CombinationProductMapper; -import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum; -import cn.iocoder.yudao.module.trade.api.order.TradeOrderApi; -import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; @@ -33,7 +29,8 @@ import java.util.List; import java.util.Map; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList; import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS; import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS; import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; @@ -53,16 +50,10 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic @Resource private CombinationProductMapper combinationProductMapper; - @Resource - @Lazy // TODO @puhui999:我感觉 validateCombination 可以挪到 CombinationRecordServiceImpl 中,因为它更偏向能不能创建拼团记录; - private CombinationRecordService combinationRecordService; - @Resource private ProductSpuApi productSpuApi; @Resource private ProductSkuApi productSkuApi; - @Resource - private TradeOrderApi tradeOrderApi; @Override @Transactional(rollbackFor = Exception.class) @@ -215,36 +206,6 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic return combinationProductMapper.selectListByActivityIds(activityIds); } - @Override - public void validateCombination(Long activityId, Long userId, Long skuId, Integer count) { - // 1.1 校验拼团活动是否存在 - CombinationActivityDO activity = validateCombinationActivityExists(activityId); - // 1.2 校验活动是否开启 - if (ObjectUtil.equal(activity.getStatus(), CommonStatusEnum.DISABLE.getStatus())) { - throw exception(COMBINATION_ACTIVITY_STATUS_DISABLE); - } - // 1.3 校验是否超出单次限购数量 - if (count > activity.getSingleLimitCount()) { - throw exception(COMBINATION_RECORD_FAILED_SINGLE_LIMIT_COUNT_EXCEED); - } - - // 2. 校验是否超出总限购数量 - List recordList = combinationRecordService.getRecordListByUserIdAndActivityId(userId, activityId); - if (CollUtil.isEmpty(recordList)) { - return; - } - // 过滤出拼团成功的 - // TODO @puhui999:count 要不存一个在 record 里? - List skuIds = convertList(recordList, CombinationRecordDO::getSkuId, - item -> ObjectUtil.equals(item.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus())); - Integer countSum = tradeOrderApi.getOrderItemCountSumByOrderIdAndSkuId(convertList(recordList, - CombinationRecordDO::getOrderId, - item -> ObjectUtil.equals(item.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus())), skuIds); - if (activity.getTotalLimitCount() < countSum) { - throw exception(COMBINATION_RECORD_FAILED_TOTAL_LIMIT_COUNT_EXCEED); - } - } - @Override public List getCombinationActivityListByCount(Integer count) { return combinationActivityMapper.selectListByStatus(CommonStatusEnum.ENABLE.getStatus(), count); diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordService.java index e75440edd..e2e26124b 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordService.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordService.java @@ -22,6 +22,17 @@ public interface CombinationRecordService { */ void updateCombinationRecordStatusByUserIdAndOrderId(Integer status, Long userId, Long orderId); + /** + * 校验是否满足拼团条件 + * 如果不满足,会抛出异常 + * + * @param activityId 活动编号 + * @param userId 用户编号 + * @param skuId sku 编号 + * @param count 数量 + */ + void validateCombinationRecord(Long activityId, Long userId, Long skuId, Integer count); + /** * 创建拼团记录 * diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordServiceImpl.java index 047e060a9..caf5d86b8 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordServiceImpl.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.promotion.service.combination; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.module.member.api.user.MemberUserApi; import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; @@ -14,6 +15,7 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationA import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO; import cn.iocoder.yudao.module.promotion.dal.mysql.combination.CombinationRecordMapper; import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum; +import cn.iocoder.yudao.module.trade.api.order.TradeOrderApi; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -24,6 +26,7 @@ import java.time.LocalDateTime; import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; // TODO 芋艿:等拼团记录做完,完整 review 下 @@ -51,6 +54,8 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { @Resource @Lazy private ProductSkuApi productSkuApi; + @Resource + private TradeOrderApi tradeOrderApi; @Override @Transactional(rollbackFor = Exception.class) @@ -97,6 +102,35 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { } // TODO @puhui999:有一个应该在创建那要做下;就是当前 activityId 已经有未支付的订单,不允许在发起新的;要么支付,要么去掉先; + @Override + public void validateCombinationRecord(Long activityId, Long userId, Long skuId, Integer count) { + // 1.1 校验拼团活动是否存在 + CombinationActivityDO activity = combinationActivityService.validateCombinationActivityExists(activityId); + // 1.2 校验活动是否开启 + if (ObjectUtil.equal(activity.getStatus(), CommonStatusEnum.DISABLE.getStatus())) { + throw exception(COMBINATION_ACTIVITY_STATUS_DISABLE); + } + // 1.3 校验是否超出单次限购数量 + if (count > activity.getSingleLimitCount()) { + throw exception(COMBINATION_RECORD_FAILED_SINGLE_LIMIT_COUNT_EXCEED); + } + + // 2. 校验是否超出总限购数量 + List recordList = getRecordListByUserIdAndActivityId(userId, activityId); + if (CollUtil.isEmpty(recordList)) { + return; + } + // 过滤出拼团成功的 + // TODO @puhui999:count 要不存一个在 record 里? + List skuIds = convertList(recordList, CombinationRecordDO::getSkuId, + item -> ObjectUtil.equals(item.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus())); + Integer countSum = tradeOrderApi.getOrderItemCountSumByOrderIdAndSkuId(convertList(recordList, + CombinationRecordDO::getOrderId, + item -> ObjectUtil.equals(item.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus())), skuIds); + if (activity.getTotalLimitCount() < countSum) { + throw exception(COMBINATION_RECORD_FAILED_TOTAL_LIMIT_COUNT_EXCEED); + } + } @Override @Transactional(rollbackFor = Exception.class) @@ -105,21 +139,26 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { CombinationActivityDO activity = combinationActivityService.validateCombinationActivityExists(reqDTO.getActivityId()); // 1.2 需要校验下,他当前是不是已经参加了该拼团; // TODO @puhui999:拼团应该可以重复参加;应该去校验总共的上限哈,就是 activity.totalLimitCount - CombinationRecordDO recordDO = recordMapper.selectByUserIdAndOrderId(reqDTO.getUserId(), reqDTO.getOrderId()); - if (recordDO != null) { - throw exception(COMBINATION_RECORD_EXISTS); + List records = recordMapper.selectListByUserId(reqDTO.getUserId()); + List orderIds = convertList(records, CombinationRecordDO::getOrderId); + // 1.2.1 如果存在订单才去校验 + if (CollUtil.isNotEmpty(orderIds)) { + } // 1.3 校验用户是否参加了其它拼团 List recordDOList = recordMapper.selectListByUserIdAndStatus(reqDTO.getUserId(), CombinationRecordStatusEnum.IN_PROGRESS.getStatus()); if (CollUtil.isNotEmpty(recordDOList)) { throw exception(COMBINATION_RECORD_FAILED_HAVE_JOINED); } - // TODO @puhui999:有个开始时间未校验 - // 1.4 校验当前活动是否过期 + // 1、4 校验活动是否开启 + if (LocalDateTime.now().isAfter(activity.getStartTime())) { + throw exception(COMBINATION_RECORD_FAILED_TIME_NOT_START); + } + // 1.5 校验当前活动是否过期 if (LocalDateTime.now().isAfter(activity.getEndTime())) { throw exception(COMBINATION_RECORD_FAILED_TIME_END); } - // 1.5 父拼团是否存在,是否已经满了 + // 1.6 父拼团是否存在,是否已经满了 if (reqDTO.getHeadId() != null) { // 查询进行中的父拼团 CombinationRecordDO record = recordMapper.selectOneByHeadId(reqDTO.getHeadId(), CombinationRecordStatusEnum.IN_PROGRESS.getStatus()); diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java index 42e77fc4b..85f700dd4 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java @@ -56,6 +56,7 @@ import cn.iocoder.yudao.module.trade.service.cart.CartService; import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressService; import cn.iocoder.yudao.module.trade.service.message.TradeMessageService; import cn.iocoder.yudao.module.trade.service.message.bo.TradeOrderMessageWhenDeliveryOrderReqBO; +import cn.iocoder.yudao.module.trade.service.order.bo.TradeAfterPayOrderReqBO; import cn.iocoder.yudao.module.trade.service.order.bo.TradeBeforeOrderCreateReqBO; import cn.iocoder.yudao.module.trade.service.order.handler.TradeOrderHandler; import cn.iocoder.yudao.module.trade.service.price.TradePriceService; @@ -333,13 +334,9 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { if (updateCount == 0) { throw exception(ORDER_UPDATE_PAID_STATUS_NOT_UNPAID); } - // 校验活动 - // 1、拼团活动 - // TODO @puhui999:这块也抽象到 handler 里 - if (Objects.equals(TradeOrderTypeEnum.COMBINATION.getType(), order.getType())) { - // 更新拼团状态 TODO puhui999:订单支付失败或订单支付过期删除这条拼团记录 - combinationRecordApi.updateRecordStatusToInProgress(order.getUserId(), order.getId(), LocalDateTime.now()); - } + // 订单支付成功后 + tradeOrderHandlers.forEach(tradeOrderHandler -> tradeOrderHandler.afterPayOrder(new TradeAfterPayOrderReqBO() + .setOrderId(order.getId()).setOrderType(order.getType()).setUserId(order.getUserId()).setPayTime(LocalDateTime.now()))); // TODO 芋艿:发送订单变化的消息 // TODO 芋艿:发送站内信 @@ -742,7 +739,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { } // 3. TODO 活动相关库存回滚需要活动 id,活动 id 怎么获取?app 端能否传过来;回复:从订单里拿呀 - tradeOrderHandlers.forEach(handler -> handler.rollback()); + tradeOrderHandlers.forEach(handler -> handler.cancelOrder()); // 4. 回滚库存 List orderItems = tradeOrderItemMapper.selectListByOrderId(id); diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/TradeAfterPayOrderReqBO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/TradeAfterPayOrderReqBO.java new file mode 100644 index 000000000..42aba4380 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/TradeAfterPayOrderReqBO.java @@ -0,0 +1,43 @@ +package cn.iocoder.yudao.module.trade.service.order.bo; + +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 订单支付后 Request BO + * + * @author HUIHUI + */ +@Data +public class TradeAfterPayOrderReqBO { + + /** + * 订单编号 + */ + @Schema(description = "订单编号", example = "6") + private Long orderId; + + /** + * 订单类型 + * + * 枚举 {@link TradeOrderTypeEnum} + */ + @Schema(description = "订单类型", example = "3") + private Integer orderType; + + /** + * 用户编号 + */ + @Schema(description = "用户编号", example = "11") + private Long userId; + + /** + * 订单支付时间 + */ + @Schema(description = "订单支付时间", example = "2023-08-15 10:00:00") + private LocalDateTime payTime; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeSeckillActivityPriceCalculator.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeSeckillActivityPriceCalculator.java index 5d33bc286..95996ab9f 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeSeckillActivityPriceCalculator.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeSeckillActivityPriceCalculator.java @@ -1,9 +1,7 @@ package cn.iocoder.yudao.module.trade.service.price.calculator; -import cn.hutool.core.util.ObjectUtil; import cn.iocoder.yudao.module.promotion.api.seckill.SeckillActivityApi; import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillActivityProductRespDTO; -import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; import org.springframework.core.annotation.Order; @@ -31,7 +29,7 @@ public class TradeSeckillActivityPriceCalculator implements TradePriceCalculator @Override public void calculate(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result) { // 1、判断订单类型和是否具有秒杀活动编号 - if (ObjectUtil.notEqual(param.getType(), TradeOrderTypeEnum.SECKILL.getType()) && param.getSeckillActivityId() == null) { + if (param.getSeckillActivityId() == null) { return; } // 2、获取秒杀活动商品信息