优化秒杀活动的管理后台代码

This commit is contained in:
YunaiV 2023-08-12 16:05:47 +08:00
parent be2ee905df
commit 6fdd4da0b3
20 changed files with 183 additions and 209 deletions

View File

@ -21,4 +21,11 @@ public interface ProductSpuApi {
*/ */
List<ProductSpuRespDTO> getSpuList(Collection<Long> ids); List<ProductSpuRespDTO> getSpuList(Collection<Long> ids);
/**
* 获得 SPU
*
* @return SPU
*/
ProductSpuRespDTO getSpu(Long id);
} }

View File

@ -5,6 +5,8 @@ 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.convert.spu.ProductSpuConvert;
import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
import cn.iocoder.yudao.module.product.dal.mysql.spu.ProductSpuMapper; import cn.iocoder.yudao.module.product.dal.mysql.spu.ProductSpuMapper;
import cn.iocoder.yudao.module.product.service.sku.ProductSkuService;
import cn.iocoder.yudao.module.product.service.spu.ProductSpuService;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
@ -24,15 +26,19 @@ import java.util.List;
public class ProductSpuApiImpl implements ProductSpuApi { public class ProductSpuApiImpl implements ProductSpuApi {
@Resource @Resource
private ProductSpuMapper productSpuMapper; private ProductSpuService spuService;
@Override @Override
public List<ProductSpuRespDTO> getSpuList(Collection<Long> spuIds) { public List<ProductSpuRespDTO> getSpuList(Collection<Long> ids) {
if (CollectionUtil.isEmpty(spuIds)) { if (CollectionUtil.isEmpty(ids)) {
return Collections.emptyList(); return Collections.emptyList();
} }
List<ProductSpuDO> productSpuDOList = productSpuMapper.selectBatchIds(spuIds); return ProductSpuConvert.INSTANCE.convertList2(spuService.getSpuList(ids));
return ProductSpuConvert.INSTANCE.convertList2(productSpuDOList); }
@Override
public ProductSpuRespDTO getSpu(Long id) {
return ProductSpuConvert.INSTANCE.convert02(spuService.getSpu(id));
} }
} }

View File

@ -64,6 +64,8 @@ public interface ProductSpuConvert {
ProductSpuDetailRespVO convert03(ProductSpuDO spu); ProductSpuDetailRespVO convert03(ProductSpuDO spu);
ProductSpuRespDTO convert02(ProductSpuDO bean);
// ========== 用户 App 相关 ========== // ========== 用户 App 相关 ==========
PageResult<AppProductSpuPageRespVO> convertPageForGetSpuPage(PageResult<ProductSpuDO> page); PageResult<AppProductSpuPageRespVO> convertPageForGetSpuPage(PageResult<ProductSpuDO> page);

View File

@ -50,14 +50,11 @@ public interface ErrorCodeConstants {
ErrorCode SECKILL_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED = new ErrorCode(1013008003, "秒杀活动已关闭,不能修改"); ErrorCode SECKILL_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED = new ErrorCode(1013008003, "秒杀活动已关闭,不能修改");
ErrorCode SECKILL_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1013008004, "秒杀活动未关闭或未结束,不能删除"); ErrorCode SECKILL_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1013008004, "秒杀活动未关闭或未结束,不能删除");
ErrorCode SECKILL_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1013008005, "秒杀活动已关闭,不能重复关闭"); ErrorCode SECKILL_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1013008005, "秒杀活动已关闭,不能重复关闭");
ErrorCode SECKILL_ACTIVITY_CLOSE_FAIL_STATUS_END = new ErrorCode(1013008006, "秒杀活动已结束,不能关闭");
// ========== 秒杀时段 1013009000 ========== // ========== 秒杀时段 1013009000 ==========
ErrorCode SECKILL_TIME_NOT_EXISTS = new ErrorCode(1013009000, "秒杀时段不存在"); ErrorCode SECKILL_CONFIG_NOT_EXISTS = new ErrorCode(1013009000, "秒杀时段不存在");
ErrorCode SECKILL_TIME_CONFLICTS = new ErrorCode(1013009001, "秒杀时段冲突"); ErrorCode SECKILL_CONFIG_TIME_CONFLICTS = new ErrorCode(1013009001, "秒杀时段冲突");
ErrorCode SECKILL_TIME_EQUAL = new ErrorCode(1013009002, "秒杀时段开始时间和结束时间不能相等"); ErrorCode SECKILL_CONFIG_DISABLE = new ErrorCode(1013009004, "秒杀时段已关闭");
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, "拼团活动不存在");

View File

@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.promotion.controller.admin.seckill; package cn.iocoder.yudao.module.promotion.controller.admin.seckill;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi; import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
@ -19,7 +20,6 @@ import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.validation.Valid; import javax.validation.Valid;
import java.util.List; import java.util.List;
import java.util.Set;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
@ -33,7 +33,7 @@ public class SeckillActivityController {
@Resource @Resource
private SeckillActivityService seckillActivityService; private SeckillActivityService seckillActivityService;
@Resource @Resource
private ProductSpuApi spuApi; private ProductSpuApi productSpuApi;
@PostMapping("/create") @PostMapping("/create")
@Operation(summary = "创建秒杀活动") @Operation(summary = "创建秒杀活动")
@ -73,21 +73,27 @@ public class SeckillActivityController {
@Parameter(name = "id", description = "编号", required = true, example = "1024") @Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('promotion:seckill-activity:query')") @PreAuthorize("@ss.hasPermission('promotion:seckill-activity:query')")
public CommonResult<SeckillActivityDetailRespVO> getSeckillActivity(@RequestParam("id") Long id) { public CommonResult<SeckillActivityDetailRespVO> getSeckillActivity(@RequestParam("id") Long id) {
SeckillActivityDO seckillActivity = seckillActivityService.getSeckillActivity(id); SeckillActivityDO activity = seckillActivityService.getSeckillActivity(id);
List<SeckillProductDO> seckillProducts = seckillActivityService.getSeckillProductListByActivityId(id); List<SeckillProductDO> products = seckillActivityService.getSeckillProductListByActivityId(id);
return success(SeckillActivityConvert.INSTANCE.convert(seckillActivity, seckillProducts)); return success(SeckillActivityConvert.INSTANCE.convert(activity, products));
} }
@GetMapping("/page") @GetMapping("/page")
@Operation(summary = "获得秒杀活动分页") @Operation(summary = "获得秒杀活动分页")
@PreAuthorize("@ss.hasPermission('promotion:seckill-activity:query')") @PreAuthorize("@ss.hasPermission('promotion:seckill-activity:query')")
public CommonResult<PageResult<SeckillActivityRespVO>> getSeckillActivityPage(@Valid SeckillActivityPageReqVO pageVO) { public CommonResult<PageResult<SeckillActivityRespVO>> getSeckillActivityPage(@Valid SeckillActivityPageReqVO pageVO) {
// 查询活动列表
PageResult<SeckillActivityDO> pageResult = seckillActivityService.getSeckillActivityPage(pageVO); PageResult<SeckillActivityDO> pageResult = seckillActivityService.getSeckillActivityPage(pageVO);
Set<Long> aIds = convertSet(pageResult.getList(), SeckillActivityDO::getId); if (CollUtil.isEmpty(pageResult.getList())) {
List<SeckillProductDO> seckillProducts = seckillActivityService.getSeckillProductListByActivityId(aIds); return success(PageResult.empty(pageResult.getTotal()));
Set<Long> spuIds = convertSet(pageResult.getList(), SeckillActivityDO::getSpuId); }
List<ProductSpuRespDTO> spuList = spuApi.getSpuList(spuIds);
return success(SeckillActivityConvert.INSTANCE.convertPage(pageResult, seckillProducts, spuList)); // 拼接数据
List<SeckillProductDO> products = seckillActivityService.getSeckillProductListByActivityId(
convertSet(pageResult.getList(), SeckillActivityDO::getId));
List<ProductSpuRespDTO> spuList = productSpuApi.getSpuList(
convertSet(pageResult.getList(), SeckillActivityDO::getSpuId));
return success(SeckillActivityConvert.INSTANCE.convertPage(pageResult, products, spuList));
} }
} }

View File

@ -92,4 +92,5 @@ public class SeckillConfigController {
PageResult<SeckillConfigDO> pageResult = seckillConfigService.getSeckillConfigPage(pageVO); PageResult<SeckillConfigDO> pageResult = seckillConfigService.getSeckillConfigPage(pageVO);
return success(SeckillConfigConvert.INSTANCE.convertPage(pageResult)); return success(SeckillConfigConvert.INSTANCE.convertPage(pageResult));
} }
} }

View File

@ -20,7 +20,7 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
@Data @Data
public class SeckillActivityBaseVO { public class SeckillActivityBaseVO {
@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 Long spuId; private Long spuId;

View File

@ -1,7 +1,7 @@
package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity; package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity;
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 io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
@ -16,6 +16,6 @@ import java.util.List;
public class SeckillActivityCreateReqVO extends SeckillActivityBaseVO { public class SeckillActivityCreateReqVO extends SeckillActivityBaseVO {
@Schema(description = "秒杀商品", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "秒杀商品", requiredMode = Schema.RequiredMode.REQUIRED)
private List<SeckillProductCreateReqVO> products; private List<SeckillProductBaseVO> products;
} }

View File

@ -21,28 +21,28 @@ public class SeckillActivityRespVO extends SeckillActivityBaseVO {
@Schema(description = "商品主图", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xx.png") @Schema(description = "商品主图", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xx.png")
private String picUrl; private String picUrl;
@Schema(description = "秒杀活动id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @Schema(description = "秒杀活动 id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long id; private Long id;
@Schema(description = "秒杀商品", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "秒杀商品", requiredMode = Schema.RequiredMode.REQUIRED)
private List<SeckillProductRespVO> products; private List<SeckillProductRespVO> products;
@Schema(description = "活动状态 开启0 禁用1", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") @Schema(description = "活动状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
private Integer status; private Integer status;
@Schema(description = "订单实付金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "22354") @Schema(description = "订单实付金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "22354")
private Integer totalPrice; private Integer totalPrice;
@Schema(description = "秒杀库存", example = "10") @Schema(description = "秒杀库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
private Integer stock; private Integer stock;
@Schema(description = "秒杀总库存", example = "20") @Schema(description = "秒杀总库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "20")
private Integer totalStock; private Integer totalStock;
@Schema(description = "新增订单数", example = "20") @Schema(description = "新增订单数", requiredMode = Schema.RequiredMode.REQUIRED, example = "20")
private Integer orderCount; private Integer orderCount;
@Schema(description = "付款人数", example = "20") @Schema(description = "付款人数", requiredMode = Schema.RequiredMode.REQUIRED, example = "20")
private Integer userCount; private Integer userCount;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)

View File

@ -1,6 +1,6 @@
package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity; package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity;
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductUpdateReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductBaseVO;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
@ -18,6 +18,6 @@ public class SeckillActivityUpdateReqVO extends SeckillActivityBaseVO {
private Long id; private Long id;
@Schema(description = "秒杀商品", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "秒杀商品", requiredMode = Schema.RequiredMode.REQUIRED)
private List<SeckillProductUpdateReqVO> products; private List<SeckillProductBaseVO> products;
} }

View File

@ -22,7 +22,7 @@ public class SeckillProductBaseVO {
@NotNull(message = "秒杀金额,单位:分不能为空") @NotNull(message = "秒杀金额,单位:分不能为空")
private Integer seckillPrice; private Integer seckillPrice;
@Schema(description = "秒杀库存", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "秒杀库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
@NotNull(message = "秒杀库存不能为空") @NotNull(message = "秒杀库存不能为空")
private Integer stock; private Integer stock;

View File

@ -1,13 +0,0 @@
package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@Schema(description = "管理后台 - 秒杀参与商品创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class SeckillProductCreateReqVO extends SeckillProductBaseVO {
}

View File

@ -1,14 +0,0 @@
package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@Schema(description = "管理后台 - 秒杀参与商品更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class SeckillProductUpdateReqVO extends SeckillProductBaseVO {
}

View File

@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.promotion.convert.seckill.seckillactivity;
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.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; 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.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;
@ -19,6 +20,8 @@ import org.mapstruct.factory.Mappers;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
/** /**
* 秒杀活动 Convert * 秒杀活动 Convert
* *
@ -37,43 +40,43 @@ public interface SeckillActivityConvert {
List<SeckillActivityRespVO> convertList(List<SeckillActivityDO> list); List<SeckillActivityRespVO> convertList(List<SeckillActivityDO> list);
PageResult<SeckillActivityRespVO> convertPage(PageResult<SeckillActivityDO> page); default PageResult<SeckillActivityRespVO> convertPage(PageResult<SeckillActivityDO> page,
List<SeckillProductDO> seckillProducts,
default PageResult<SeckillActivityRespVO> convertPage(PageResult<SeckillActivityDO> page, List<SeckillProductDO> seckillProducts, List<ProductSpuRespDTO> spuList) { List<ProductSpuRespDTO> spuList) {
Map<Long, ProductSpuRespDTO> spuMap = CollectionUtils.convertMap(spuList, ProductSpuRespDTO::getId, c -> c);
PageResult<SeckillActivityRespVO> pageResult = convertPage(page); PageResult<SeckillActivityRespVO> pageResult = convertPage(page);
// 拼接商品
Map<Long, ProductSpuRespDTO> spuMap = convertMap(spuList, ProductSpuRespDTO::getId);
pageResult.getList().forEach(item -> { pageResult.getList().forEach(item -> {
item.setSpuName(spuMap.get(item.getSpuId()).getName());
item.setPicUrl(spuMap.get(item.getSpuId()).getPicUrl());
item.setProducts(convertList2(seckillProducts)); item.setProducts(convertList2(seckillProducts));
MapUtils.findAndThen(spuMap, item.getSpuId(),
spu -> item.setSpuName(spu.getName()).setPicUrl(spu.getPicUrl()));
}); });
return pageResult; return pageResult;
} }
PageResult<SeckillActivityRespVO> convertPage(PageResult<SeckillActivityDO> page);
SeckillActivityDetailRespVO convert1(SeckillActivityDO seckillActivity); SeckillActivityDetailRespVO convert1(SeckillActivityDO seckillActivity);
default SeckillActivityDetailRespVO convert(SeckillActivityDO seckillActivity, List<SeckillProductDO> seckillProducts) { default SeckillActivityDetailRespVO convert(SeckillActivityDO activity,
return convert1(seckillActivity).setProducts(convertList2(seckillProducts)); List<SeckillProductDO> products) {
return convert1(activity).setProducts(convertList2(products));
} }
List<SeckillProductRespVO> convertList2(List<SeckillProductDO> productDOs);
// TODO @puhui999参数改成 activityproduct 会不会干净一点哈
@Mappings({
@Mapping(target = "id", ignore = true),
@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(List<? extends SeckillProductBaseVO> products, SeckillActivityDO activityDO) { default List<SeckillProductDO> convertList(List<? extends SeckillProductBaseVO> products, SeckillActivityDO activityDO) {
return CollectionUtils.convertList(products, item -> convert(activityDO, item).setActivityStatus(activityDO.getStatus())); return CollectionUtils.convertList(products, item -> convert(activityDO, item).setActivityStatus(activityDO.getStatus()));
} }
@Mappings({
List<SeckillProductRespVO> convertList2(List<SeckillProductDO> productDOs); @Mapping(target = "id", ignore = true),
@Mapping(target = "activityId", source = "activity.id"),
@Mapping(target = "configIds", source = "activity.configIds"),
@Mapping(target = "spuId", source = "activity.spuId"),
@Mapping(target = "skuId", source = "product.skuId"),
@Mapping(target = "seckillPrice", source = "product.seckillPrice"),
@Mapping(target = "stock", source = "product.stock"),
@Mapping(target = "activityStartTime", source = "activity.startTime"),
@Mapping(target = "activityEndTime", source = "activity.endTime")
})
SeckillProductDO convert(SeckillActivityDO activity, SeckillProductBaseVO product);
} }

View File

@ -1,9 +1,7 @@
package cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillactivity; package cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillactivity;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
import java.util.Collection; import java.util.Collection;
@ -25,15 +23,4 @@ public interface SeckillProductMapper extends BaseMapperX<SeckillProductDO> {
return selectList(SeckillProductDO::getActivityId, ids); return selectList(SeckillProductDO::getActivityId, ids);
} }
default List<SeckillProductDO> selectListBySkuIds(Collection<Long> skuIds) {
return selectList(SeckillProductDO::getSkuId, skuIds);
}
default void updateTimeIdsByActivityId(Long id, List<Long> timeIds) {
new LambdaUpdateChainWrapper<>(this)
.set(SeckillProductDO::getConfigIds, CollUtil.join(timeIds, ","))
.eq(SeckillProductDO::getActivityId, id)
.update();
}
} }

View File

@ -55,14 +55,6 @@ public interface SeckillActivityService {
*/ */
SeckillActivityDO getSeckillActivity(Long id); SeckillActivityDO getSeckillActivity(Long id);
/**
* 获得秒杀活动列表
*
* @param ids 编号
* @return 秒杀活动列表
*/
List<SeckillActivityDO> getSeckillActivityList(Collection<Long> ids);
/** /**
* 获得秒杀活动分页 * 获得秒杀活动分页
* *
@ -74,17 +66,17 @@ public interface SeckillActivityService {
/** /**
* 通过活动编号获取活动商品 * 通过活动编号获取活动商品
* *
* @param id 活动编号 * @param activityId 活动编号
* @return 活动商品列表 * @return 活动商品列表
*/ */
List<SeckillProductDO> getSeckillProductListByActivityId(Long id); List<SeckillProductDO> getSeckillProductListByActivityId(Long activityId);
/** /**
* 通过活动编号获取活动商品 * 通过活动编号获取活动商品
* *
* @param ids 活动编号 * @param activityIds 活动编号
* @return 活动商品列表 * @return 活动商品列表
*/ */
List<SeckillProductDO> getSeckillProductListByActivityId(Collection<Long> ids); List<SeckillProductDO> getSeckillProductListByActivityId(Collection<Long> activityIds);
} }

View File

@ -1,6 +1,5 @@
package cn.iocoder.yudao.module.promotion.service.seckill.seckillactivity; package cn.iocoder.yudao.module.promotion.service.seckill.seckillactivity;
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;
@ -11,8 +10,7 @@ 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.SeckillActivityCreateReqVO;
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityPageReqVO; 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.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.convert.seckill.seckillactivity.SeckillActivityConvert; 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.SeckillActivityDO;
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO;
@ -27,7 +25,7 @@ import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Map;
import static cn.hutool.core.collection.CollUtil.isNotEmpty; import static cn.hutool.core.collection.CollUtil.isNotEmpty;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
@ -35,7 +33,7 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS; 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.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.validateProductSkuAllExists; import static java.util.Collections.singletonList;
/** /**
* 秒杀活动 Service 实现类 * 秒杀活动 Service 实现类
@ -60,19 +58,15 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public Long createSeckillActivity(SeckillActivityCreateReqVO createReqVO) { public Long createSeckillActivity(SeckillActivityCreateReqVO createReqVO) {
// 校验商品秒秒杀时段是否冲突 // 校验商品秒杀时段是否冲突
validateProductSpuSeckillConflict(createReqVO.getConfigIds(), createReqVO.getSpuId(), null); validateProductConflict(createReqVO.getConfigIds(), createReqVO.getSpuId(), null);
// 获取所选 spu 下的所有 sku // 校验商品是否存在
List<ProductSkuRespDTO> skus = productSkuApi.getSkuListBySpuId(CollUtil.newArrayList(createReqVO.getSpuId())); validateProductExists(createReqVO.getSpuId(), createReqVO.getProducts());
// 校验商品 sku 是否存在
if (skus.size() != createReqVO.getProducts().size()) {
throw exception(SKU_NOT_EXISTS);
}
// 插入秒杀活动 // 插入秒杀活动
SeckillActivityDO activity = SeckillActivityConvert.INSTANCE.convert(createReqVO) SeckillActivityDO activity = SeckillActivityConvert.INSTANCE.convert(createReqVO)
.setStatus(PromotionUtils.calculateActivityStatus(createReqVO.getEndTime())) .setStatus(PromotionUtils.calculateActivityStatus(createReqVO.getEndTime()))
.setTotalStock(getSumValue(createReqVO.getProducts(), SeckillProductCreateReqVO::getStock, Integer::sum)); .setTotalStock(getSumValue(createReqVO.getProducts(), SeckillProductBaseVO::getStock, Integer::sum));
seckillActivityMapper.insert(activity); seckillActivityMapper.insert(activity);
// 插入商品 // 插入商品
List<SeckillProductDO> products = SeckillActivityConvert.INSTANCE.convertList(createReqVO.getProducts(), activity); List<SeckillProductDO> products = SeckillActivityConvert.INSTANCE.convertList(createReqVO.getProducts(), activity);
@ -80,35 +74,62 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
return activity.getId(); return activity.getId();
} }
private void validateProductSpuSeckillConflict(List<Long> configIds, Long spuId, Long activityId) { /**
// 校验秒杀时段是否存在 * 校验秒杀商品参与的活动是否存在冲突
*
* 1. 校验秒杀时段是否存在
* 2. 校验商品 spu 是否存在
* 3. 秒杀商品是否参加其它活动
*
* @param configIds 秒杀时段数组
* @param spuId 商品 SPU 编号
* @param activityId 秒杀活动编号
*/
private void validateProductConflict(List<Long> configIds, Long spuId, Long activityId) {
// 1. 校验秒杀时段是否存在
seckillConfigService.validateSeckillConfigExists(configIds); seckillConfigService.validateSeckillConfigExists(configIds);
// 校验商品 spu 是否存在
List<ProductSpuRespDTO> spuList = productSpuApi.getSpuList(CollUtil.newArrayList(spuId)); // 2.1 查询所有开启的秒杀活动
if (CollUtil.isEmpty(spuList)) { List<SeckillActivityDO> activityList = seckillActivityMapper.selectListByStatus(CommonStatusEnum.ENABLE.getStatus());
throw exception(SPU_NOT_EXISTS); if (activityId != null) { // 排除自己
activityList.removeIf(item -> ObjectUtil.equal(item.getId(), activityId));
} }
// 查询所有开启的秒杀活动 // TODO @puhui999一个 spu参与两个活动应该没关系关键是活动时间不充能重叠
List<SeckillActivityDO> activityDOs = seckillActivityMapper.selectListByStatus(CommonStatusEnum.ENABLE.getStatus()); // 2.2 过滤出所有 spuId 有交集的活动判断是否存在重叠
if (activityId != null) { List<SeckillActivityDO> activityDOs1 = filterList(activityList, s -> ObjectUtil.equal(s.getSpuId(), spuId));
// 更新时移除本活动
activityDOs.removeIf(item -> ObjectUtil.equal(item.getId(), activityId));
}
// 过滤出所有 spuId 有交集的活动
List<SeckillActivityDO> activityDOs1 = convertList(activityDOs, c -> c, s -> ObjectUtil.equal(s.getSpuId(), spuId));
if (isNotEmpty(activityDOs1)) { if (isNotEmpty(activityDOs1)) {
throw exception(SECKILL_ACTIVITY_SPU_CONFLICTS); throw exception(SECKILL_ACTIVITY_SPU_CONFLICTS);
} }
List<SeckillActivityDO> activityDOs2 = convertList(activityDOs, c -> c, s -> { // 2.3 过滤出所有 configIds 有交集的活动判断是否存在重叠
// 判断秒杀时段是否有交集 List<SeckillActivityDO> activityDOs2 = filterList(activityList, s -> containsAny(s.getConfigIds(), configIds));
return containsAny(s.getConfigIds(), configIds);
});
if (isNotEmpty(activityDOs2)) { if (isNotEmpty(activityDOs2)) {
throw exception(SECKILL_TIME_CONFLICTS); throw exception(SECKILL_ACTIVITY_SPU_CONFLICTS);
} }
} }
/**
* 校验秒杀商品是否都存在
*
* @param spuId 商品 SPU 编号
* @param products 秒杀商品
*/
private void validateProductExists(Long spuId, List<SeckillProductBaseVO> products) {
// 1. 校验商品 spu 是否存在
ProductSpuRespDTO spu = productSpuApi.getSpu(spuId);
if (spu == null) {
throw exception(SPU_NOT_EXISTS);
}
// 2. 校验商品 sku 都存在
Map<Long, ProductSkuRespDTO> skuMap = convertMap(productSkuApi.getSkuListBySpuId(singletonList(spuId)),
ProductSkuRespDTO::getId);
products.forEach(product -> {
if (!skuMap.containsKey(product.getSkuId())) {
throw exception(SKU_NOT_EXISTS);
}
});
}
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void updateSeckillActivity(SeckillActivityUpdateReqVO updateReqVO) { public void updateSeckillActivity(SeckillActivityUpdateReqVO updateReqVO) {
@ -118,29 +139,26 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
throw exception(SECKILL_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED); throw exception(SECKILL_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED);
} }
// 校验商品是否冲突 // 校验商品是否冲突
validateProductSpuSeckillConflict(updateReqVO.getConfigIds(), updateReqVO.getSpuId(), updateReqVO.getId()); validateProductConflict(updateReqVO.getConfigIds(), updateReqVO.getSpuId(), updateReqVO.getId());
// 获取所选 spu下的所有 sku // 校验商品是否存在
List<ProductSkuRespDTO> skus = productSkuApi.getSkuListBySpuId(CollUtil.newArrayList(updateReqVO.getSpuId())); validateProductExists(updateReqVO.getSpuId(), updateReqVO.getProducts());
// 校验商品 sku 是否存在
validateProductSkuAllExists(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(getSumValue(updateReqVO.getProducts(), SeckillProductUpdateReqVO::getStock, Integer::sum)); .setTotalStock(getSumValue(updateReqVO.getProducts(), SeckillProductBaseVO::getStock, Integer::sum));
seckillActivityMapper.updateById(updateObj); seckillActivityMapper.updateById(updateObj);
// 更新商品 // 更新商品
updateSeckillProduct(updateObj, updateReqVO.getProducts()); updateSeckillProduct(updateObj, updateReqVO.getProducts());
} }
/** /**
* 更新秒杀商品 * 更新秒杀商品
* *
* @param activity 秒杀活动 * @param activity 秒杀活动
* @param products 该活动的最新商品配置 * @param products 该活动的最新商品配置
*/ */
private void updateSeckillProduct(SeckillActivityDO activity, List<SeckillProductUpdateReqVO> products) { private void updateSeckillProduct(SeckillActivityDO activity, List<SeckillProductBaseVO> products) {
// 第一步对比新老数据获得添加修改删除的列表 // 第一步对比新老数据获得添加修改删除的列表
List<SeckillProductDO> newList = SeckillActivityConvert.INSTANCE.convertList(products, activity); List<SeckillProductDO> newList = SeckillActivityConvert.INSTANCE.convertList(products, activity);
List<SeckillProductDO> oldList = seckillProductMapper.selectListByActivityId(activity.getId()); List<SeckillProductDO> oldList = seckillProductMapper.selectListByActivityId(activity.getId());
@ -159,7 +177,6 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
if (isNotEmpty(diffList.get(1))) { if (isNotEmpty(diffList.get(1))) {
seckillProductMapper.updateBatch(diffList.get(1)); seckillProductMapper.updateBatch(diffList.get(1));
} }
// delete
if (isNotEmpty(diffList.get(2))) { if (isNotEmpty(diffList.get(2))) {
seckillProductMapper.deleteBatchIds(convertList(diffList.get(2), SeckillProductDO::getId)); seckillProductMapper.deleteBatchIds(convertList(diffList.get(2), SeckillProductDO::getId));
} }
@ -167,7 +184,6 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
@Override @Override
public void closeSeckillActivity(Long id) { public void closeSeckillActivity(Long id) {
// TODO 待验证没使用过
// 校验存在 // 校验存在
SeckillActivityDO activity = validateSeckillActivityExists(id); SeckillActivityDO activity = validateSeckillActivityExists(id);
if (CommonStatusEnum.DISABLE.getStatus().equals(activity.getStatus())) { if (CommonStatusEnum.DISABLE.getStatus().equals(activity.getStatus())) {
@ -191,9 +207,8 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
// 删除活动 // 删除活动
seckillActivityMapper.deleteById(id); seckillActivityMapper.deleteById(id);
// 删除活动商品 // 删除活动商品
List<SeckillProductDO> productDOs = seckillProductMapper.selectListByActivityId(id); List<SeckillProductDO> products = seckillProductMapper.selectListByActivityId(id);
Set<Long> convertSet = convertSet(productDOs, SeckillProductDO::getSkuId); seckillProductMapper.deleteBatchIds(convertSet(products, SeckillProductDO::getId));
seckillProductMapper.deleteBatchIds(convertSet);
} }
private SeckillActivityDO validateSeckillActivityExists(Long id) { private SeckillActivityDO validateSeckillActivityExists(Long id) {
@ -209,24 +224,19 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
return validateSeckillActivityExists(id); return validateSeckillActivityExists(id);
} }
@Override
public List<SeckillActivityDO> getSeckillActivityList(Collection<Long> ids) {
return seckillActivityMapper.selectBatchIds(ids);
}
@Override @Override
public PageResult<SeckillActivityDO> getSeckillActivityPage(SeckillActivityPageReqVO pageReqVO) { public PageResult<SeckillActivityDO> getSeckillActivityPage(SeckillActivityPageReqVO pageReqVO) {
return seckillActivityMapper.selectPage(pageReqVO); return seckillActivityMapper.selectPage(pageReqVO);
} }
@Override @Override
public List<SeckillProductDO> getSeckillProductListByActivityId(Long id) { public List<SeckillProductDO> getSeckillProductListByActivityId(Long activityId) {
return seckillProductMapper.selectListByActivityId(id); return seckillProductMapper.selectListByActivityId(activityId);
} }
@Override @Override
public List<SeckillProductDO> getSeckillProductListByActivityId(Collection<Long> ids) { public List<SeckillProductDO> getSeckillProductListByActivityId(Collection<Long> activityIds) {
return seckillProductMapper.selectListByActivityId(ids); return seckillProductMapper.selectListByActivityId(activityIds);
} }
} }

View File

@ -57,10 +57,9 @@ public interface SeckillConfigService {
/** /**
* 校验秒杀时段是否存在 * 校验秒杀时段是否存在
* *
* @param timeIds 秒杀时段id集合 * @param ids 秒杀时段 id 集合
*/ */
void validateSeckillConfigExists(Collection<Long> timeIds); void validateSeckillConfigExists(Collection<Long> ids);
/** /**
* 获得秒杀时间段配置分页数据 * 获得秒杀时间段配置分页数据
@ -85,4 +84,5 @@ public interface SeckillConfigService {
* @param status 状态 * @param status 状态
*/ */
void updateSeckillConfigStatus(Long id, Integer status); void updateSeckillConfigStatus(Long id, Integer status);
} }

View File

@ -4,7 +4,6 @@ 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.framework.common.util.date.LocalDateTimeUtils; import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils;
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;
@ -13,7 +12,6 @@ import cn.iocoder.yudao.module.promotion.convert.seckill.seckillconfig.SeckillCo
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillconfig.SeckillConfigDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillconfig.SeckillConfigDO;
import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillconfig.SeckillConfigMapper; import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillconfig.SeckillConfigMapper;
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;
@ -37,7 +35,6 @@ public class SeckillConfigServiceImpl implements SeckillConfigService {
private SeckillConfigMapper seckillConfigMapper; private SeckillConfigMapper seckillConfigMapper;
@Override @Override
@Transactional(rollbackFor = Exception.class)
public Long createSeckillConfig(SeckillConfigCreateReqVO createReqVO) { public Long createSeckillConfig(SeckillConfigCreateReqVO createReqVO) {
// 校验时间段是否冲突 // 校验时间段是否冲突
validateSeckillConfigConflict(createReqVO.getStartTime(), createReqVO.getEndTime(), null); validateSeckillConfigConflict(createReqVO.getStartTime(), createReqVO.getEndTime(), null);
@ -50,7 +47,6 @@ public class SeckillConfigServiceImpl implements SeckillConfigService {
} }
@Override @Override
@Transactional(rollbackFor = Exception.class)
public void updateSeckillConfig(SeckillConfigUpdateReqVO updateReqVO) { public void updateSeckillConfig(SeckillConfigUpdateReqVO updateReqVO) {
// 校验存在 // 校验存在
validateSeckillConfigExists(updateReqVO.getId()); validateSeckillConfigExists(updateReqVO.getId());
@ -62,7 +58,6 @@ public class SeckillConfigServiceImpl implements SeckillConfigService {
seckillConfigMapper.updateById(updateObj); seckillConfigMapper.updateById(updateObj);
} }
// TODO @puhui999: 这个要不合并到更新操作里? 不单独有个操作咧; fix: 更新状态不用那么多必须的参数更新的时候需要校验时间段
@Override @Override
public void updateSeckillConfigStatus(Long id, Integer status) { public void updateSeckillConfigStatus(Long id, Integer status) {
// 校验秒杀时段是否存在 // 校验秒杀时段是否存在
@ -73,7 +68,6 @@ public class SeckillConfigServiceImpl implements SeckillConfigService {
} }
@Override @Override
@Transactional(rollbackFor = Exception.class)
public void deleteSeckillConfig(Long id) { public void deleteSeckillConfig(Long id) {
// 校验存在 // 校验存在
validateSeckillConfigExists(id); validateSeckillConfigExists(id);
@ -84,35 +78,31 @@ public class SeckillConfigServiceImpl implements SeckillConfigService {
private void validateSeckillConfigExists(Long id) { private void validateSeckillConfigExists(Long id) {
if (seckillConfigMapper.selectById(id) == null) { if (seckillConfigMapper.selectById(id) == null) {
throw exception(SECKILL_TIME_NOT_EXISTS); throw exception(SECKILL_CONFIG_NOT_EXISTS);
} }
} }
/** /**
* 校验时间是否存在冲突 * 校验时间是否存在冲突
* *
* @param startTime 开始时间 * @param startTimeStr 开始时间
* @param endTime 结束时间 * @param endTimeStr 结束时间
*/ */
private void validateSeckillConfigConflict(String startTime, String endTime, Long seckillConfigId) { private void validateSeckillConfigConflict(String startTimeStr, String endTimeStr, Long id) {
LocalTime startTime1 = LocalTime.parse(startTime); // 1. 查询出所有的时段配置
LocalTime endTime1 = LocalTime.parse(endTime); LocalTime startTime = LocalTime.parse(startTimeStr);
// 查询出所有的时段配置 LocalTime endTime = LocalTime.parse(endTimeStr);
List<SeckillConfigDO> configDOs = seckillConfigMapper.selectList(); List<SeckillConfigDO> configs = seckillConfigMapper.selectList();
// 更新时排除自己 // 更新时排除自己
if (seckillConfigId != null) { if (id != null) {
configDOs.removeIf(item -> ObjectUtil.equal(item.getId(), seckillConfigId)); configs.removeIf(item -> ObjectUtil.equal(item.getId(), id));
} }
// 过滤出重叠的时段 ids
boolean hasConflict = configDOs.stream().anyMatch(config -> {
LocalTime startTime2 = LocalTime.parse(config.getStartTime());
LocalTime endTime2 = LocalTime.parse(config.getEndTime());
// 判断时间是否重叠
return LocalDateTimeUtils.isOverlap(startTime1, endTime1, startTime2, endTime2);
});
// 2. 判断是否有重叠的时间
boolean hasConflict = configs.stream().anyMatch(config -> LocalDateTimeUtils.isOverlap(startTime, endTime,
LocalTime.parse(config.getStartTime()), LocalTime.parse(config.getEndTime())));
if (hasConflict) { if (hasConflict) {
throw exception(SECKILL_TIME_CONFLICTS); throw exception(SECKILL_CONFIG_TIME_CONFLICTS);
} }
} }
@ -128,22 +118,22 @@ public class SeckillConfigServiceImpl implements SeckillConfigService {
} }
@Override @Override
public void validateSeckillConfigExists(Collection<Long> configIds) { public void validateSeckillConfigExists(Collection<Long> ids) {
if (CollUtil.isEmpty(configIds)) { if (CollUtil.isEmpty(ids)) {
throw exception(SECKILL_TIME_NOT_EXISTS); return;
} }
List<SeckillConfigDO> configDOs = seckillConfigMapper.selectBatchIds(configIds); // 1. 如果有数量不匹配说明有不存在的则抛出 SECKILL_CONFIG_NOT_EXISTS 业务异常
if (CollUtil.isEmpty(configDOs)) { List<SeckillConfigDO> configs = seckillConfigMapper.selectBatchIds(ids);
throw exception(SECKILL_TIME_NOT_EXISTS); if (configs.size() != ids.size()) {
throw exception(SECKILL_CONFIG_NOT_EXISTS);
} }
// 过滤出关闭的时段
List<SeckillConfigDO> filterList = CollectionUtils.filterList(configDOs, item -> ObjectUtil.equal(item.getStatus(), CommonStatusEnum.DISABLE.getStatus())); // 2. 如果存在关闭则抛出 SECKILL_CONFIG_DISABLE 业务异常
if (CollUtil.isNotEmpty(filterList)) { configs.forEach(config -> {
throw exception(SECKILL_TIME_DISABLE); if (ObjectUtil.equal(config.getStatus(), CommonStatusEnum.DISABLE.getStatus())) {
} throw exception(SECKILL_CONFIG_DISABLE);
if (configDOs.size() != configIds.size()) {
throw exception(SECKILL_TIME_NOT_EXISTS);
} }
});
} }
@Override @Override

View File

@ -19,7 +19,7 @@ import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEq
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.SECKILL_TIME_NOT_EXISTS; import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.SECKILL_CONFIG_NOT_EXISTS;
import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertNull;
@ -94,7 +94,7 @@ public class SeckillConfigServiceImplTest extends BaseDbUnitTest {
SeckillConfigUpdateReqVO reqVO = randomPojo(SeckillConfigUpdateReqVO.class); SeckillConfigUpdateReqVO reqVO = randomPojo(SeckillConfigUpdateReqVO.class);
// 调用, 并断言异常 // 调用, 并断言异常
assertServiceException(() -> SeckillConfigService.updateSeckillConfig(reqVO), SECKILL_TIME_NOT_EXISTS); assertServiceException(() -> SeckillConfigService.updateSeckillConfig(reqVO), SECKILL_CONFIG_NOT_EXISTS);
} }
@Test @Test
@ -117,7 +117,7 @@ public class SeckillConfigServiceImplTest extends BaseDbUnitTest {
Long id = randomLongId(); Long id = randomLongId();
// 调用, 并断言异常 // 调用, 并断言异常
assertServiceException(() -> SeckillConfigService.deleteSeckillConfig(id), SECKILL_TIME_NOT_EXISTS); assertServiceException(() -> SeckillConfigService.deleteSeckillConfig(id), SECKILL_CONFIG_NOT_EXISTS);
} }
@Test @Test