fix:完善 mall seckill 相关 ②

This commit is contained in:
puhui999 2023-06-23 00:57:27 +08:00
parent b44ad3a0f7
commit ab30ff6480
15 changed files with 167 additions and 120 deletions

View File

@ -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<ProductSkuRespDTO> getSkuList(Collection<Long> ids);
/**
* 批量查询 SKU 数组
*
* @param spuIds SPU 编号列表
* @return SKU 数组
*/
List<ProductSkuRespDTO> getSkuListBySpuId(List<Long> spuIds);
/**
* 更新 SKU 库存
*

View File

@ -42,6 +42,15 @@ public class ProductSkuApiImpl implements ProductSkuApi {
return ProductSkuConvert.INSTANCE.convertList04(skus);
}
@Override
public List<ProductSkuRespDTO> getSkuListBySpuId(List<Long> spuIds) {
if (CollUtil.isEmpty(spuIds)) {
return Collections.emptyList();
}
List<ProductSkuDO> skus = productSkuService.getSkuListBySpuId(spuIds);
return ProductSkuConvert.INSTANCE.convertList04(skus);
}
@Override
public void updateSkuStock(ProductSkuUpdateStockReqDTO updateStockReqDTO) {
productSkuService.updateSkuStock(updateStockReqDTO);

View File

@ -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<ProductSpuRespDTO> getSpuList(Collection<Long> spuIds) {
// TODO TODO LeeYan9: AllEmpty?
if (CollectionUtils.isAnyEmpty(spuIds)) {
// TODO 需不需要判断集合中是否有 null
if (CollectionUtil.isEmpty(spuIds)) {
return Collections.emptyList();
}
List<ProductSpuDO> productSpuDOList = productSpuMapper.selectBatchIds(spuIds);
return ProductSpuConvert.INSTANCE.convertList2(productSpuDOList);
}
}

View File

@ -55,7 +55,7 @@ public interface ProductSkuService {
* 批量创建 SKU
*
* @param spuId 商品 SPU 编号
* @param list SKU 对象集合
* @param list SKU 对象集合
*/
void createSkuList(Long spuId, List<ProductSkuCreateOrUpdateReqVO> list);
@ -63,13 +63,13 @@ public interface ProductSkuService {
* 根据 SPU 编号批量更新它的 SKU 信息
*
* @param spuId SPU 编码
* @param skus SKU 的集合
* @param skus SKU 的集合
*/
void updateSkuList(Long spuId, List<ProductSkuCreateOrUpdateReqVO> skus);
/**
* 更新 SKU 库存增量
*
* <p>
* 如果更新的库存不足会抛出异常
*
* @param updateStockReqDTO 更行请求
@ -88,7 +88,7 @@ public interface ProductSkuService {
* 获得 spu 对应的 SKU 集合
*
* @param spuIds spu 编码集合
* @return 商品 sku 集合
* @return 商品 sku 集合
*/
List<ProductSkuDO> getSkuListBySpuId(List<Long> spuIds);
@ -123,4 +123,5 @@ public interface ProductSkuService {
* @return int 影响的行数
*/
int updateSkuPropertyValue(Long propertyValueId, String propertyValueName);
}

View File

@ -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<Long> 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<Long> configIds;
@Schema(description = "总限购数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "12877")

View File

@ -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<SeckillProductRespVO> products;
private List<SeckillProductRespVO> products; // TODO puhui: 考虑是否去除
@Schema(description = "活动状态 开启0 禁用1", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
private Integer status;
}

View File

@ -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;
}

View File

@ -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<SeckillProductDO> convertList(SeckillActivityDO seckillActivity, List<SeckillProductCreateReqVO> products) {
List<SeckillProductDO> 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;
}
}

View File

@ -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<Long> spuIds;
/**
* 秒杀活动名称
*/

View File

@ -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<Long> configIds;
/**
* 商品 spu_id
*/
@ -51,6 +59,7 @@ public class SeckillProductDO extends BaseDO {
private Integer stock;
/**
* 秒杀商品状态
* 枚举 {@link CommonStatusEnum 对应的类}
*/
private Integer activityStatus;
/**

View File

@ -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<SeckillActivityDO> {
.apply(ObjectUtil.isNotNull(reqVO.getConfigId()), "FIND_IN_SET(" + reqVO.getConfigId() + ",time_ids) > 0")
.orderByDesc(SeckillActivityDO::getId));
}
default List<SeckillActivityDO> selectListByStatus(Integer status) {
return selectList(new LambdaQueryWrapperX<SeckillActivityDO>()
.eqIfPresent(SeckillActivityDO::getStatus, status));
}
}

View File

@ -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<DiscountProductDO> 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);

View File

@ -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);
}

View File

@ -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<SeckillProductDO> productDOs = SeckillActivityConvert.INSTANCE.convertList(createReqVO.getProducts(), seckillActivity);
//seckillProductMapper.insertBatch(productDOs);
List<SeckillProductDO> productDOs = SeckillActivityConvert.INSTANCE.convertList(seckillActivity, createReqVO.getProducts());
seckillProductMapper.insertBatch(productDOs);
return seckillActivity.getId();
}
private <T extends SeckillProductBaseVO> void validateProductSkuExistence(List<Long> spuIds, List<T> products) {
Set<Long> convertedSpuIds = CollectionUtils.convertSet(products, T::getSpuId);
// 校验 spu 个数是否相等
if (ObjectUtil.notEqual(spuIds.size(), convertedSpuIds.size())) {
throw exception(SKU_NOT_EXISTS);
}
// 获取所选 spu下的所有 sku
List<ProductSkuRespDTO> skuRespDTOs = productSkuApi.getSkuListBySpuId(spuIds);
// 校验 sku 个数是否一致
Set<Long> skuIdsSet = CollectionUtils.convertSet(products, T::getSkuId);
Set<Long> 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<Long> configIds, List<Long> spuIds) {
// 校验秒杀时段是否存在
seckillConfigService.validateSeckillConfigExists(configIds);
// 校验商品 spu 是否存在
List<ProductSpuRespDTO> spuList = productSpuApi.getSpuList(spuIds);
if (ObjectUtil.notEqual(spuIds.size(), spuList.size())) {
throw exception(SPU_NOT_EXISTS);
}
// 查询所有开启的秒杀活动
List<SeckillActivityDO> activityDOs = seckillActivityMapper.selectListByStatus(CommonStatusEnum.ENABLE.getStatus());
// 过滤出所有 spuIds 有交集的活动
List<SeckillActivityDO> doList = activityDOs.stream().filter(s -> {
// 判断 spu 是否有交集
List<Long> spuIdsClone = ArrayUtil.clone(s.getSpuIds());
spuIdsClone.retainAll(spuIds);
if (CollUtil.isEmpty(spuIdsClone)) {
return false;
}
// 判断秒杀时段是否有交集
List<Long> 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<SeckillProductDO> seckillProductDOs = seckillProductMapper.selectListByActivityId(updateReqVO.getId());
//List<SeckillActivityBaseVO.Product> products = updateReqVO.getProducts();
// TODO puhui999后续完善
//List<SeckillProductDO> seckillProductDOs = seckillProductMapper.selectListByActivityId(updateReqVO.getId());
//List<SeckillProductUpdateReqVO> products = updateReqVO.getProducts();
// 计算需要删除的数据
////计算需要删除的数据
//List<Long> 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 <T extends SeckillProductBaseVO> void validateSeckillActivityProductConflicts(Long id, List<T> products) {
if (CollUtil.isEmpty(products)) {
return;
}
// 校验秒杀商品是否存在
List<SeckillProductDO> seckillProductDOs = seckillProductMapper
.selectListBySkuIds(CollectionUtils.convertSet(products, T::getSkuId));
if (CollUtil.isEmpty(seckillProductDOs)) {
return;
}
// 获取秒杀商品所在活动
List<SeckillActivityDO> 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) {
// 校验存在

View File

@ -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();
}
}