From ab30ff64804ee892cadccaa36ed70fac48abf590 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Fri, 23 Jun 2023 00:57:27 +0800 Subject: [PATCH] =?UTF-8?q?fix=EF=BC=9A=E5=AE=8C=E5=96=84=20mall=20seckill?= =?UTF-8?q?=20=E7=9B=B8=E5=85=B3=20=E2=91=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/product/api/sku/ProductSkuApi.java | 10 +- .../product/api/sku/ProductSkuApiImpl.java | 9 ++ .../product/api/spu/ProductSpuApiImpl.java | 9 +- .../service/sku/ProductSkuService.java | 9 +- .../vo/activity/SeckillActivityBaseVO.java | 15 +-- .../vo/activity/SeckillActivityRespVO.java | 5 +- .../vo/product/SeckillProductBaseVO.java | 30 +---- .../SeckillActivityConvert.java | 24 +++- .../seckillactivity/SeckillActivityDO.java | 4 +- .../seckillactivity/SeckillProductDO.java | 17 ++- .../SeckillActivityMapper.java | 7 + .../discount/DiscountActivityServiceImpl.java | 4 +- .../reward/RewardActivityServiceImpl.java | 4 +- .../SeckillActivityServiceImpl.java | 127 +++++++++++------- .../module/promotion/util/PromotionUtils.java | 13 +- 15 files changed, 167 insertions(+), 120 deletions(-) diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApi.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApi.java index d5d93dc37..6be0ae0af 100644 --- a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApi.java +++ b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApi.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.product.api.sku; -import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO; import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; +import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO; import java.util.Collection; import java.util.List; @@ -30,6 +30,14 @@ public interface ProductSkuApi { */ List getSkuList(Collection ids); + /** + * 批量查询 SKU 数组 + * + * @param spuIds SPU 编号列表 + * @return SKU 数组 + */ + List getSkuListBySpuId(List spuIds); + /** * 更新 SKU 库存 * diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApiImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApiImpl.java index 6bec2a74c..4a8425f61 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApiImpl.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApiImpl.java @@ -42,6 +42,15 @@ public class ProductSkuApiImpl implements ProductSkuApi { return ProductSkuConvert.INSTANCE.convertList04(skus); } + @Override + public List getSkuListBySpuId(List spuIds) { + if (CollUtil.isEmpty(spuIds)) { + return Collections.emptyList(); + } + List skus = productSkuService.getSkuListBySpuId(spuIds); + return ProductSkuConvert.INSTANCE.convertList04(skus); + } + @Override public void updateSkuStock(ProductSkuUpdateStockReqDTO updateStockReqDTO) { productSkuService.updateSkuStock(updateStockReqDTO); diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/spu/ProductSpuApiImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/spu/ProductSpuApiImpl.java index 4d880e662..0055f2aaf 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/spu/ProductSpuApiImpl.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/spu/ProductSpuApiImpl.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.product.api.spu; -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.hutool.core.collection.CollectionUtil; import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert; import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; @@ -14,7 +14,7 @@ import java.util.Collections; import java.util.List; /** - * TODO LeeYan9: 类注释; + * 商品 SPU API 接口实现类 * * @author LeeYan9 * @since 2022-09-06 @@ -28,11 +28,12 @@ public class ProductSpuApiImpl implements ProductSpuApi { @Override public List getSpuList(Collection spuIds) { - // TODO TODO LeeYan9: AllEmpty? - if (CollectionUtils.isAnyEmpty(spuIds)) { + // TODO 需不需要判断集合中是否有 null 值 + if (CollectionUtil.isEmpty(spuIds)) { return Collections.emptyList(); } List productSpuDOList = productSpuMapper.selectBatchIds(spuIds); return ProductSpuConvert.INSTANCE.convertList2(productSpuDOList); } + } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java index 9ee2c00a2..4c106d1bc 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java @@ -55,7 +55,7 @@ public interface ProductSkuService { * 批量创建 SKU * * @param spuId 商品 SPU 编号 - * @param list SKU 对象集合 + * @param list SKU 对象集合 */ void createSkuList(Long spuId, List list); @@ -63,13 +63,13 @@ public interface ProductSkuService { * 根据 SPU 编号,批量更新它的 SKU 信息 * * @param spuId SPU 编码 - * @param skus SKU 的集合 + * @param skus SKU 的集合 */ void updateSkuList(Long spuId, List skus); /** * 更新 SKU 库存(增量) - * + *

* 如果更新的库存不足,会抛出异常 * * @param updateStockReqDTO 更行请求 @@ -88,7 +88,7 @@ public interface ProductSkuService { * 获得 spu 对应的 SKU 集合 * * @param spuIds spu 编码集合 - * @return 商品 sku 集合 + * @return 商品 sku 集合 */ List getSkuListBySpuId(List spuIds); @@ -123,4 +123,5 @@ public interface ProductSkuService { * @return int 影响的行数 */ int updateSkuPropertyValue(Long propertyValueId, String propertyValueName); + } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityBaseVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityBaseVO.java index 8a4716384..31ff84935 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityBaseVO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityBaseVO.java @@ -1,17 +1,14 @@ package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity; -import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import org.springframework.format.annotation.DateTimeFormat; -import javax.validation.constraints.Min; import javax.validation.constraints.NotNull; import java.time.LocalDateTime; import java.util.List; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.TIME_ZONE_DEFAULT; /** * 秒杀活动基地签证官 @@ -23,18 +20,14 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.TIME_ZONE_DE @Data public class SeckillActivityBaseVO { - @Schema(description = "秒杀活动商品", requiredMode = Schema.RequiredMode.REQUIRED, example = "121") + @Schema(description = "秒杀活动商品id", requiredMode = Schema.RequiredMode.REQUIRED, example = "[121,1212]") @NotNull(message = "秒杀活动商品不能为空") - private Long spuId; + private List spuIds; @Schema(description = "秒杀活动名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "618大促") @NotNull(message = "秒杀活动名称不能为空") private String name; - @Schema(description = "活动状态 开启:0 禁用:1", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") - @NotNull(message = "活动状态 开启:0 禁用:1不能为空") - private Integer status; - @Schema(description = "备注", example = "清仓大甩卖割韭菜") private String remark; @@ -52,8 +45,8 @@ public class SeckillActivityBaseVO { @NotNull(message = "排序不能为空") private Integer sort; - @Schema(description = "秒杀时段id", requiredMode = Schema.RequiredMode.REQUIRED) - @NotNull(message = "秒杀时段id不能为空") + @Schema(description = "秒杀时段id", requiredMode = Schema.RequiredMode.REQUIRED, example = "[1,2,3]") + @NotNull(message = "秒杀时段不能为空") private List configIds; @Schema(description = "总限购数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "12877") diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityRespVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityRespVO.java index ce275b915..bd5ec40eb 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityRespVO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityRespVO.java @@ -6,7 +6,6 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; -import java.time.LocalDateTime; import java.util.List; /** @@ -24,8 +23,10 @@ public class SeckillActivityRespVO extends SeckillActivityBaseVO { private Long id; @Schema(description = "秒杀商品", requiredMode = Schema.RequiredMode.REQUIRED) - private List products; + private List products; // TODO puhui: 考虑是否去除 + @Schema(description = "活动状态 开启:0 禁用:1", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + private Integer status; } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductBaseVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductBaseVO.java index f22149aa7..b34c7fcc7 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductBaseVO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/product/SeckillProductBaseVO.java @@ -1,12 +1,9 @@ package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; -import java.time.LocalDateTime; -import javax.validation.constraints.*; -import org.springframework.format.annotation.DateTimeFormat; +import lombok.Data; -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; +import javax.validation.constraints.NotNull; /** * 秒杀参与商品 Base VO,提供给添加、修改、详细的子 VO 使用 @@ -17,15 +14,7 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ @Data public class SeckillProductBaseVO { - @Schema(description = "秒杀活动id", requiredMode = Schema.RequiredMode.REQUIRED, example = "20173") - @NotNull(message = "秒杀活动id不能为空") - private Long activityId; - - @Schema(description = "秒杀时段id", requiredMode = Schema.RequiredMode.REQUIRED) - @NotNull(message = "秒杀时段id不能为空") - private String configIds; - - @Schema(description = "商品spu_id", requiredMode = Schema.RequiredMode.REQUIRED, example = "10290") + @Schema(description = "商品spu_id", requiredMode = Schema.RequiredMode.REQUIRED, example = "30563") @NotNull(message = "商品spu_id不能为空") private Long spuId; @@ -41,18 +30,5 @@ public class SeckillProductBaseVO { @NotNull(message = "秒杀库存不能为空") private Integer stock; - @Schema(description = "秒杀商品状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "秒杀商品状态不能为空") - private Integer activityStatus; - - @Schema(description = "活动开始时间点", requiredMode = Schema.RequiredMode.REQUIRED) - @NotNull(message = "活动开始时间点不能为空") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime activityStartTime; - - @Schema(description = "活动结束时间点", requiredMode = Schema.RequiredMode.REQUIRED) - @NotNull(message = "活动结束时间点不能为空") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime activityEndTime; } 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 ea4110e15..841792341 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,6 +1,7 @@ package cn.iocoder.yudao.module.promotion.convert.seckill.seckillactivity; import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityCreateReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityDetailRespVO; @@ -12,6 +13,7 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity. import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; +import java.util.ArrayList; import java.util.List; /** @@ -47,7 +49,7 @@ public interface SeckillActivityConvert { * @return 是否匹配 */ default boolean isEquals(SeckillProductDO productDO, SeckillProductCreateReqVO productVO) { - return ObjectUtil.equals(productDO.getSpuId(), productVO.getSpuId()) + return ObjectUtil.equals(productDO.getSpuId(), 1) // TODO puhui:再看看 && ObjectUtil.equals(productDO.getSkuId(), productVO.getSkuId()) && ObjectUtil.equals(productDO.getSeckillPrice(), productVO.getSeckillPrice()); //&& ObjectUtil.equals(productDO.getQuota(), productVO.getQuota()) @@ -65,9 +67,25 @@ public interface SeckillActivityConvert { return ObjectUtil.equals(productDO.getSpuId(), productVO.getSpuId()) && ObjectUtil.equals(productDO.getSkuId(), productVO.getSkuId()) && ObjectUtil.equals(productDO.getSeckillPrice(), productVO.getSeckillPrice()); - //&& ObjectUtil.equals(productDO.getQuota(), productVO.getQuota()) - //&& ObjectUtil.equals(productDO.getLimitCount(), productVO.getLimitCount()); + //&& ObjectUtil.equals(productDO.getQuota(), productVO.getQuota()) + //&& ObjectUtil.equals(productDO.getLimitCount(), productVO.getLimitCount()); } + default List convertList(SeckillActivityDO seckillActivity, List products) { + List list = new ArrayList<>(); + products.forEach(sku -> { + SeckillProductDO productDO = new SeckillProductDO(); + productDO.setActivityId(seckillActivity.getId()); + productDO.setConfigIds(seckillActivity.getConfigIds()); + productDO.setSpuId(sku.getSpuId()); + productDO.setSkuId(sku.getSkuId()); + productDO.setSeckillPrice(sku.getSeckillPrice()); + productDO.setStock(sku.getStock()); + productDO.setActivityStatus(CommonStatusEnum.ENABLE.getStatus()); + productDO.setActivityStartTime(seckillActivity.getStartTime()); + productDO.setActivityEndTime(seckillActivity.getEndTime()); + }); + return list; + } } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckillactivity/SeckillActivityDO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckillactivity/SeckillActivityDO.java index 0cee71cce..be6663592 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckillactivity/SeckillActivityDO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckillactivity/SeckillActivityDO.java @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import cn.iocoder.yudao.framework.mybatis.core.type.LongListTypeHandler; -import cn.iocoder.yudao.module.promotion.enums.common.PromotionActivityStatusEnum; import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; @@ -35,7 +34,8 @@ public class SeckillActivityDO extends BaseDO { /** * 秒杀活动商品 */ - private Long spuId; + @TableField(typeHandler = LongListTypeHandler.class) + private List spuIds; /** * 秒杀活动名称 */ diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckillactivity/SeckillProductDO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckillactivity/SeckillProductDO.java index cf59eec91..45aab8b11 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckillactivity/SeckillProductDO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckillactivity/SeckillProductDO.java @@ -1,9 +1,16 @@ package cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity; -import lombok.*; -import java.time.LocalDateTime; -import com.baomidou.mybatisplus.annotation.*; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.framework.mybatis.core.type.LongListTypeHandler; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.time.LocalDateTime; +import java.util.List; /** * 秒杀参与商品 DO @@ -32,7 +39,8 @@ public class SeckillProductDO extends BaseDO { /** * 秒杀时段 id */ - private String configIds; + @TableField(typeHandler = LongListTypeHandler.class) + private List configIds; /** * 商品 spu_id */ @@ -51,6 +59,7 @@ public class SeckillProductDO extends BaseDO { private Integer stock; /** * 秒杀商品状态 + * 枚举 {@link CommonStatusEnum 对应的类} */ private Integer activityStatus; /** diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillActivityMapper.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillActivityMapper.java index 6bad96ff9..e8542f3c2 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillActivityMapper.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillActivityMapper.java @@ -8,6 +8,8 @@ import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.Se import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO; import org.apache.ibatis.annotations.Mapper; +import java.util.List; + /** * 秒杀活动 Mapper * @@ -23,4 +25,9 @@ public interface SeckillActivityMapper extends BaseMapperX { .apply(ObjectUtil.isNotNull(reqVO.getConfigId()), "FIND_IN_SET(" + reqVO.getConfigId() + ",time_ids) > 0") .orderByDesc(SeckillActivityDO::getId)); } + + default List selectListByStatus(Integer status) { + return selectList(new LambdaQueryWrapperX() + .eqIfPresent(SeckillActivityDO::getStatus, status)); + } } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityServiceImpl.java index 97d70491b..4c628ed83 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityServiceImpl.java @@ -52,7 +52,7 @@ public class DiscountActivityServiceImpl implements DiscountActivityService { // 插入活动 DiscountActivityDO discountActivity = DiscountActivityConvert.INSTANCE.convert(createReqVO) - .setStatus(PromotionUtils.calculateActivityStatus(createReqVO.getStartTime(), createReqVO.getEndTime())); + .setStatus(PromotionUtils.calculateActivityStatus(createReqVO.getEndTime())); discountActivityMapper.insert(discountActivity); // 插入商品 List discountProducts = convertList(createReqVO.getProducts(), @@ -74,7 +74,7 @@ public class DiscountActivityServiceImpl implements DiscountActivityService { // 更新活动 DiscountActivityDO updateObj = DiscountActivityConvert.INSTANCE.convert(updateReqVO) - .setStatus(PromotionUtils.calculateActivityStatus(updateReqVO.getStartTime(), updateReqVO.getEndTime())); + .setStatus(PromotionUtils.calculateActivityStatus(updateReqVO.getEndTime())); discountActivityMapper.updateById(updateObj); // 更新商品 updateDiscountProduct(updateReqVO); diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImpl.java index cdb73853c..3dd112f72 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImpl.java @@ -41,7 +41,7 @@ public class RewardActivityServiceImpl implements RewardActivityService { // 插入 RewardActivityDO rewardActivity = RewardActivityConvert.INSTANCE.convert(createReqVO) - .setStatus(PromotionUtils.calculateActivityStatus(createReqVO.getStartTime(), createReqVO.getEndTime())); + .setStatus(PromotionUtils.calculateActivityStatus(createReqVO.getEndTime())); rewardActivityMapper.insert(rewardActivity); // 返回 return rewardActivity.getId(); @@ -59,7 +59,7 @@ public class RewardActivityServiceImpl implements RewardActivityService { // 更新 RewardActivityDO updateObj = RewardActivityConvert.INSTANCE.convert(updateReqVO) - .setStatus(PromotionUtils.calculateActivityStatus(updateReqVO.getStartTime(), updateReqVO.getEndTime())); + .setStatus(PromotionUtils.calculateActivityStatus(updateReqVO.getEndTime())); rewardActivityMapper.updateById(updateObj); } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillactivity/SeckillActivityServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillactivity/SeckillActivityServiceImpl.java index 52ef64190..6f540c759 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillactivity/SeckillActivityServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/seckillactivity/SeckillActivityServiceImpl.java @@ -1,16 +1,19 @@ package cn.iocoder.yudao.module.promotion.service.seckill.seckillactivity; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.ObjectUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; -import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityBaseVO; +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.controller.admin.seckill.vo.activity.SeckillActivityCreateReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityPageReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityUpdateReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductBaseVO; -import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductCreateReqVO; import cn.iocoder.yudao.module.promotion.convert.seckill.seckillactivity.SeckillActivityConvert; import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO; @@ -25,8 +28,12 @@ import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; import java.util.Collection; import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +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.*; import static java.util.Arrays.asList; @@ -45,40 +52,94 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { private SeckillProductMapper seckillProductMapper; @Resource private SeckillConfigService seckillConfigService; + @Resource + private ProductSpuApi productSpuApi; + @Resource + private ProductSkuApi productSkuApi; @Override public Long createSeckillActivity(SeckillActivityCreateReqVO createReqVO) { - // 校验商品是否冲突 - validateSeckillActivityProductConflicts(null, createReqVO.getProducts()); - // 校验秒杀时段是否存在 - seckillConfigService.validateSeckillConfigExists(createReqVO.getConfigIds()); + // 校验商品秒秒杀时段是否冲突 + validateProductSpuSeckillConflict(createReqVO.getConfigIds(), createReqVO.getSpuIds()); + // 校验商品 sku 是否存在 + validateProductSkuExistence(createReqVO.getSpuIds(), createReqVO.getProducts()); - // 插入秒杀活动 TODO 活动日期拼接上秒杀时段 -> 2023-06-08 09:00:00 + // 插入秒杀活动 SeckillActivityDO seckillActivity = SeckillActivityConvert.INSTANCE.convert(createReqVO) - .setStatus(PromotionUtils.calculateActivityStatus(createReqVO.getStartTime(), createReqVO.getEndTime())); + .setStatus(PromotionUtils.calculateActivityStatus(createReqVO.getEndTime())); seckillActivityMapper.insert(seckillActivity); // 插入商品 - //List productDOs = SeckillActivityConvert.INSTANCE.convertList(createReqVO.getProducts(), seckillActivity); - //seckillProductMapper.insertBatch(productDOs); + List productDOs = SeckillActivityConvert.INSTANCE.convertList(seckillActivity, createReqVO.getProducts()); + seckillProductMapper.insertBatch(productDOs); return seckillActivity.getId(); } + private void validateProductSkuExistence(List spuIds, List products) { + Set convertedSpuIds = CollectionUtils.convertSet(products, T::getSpuId); + // 校验 spu 个数是否相等 + if (ObjectUtil.notEqual(spuIds.size(), convertedSpuIds.size())) { + throw exception(SKU_NOT_EXISTS); + } + // 获取所选 spu下的所有 sku + List skuRespDTOs = productSkuApi.getSkuListBySpuId(spuIds); + // 校验 sku 个数是否一致 + Set skuIdsSet = CollectionUtils.convertSet(products, T::getSkuId); + Set skuIdsSet1 = CollectionUtils.convertSet(skuRespDTOs, ProductSkuRespDTO::getId); + if (ObjectUtil.notEqual(skuIdsSet.size(), skuIdsSet1.size())) { + throw exception(SKU_NOT_EXISTS); + } + // 校验 skuId 是否存在 + if (!skuIdsSet1.containsAll(skuIdsSet) || !skuIdsSet.containsAll(skuIdsSet1)) { + throw exception(SKU_NOT_EXISTS); + } + } + + private void validateProductSpuSeckillConflict(List configIds, List spuIds) { + // 校验秒杀时段是否存在 + seckillConfigService.validateSeckillConfigExists(configIds); + // 校验商品 spu 是否存在 + List spuList = productSpuApi.getSpuList(spuIds); + if (ObjectUtil.notEqual(spuIds.size(), spuList.size())) { + throw exception(SPU_NOT_EXISTS); + } + // 查询所有开启的秒杀活动 + List activityDOs = seckillActivityMapper.selectListByStatus(CommonStatusEnum.ENABLE.getStatus()); + // 过滤出所有 spuIds 有交集的活动 + List doList = activityDOs.stream().filter(s -> { + // 判断 spu 是否有交集 + List spuIdsClone = ArrayUtil.clone(s.getSpuIds()); + spuIdsClone.retainAll(spuIds); + if (CollUtil.isEmpty(spuIdsClone)) { + return false; + } + // 判断秒杀时段是否有交集 + List configIdsClone = ArrayUtil.clone(s.getConfigIds()); + configIdsClone.retainAll(configIds); + return CollUtil.isNotEmpty(configIdsClone); + }).collect(Collectors.toList()); + if (CollUtil.isNotEmpty(doList)) { + throw exception(SECKILL_ACTIVITY_SPU_CONFLICTS); + } + } + @Override public void updateSeckillActivity(SeckillActivityUpdateReqVO updateReqVO) { // 校验存在 SeckillActivityDO seckillActivity = validateSeckillActivityExists(updateReqVO.getId()); - if (PromotionActivityStatusEnum.CLOSE.getStatus().equals(seckillActivity.getStatus())) { + if (CommonStatusEnum.ENABLE.getStatus().equals(seckillActivity.getStatus())) { throw exception(SECKILL_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED); } // 校验商品是否冲突 - validateSeckillActivityProductConflicts(updateReqVO.getId(), updateReqVO.getProducts()); + validateProductSpuSeckillConflict(updateReqVO.getConfigIds(), updateReqVO.getSpuIds()); + // 校验商品 sku 是否存在 + validateProductSkuExistence(updateReqVO.getSpuIds(), updateReqVO.getProducts()); // 更新活动 SeckillActivityDO updateObj = SeckillActivityConvert.INSTANCE.convert(updateReqVO) - .setStatus(PromotionUtils.calculateActivityStatus(updateReqVO.getStartTime(), updateReqVO.getEndTime())); + .setStatus(PromotionUtils.calculateActivityStatus(updateReqVO.getEndTime())); seckillActivityMapper.updateById(updateObj); // 更新商品 - updateSeckillProduct(updateReqVO); + //updateSeckillProduct(updateReqVO); } @@ -92,10 +153,11 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { * @param updateReqVO 更新的请求VO */ private void updateSeckillProduct(SeckillActivityUpdateReqVO updateReqVO) { - List seckillProductDOs = seckillProductMapper.selectListByActivityId(updateReqVO.getId()); - //List products = updateReqVO.getProducts(); + // TODO puhui999:后续完善 + //List seckillProductDOs = seckillProductMapper.selectListByActivityId(updateReqVO.getId()); + //List products = updateReqVO.getProducts(); - // 计算需要删除的数据 + ////计算需要删除的数据 //List deleteIds = CollectionUtils.convertList(seckillProductDOs, SeckillProductDO::getId, // seckillProductDO -> products.stream() // .noneMatch(product -> SeckillActivityConvert.INSTANCE.isEquals(seckillProductDO, product))); @@ -116,37 +178,6 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { seckillProductMapper.updateTimeIdsByActivityId(updateReqVO.getId(), updateReqVO.getConfigIds()); } - /** - * 校验商品是否冲突 - * - * @param id 秒杀活动编号 - * @param products 商品列表 - */ - private void validateSeckillActivityProductConflicts(Long id, List products) { - if (CollUtil.isEmpty(products)) { - return; - } - // 校验秒杀商品是否存在 - List seckillProductDOs = seckillProductMapper - .selectListBySkuIds(CollectionUtils.convertSet(products, T::getSkuId)); - if (CollUtil.isEmpty(seckillProductDOs)) { - return; - } - // 获取秒杀商品所在活动 - List seckillActivityDOs = seckillActivityMapper - .selectBatchIds(CollectionUtils.convertSet(seckillProductDOs, SeckillProductDO::getActivityId)); - if (id != null) { - // 排除自己这个活动 - seckillActivityDOs.removeIf(item -> id.equals(item.getId())); - } - // 排除关闭了的活动 - seckillActivityDOs.removeIf(item -> ObjectUtil.equal(item.getStatus(), CommonStatusEnum.DISABLE.getStatus())); - // 如果非空,则说明冲突 - if (CollUtil.isNotEmpty(seckillActivityDOs)) { - throw exception(SECKILL_ACTIVITY_SPU_CONFLICTS); - } - } - @Override public void closeSeckillActivity(Long id) { // 校验存在 diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/util/PromotionUtils.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/util/PromotionUtils.java index fc8ca16cf..2ad362fe2 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/util/PromotionUtils.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/util/PromotionUtils.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.promotion.util; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; -import cn.iocoder.yudao.module.promotion.enums.common.PromotionActivityStatusEnum; import java.time.LocalDateTime; @@ -15,18 +15,11 @@ public class PromotionUtils { /** * 根据时间,计算活动状态 * - * @param startTime 开始时间 * @param endTime 结束时间 * @return 活动状态 */ - public static Integer calculateActivityStatus(LocalDateTime startTime, LocalDateTime endTime) { - if (LocalDateTimeUtils.beforeNow(endTime)) { - return PromotionActivityStatusEnum.END.getStatus(); - } - if (LocalDateTimeUtils.afterNow(startTime)) { - return PromotionActivityStatusEnum.WAIT.getStatus(); - } - return PromotionActivityStatusEnum.RUN.getStatus(); + public static Integer calculateActivityStatus(LocalDateTime endTime) { + return LocalDateTimeUtils.beforeNow(endTime) ? CommonStatusEnum.DISABLE.getStatus() : CommonStatusEnum.ENABLE.getStatus(); } }