【代码优化】商城: 限时折扣活动

This commit is contained in:
puhui999 2024-09-15 13:24:01 +08:00
parent ea6e365097
commit ad1ceaaf1c
8 changed files with 101 additions and 198 deletions

View File

@ -11,7 +11,7 @@ public interface ErrorCodeConstants {
// ========== 促销活动相关 1-013-001-000 ============ // ========== 促销活动相关 1-013-001-000 ============
ErrorCode DISCOUNT_ACTIVITY_NOT_EXISTS = new ErrorCode(1_013_001_000, "限时折扣活动不存在"); ErrorCode DISCOUNT_ACTIVITY_NOT_EXISTS = new ErrorCode(1_013_001_000, "限时折扣活动不存在");
ErrorCode DISCOUNT_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1_013_001_001, "存在商品参加了其它限时折扣活动"); ErrorCode DISCOUNT_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1_013_001_001, "存在商品参加了其它限时折扣活动【{}】");
ErrorCode DISCOUNT_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED = new ErrorCode(1_013_001_002, "限时折扣活动已关闭,不能修改"); ErrorCode DISCOUNT_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED = new ErrorCode(1_013_001_002, "限时折扣活动已关闭,不能修改");
ErrorCode DISCOUNT_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED = new ErrorCode(1_013_001_003, "限时折扣活动未关闭,不能删除"); ErrorCode DISCOUNT_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED = new ErrorCode(1_013_001_003, "限时折扣活动未关闭,不能删除");
ErrorCode DISCOUNT_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1_013_001_004, "限时折扣活动已关闭,不能重复关闭"); ErrorCode DISCOUNT_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1_013_001_004, "限时折扣活动已关闭,不能重复关闭");

View File

@ -3,9 +3,10 @@ package cn.iocoder.yudao.module.promotion.controller.admin.discount;
import cn.hutool.core.collection.CollUtil; 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.promotion.controller.admin.discount.vo.DiscountActivityCreateReqVO;
import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityPageReqVO;
import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.*; import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityRespVO;
import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityUpdateReqVO;
import cn.iocoder.yudao.module.promotion.convert.discount.DiscountActivityConvert; import cn.iocoder.yudao.module.promotion.convert.discount.DiscountActivityConvert;
import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountActivityDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountActivityDO;
import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO;
@ -13,12 +14,12 @@ import cn.iocoder.yudao.module.promotion.service.discount.DiscountActivityServic
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import java.util.List; import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@ -33,9 +34,6 @@ public class DiscountActivityController {
@Resource @Resource
private DiscountActivityService discountActivityService; private DiscountActivityService discountActivityService;
@Resource
private ProductSpuApi productSpuApi;
@PostMapping("/create") @PostMapping("/create")
@Operation(summary = "创建限时折扣活动") @Operation(summary = "创建限时折扣活动")
@PreAuthorize("@ss.hasPermission('promotion:discount-activity:create')") @PreAuthorize("@ss.hasPermission('promotion:discount-activity:create')")
@ -73,7 +71,7 @@ public class DiscountActivityController {
@Operation(summary = "获得限时折扣活动") @Operation(summary = "获得限时折扣活动")
@Parameter(name = "id", description = "编号", required = true, example = "1024") @Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('promotion:discount-activity:query')") @PreAuthorize("@ss.hasPermission('promotion:discount-activity:query')")
public CommonResult<DiscountActivityDetailRespVO> getDiscountActivity(@RequestParam("id") Long id) { public CommonResult<DiscountActivityRespVO> getDiscountActivity(@RequestParam("id") Long id) {
DiscountActivityDO discountActivity = discountActivityService.getDiscountActivity(id); DiscountActivityDO discountActivity = discountActivityService.getDiscountActivity(id);
if (discountActivity == null) { if (discountActivity == null) {
return success(null); return success(null);
@ -88,18 +86,14 @@ public class DiscountActivityController {
@PreAuthorize("@ss.hasPermission('promotion:discount-activity:query')") @PreAuthorize("@ss.hasPermission('promotion:discount-activity:query')")
public CommonResult<PageResult<DiscountActivityRespVO>> getDiscountActivityPage(@Valid DiscountActivityPageReqVO pageVO) { public CommonResult<PageResult<DiscountActivityRespVO>> getDiscountActivityPage(@Valid DiscountActivityPageReqVO pageVO) {
PageResult<DiscountActivityDO> pageResult = discountActivityService.getDiscountActivityPage(pageVO); PageResult<DiscountActivityDO> pageResult = discountActivityService.getDiscountActivityPage(pageVO);
if (CollUtil.isEmpty(pageResult.getList())) {
if (CollUtil.isEmpty(pageResult.getList())) { // TODO @zhangshuai方法里的空行目的是让代码分块可以更清晰所以上面这个空格可以不要而下面判断之后的空格其实加下比较好类似的还有 spuList以及后面的 convert
return success(PageResult.empty(pageResult.getTotal())); return success(PageResult.empty(pageResult.getTotal()));
} }
// 拼接数据 // 拼接数据
List<DiscountProductDO> products = discountActivityService.getDiscountProductsByActivityId( List<DiscountProductDO> products = discountActivityService.getDiscountProductsByActivityId(
convertSet(pageResult.getList(), DiscountActivityDO::getId)); convertSet(pageResult.getList(), DiscountActivityDO::getId));
return success(DiscountActivityConvert.INSTANCE.convertPage(pageResult, products));
List<ProductSpuRespDTO> spuList = productSpuApi.getSpuList(
convertSet(products, DiscountProductDO::getSpuId));
return success(DiscountActivityConvert.INSTANCE.convertPage(pageResult, products, spuList));
} }
} }

View File

@ -1,21 +0,0 @@
package cn.iocoder.yudao.module.promotion.controller.admin.discount.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.util.List;
@Schema(description = "管理后台 - 限时折扣活动的详细 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class DiscountActivityDetailRespVO extends DiscountActivityRespVO {
/**
* 商品列表
*/
private List<Product> products;
}

View File

@ -1,11 +1,11 @@
package cn.iocoder.yudao.module.promotion.controller.admin.discount.vo; package cn.iocoder.yudao.module.promotion.controller.admin.discount.vo;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.ToString; import lombok.ToString;
import jakarta.validation.constraints.NotNull;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List; import java.util.List;
@ -25,25 +25,7 @@ public class DiscountActivityRespVO extends DiscountActivityBaseVO {
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime; private LocalDateTime createTime;
@Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048") // TODO @zhangshuai属性和属性之间最多空一行噢
private Long spuId;
@Schema(description = "限时折扣商品", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "限时折扣商品", requiredMode = Schema.RequiredMode.REQUIRED)
private List<DiscountActivityBaseVO.Product> products; private List<Product> products;
// ========== 商品字段 ==========
// TODO @zhangshuai一个优惠活动会关联多个商品所以它不用返回 spuName
// TODO 最终界面展示字段就编号活动名称参与商品数活动状态开始时间结束时间操作
@Schema(description = "商品名称", requiredMode = Schema.RequiredMode.REQUIRED, // SPU name 读取
example = "618大促")
private String spuName;
@Schema(description = "商品主图", requiredMode = Schema.RequiredMode.REQUIRED, // SPU picUrl 读取
example = "https://www.iocoder.cn/xx.png")
private String picUrl;
@Schema(description = "商品市场价,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, // SPU marketPrice 读取
example = "50")
private Integer marketPrice;
} }

View File

@ -1,13 +1,13 @@
package cn.iocoder.yudao.module.promotion.controller.admin.discount.vo; package cn.iocoder.yudao.module.promotion.controller.admin.discount.vo;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.ToString; import lombok.ToString;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import java.util.List; import java.util.List;
@Schema(description = "管理后台 - 限时折扣活动更新 Request VO") @Schema(description = "管理后台 - 限时折扣活动更新 Request VO")
@ -25,6 +25,6 @@ public class DiscountActivityUpdateReqVO extends DiscountActivityBaseVO {
*/ */
@NotEmpty(message = "商品列表不能为空") @NotEmpty(message = "商品列表不能为空")
@Valid @Valid
private List<DiscountActivityCreateReqVO.Product> products; private List<Product> products;
} }

View File

@ -1,20 +1,18 @@
package cn.iocoder.yudao.module.promotion.convert.discount; package cn.iocoder.yudao.module.promotion.convert.discount;
import cn.hutool.core.util.ObjectUtil;
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.object.BeanUtils;
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
import cn.iocoder.yudao.module.promotion.api.discount.dto.DiscountProductRespDTO; import cn.iocoder.yudao.module.promotion.api.discount.dto.DiscountProductRespDTO;
import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.*; import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityBaseVO;
import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityCreateReqVO;
import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityRespVO;
import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityUpdateReqVO;
import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountActivityDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountActivityDO;
import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO;
import cn.iocoder.yudao.module.promotion.enums.common.PromotionDiscountTypeEnum;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers; import org.mapstruct.factory.Mappers;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* 限时折扣活动 Convert * 限时折扣活动 Convert
@ -33,6 +31,7 @@ public interface DiscountActivityConvert {
DiscountActivityRespVO convert(DiscountActivityDO bean); DiscountActivityRespVO convert(DiscountActivityDO bean);
List<DiscountActivityRespVO> convertList(List<DiscountActivityDO> list); List<DiscountActivityRespVO> convertList(List<DiscountActivityDO> list);
List<DiscountActivityBaseVO.Product> convertList2(List<DiscountProductDO> list); List<DiscountActivityBaseVO.Product> convertList2(List<DiscountProductDO> list);
List<DiscountProductRespDTO> convertList02(List<DiscountProductDO> list); List<DiscountProductRespDTO> convertList02(List<DiscountProductDO> list);
@ -40,98 +39,16 @@ public interface DiscountActivityConvert {
PageResult<DiscountActivityRespVO> convertPage(PageResult<DiscountActivityDO> page); PageResult<DiscountActivityRespVO> convertPage(PageResult<DiscountActivityDO> page);
default PageResult<DiscountActivityRespVO> convertPage(PageResult<DiscountActivityDO> page, default PageResult<DiscountActivityRespVO> convertPage(PageResult<DiscountActivityDO> page,
List<DiscountProductDO> discountProductDOList, List<DiscountProductDO> discountProductDOList) {
List<ProductSpuRespDTO> spuList) {
PageResult<DiscountActivityRespVO> pageResult = convertPage(page); PageResult<DiscountActivityRespVO> pageResult = convertPage(page);
pageResult.getList().forEach(item -> item.setProducts(convertList2(discountProductDOList)));
// 拼接商品 TODO @zhangshuai类似空行的问题也可以看看
Map<Long, DiscountProductDO> discountActivityMap = CollectionUtils.convertMap(discountProductDOList, DiscountProductDO::getActivityId);
Map<Long, ProductSpuRespDTO> spuMap = CollectionUtils.convertMap(spuList, ProductSpuRespDTO::getId);
pageResult.getList().forEach(item -> {
item.setProducts(convertList2(discountProductDOList));
item.setSpuId(discountActivityMap.get(item.getId())==null?null: discountActivityMap.get(item.getId()).getSpuId());
if (item.getSpuId() != null) {
MapUtils.findAndThen(spuMap, item.getSpuId(),
spu -> item.setSpuName(spu.getName()).setPicUrl(spu.getPicUrl()).setMarketPrice(spu.getMarketPrice()));
}
});
return pageResult; return pageResult;
} }
DiscountProductDO convert(DiscountActivityBaseVO.Product bean); DiscountProductDO convert(DiscountActivityBaseVO.Product bean);
default DiscountActivityDetailRespVO convert(DiscountActivityDO activity, List<DiscountProductDO> products){ default DiscountActivityRespVO convert(DiscountActivityDO activity, List<DiscountProductDO> products) {
if ( activity == null && products == null ) { return BeanUtils.toBean(activity, DiscountActivityRespVO.class).setProducts(convertList2(products));
return null;
}
DiscountActivityDetailRespVO discountActivityDetailRespVO = new DiscountActivityDetailRespVO();
if ( activity != null ) {
discountActivityDetailRespVO.setName( activity.getName() );
discountActivityDetailRespVO.setStartTime( activity.getStartTime() );
discountActivityDetailRespVO.setEndTime( activity.getEndTime() );
discountActivityDetailRespVO.setRemark( activity.getRemark() );
discountActivityDetailRespVO.setId( activity.getId() );
discountActivityDetailRespVO.setStatus( activity.getStatus() );
discountActivityDetailRespVO.setCreateTime( activity.getCreateTime() );
}
if (!products.isEmpty()) {
discountActivityDetailRespVO.setSpuId(products.get(0).getSpuId());
}
discountActivityDetailRespVO.setProducts( convertList2( products ) );
return discountActivityDetailRespVO;
} }
// =========== 比较是否相等 ==========
/**
* 比较两个限时折扣商品是否相等
*
* @param productDO 数据库中的商品
* @param productVO 前端传入的商品
* @return 是否匹配
*/
@SuppressWarnings("DuplicatedCode")
default boolean isEquals(DiscountProductDO productDO, DiscountActivityBaseVO.Product productVO) {
if (ObjectUtil.notEqual(productDO.getSpuId(), productVO.getSpuId())
|| ObjectUtil.notEqual(productDO.getSkuId(), productVO.getSkuId())
|| ObjectUtil.notEqual(productDO.getDiscountType(), productVO.getDiscountType())) {
return false;
}
if (productDO.getDiscountType().equals(PromotionDiscountTypeEnum.PRICE.getType())) {
return ObjectUtil.equal(productDO.getDiscountPrice(), productVO.getDiscountPrice());
}
if (productDO.getDiscountType().equals(PromotionDiscountTypeEnum.PERCENT.getType())) {
return ObjectUtil.equal(productDO.getDiscountPercent(), productVO.getDiscountPercent());
}
return true;
}
/**
* 比较两个限时折扣商品是否相等
* 注意比较时忽略 id 编号
*
* @param productDO 商品 1
* @param productVO 商品 2
* @return 是否匹配
*/
@SuppressWarnings("DuplicatedCode")
default boolean isEquals(DiscountProductDO productDO, DiscountProductDO productVO) {
if (ObjectUtil.notEqual(productDO.getSpuId(), productVO.getSpuId())
|| ObjectUtil.notEqual(productDO.getSkuId(), productVO.getSkuId())
|| ObjectUtil.notEqual(productDO.getDiscountType(), productVO.getDiscountType())) {
return false;
}
if (productDO.getDiscountType().equals(PromotionDiscountTypeEnum.PRICE.getType())) {
return ObjectUtil.equal(productDO.getDiscountPrice(), productVO.getDiscountPrice());
}
if (productDO.getDiscountType().equals(PromotionDiscountTypeEnum.PERCENT.getType())) {
return ObjectUtil.equal(productDO.getDiscountPercent(), productVO.getDiscountPercent());
}
return true;
}
} }

View File

@ -18,9 +18,6 @@ import java.util.Map;
@Mapper @Mapper
public interface DiscountProductMapper extends BaseMapperX<DiscountProductDO> { public interface DiscountProductMapper extends BaseMapperX<DiscountProductDO> {
default List<DiscountProductDO> selectListBySkuId(Collection<Long> skuIds) {
return selectList(DiscountProductDO::getSkuId, skuIds);
}
default List<DiscountProductDO> selectListByActivityId(Long activityId) { default List<DiscountProductDO> selectListByActivityId(Long activityId) {
return selectList(DiscountProductDO::getActivityId, activityId); return selectList(DiscountProductDO::getActivityId, activityId);

View File

@ -1,11 +1,14 @@
package cn.iocoder.yudao.module.promotion.service.discount; package cn.iocoder.yudao.module.promotion.service.discount;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.map.MapUtil; import cn.hutool.core.map.MapUtil;
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.object.BeanUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityBaseVO; import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityBaseVO;
import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityCreateReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityCreateReqVO;
import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityPageReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityPageReqVO;
@ -27,11 +30,12 @@ import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors;
import static cn.hutool.core.collection.CollUtil.intersectionDistinct;
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.framework.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen;
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS;
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
/** /**
@ -47,6 +51,8 @@ public class DiscountActivityServiceImpl implements DiscountActivityService {
private DiscountActivityMapper discountActivityMapper; private DiscountActivityMapper discountActivityMapper;
@Resource @Resource
private DiscountProductMapper discountProductMapper; private DiscountProductMapper discountProductMapper;
@Resource
private ProductSkuApi productSkuApi;
@Override @Override
public List<DiscountProductDO> getMatchDiscountProductList(Collection<Long> skuIds) { public List<DiscountProductDO> getMatchDiscountProductList(Collection<Long> skuIds) {
@ -58,6 +64,8 @@ public class DiscountActivityServiceImpl implements DiscountActivityService {
public Long createDiscountActivity(DiscountActivityCreateReqVO createReqVO) { public Long createDiscountActivity(DiscountActivityCreateReqVO createReqVO) {
// 校验商品是否冲突 // 校验商品是否冲突
validateDiscountActivityProductConflicts(null, createReqVO.getProducts()); validateDiscountActivityProductConflicts(null, createReqVO.getProducts());
// 校验商品是否存在
validateProductExists(createReqVO.getProducts());
// 插入活动 // 插入活动
DiscountActivityDO discountActivity = DiscountActivityConvert.INSTANCE.convert(createReqVO) DiscountActivityDO discountActivity = DiscountActivityConvert.INSTANCE.convert(createReqVO)
@ -82,36 +90,40 @@ public class DiscountActivityServiceImpl implements DiscountActivityService {
} }
// 校验商品是否冲突 // 校验商品是否冲突
validateDiscountActivityProductConflicts(updateReqVO.getId(), updateReqVO.getProducts()); validateDiscountActivityProductConflicts(updateReqVO.getId(), updateReqVO.getProducts());
// 校验商品是否存在
validateProductExists(updateReqVO.getProducts());
// 更新活动 // 更新活动
DiscountActivityDO updateObj = DiscountActivityConvert.INSTANCE.convert(updateReqVO) DiscountActivityDO updateObj = DiscountActivityConvert.INSTANCE.convert(updateReqVO)
.setStatus(PromotionUtils.calculateActivityStatus(updateReqVO.getEndTime())); .setStatus(PromotionUtils.calculateActivityStatus(updateReqVO.getEndTime()));
discountActivityMapper.updateById(updateObj); discountActivityMapper.updateById(updateObj);
// 更新商品 // 更新商品
updateDiscountProduct(updateReqVO); updateDiscountProduct(updateObj, updateReqVO.getProducts());
} }
private void updateDiscountProduct(DiscountActivityUpdateReqVO updateReqVO) { private void updateDiscountProduct(DiscountActivityDO activity, List<DiscountActivityCreateReqVO.Product> products) {
// TODO @zhangshuai这里的逻辑可以优化下哈参考 CombinationActivityServiceImpl updateCombinationProduct主要是 CollectionUtils.diffList 的使用哈 // 第一步对比新老数据获得添加修改删除的列表
// 然后原先是使用 DiscountActivityConvert.INSTANCE.isEquals 对比现在看看是不是简化就基于 skuId 对比就完事了之前写的太精细意义不大 List<DiscountProductDO> newList = BeanUtils.toBean(products, DiscountProductDO.class,
List<DiscountProductDO> dbDiscountProducts = discountProductMapper.selectListByActivityId(updateReqVO.getId()); product -> product.setActivityId(activity.getId()).setActivityStatus(activity.getStatus())
// 计算要删除的记录 .setActivityStartTime(activity.getStartTime()).setActivityEndTime(activity.getEndTime()));
List<Long> deleteIds = convertList(dbDiscountProducts, DiscountProductDO::getId, List<DiscountProductDO> oldList = discountProductMapper.selectListByActivityId(activity.getId());
discountProductDO -> updateReqVO.getProducts().stream() List<List<DiscountProductDO>> diffList = CollectionUtils.diffList(oldList, newList, (oldVal, newVal) -> {
.noneMatch(product -> DiscountActivityConvert.INSTANCE.isEquals(discountProductDO, product))); boolean same = ObjectUtil.equal(oldVal.getSkuId(), newVal.getSkuId());
if (CollUtil.isNotEmpty(deleteIds)) { if (same) {
discountProductMapper.deleteBatchIds(deleteIds); newVal.setId(oldVal.getId());
}
return same;
});
// 第二步批量添加修改删除
if (CollUtil.isNotEmpty(diffList.get(0))) {
discountProductMapper.insertBatch(diffList.get(0));
} }
// 计算新增的记录 if (CollUtil.isNotEmpty(diffList.get(1))) {
List<DiscountProductDO> newDiscountProducts = convertList(updateReqVO.getProducts(), discountProductMapper.updateBatch(diffList.get(1));
product -> DiscountActivityConvert.INSTANCE.convert(product) }
.setActivityId(updateReqVO.getId()) if (CollUtil.isNotEmpty(diffList.get(2))) {
.setActivityStartTime(updateReqVO.getStartTime()) discountProductMapper.deleteBatchIds(convertList(diffList.get(2), DiscountProductDO::getId));
.setActivityEndTime(updateReqVO.getEndTime()));
newDiscountProducts.removeIf(product -> dbDiscountProducts.stream().anyMatch(
dbProduct -> DiscountActivityConvert.INSTANCE.isEquals(dbProduct, product))); // 如果匹配到说明是更新的
if (CollectionUtil.isNotEmpty(newDiscountProducts)) {
discountProductMapper.insertBatch(newDiscountProducts);
} }
} }
@ -122,22 +134,44 @@ public class DiscountActivityServiceImpl implements DiscountActivityService {
* @param products 商品列表 * @param products 商品列表
*/ */
private void validateDiscountActivityProductConflicts(Long id, List<DiscountActivityBaseVO.Product> products) { private void validateDiscountActivityProductConflicts(Long id, List<DiscountActivityBaseVO.Product> products) {
if (CollUtil.isEmpty(products)) { // 1.1 查询所有开启的折扣活动
return; List<DiscountActivityDO> activityList = discountActivityMapper.selectList(DiscountActivityDO::getStatus,
} CommonStatusEnum.ENABLE.getStatus());
// 查询商品参加的活动 if (id != null) { // 时排除自己
// TODO @zhangshuai下面 121 这个查询是不是不用做呀直接 convert skuId 集合就 ok activityList.removeIf(item -> ObjectUtil.equal(item.getId(), id));
List<DiscountProductDO> list = discountProductMapper.selectListByActivityId(id);
// TODO @zhangshuai一般简单的 stream 方法建议是使用 CollectionUtils例如说这里是 convertList 对把
List<Long> skuIds = list.stream().map(item -> item.getSkuId()).collect(Collectors.toList());
List<DiscountProductDO> matchDiscountProductList = getMatchDiscountProductList(skuIds);
if (id != null) { // 排除自己这个活动
matchDiscountProductList.removeIf(product -> id.equals(product.getActivityId()));
}
// 如果非空则说明冲突
if (CollUtil.isNotEmpty(matchDiscountProductList)) {
throw exception(DISCOUNT_ACTIVITY_SPU_CONFLICTS);
} }
// 1.2 查询活动下的所有商品
List<DiscountProductDO> productList = discountProductMapper.selectListByActivityId(
convertList(activityList, DiscountActivityDO::getId));
Map<Long, List<DiscountProductDO>> productListMap = convertMultiMap(productList, DiscountProductDO::getActivityId);
// 2. 校验商品是否冲突
activityList.forEach(item -> {
findAndThen(productListMap, item.getId(), discountProducts -> {
if (!intersectionDistinct(convertList(discountProducts, DiscountProductDO::getSpuId),
convertList(products, DiscountActivityBaseVO.Product::getSpuId)).isEmpty()) {
throw exception(DISCOUNT_ACTIVITY_SPU_CONFLICTS, item.getName());
}
});
});
}
/**
* 校验活动商品是否都存在
*
* @param products 活动商品
*/
private void validateProductExists(List<DiscountActivityBaseVO.Product> products) {
// 1.获得商品所有的 sku
List<ProductSkuRespDTO> skus = productSkuApi.getSkuListBySpuId(
convertList(products, DiscountActivityBaseVO.Product::getSpuId));
Map<Long, ProductSkuRespDTO> skuMap = convertMap(skus, ProductSkuRespDTO::getId);
// 2. 校验商品 sku 都存在
products.forEach(product -> {
if (!skuMap.containsKey(product.getSkuId())) {
throw exception(SKU_NOT_EXISTS);
}
});
} }
@Override @Override