mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2024-11-22 23:31:52 +08:00
fix:mall promotion Combination
This commit is contained in:
parent
41d996f7f3
commit
78b3d2a20f
@ -30,14 +30,13 @@ public interface ProductSkuApi {
|
|||||||
*/
|
*/
|
||||||
List<ProductSkuRespDTO> getSkuList(Collection<Long> ids);
|
List<ProductSkuRespDTO> getSkuList(Collection<Long> ids);
|
||||||
|
|
||||||
// TODO puhui999:入参用 Collection<Long> 更通用
|
|
||||||
/**
|
/**
|
||||||
* 批量查询 SKU 数组
|
* 批量查询 SKU 数组
|
||||||
*
|
*
|
||||||
* @param spuIds SPU 编号列表
|
* @param spuIds SPU 编号列表
|
||||||
* @return SKU 数组
|
* @return SKU 数组
|
||||||
*/
|
*/
|
||||||
List<ProductSkuRespDTO> getSkuListBySpuId(List<Long> spuIds);
|
List<ProductSkuRespDTO> getSkuListBySpuId(Collection<Long> spuIds);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新 SKU 库存
|
* 更新 SKU 库存
|
||||||
|
@ -43,7 +43,7 @@ public class ProductSkuApiImpl implements ProductSkuApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ProductSkuRespDTO> getSkuListBySpuId(List<Long> spuIds) {
|
public List<ProductSkuRespDTO> getSkuListBySpuId(Collection<Long> spuIds) {
|
||||||
if (CollUtil.isEmpty(spuIds)) {
|
if (CollUtil.isEmpty(spuIds)) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Promotion 错误码枚举类
|
* Promotion 错误码枚举类
|
||||||
*
|
* <p>
|
||||||
* promotion 系统,使用 1-013-000-000 段
|
* promotion 系统,使用 1-013-000-000 段
|
||||||
*/
|
*/
|
||||||
public interface ErrorCodeConstants {
|
public interface ErrorCodeConstants {
|
||||||
@ -58,6 +58,7 @@ public interface ErrorCodeConstants {
|
|||||||
ErrorCode SECKILL_TIME_CONFLICTS = new ErrorCode(1013009001, "秒杀时段冲突");
|
ErrorCode SECKILL_TIME_CONFLICTS = new ErrorCode(1013009001, "秒杀时段冲突");
|
||||||
ErrorCode SECKILL_TIME_EQUAL = new ErrorCode(1013009002, "秒杀时段开始时间和结束时间不能相等");
|
ErrorCode SECKILL_TIME_EQUAL = new ErrorCode(1013009002, "秒杀时段开始时间和结束时间不能相等");
|
||||||
ErrorCode SECKILL_START_TIME_BEFORE_END_TIME = new ErrorCode(1013009003, "秒杀时段开始时间不能在结束时间之后");
|
ErrorCode SECKILL_START_TIME_BEFORE_END_TIME = new ErrorCode(1013009003, "秒杀时段开始时间不能在结束时间之后");
|
||||||
|
ErrorCode SECKILL_TIME_DISABLE = new ErrorCode(1013009004, "秒杀时段已关闭");
|
||||||
|
|
||||||
// ========== 拼团活动 1013010000 ==========
|
// ========== 拼团活动 1013010000 ==========
|
||||||
ErrorCode COMBINATION_ACTIVITY_NOT_EXISTS = new ErrorCode(1013010000, "拼团活动不存在");
|
ErrorCode COMBINATION_ACTIVITY_NOT_EXISTS = new ErrorCode(1013010000, "拼团活动不存在");
|
||||||
|
@ -20,10 +20,9 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
|
|||||||
@Data
|
@Data
|
||||||
public class SeckillActivityBaseVO {
|
public class SeckillActivityBaseVO {
|
||||||
|
|
||||||
// TODO @puhui999:对应单 spuId 哈
|
|
||||||
@Schema(description = "秒杀活动商品id", requiredMode = Schema.RequiredMode.REQUIRED, example = "[121,1212]")
|
@Schema(description = "秒杀活动商品id", requiredMode = Schema.RequiredMode.REQUIRED, example = "[121,1212]")
|
||||||
@NotNull(message = "秒杀活动商品不能为空")
|
@NotNull(message = "秒杀活动商品不能为空")
|
||||||
private List<Long> spuIds;
|
private Long spuId;
|
||||||
|
|
||||||
@Schema(description = "秒杀活动名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "618大促")
|
@Schema(description = "秒杀活动名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "618大促")
|
||||||
@NotNull(message = "秒杀活动名称不能为空")
|
@NotNull(message = "秒杀活动名称不能为空")
|
||||||
@ -56,8 +55,4 @@ public class SeckillActivityBaseVO {
|
|||||||
@Schema(description = "单次限够数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "31683")
|
@Schema(description = "单次限够数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "31683")
|
||||||
private Integer singleLimitCount;
|
private Integer singleLimitCount;
|
||||||
|
|
||||||
// TODO @puhui999:这个应该是计算出来的字段,只返回,create 和 update 不用哈
|
|
||||||
@Schema(description = "秒杀总库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
|
|
||||||
private Integer totalStock;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ public class SeckillActivityRespVO extends SeckillActivityBaseVO {
|
|||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
@Schema(description = "秒杀商品", requiredMode = Schema.RequiredMode.REQUIRED)
|
@Schema(description = "秒杀商品", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
private List<SeckillProductRespVO> products; // TODO puhui: 考虑是否去除
|
private List<SeckillProductRespVO> products;
|
||||||
|
|
||||||
@Schema(description = "活动状态 开启:0 禁用:1", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
|
@Schema(description = "活动状态 开启:0 禁用:1", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
|
||||||
private Integer status;
|
private Integer status;
|
||||||
|
@ -14,11 +14,6 @@ import javax.validation.constraints.NotNull;
|
|||||||
@Data
|
@Data
|
||||||
public class SeckillProductBaseVO {
|
public class SeckillProductBaseVO {
|
||||||
|
|
||||||
// TODO @puhui:spuId 不用传递;因为一个秒杀活动只对应一个 SPU 哈;
|
|
||||||
@Schema(description = "商品spu_id", requiredMode = Schema.RequiredMode.REQUIRED, example = "30563")
|
|
||||||
@NotNull(message = "商品spu_id不能为空")
|
|
||||||
private Long spuId;
|
|
||||||
|
|
||||||
@Schema(description = "商品sku_id", requiredMode = Schema.RequiredMode.REQUIRED, example = "30563")
|
@Schema(description = "商品sku_id", requiredMode = Schema.RequiredMode.REQUIRED, example = "30563")
|
||||||
@NotNull(message = "商品sku_id不能为空")
|
@NotNull(message = "商品sku_id不能为空")
|
||||||
private Long skuId;
|
private Long skuId;
|
||||||
@ -31,5 +26,4 @@ public class SeckillProductBaseVO {
|
|||||||
@NotNull(message = "秒杀库存不能为空")
|
@NotNull(message = "秒杀库存不能为空")
|
||||||
private Integer stock;
|
private Integer stock;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product;
|
package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product;
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.*;
|
import lombok.Data;
|
||||||
import javax.validation.constraints.*;
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 管理后台 - 秒杀参与商品更新 Request VO
|
* 管理后台 - 秒杀参与商品更新 Request VO
|
||||||
@ -15,8 +16,4 @@ import javax.validation.constraints.*;
|
|||||||
@ToString(callSuper = true)
|
@ToString(callSuper = true)
|
||||||
public class SeckillProductUpdateReqVO extends SeckillProductBaseVO {
|
public class SeckillProductUpdateReqVO extends SeckillProductBaseVO {
|
||||||
|
|
||||||
@Schema(description = "秒杀参与商品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "256")
|
|
||||||
@NotNull(message = "秒杀参与商品编号不能为空")
|
|
||||||
private Long id;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,20 +1,24 @@
|
|||||||
package cn.iocoder.yudao.module.promotion.convert.seckill.seckillactivity;
|
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.enums.CommonStatusEnum;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||||
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityCreateReqVO;
|
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityCreateReqVO;
|
||||||
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityDetailRespVO;
|
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityDetailRespVO;
|
||||||
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityRespVO;
|
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityRespVO;
|
||||||
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityUpdateReqVO;
|
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityUpdateReqVO;
|
||||||
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductCreateReqVO;
|
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductBaseVO;
|
||||||
|
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductUpdateReqVO;
|
||||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO;
|
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO;
|
||||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO;
|
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO;
|
||||||
import org.mapstruct.Mapper;
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.Mapping;
|
||||||
|
import org.mapstruct.Mappings;
|
||||||
import org.mapstruct.factory.Mappers;
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 秒杀活动 Convert
|
* 秒杀活动 Convert
|
||||||
@ -26,8 +30,6 @@ public interface SeckillActivityConvert {
|
|||||||
|
|
||||||
SeckillActivityConvert INSTANCE = Mappers.getMapper(SeckillActivityConvert.class);
|
SeckillActivityConvert INSTANCE = Mappers.getMapper(SeckillActivityConvert.class);
|
||||||
|
|
||||||
SeckillProductDO convert(SeckillProductCreateReqVO product);
|
|
||||||
|
|
||||||
SeckillActivityDO convert(SeckillActivityCreateReqVO bean);
|
SeckillActivityDO convert(SeckillActivityCreateReqVO bean);
|
||||||
|
|
||||||
SeckillActivityDO convert(SeckillActivityUpdateReqVO bean);
|
SeckillActivityDO convert(SeckillActivityUpdateReqVO bean);
|
||||||
@ -40,51 +42,38 @@ public interface SeckillActivityConvert {
|
|||||||
|
|
||||||
SeckillActivityDetailRespVO convert(SeckillActivityDO seckillActivity, List<SeckillProductDO> seckillProducts);
|
SeckillActivityDetailRespVO convert(SeckillActivityDO seckillActivity, List<SeckillProductDO> seckillProducts);
|
||||||
|
|
||||||
|
@Mappings({
|
||||||
|
@Mapping(target = "activityId", source = "activityDO.id"),
|
||||||
|
@Mapping(target = "configIds", source = "activityDO.configIds"),
|
||||||
|
@Mapping(target = "spuId", source = "activityDO.spuId"),
|
||||||
|
@Mapping(target = "skuId", source = "vo.skuId"),
|
||||||
|
@Mapping(target = "seckillPrice", source = "vo.seckillPrice"),
|
||||||
|
@Mapping(target = "stock", source = "vo.stock"),
|
||||||
|
@Mapping(target = "activityStartTime", source = "activityDO.startTime"),
|
||||||
|
@Mapping(target = "activityEndTime", source = "activityDO.endTime")
|
||||||
|
})
|
||||||
|
SeckillProductDO convert(SeckillActivityDO activityDO, SeckillProductBaseVO vo);
|
||||||
|
|
||||||
/**
|
default List<SeckillProductDO> convertList(SeckillActivityDO activityDO, List<? extends SeckillProductBaseVO> products) {
|
||||||
* 比较两个秒杀商品对象是否相等
|
|
||||||
*
|
|
||||||
* @param productDO 数据库中的商品
|
|
||||||
* @param productVO 前端传入的商品
|
|
||||||
* @return 是否匹配
|
|
||||||
*/
|
|
||||||
default boolean isEquals(SeckillProductDO productDO, SeckillProductCreateReqVO productVO) {
|
|
||||||
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())
|
|
||||||
//&& ObjectUtil.equals(productDO.getLimitCount(), productVO.getLimitCount());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 比较两个秒杀商品对象是否相等
|
|
||||||
*
|
|
||||||
* @param productDO 商品1
|
|
||||||
* @param productVO 商品2
|
|
||||||
* @return 是否匹配
|
|
||||||
*/
|
|
||||||
default boolean isEquals(SeckillProductDO productDO, SeckillProductDO productVO) {
|
|
||||||
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());
|
|
||||||
}
|
|
||||||
|
|
||||||
default List<SeckillProductDO> convertList(SeckillActivityDO seckillActivity, List<SeckillProductCreateReqVO> products) {
|
|
||||||
List<SeckillProductDO> list = new ArrayList<>();
|
List<SeckillProductDO> list = new ArrayList<>();
|
||||||
products.forEach(sku -> {
|
products.forEach(sku -> {
|
||||||
SeckillProductDO productDO = new SeckillProductDO();
|
SeckillProductDO productDO = convert(activityDO, sku);
|
||||||
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.setActivityStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||||
productDO.setActivityStartTime(seckillActivity.getStartTime());
|
list.add(productDO);
|
||||||
productDO.setActivityEndTime(seckillActivity.getEndTime());
|
|
||||||
});
|
});
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default List<SeckillProductDO> convertList1(SeckillActivityDO activityDO, List<SeckillProductUpdateReqVO> vos, List<SeckillProductDO> productDOs) {
|
||||||
|
Map<Long, Long> longMap = CollectionUtils.convertMap(productDOs, SeckillProductDO::getSkuId, SeckillProductDO::getId);
|
||||||
|
List<SeckillProductDO> list = new ArrayList<>();
|
||||||
|
vos.forEach(sku -> {
|
||||||
|
SeckillProductDO productDO = convert(activityDO, sku);
|
||||||
|
productDO.setId(longMap.get(sku.getSkuId()));
|
||||||
|
productDO.setActivityStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||||
|
list.add(productDO);
|
||||||
|
});
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -34,8 +34,7 @@ public class SeckillActivityDO extends BaseDO {
|
|||||||
/**
|
/**
|
||||||
* 秒杀活动商品
|
* 秒杀活动商品
|
||||||
*/
|
*/
|
||||||
@TableField(typeHandler = LongListTypeHandler.class)
|
private Long spuId;
|
||||||
private List<Long> spuIds;
|
|
||||||
/**
|
/**
|
||||||
* 秒杀活动名称
|
* 秒杀活动名称
|
||||||
*/
|
*/
|
||||||
|
@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollUtil;
|
|||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||||
import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
|
import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
|
||||||
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
|
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
|
||||||
import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
|
import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
|
||||||
@ -18,23 +19,21 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.
|
|||||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO;
|
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO;
|
||||||
import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillactivity.SeckillActivityMapper;
|
import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillactivity.SeckillActivityMapper;
|
||||||
import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillactivity.SeckillProductMapper;
|
import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillactivity.SeckillProductMapper;
|
||||||
import cn.iocoder.yudao.module.promotion.enums.common.PromotionActivityStatusEnum;
|
|
||||||
import cn.iocoder.yudao.module.promotion.service.seckill.seckillconfig.SeckillConfigService;
|
import cn.iocoder.yudao.module.promotion.service.seckill.seckillconfig.SeckillConfigService;
|
||||||
import cn.iocoder.yudao.module.promotion.util.PromotionUtils;
|
import cn.iocoder.yudao.module.promotion.util.PromotionUtils;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.Set;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS;
|
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS;
|
||||||
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
|
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
|
||||||
import static cn.iocoder.yudao.module.promotion.util.PromotionUtils.validateProductSkuExistence;
|
import static cn.iocoder.yudao.module.promotion.util.PromotionUtils.validateProductSkuExistence;
|
||||||
import static java.util.Arrays.asList;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 秒杀活动 Service 实现类
|
* 秒杀活动 Service 实现类
|
||||||
@ -57,17 +56,19 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
|
|||||||
private ProductSkuApi productSkuApi;
|
private ProductSkuApi productSkuApi;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public Long createSeckillActivity(SeckillActivityCreateReqVO createReqVO) {
|
public Long createSeckillActivity(SeckillActivityCreateReqVO createReqVO) {
|
||||||
// 校验商品秒秒杀时段是否冲突
|
// 校验商品秒秒杀时段是否冲突
|
||||||
validateProductSpuSeckillConflict(createReqVO.getConfigIds(), createReqVO.getSpuIds());
|
validateProductSpuSeckillConflict(createReqVO.getConfigIds(), createReqVO.getSpuId(), null);
|
||||||
// 获取所选 spu下的所有 sku
|
// 获取所选 spu下的所有 sku
|
||||||
List<ProductSkuRespDTO> skus = productSkuApi.getSkuListBySpuId(createReqVO.getSpuIds());
|
List<ProductSkuRespDTO> skus = productSkuApi.getSkuListBySpuId(CollUtil.newArrayList(createReqVO.getSpuId()));
|
||||||
// 校验商品 sku 是否存在
|
// 校验商品 sku 是否存在
|
||||||
validateProductSkuExistence(skus, createReqVO.getProducts(), SeckillProductCreateReqVO::getSkuId);
|
validateProductSkuExistence(skus, createReqVO.getProducts(), SeckillProductCreateReqVO::getSkuId);
|
||||||
|
|
||||||
// 插入秒杀活动
|
// 插入秒杀活动
|
||||||
SeckillActivityDO activity = SeckillActivityConvert.INSTANCE.convert(createReqVO)
|
SeckillActivityDO activity = SeckillActivityConvert.INSTANCE.convert(createReqVO)
|
||||||
.setStatus(PromotionUtils.calculateActivityStatus(createReqVO.getEndTime()));
|
.setStatus(PromotionUtils.calculateActivityStatus(createReqVO.getEndTime()))
|
||||||
|
.setTotalStock(CollectionUtils.getSumValue(createReqVO.getProducts(), SeckillProductCreateReqVO::getStock, Integer::sum));
|
||||||
seckillActivityMapper.insert(activity);
|
seckillActivityMapper.insert(activity);
|
||||||
// 插入商品
|
// 插入商品
|
||||||
List<SeckillProductDO> product = SeckillActivityConvert.INSTANCE.convertList(activity, createReqVO.getProducts());
|
List<SeckillProductDO> product = SeckillActivityConvert.INSTANCE.convertList(activity, createReqVO.getProducts());
|
||||||
@ -75,119 +76,124 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
|
|||||||
return activity.getId();
|
return activity.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateProductSpuSeckillConflict(List<Long> configIds, List<Long> spuIds) {
|
private void validateProductSpuSeckillConflict(List<Long> configIds, Long spuId, Long activityId) {
|
||||||
// 校验秒杀时段是否存在
|
// 校验秒杀时段是否存在
|
||||||
seckillConfigService.validateSeckillConfigExists(configIds);
|
seckillConfigService.validateSeckillConfigExists(configIds);
|
||||||
// 校验商品 spu 是否存在
|
// 校验商品 spu 是否存在
|
||||||
List<ProductSpuRespDTO> spuList = productSpuApi.getSpuList(spuIds);
|
List<ProductSpuRespDTO> spuList = productSpuApi.getSpuList(CollUtil.newArrayList(spuId));
|
||||||
if (ObjectUtil.notEqual(spuIds.size(), spuList.size())) {
|
if (CollUtil.isEmpty(spuList)) {
|
||||||
throw exception(SPU_NOT_EXISTS);
|
throw exception(SPU_NOT_EXISTS);
|
||||||
}
|
}
|
||||||
// 查询所有开启的秒杀活动
|
// 查询所有开启的秒杀活动
|
||||||
List<SeckillActivityDO> activityDOs = seckillActivityMapper.selectListByStatus(CommonStatusEnum.ENABLE.getStatus());
|
List<SeckillActivityDO> activityDOs = seckillActivityMapper.selectListByStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||||
// 过滤出所有 spuIds 有交集的活动
|
if (activityId != null) {
|
||||||
List<SeckillActivityDO> doList = activityDOs.stream().filter(s -> {
|
// 更新时移除本活动
|
||||||
// 判断 spu 是否有交集
|
activityDOs.removeIf(item -> ObjectUtil.equal(item.getId(), activityId));
|
||||||
ArrayList<Long> spuIdsClone = CollUtil.newArrayList(s.getSpuIds());
|
|
||||||
spuIdsClone.retainAll(spuIds);
|
|
||||||
if (CollUtil.isEmpty(spuIdsClone)) {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
// 过滤出所有 spuId 有交集的活动
|
||||||
|
List<SeckillActivityDO> activityDOs1 = CollectionUtils.convertList(activityDOs, c -> c, s -> ObjectUtil.equal(s.getSpuId(), spuId));
|
||||||
|
if (CollUtil.isNotEmpty(activityDOs1)) {
|
||||||
|
throw exception(SECKILL_ACTIVITY_SPU_CONFLICTS);
|
||||||
|
}
|
||||||
|
List<SeckillActivityDO> activityDOs2 = CollectionUtils.convertList(activityDOs, c -> c, s -> {
|
||||||
// 判断秒杀时段是否有交集
|
// 判断秒杀时段是否有交集
|
||||||
List<Long> configIdsClone = CollUtil.newArrayList(s.getConfigIds());
|
List<Long> configIdsClone = CollUtil.newArrayList(s.getConfigIds());
|
||||||
configIdsClone.retainAll(configIds);
|
configIdsClone.retainAll(configIds);
|
||||||
return CollUtil.isNotEmpty(configIdsClone);
|
return CollUtil.isNotEmpty(configIdsClone);
|
||||||
}).collect(Collectors.toList());
|
});
|
||||||
if (CollUtil.isNotEmpty(doList)) {
|
if (CollUtil.isNotEmpty(activityDOs2)) {
|
||||||
throw exception(SECKILL_ACTIVITY_SPU_CONFLICTS);
|
throw exception(SECKILL_TIME_CONFLICTS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void updateSeckillActivity(SeckillActivityUpdateReqVO updateReqVO) {
|
public void updateSeckillActivity(SeckillActivityUpdateReqVO updateReqVO) {
|
||||||
// 校验存在
|
// 校验存在
|
||||||
SeckillActivityDO seckillActivity = validateSeckillActivityExists(updateReqVO.getId());
|
SeckillActivityDO seckillActivity = validateSeckillActivityExists(updateReqVO.getId());
|
||||||
if (CommonStatusEnum.ENABLE.getStatus().equals(seckillActivity.getStatus())) {
|
if (CommonStatusEnum.DISABLE.getStatus().equals(seckillActivity.getStatus())) {
|
||||||
throw exception(SECKILL_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED);
|
throw exception(SECKILL_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED);
|
||||||
}
|
}
|
||||||
// 校验商品是否冲突
|
// 校验商品是否冲突
|
||||||
validateProductSpuSeckillConflict(updateReqVO.getConfigIds(), updateReqVO.getSpuIds());
|
validateProductSpuSeckillConflict(updateReqVO.getConfigIds(), updateReqVO.getSpuId(), updateReqVO.getId());
|
||||||
// 获取所选 spu下的所有 sku
|
// 获取所选 spu下的所有 sku
|
||||||
List<ProductSkuRespDTO> skus = productSkuApi.getSkuListBySpuId(updateReqVO.getSpuIds());
|
List<ProductSkuRespDTO> skus = productSkuApi.getSkuListBySpuId(CollUtil.newArrayList(updateReqVO.getSpuId()));
|
||||||
// 校验商品 sku 是否存在
|
// 校验商品 sku 是否存在
|
||||||
validateProductSkuExistence(skus, updateReqVO.getProducts(), SeckillProductUpdateReqVO::getSkuId);
|
validateProductSkuExistence(skus, updateReqVO.getProducts(), SeckillProductUpdateReqVO::getSkuId);
|
||||||
|
|
||||||
// 更新活动
|
// 更新活动
|
||||||
SeckillActivityDO updateObj = SeckillActivityConvert.INSTANCE.convert(updateReqVO)
|
SeckillActivityDO updateObj = SeckillActivityConvert.INSTANCE.convert(updateReqVO)
|
||||||
.setStatus(PromotionUtils.calculateActivityStatus(updateReqVO.getEndTime()));
|
.setStatus(PromotionUtils.calculateActivityStatus(updateReqVO.getEndTime()))
|
||||||
|
.setTotalStock(CollectionUtils.getSumValue(updateReqVO.getProducts(), SeckillProductUpdateReqVO::getStock, Integer::sum));
|
||||||
seckillActivityMapper.updateById(updateObj);
|
seckillActivityMapper.updateById(updateObj);
|
||||||
// 更新商品
|
// 更新商品
|
||||||
//updateSeckillProduct(updateReqVO);
|
updateSeckillProduct(updateObj, updateReqVO.getProducts());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新秒杀商品
|
* 更新秒杀商品
|
||||||
* 后台查出的数据和前台查出的数据进行遍历,
|
|
||||||
* 1. 对前台数据进行遍历:如果不存在于后台的 sku 中需要新增
|
|
||||||
* 2. 对后台数据进行遍历:如果不存在于前台的 sku 中需要删除
|
|
||||||
* 3. 最后对当前活动商品全部更新,更新秒杀时段id列表
|
|
||||||
*
|
*
|
||||||
* @param updateReqVO 更新的请求VO
|
* @param updateObj DO
|
||||||
|
* @param products 商品配置
|
||||||
*/
|
*/
|
||||||
private void updateSeckillProduct(SeckillActivityUpdateReqVO updateReqVO) {
|
private void updateSeckillProduct(SeckillActivityDO updateObj, List<SeckillProductUpdateReqVO> products) {
|
||||||
// TODO puhui999:要不这里简单一点;删除原本的,插入新增的;不做的这么细致
|
List<SeckillProductDO> seckillProductDOs = seckillProductMapper.selectListByActivityId(updateObj.getId());
|
||||||
// TODO puhui999:后续完善
|
// 数据库中的活动商品
|
||||||
//List<SeckillProductDO> seckillProductDOs = seckillProductMapper.selectListByActivityId(updateReqVO.getId());
|
Set<Long> convertSet = CollectionUtils.convertSet(seckillProductDOs, SeckillProductDO::getSkuId);
|
||||||
//List<SeckillProductUpdateReqVO> products = updateReqVO.getProducts();
|
// 前端传过来的活动商品
|
||||||
|
Set<Long> convertSet1 = CollectionUtils.convertSet(products, SeckillProductUpdateReqVO::getSkuId);
|
||||||
////计算需要删除的数据
|
// 删除后台存在的前端不存在的商品
|
||||||
//List<Long> deleteIds = CollectionUtils.convertList(seckillProductDOs, SeckillProductDO::getId,
|
List<Long> d = CollectionUtils.filterList(convertSet, item -> !convertSet1.contains(item));
|
||||||
// seckillProductDO -> products.stream()
|
if (CollUtil.isNotEmpty(d)) {
|
||||||
// .noneMatch(product -> SeckillActivityConvert.INSTANCE.isEquals(seckillProductDO, product)));
|
seckillProductMapper.deleteBatchIds(d);
|
||||||
//if (CollUtil.isNotEmpty(deleteIds)) {
|
}
|
||||||
// seckillProductMapper.deleteBatchIds(deleteIds);
|
// 前端存在的后端不存在的商品
|
||||||
//}
|
List<Long> c = CollectionUtils.filterList(convertSet1, item -> !convertSet.contains(item));
|
||||||
//
|
if (CollUtil.isNotEmpty(c)) {
|
||||||
//// 计算需要新增的数据
|
List<SeckillProductUpdateReqVO> vos = CollectionUtils.filterList(products, item -> c.contains(item.getSkuId()));
|
||||||
//List<SeckillProductDO> newSeckillProductDOs = CollectionUtils.convertList(products,
|
List<SeckillProductDO> productDOs = SeckillActivityConvert.INSTANCE.convertList(updateObj, vos);
|
||||||
// product -> SeckillActivityConvert.INSTANCE.convert(product).setActivityId(updateReqVO.getId()));
|
seckillProductMapper.insertBatch(productDOs);
|
||||||
//newSeckillProductDOs.removeIf(product -> seckillProductDOs.stream()
|
}
|
||||||
// .anyMatch(seckillProduct -> SeckillActivityConvert.INSTANCE.isEquals(seckillProduct, product)));
|
// 更新已存在的商品
|
||||||
//if (CollUtil.isNotEmpty(newSeckillProductDOs)) {
|
List<Long> u = CollectionUtils.filterList(convertSet1, convertSet::contains);
|
||||||
// seckillProductMapper.insertBatch(newSeckillProductDOs);
|
if (CollUtil.isNotEmpty(u)) {
|
||||||
//}
|
List<SeckillProductUpdateReqVO> vos = CollectionUtils.filterList(products, item -> u.contains(item.getSkuId()));
|
||||||
|
List<SeckillProductDO> productDOs = SeckillActivityConvert.INSTANCE.convertList1(updateObj, vos, seckillProductDOs);
|
||||||
//全量更新当前活动商品的秒杀时段id列表(timeIds)
|
seckillProductMapper.insertBatch(productDOs);
|
||||||
seckillProductMapper.updateTimeIdsByActivityId(updateReqVO.getId(), updateReqVO.getConfigIds());
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void closeSeckillActivity(Long id) {
|
public void closeSeckillActivity(Long id) {
|
||||||
|
// TODO 待验证没使用过
|
||||||
// 校验存在
|
// 校验存在
|
||||||
SeckillActivityDO seckillActivity = this.validateSeckillActivityExists(id);
|
SeckillActivityDO seckillActivity = validateSeckillActivityExists(id);
|
||||||
if (PromotionActivityStatusEnum.CLOSE.getStatus().equals(seckillActivity.getStatus())) {
|
if (CommonStatusEnum.DISABLE.getStatus().equals(seckillActivity.getStatus())) {
|
||||||
throw exception(SECKILL_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED);
|
throw exception(SECKILL_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED);
|
||||||
}
|
}
|
||||||
if (PromotionActivityStatusEnum.END.getStatus().equals(seckillActivity.getStatus())) {
|
|
||||||
throw exception(SECKILL_ACTIVITY_CLOSE_FAIL_STATUS_END);
|
|
||||||
}
|
|
||||||
// 更新
|
// 更新
|
||||||
SeckillActivityDO updateObj = new SeckillActivityDO().setId(id).setStatus(PromotionActivityStatusEnum.CLOSE.getStatus());
|
SeckillActivityDO updateObj = new SeckillActivityDO().setId(id).setStatus(CommonStatusEnum.DISABLE.getStatus());
|
||||||
seckillActivityMapper.updateById(updateObj);
|
seckillActivityMapper.updateById(updateObj);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void deleteSeckillActivity(Long id) {
|
public void deleteSeckillActivity(Long id) {
|
||||||
// 校验存在
|
// 校验存在
|
||||||
SeckillActivityDO seckillActivity = this.validateSeckillActivityExists(id);
|
SeckillActivityDO seckillActivity = this.validateSeckillActivityExists(id);
|
||||||
List<Integer> statuses = asList(PromotionActivityStatusEnum.CLOSE.getStatus(), PromotionActivityStatusEnum.END.getStatus());
|
if (CommonStatusEnum.ENABLE.getStatus().equals(seckillActivity.getStatus())) {
|
||||||
if (!statuses.contains(seckillActivity.getStatus())) {
|
|
||||||
throw exception(SECKILL_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END);
|
throw exception(SECKILL_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除
|
// 删除活动
|
||||||
seckillActivityMapper.deleteById(id);
|
seckillActivityMapper.deleteById(id);
|
||||||
|
// 删除活动商品
|
||||||
|
List<SeckillProductDO> productDOs = seckillProductMapper.selectListByActivityId(id);
|
||||||
|
Set<Long> convertSet = CollectionUtils.convertSet(productDOs, SeckillProductDO::getSkuId);
|
||||||
|
seckillProductMapper.deleteBatchIds(convertSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
private SeckillActivityDO validateSeckillActivityExists(Long id) {
|
private SeckillActivityDO validateSeckillActivityExists(Long id) {
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
package cn.iocoder.yudao.module.promotion.service.seckill.seckillconfig;
|
package cn.iocoder.yudao.module.promotion.service.seckill.seckillconfig;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
|
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||||
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigCreateReqVO;
|
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigCreateReqVO;
|
||||||
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigPageReqVO;
|
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigPageReqVO;
|
||||||
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigUpdateReqVO;
|
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigUpdateReqVO;
|
||||||
@ -127,10 +129,18 @@ public class SeckillConfigServiceImpl implements SeckillConfigService {
|
|||||||
if (CollUtil.isEmpty(configIds)) {
|
if (CollUtil.isEmpty(configIds)) {
|
||||||
throw exception(SECKILL_TIME_NOT_EXISTS);
|
throw exception(SECKILL_TIME_NOT_EXISTS);
|
||||||
}
|
}
|
||||||
if (seckillConfigMapper.selectBatchIds(configIds).size() != configIds.size()) {
|
List<SeckillConfigDO> configDOs = seckillConfigMapper.selectBatchIds(configIds);
|
||||||
|
if (CollUtil.isEmpty(configDOs)) {
|
||||||
|
throw exception(SECKILL_TIME_NOT_EXISTS);
|
||||||
|
}
|
||||||
|
// 过滤出关闭的时段
|
||||||
|
List<SeckillConfigDO> filterList = CollectionUtils.filterList(configDOs, item -> ObjectUtil.equal(item.getStatus(), CommonStatusEnum.DISABLE.getStatus()));
|
||||||
|
if (CollUtil.isNotEmpty(filterList)) {
|
||||||
|
throw exception(SECKILL_TIME_DISABLE);
|
||||||
|
}
|
||||||
|
if (configDOs.size() != configIds.size()) {
|
||||||
throw exception(SECKILL_TIME_NOT_EXISTS);
|
throw exception(SECKILL_TIME_NOT_EXISTS);
|
||||||
}
|
}
|
||||||
// TODO @puhui999:应该要校验个 status 哈;如果有禁用的,也不行
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package cn.iocoder.yudao.module.promotion.util;
|
package cn.iocoder.yudao.module.promotion.util;
|
||||||
|
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
|
||||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||||
import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils;
|
import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils;
|
||||||
@ -35,9 +34,6 @@ public class PromotionUtils {
|
|||||||
// 校验 sku 个数是否一致
|
// 校验 sku 个数是否一致
|
||||||
Set<Long> skuIdsSet = CollectionUtils.convertSet(products, func);
|
Set<Long> skuIdsSet = CollectionUtils.convertSet(products, func);
|
||||||
Set<Long> skuIdsSet1 = CollectionUtils.convertSet(skus, ProductSkuRespDTO::getId);
|
Set<Long> skuIdsSet1 = CollectionUtils.convertSet(skus, ProductSkuRespDTO::getId);
|
||||||
if (ObjectUtil.notEqual(skuIdsSet.size(), skuIdsSet1.size())) {
|
|
||||||
throw exception(SKU_NOT_EXISTS);
|
|
||||||
}
|
|
||||||
// 校验 skuId 是否存在
|
// 校验 skuId 是否存在
|
||||||
if (!skuIdsSet1.containsAll(skuIdsSet) || !skuIdsSet.containsAll(skuIdsSet1)) {
|
if (!skuIdsSet1.containsAll(skuIdsSet) || !skuIdsSet.containsAll(skuIdsSet1)) {
|
||||||
throw exception(SKU_NOT_EXISTS);
|
throw exception(SKU_NOT_EXISTS);
|
||||||
|
Loading…
Reference in New Issue
Block a user