From c2fd24f597003ea04ff8e726c85c169735f8e0c3 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 23 Aug 2022 23:58:22 +0800 Subject: [PATCH] =?UTF-8?q?mall=EF=BC=9Acode=20review=20=E5=95=86=E5=93=81?= =?UTF-8?q?=20spu=20=E7=9A=84=E5=90=8E=E7=AB=AF=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/sku/vo/ProductSkuBaseVO.java | 4 +- .../admin/spu/ProductSpuController.java | 6 +-- .../dal/mysql/sku/ProductSkuMapper.java | 1 + .../service/sku/ProductSkuService.java | 23 +++++----- .../service/sku/ProductSkuServiceImpl.java | 33 ++++++++------- .../service/spu/ProductSpuService.java | 8 ++-- .../service/spu/ProductSpuServiceImpl.java | 42 +++++++++++++------ .../spu/ProductSpuServiceImplTest.java | 6 +-- 8 files changed, 74 insertions(+), 49 deletions(-) diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuBaseVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuBaseVO.java index 07fddc9ac..c6d8b5459 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuBaseVO.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuBaseVO.java @@ -21,7 +21,9 @@ public class ProductSkuBaseVO { @NotEmpty(message = "商品 SKU 名字不能为空") private String name; - @ApiModelProperty(value = "规格值数组-json格式 单规格中无此列表, [{propertyId: , valueId: }, {propertyId: , valueId: }]") + /** + * 规格值数组 + */ private List properties; @ApiModelProperty(value = "销售价格,单位:分", required = true, example = "1024", notes = "单位:分") diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.java index 7aa73068f..565a20c7b 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.java @@ -35,15 +35,15 @@ public class ProductSpuController { @PostMapping("/create") @ApiOperation("创建商品 SPU") @PreAuthorize("@ss.hasPermission('product:spu:create')") - public CommonResult createSpu(@Valid @RequestBody ProductSpuCreateReqVO createReqVO) { - return success(spuService.createSpu(createReqVO)); + public CommonResult createProductSpu(@Valid @RequestBody ProductSpuCreateReqVO createReqVO) { + return success(spuService.createProductSpu(createReqVO)); } @PutMapping("/update") @ApiOperation("更新商品 SPU") @PreAuthorize("@ss.hasPermission('product:spu:update')") public CommonResult updateSpu(@Valid @RequestBody ProductSpuUpdateReqVO updateReqVO) { - spuService.updateSpu(updateReqVO); + spuService.updateProductSpu(updateReqVO); return success(true); } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/sku/ProductSkuMapper.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/sku/ProductSkuMapper.java index eff999be0..134631650 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/sku/ProductSkuMapper.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/sku/ProductSkuMapper.java @@ -44,4 +44,5 @@ public interface ProductSkuMapper extends BaseMapperX { .eqIfPresent(ProductSkuDO::getSpuId, spuId); delete(lambdaQueryWrapperX); } + } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java index 4b299030b..20c7680bf 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java @@ -68,14 +68,22 @@ public interface ProductSkuService { * * @param list sku组合的集合 */ - void validateSkus(List list); + void validateProductSkus(List list); /** - * 批量保存 sku + * 批量创建 SKU * - * @param list sku对象集合 + * @param list SKU 对象集合 */ - void createSkus(List list); + void createProductSkus(List list); + + /** + * 根据 SPU 编号,批量更新它的 SKU 信息 + * + * @param spuId SPU 编码 + * @param skus SKU 的集合 + */ + void updateProductSkus(Long spuId, List skus); /** * 获得商品 sku 集合 @@ -100,11 +108,4 @@ public interface ProductSkuService { */ void deleteSkuBySpuId(Long spuId); - /** - * 根据 spuId 更新 spu 下的 sku 信息 - * - * @param spuId spu 编码 - * @param skus sku 的集合 - */ - void updateSkus(Long spuId, List skus); } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java index ea9e97c81..50408bcb3 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java @@ -1,6 +1,5 @@ package cn.iocoder.yudao.module.product.service.sku; -import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.product.controller.admin.property.vo.ProductPropertyRespVO; import cn.iocoder.yudao.module.product.controller.admin.propertyvalue.vo.ProductPropertyValueRespVO; @@ -87,25 +86,30 @@ public class ProductSkuServiceImpl implements ProductSkuService { return productSkuMapper.selectPage(pageReqVO); } + // TODO luowenfeng:参考下 yudao-cloud 的 checkProductAttr 方法,重构下 @Override - public void validateSkus(List list) { + public void validateProductSkus(List list) { List skuPropertyList = list.stream().flatMap(p -> Optional.of(p.getProperties()).orElse(new ArrayList<>()).stream()).collect(Collectors.toList()); - // 校验规格属性以及规格值是否存在 + // 校验规格属性存在 + // TODO @luowenfeng:使用 CollectionUtils.convert List propertyIds = skuPropertyList.stream().map(ProductSkuBaseVO.Property::getPropertyId).collect(Collectors.toList()); List propertyAndValueList = productPropertyService.selectByIds(propertyIds); + // TODO @luowenfeng:校验数量一致; if (propertyAndValueList.isEmpty()) { - throw ServiceExceptionUtil.exception(PROPERTY_NOT_EXISTS); + throw exception(PROPERTY_NOT_EXISTS); } + // 校验规格属性值存在 + // TODO @luowenfeng:使用 CollectionUtils.convert Map propertyMap = propertyAndValueList.stream().collect(Collectors.toMap(ProductPropertyRespVO::getId, p -> p)); skuPropertyList.forEach(p -> { ProductPropertyRespVO productPropertyRespVO = propertyMap.get(p.getPropertyId()); // 如果对应的属性名不存在或属性名下的属性值集合为空,给出提示 if (null == productPropertyRespVO || productPropertyRespVO.getPropertyValueList().isEmpty()) { - throw ServiceExceptionUtil.exception(PROPERTY_NOT_EXISTS); + throw exception(PROPERTY_NOT_EXISTS); } // 判断改属性名对应的属性值是否存在,不存在,给出提示 if (!productPropertyRespVO.getPropertyValueList().stream().map(ProductPropertyValueRespVO::getId).collect(Collectors.toSet()).contains(p.getValueId())) { - throw ServiceExceptionUtil.exception(ErrorCodeConstants.PROPERTY_VALUE_NOT_EXISTS); + throw exception(ErrorCodeConstants.PROPERTY_VALUE_NOT_EXISTS); } }); // 校验是否有重复的sku组合 @@ -114,13 +118,13 @@ public class ProductSkuServiceImpl implements ProductSkuService { skuProperties.forEach(p -> { // 组合属性值id为 1~2~3.... 形式的字符串,通过set的特性判断是否有重复的组合 if (!skuPropertiesConvertSet.add(p.stream().map(pr -> String.valueOf(pr.getValueId())).sorted().collect(Collectors.joining("~")))) { - throw ServiceExceptionUtil.exception(ErrorCodeConstants.SKU_PROPERTIES_DUPLICATED); + throw exception(ErrorCodeConstants.SKU_PROPERTIES_DUPLICATED); } }); } @Override - public void createSkus(List skuDOList) { + public void createProductSkus(List skuDOList) { productSkuMapper.insertBatch(skuDOList); } @@ -141,21 +145,23 @@ public class ProductSkuServiceImpl implements ProductSkuService { @Override @Transactional - public void updateSkus(Long spuId, List skus) { - List allUpdateSkus = ProductSkuConvert.INSTANCE.convertSkuDOList(skus); + public void updateProductSkus(Long spuId, List skus) { // 查询 spu 下已经存在的 sku 的集合 + // TODO @luowenfeng:selectListBySpuId 搞个 List existsSkus = productSkuMapper.selectBySpuIds(Collections.singletonList(spuId)); // TODO @franky:使用 CollUtils 即可 Map existsSkuMap = existsSkus.stream().collect(Collectors.toMap(ProductSkuDO::getId, p -> p)); - // 拆分三个集合, 新插入的, 需要更新的,需要删除的 + // 拆分三个集合,新插入的、需要更新的、需要删除的 List insertSkus = new ArrayList<>(); List updateSkus = new ArrayList<>(); List deleteSkus = new ArrayList<>(); // TODO @芋艿:是不是基于规格匹配会比较好。 + List allUpdateSkus = ProductSkuConvert.INSTANCE.convertSkuDOList(skus); allUpdateSkus.forEach(p -> { - if (null != p.getId()) { + if (p.getId() != null) { + // TODO @luowenfeng:contains if (existsSkuMap.get(p.getId()) != null) { updateSkus.add(p); return; @@ -167,14 +173,13 @@ public class ProductSkuServiceImpl implements ProductSkuService { insertSkus.add(p); }); + // TODO @luowenfeng:使用 CollUtil.isNotEmpty 判断 if (insertSkus.size() > 0) { productSkuMapper.insertBatch(insertSkus); } - if (updateSkus.size() > 0) { updateSkus.forEach(p -> productSkuMapper.updateById(p)); } - if (deleteSkus.size() > 0) { productSkuMapper.deleteBatchIds(deleteSkus.stream().map(ProductSkuDO::getId).collect(Collectors.toList())); } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuService.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuService.java index b3ba4b99f..37883b677 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuService.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuService.java @@ -21,19 +21,19 @@ import java.util.List; public interface ProductSpuService { /** - * 创建商品spu + * 创建商品 SPU * * @param createReqVO 创建信息 * @return 编号 */ - Long createSpu(@Valid ProductSpuCreateReqVO createReqVO); + Long createProductSpu(@Valid ProductSpuCreateReqVO createReqVO); /** - * 更新商品spu + * 更新商品 SPU * * @param updateReqVO 更新信息 */ - void updateSpu(@Valid ProductSpuUpdateReqVO updateReqVO); + void updateProductSpu(@Valid ProductSpuUpdateReqVO updateReqVO); /** * 删除商品spu diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java index 988f8e1df..26c564f34 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java @@ -7,7 +7,10 @@ import cn.iocoder.yudao.module.product.controller.admin.propertyvalue.vo.Product import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuBaseVO; import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO; import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuRespVO; -import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*; +import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuCreateReqVO; +import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuUpdateReqVO; +import cn.iocoder.yudao.module.product.controller.admin.spu.vo.SpuPageReqVO; +import cn.iocoder.yudao.module.product.controller.admin.spu.vo.SpuRespVO; import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageReqVO; import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageRespVO; import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert; @@ -53,47 +56,60 @@ public class ProductSpuServiceImpl implements ProductSpuService { @Override @Transactional - public Long createSpu(ProductSpuCreateReqVO createReqVO) { + public Long createProductSpu(ProductSpuCreateReqVO createReqVO) { // 校验分类 + // TODO @luowenfeng:可以在这个类里加个方法,校验分类;商品必须挂在三级分类下; categoryService.validateProductCategory(createReqVO.getCategoryId()); + // TODO @luowenfeng:校验品牌 // 校验SKU List skuCreateReqList = createReqVO.getSkus(); // 多规格才需校验 + // TODO @luowenfeng:可以把 type 传递到 productSkuService 里,通过它统一判断处理 if(Objects.equals(createReqVO.getSpecType(), ProductSpuSpecTypeEnum.DISABLE.getType())) { - productSkuService.validateSkus(skuCreateReqList); + productSkuService.validateProductSkus(skuCreateReqList); } - // 插入SPU + + // 插入 SPU ProductSpuDO spu = ProductSpuConvert.INSTANCE.convert(createReqVO); + // TODO @luowenfeng:可以在 CollectionUtils 增加 getMaxValue 方法,增加一个 defaultValue 方法,如果为空,则返回 defaultValue spu.setMarketPrice(skuCreateReqList.stream().map(ProductSkuCreateOrUpdateReqVO::getMarketPrice).max(Integer::compare).orElse(0)); spu.setMaxPrice(skuCreateReqList.stream().map(ProductSkuCreateOrUpdateReqVO::getPrice).max(Integer::compare).orElse(0)); spu.setMinPrice(skuCreateReqList.stream().map(ProductSkuCreateOrUpdateReqVO::getPrice).min(Integer::compare).orElse(0)); + // TODO @luowenfeng:库存求和 ProductSpuMapper.insert(spu); + + // 批量插入 SKU + // TODO @luowenfeng:convert 逻辑,交给 createProductSkus 一起处理 List skuDOList = ProductSkuConvert.INSTANCE.convertSkuDOList(skuCreateReqList); skuDOList.forEach(v->v.setSpuId(spu.getId())); - // 批量插入sku - productSkuService.createSkus(skuDOList); + productSkuService.createProductSkus(skuDOList); // 返回 return spu.getId(); } @Override @Transactional - public void updateSpu(ProductSpuUpdateReqVO updateReqVO) { - // 校验 spu 是否存在 - this.validateSpuExists(updateReqVO.getId()); + public void updateProductSpu(ProductSpuUpdateReqVO updateReqVO) { + // 校验 SPU 是否存在 + validateSpuExists(updateReqVO.getId()); // 校验分类 categoryService.validateProductCategory(updateReqVO.getCategoryId()); + // TODO @luowenfeng:校验品牌 // 校验SKU List skuCreateReqList = updateReqVO.getSkus(); // 多规格才需校验 + // TODO @luowenfeng:可以把 type 传递到 productSkuService 里,通过它统一判断处理 if(updateReqVO.getSpecType().equals(ProductSpuSpecTypeEnum.DISABLE.getType())) { - productSkuService.validateSkus(skuCreateReqList); + productSkuService.validateProductSkus(skuCreateReqList); } - // 更新 + + // 更新 SPU ProductSpuDO updateObj = ProductSpuConvert.INSTANCE.convert(updateReqVO); + // TODO @计算各种字段 ProductSpuMapper.updateById(updateObj); - // 更新 sku - productSkuService.updateSkus(updateObj.getId(), updateReqVO.getSkus()); + + // 更新 SKU + productSkuService.updateProductSkus(updateObj.getId(), updateReqVO.getSkus()); } @Override diff --git a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java index 57b7fdfeb..e2b3a3d98 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java +++ b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java @@ -41,7 +41,7 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest { ProductSpuCreateReqVO reqVO = randomPojo(ProductSpuCreateReqVO.class); // 调用 - Long spuId = spuService.createSpu(reqVO); + Long spuId = spuService.createProductSpu(reqVO); // 断言 assertNotNull(spuId); // 校验记录的属性是否正确 @@ -60,7 +60,7 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest { }); // 调用 - spuService.updateSpu(reqVO); + spuService.updateProductSpu(reqVO); // 校验是否更新正确 ProductSpuDO spu = ProductSpuMapper.selectById(reqVO.getId()); // 获取最新的 assertPojoEquals(reqVO, spu); @@ -72,7 +72,7 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest { ProductSpuUpdateReqVO reqVO = randomPojo(ProductSpuUpdateReqVO.class); // 调用, 并断言异常 - assertServiceException(() -> spuService.updateSpu(reqVO), SPU_NOT_EXISTS); + assertServiceException(() -> spuService.updateProductSpu(reqVO), SPU_NOT_EXISTS); } @Test