Commit f4324a22f267da7b16d1725dab8df37b683c6aab

Authored by YunaiV
1 parent 833fd338

mall: code review 商品模块的代码

Showing 27 changed files with 226 additions and 214 deletions
yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/ErrorCodeConstants.java
... ... @@ -10,30 +10,29 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode;
10 10 public interface ErrorCodeConstants {
11 11  
12 12 // ========== 商品分类相关 1008001000 ============
13   - ErrorCode PRODUCT_CATEGORY_NOT_EXISTS = new ErrorCode(1008001000, "商品分类不存在");
14   - ErrorCode PRODUCT_CATEGORY_PARENT_NOT_EXISTS = new ErrorCode(1008001001, "父分类不存在");
15   - ErrorCode PRODUCT_CATEGORY_PARENT_NOT_FIRST_LEVEL = new ErrorCode(1008001002, "父分类不能是二级分类");
16   - ErrorCode PRODUCT_CATEGORY_EXISTS_CHILDREN = new ErrorCode(1008001003, "存在子分类,无法删除");
17   - ErrorCode PRODUCT_CATEGORY_DISABLED = new ErrorCode(1008001004, "商品分类({})已禁用,无法使用");
18   - ErrorCode PRODUCT_CATEGORY_LEVEL = new ErrorCode(1008001005, "商品需挂在三级分类下");
  13 + ErrorCode CATEGORY_NOT_EXISTS = new ErrorCode(1008001000, "商品分类不存在");
  14 + ErrorCode CATEGORY_PARENT_NOT_EXISTS = new ErrorCode(1008001001, "父分类不存在");
  15 + ErrorCode CATEGORY_PARENT_NOT_FIRST_LEVEL = new ErrorCode(1008001002, "父分类不能是二级分类");
  16 + ErrorCode CATEGORY_EXISTS_CHILDREN = new ErrorCode(1008001003, "存在子分类,无法删除");
  17 + ErrorCode CATEGORY_DISABLED = new ErrorCode(1008001004, "商品分类({})已禁用,无法使用");
  18 + ErrorCode CATEGORY_LEVEL_ERROR = new ErrorCode(1008001005, "商品分类不正确,原因:必须使用第三级的商品分类下");
19 19  
20   - // ========== 品牌相关编号 1008002000 ==========
21   - ErrorCode PRODUCT_BRAND_NOT_EXISTS = new ErrorCode(1008002000, "品牌不存在");
  20 + // ========== 商品品牌相关编号 1008002000 ==========
  21 + ErrorCode BRAND_NOT_EXISTS = new ErrorCode(1008002000, "品牌不存在");
22 22  
23   - // ========== 规格名称 1008003000 ==========
  23 + // ========== 商品规格名称 1008003000 ==========
24 24 ErrorCode PROPERTY_NOT_EXISTS = new ErrorCode(1008003000, "规格名称不存在");
25 25  
26 26 // ========== 规格值 1008004000 ==========
27 27 ErrorCode PROPERTY_VALUE_NOT_EXISTS = new ErrorCode(1008004000, "规格值不存在");
28 28  
29   - // ========== 商品spu 1008005000 ==========
30   - ErrorCode SPU_NOT_EXISTS = new ErrorCode(1008005000, "商品spu不存在");
  29 + // ========== 商品 SPU 1008005000 ==========
  30 + ErrorCode SPU_NOT_EXISTS = new ErrorCode(1008005000, "商品 SPU 不存在");
31 31  
32   - // ========== 商品sku 1008006000 ==========
33   - ErrorCode SKU_NOT_EXISTS = new ErrorCode(1008006000, "商品sku不存在");
34   - ErrorCode SKU_PROPERTIES_DUPLICATED = new ErrorCode(1008006001, "商品sku的属性组合存在重复");
  32 + // ========== 商品 SKU 1008006000 ==========
  33 + ErrorCode SKU_NOT_EXISTS = new ErrorCode(1008006000, "商品 SKU 不存在");
  34 + ErrorCode SKU_PROPERTIES_DUPLICATED = new ErrorCode(1008006001, "商品 SKU 的属性组合存在重复");
  35 + ErrorCode SPU_ATTR_NUMBERS_MUST_BE_EQUALS = new ErrorCode(1008006002, "一个 SPU 下的每个 SKU,其规格数必须一致");
  36 + ErrorCode SPU_SKU_NOT_DUPLICATE = new ErrorCode(1008006003, "一个 SPU 下的每个 SKU,必须不重复");
35 37  
36   - ErrorCode PRODUCT_SPU_ATTR_NUMBERS_MUST_BE_EQUALS = new ErrorCode(1008006002, "一个 Spu 下的每个 SKU ,其规格数必须一致");
37   -
38   - ErrorCode PRODUCT_SPU_SKU_NOT_DUPLICATE = new ErrorCode(1008006003, "一个 SPU 下的每个 SKU ,必须不重复");
39 38 }
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/ProductBrandController.java
... ... @@ -2,15 +2,9 @@ package cn.iocoder.yudao.module.product.controller.admin.brand;
2 2  
3 3 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5   -import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
6   -import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
7 5 import cn.iocoder.yudao.module.product.controller.admin.brand.vo.*;
8   -import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryListReqVO;
9   -import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryRespVO;
10 6 import cn.iocoder.yudao.module.product.convert.brand.ProductBrandConvert;
11   -import cn.iocoder.yudao.module.product.convert.category.ProductCategoryConvert;
12 7 import cn.iocoder.yudao.module.product.dal.dataobject.brand.ProductBrandDO;
13   -import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO;
14 8 import cn.iocoder.yudao.module.product.service.brand.ProductBrandService;
15 9 import io.swagger.annotations.Api;
16 10 import io.swagger.annotations.ApiImplicitParam;
... ... @@ -20,14 +14,11 @@ import org.springframework.validation.annotation.Validated;
20 14 import org.springframework.web.bind.annotation.*;
21 15  
22 16 import javax.annotation.Resource;
23   -import javax.servlet.http.HttpServletResponse;
24 17 import javax.validation.Valid;
25   -import java.io.IOException;
26 18 import java.util.Comparator;
27 19 import java.util.List;
28 20  
29 21 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
30   -import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
31 22  
32 23 @Api(tags = "管理后台 - 商品品牌")
33 24 @RestController
... ... @@ -88,5 +79,4 @@ public class ProductBrandController {
88 79 return success(ProductBrandConvert.INSTANCE.convertList(list));
89 80 }
90 81  
91   -
92 82 }
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/ProductCategoryController.java
... ... @@ -35,14 +35,14 @@ public class ProductCategoryController {
35 35 @ApiOperation("创建商品分类")
36 36 @PreAuthorize("@ss.hasPermission('product:category:create')")
37 37 public CommonResult<Long> createProductCategory(@Valid @RequestBody ProductCategoryCreateReqVO createReqVO) {
38   - return success(categoryService.createProductCategory(createReqVO));
  38 + return success(categoryService.createCategory(createReqVO));
39 39 }
40 40  
41 41 @PutMapping("/update")
42 42 @ApiOperation("更新商品分类")
43 43 @PreAuthorize("@ss.hasPermission('product:category:update')")
44 44 public CommonResult<Boolean> updateProductCategory(@Valid @RequestBody ProductCategoryUpdateReqVO updateReqVO) {
45   - categoryService.updateProductCategory(updateReqVO);
  45 + categoryService.updateCategory(updateReqVO);
46 46 return success(true);
47 47 }
48 48  
... ... @@ -51,7 +51,7 @@ public class ProductCategoryController {
51 51 @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
52 52 @PreAuthorize("@ss.hasPermission('product:category:delete')")
53 53 public CommonResult<Boolean> deleteProductCategory(@RequestParam("id") Long id) {
54   - categoryService.deleteProductCategory(id);
  54 + categoryService.deleteCategory(id);
55 55 return success(true);
56 56 }
57 57  
... ... @@ -60,7 +60,7 @@ public class ProductCategoryController {
60 60 @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
61 61 @PreAuthorize("@ss.hasPermission('product:category:query')")
62 62 public CommonResult<ProductCategoryRespVO> getProductCategory(@RequestParam("id") Long id) {
63   - ProductCategoryDO category = categoryService.getProductCategory(id);
  63 + ProductCategoryDO category = categoryService.getCategory(id);
64 64 return success(ProductCategoryConvert.INSTANCE.convert(category));
65 65 }
66 66  
... ... @@ -68,7 +68,7 @@ public class ProductCategoryController {
68 68 @ApiOperation("获得商品分类列表")
69 69 @PreAuthorize("@ss.hasPermission('product:category:query')")
70 70 public CommonResult<List<ProductCategoryRespVO>> getProductCategoryList(@Valid ProductCategoryListReqVO treeListReqVO) {
71   - List<ProductCategoryDO> list = categoryService.getEnableProductCategoryList(treeListReqVO);
  71 + List<ProductCategoryDO> list = categoryService.getEnableCategoryList(treeListReqVO);
72 72 list.sort(Comparator.comparing(ProductCategoryDO::getSort));
73 73 return success(ProductCategoryConvert.INSTANCE.convertList(list));
74 74 }
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyController.java
... ... @@ -62,7 +62,7 @@ public class ProductPropertyController {
62 62 @ApiOperation("获得规格名称")
63 63 @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
64 64 @PreAuthorize("@ss.hasPermission('product:property:query')")
65   - public CommonResult<ProductPropertyRespVO> getProperty(@RequestParam("id") Long id) {
  65 + public CommonResult<ProductPropertyAndValueRespVO> getProperty(@RequestParam("id") Long id) {
66 66 return success(productPropertyService.getPropertyResp(id));
67 67 }
68 68  
... ... @@ -70,7 +70,7 @@ public class ProductPropertyController {
70 70 @ApiOperation("获得规格名称列表")
71 71 @ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class)
72 72 @PreAuthorize("@ss.hasPermission('product:property:query')")
73   - public CommonResult<List<ProductPropertyRespVO>> getPropertyList(@RequestParam("ids") Collection<Long> ids) {
  73 + public CommonResult<List<ProductPropertyAndValueRespVO>> getPropertyList(@RequestParam("ids") Collection<Long> ids) {
74 74 List<ProductPropertyDO> list = productPropertyService.getPropertyList(ids);
75 75 return success(ProductPropertyConvert.INSTANCE.convertList(list));
76 76 }
... ... @@ -78,7 +78,7 @@ public class ProductPropertyController {
78 78 @GetMapping("/page")
79 79 @ApiOperation("获得规格名称分页")
80 80 @PreAuthorize("@ss.hasPermission('product:property:query')")
81   - public CommonResult<PageResult<ProductPropertyRespVO>> getPropertyPage(@Valid ProductPropertyPageReqVO pageVO) {
  81 + public CommonResult<PageResult<ProductPropertyAndValueRespVO>> getPropertyPage(@Valid ProductPropertyPageReqVO pageVO) {
82 82 return success(productPropertyService.getPropertyListPage(pageVO));
83 83 }
84 84  
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/ProductPropertyAndValueRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.product.controller.admin.property.vo;
  2 +
  3 +import cn.iocoder.yudao.module.product.controller.admin.propertyvalue.vo.ProductPropertyValueRespVO;
  4 +import io.swagger.annotations.ApiModel;
  5 +import io.swagger.annotations.ApiModelProperty;
  6 +import lombok.Data;
  7 +import lombok.EqualsAndHashCode;
  8 +import lombok.ToString;
  9 +
  10 +import java.util.Date;
  11 +import java.util.List;
  12 +
  13 +@ApiModel("管理后台 - 规格 + 规格值 Response VO")
  14 +@Data
  15 +@EqualsAndHashCode(callSuper = true)
  16 +@ToString(callSuper = true)
  17 +public class ProductPropertyAndValueRespVO extends ProductPropertyBaseVO {
  18 +
  19 + @ApiModelProperty(value = "规格的编号", required = true, example = "1024")
  20 + private Long id;
  21 +
  22 + @ApiModelProperty(value = "创建时间", required = true)
  23 + private Date createTime;
  24 +
  25 + /**
  26 + * 规格值的集合
  27 + */
  28 + private List<ProductPropertyValueRespVO> values;
  29 +
  30 +}
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/ProductPropertyBaseVO.java
1 1 package cn.iocoder.yudao.module.product.controller.admin.property.vo;
2 2  
3   -import lombok.*;
4   -import java.util.*;
5   -import io.swagger.annotations.*;
6   -import javax.validation.constraints.*;
  3 +import io.swagger.annotations.ApiModelProperty;
  4 +import lombok.Data;
7 5  
  6 +// TODO @芋艿:完整的 review 下规格
8 7 /**
9 8 * 规格名称 Base VO,提供给添加、修改、详细的子 VO 使用
10 9 * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/ProductPropertyRespVO.java deleted
1   -package cn.iocoder.yudao.module.product.controller.admin.property.vo;
2   -
3   -import cn.iocoder.yudao.module.product.controller.admin.propertyvalue.vo.ProductPropertyValueRespVO;
4   -import lombok.*;
5   -import java.util.*;
6   -import io.swagger.annotations.*;
7   -
8   -@ApiModel("管理后台 - 规格名称 Response VO")
9   -@Data
10   -@EqualsAndHashCode(callSuper = true)
11   -@ToString(callSuper = true)
12   -public class ProductPropertyRespVO extends ProductPropertyBaseVO {
13   -
14   - @ApiModelProperty(value = "主键", required = true)
15   - private Long id;
16   -
17   - @ApiModelProperty(value = "创建时间")
18   - private Date createTime;
19   -
20   - @ApiModelProperty(value = "属性值")
21   - private List<ProductPropertyValueRespVO> propertyValueList;
22   -
23   -}
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuCreateOrUpdateReqVO.java
... ... @@ -6,14 +6,13 @@ import lombok.Data;
6 6 import lombok.EqualsAndHashCode;
7 7 import lombok.ToString;
8 8  
9   -import javax.validation.constraints.NotEmpty;
10   -
11 9 @ApiModel("管理后台 - 商品 SKU 创建/更新 Request VO")
12 10 @Data
13 11 @EqualsAndHashCode(callSuper = true)
14 12 @ToString(callSuper = true)
15 13 public class ProductSkuCreateOrUpdateReqVO extends ProductSkuBaseVO {
16 14  
  15 + // TODO @Luowenfeng:可以不用哈,如果基于规格匹配
17 16 @ApiModelProperty(value = "商品 id 更新时须有", example = "1")
18 17 private Long id;
19 18  
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.java
... ... @@ -36,14 +36,14 @@ public class ProductSpuController {
36 36 @ApiOperation("创建商品 SPU")
37 37 @PreAuthorize("@ss.hasPermission('product:spu:create')")
38 38 public CommonResult<Long> createProductSpu(@Valid @RequestBody ProductSpuCreateReqVO createReqVO) {
39   - return success(spuService.createProductSpu(createReqVO));
  39 + return success(spuService.createSpu(createReqVO));
40 40 }
41 41  
42 42 @PutMapping("/update")
43 43 @ApiOperation("更新商品 SPU")
44 44 @PreAuthorize("@ss.hasPermission('product:spu:update')")
45 45 public CommonResult<Boolean> updateSpu(@Valid @RequestBody ProductSpuUpdateReqVO updateReqVO) {
46   - spuService.updateProductSpu(updateReqVO);
  46 + spuService.updateSpu(updateReqVO);
47 47 return success(true);
48 48 }
49 49  
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/SpuRespVO.java
... ... @@ -35,6 +35,8 @@ public class SpuRespVO extends ProductSpuBaseVO {
35 35 @ApiModelProperty(value = "分类id数组,一直递归到一级父节点", example = "[1,2,4]")
36 36 private LinkedList<Long> categoryIds;
37 37  
  38 + // TODO @芋艿:再琢磨下 这个 VO 类,其实变成 SpuRespVO 内嵌的 VO 类会更好一点;然后把 SpuRespVO 改成 SpuDetailSpuVO
  39 +
38 40 @ApiModelProperty(value = "规格属性修改和详情展示组合", example = "[{\"propertyId\":2,\"name\":\"内存\",\"propertyValues\":[{\"v1\":11,\"v2\":\"64G\"},{\"v1\":10,\"v2\":\"32G\"}]},{\"propertyId\":3,\"name\":\"尺寸\",\"propertyValues\":[{\"v1\":16,\"v2\":\"6.1\"},{\"v1\":15,\"v2\":\"5.7\"}]}]")
39 41 private List<ProductPropertyViewRespVO> productPropertyViews;
40 42  
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/category/AppCategoryController.java
... ... @@ -30,7 +30,7 @@ public class AppCategoryController {
30 30 @GetMapping("/list")
31 31 @ApiOperation("获得商品分类列表")
32 32 public CommonResult<List<AppCategoryRespVO>> getProductCategoryList() {
33   - List<ProductCategoryDO> list = categoryService.getEnableProductCategoryList();
  33 + List<ProductCategoryDO> list = categoryService.getEnableCategoryList();
34 34 list.sort(Comparator.comparing(ProductCategoryDO::getSort));
35 35 return success(ProductCategoryConvert.INSTANCE.convertList03(list));
36 36 }
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/property/ProductPropertyConvert.java
... ... @@ -23,11 +23,11 @@ public interface ProductPropertyConvert {
23 23  
24 24 ProductPropertyDO convert(ProductPropertyUpdateReqVO bean);
25 25  
26   - ProductPropertyRespVO convert(ProductPropertyDO bean);
  26 + ProductPropertyAndValueRespVO convert(ProductPropertyDO bean);
27 27  
28   - List<ProductPropertyRespVO> convertList(List<ProductPropertyDO> list);
  28 + List<ProductPropertyAndValueRespVO> convertList(List<ProductPropertyDO> list);
29 29  
30   - PageResult<ProductPropertyRespVO> convertPage(PageResult<ProductPropertyDO> page);
  30 + PageResult<ProductPropertyAndValueRespVO> convertPage(PageResult<ProductPropertyDO> page);
31 31  
32 32 List<ProductPropertyExcelVO> convertList02(List<ProductPropertyDO> list);
33 33  
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/brand/ProductBrandMapper.java
... ... @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.product.dal.mysql.brand;
3 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 4 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
5 5 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
6   -import cn.iocoder.yudao.module.product.controller.admin.brand.vo.ProductBrandBaseVO;
7 6 import cn.iocoder.yudao.module.product.controller.admin.brand.vo.ProductBrandListReqVO;
8 7 import cn.iocoder.yudao.module.product.controller.admin.brand.vo.ProductBrandPageReqVO;
9 8 import cn.iocoder.yudao.module.product.dal.dataobject.brand.ProductBrandDO;
... ... @@ -27,4 +26,5 @@ public interface ProductBrandMapper extends BaseMapperX&lt;ProductBrandDO&gt; {
27 26 return selectList(new LambdaQueryWrapperX<ProductBrandDO>()
28 27 .likeIfPresent(ProductBrandDO::getName, reqVO.getName()));
29 28 }
  29 +
30 30 }
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/sku/ProductSkuMapper.java
... ... @@ -7,7 +7,6 @@ import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuPageReq
7 7 import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
8 8 import org.apache.ibatis.annotations.Mapper;
9 9  
10   -import java.util.Collections;
11 10 import java.util.List;
12 11  
13 12 /**
... ... @@ -34,13 +33,12 @@ public interface ProductSkuMapper extends BaseMapperX&lt;ProductSkuDO&gt; {
34 33  
35 34  
36 35 // TODO @franky:方法名 selectList; 可以直接调用 selectList
37   - default List<ProductSkuDO> selectBySpuIds(List<Long> spuIds) {
38   - return selectList(new LambdaQueryWrapperX<ProductSkuDO>()
39   - .inIfPresent(ProductSkuDO::getSpuId, spuIds));
  36 + default List<ProductSkuDO> selectListBySpuIds(List<Long> spuIds) {
  37 + return selectList(ProductSkuDO::getSpuId, spuIds);
40 38 }
41 39  
42   - default List<ProductSkuDO> selectBySpuId(Long spuIds) {
43   - return selectBySpuIds(Collections.singletonList(spuIds));
  40 + default List<ProductSkuDO> selectListBySpuId(Long spuId) {
  41 + return selectList(ProductSkuDO::getSpuId, spuId);
44 42 }
45 43  
46 44 default void deleteBySpuId(Long spuId) {
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandService.java
... ... @@ -55,10 +55,11 @@ public interface ProductBrandService {
55 55  
56 56 /**
57 57 * 获得品牌列表
58   - * @param listVo 请求参数
  58 + *
  59 + * @param listReqVO 请求参数
59 60 * @return 品牌列表
60 61 */
61   - List<ProductBrandDO> getBrandList(ProductBrandListReqVO listVo);
  62 + List<ProductBrandDO> getBrandList(ProductBrandListReqVO listReqVO);
62 63  
63 64 /**
64 65 * 验证选择的商品分类是否合法
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandServiceImpl.java
1 1 package cn.iocoder.yudao.module.product.service.brand;
2 2  
3 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4   -import cn.iocoder.yudao.module.product.controller.admin.brand.vo.*;
  4 +import cn.iocoder.yudao.module.product.controller.admin.brand.vo.ProductBrandCreateReqVO;
  5 +import cn.iocoder.yudao.module.product.controller.admin.brand.vo.ProductBrandListReqVO;
  6 +import cn.iocoder.yudao.module.product.controller.admin.brand.vo.ProductBrandPageReqVO;
  7 +import cn.iocoder.yudao.module.product.controller.admin.brand.vo.ProductBrandUpdateReqVO;
5 8 import cn.iocoder.yudao.module.product.convert.brand.ProductBrandConvert;
6 9 import cn.iocoder.yudao.module.product.dal.dataobject.brand.ProductBrandDO;
7 10 import cn.iocoder.yudao.module.product.dal.mysql.brand.ProductBrandMapper;
8   -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
9 11 import org.springframework.stereotype.Service;
10 12 import org.springframework.validation.annotation.Validated;
11 13  
... ... @@ -14,8 +16,7 @@ import java.util.Collection;
14 16 import java.util.List;
15 17  
16 18 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
17   -import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.PRODUCT_BRAND_NOT_EXISTS;
18   -import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.PRODUCT_CATEGORY_LEVEL;
  19 +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.BRAND_NOT_EXISTS;
19 20  
20 21 /**
21 22 * 品牌 Service 实现类
... ... @@ -57,7 +58,7 @@ public class ProductBrandServiceImpl implements ProductBrandService {
57 58  
58 59 private void validateBrandExists(Long id) {
59 60 if (brandMapper.selectById(id) == null) {
60   - throw exception(PRODUCT_BRAND_NOT_EXISTS);
  61 + throw exception(BRAND_NOT_EXISTS);
61 62 }
62 63 }
63 64  
... ... @@ -72,14 +73,14 @@ public class ProductBrandServiceImpl implements ProductBrandService {
72 73 }
73 74  
74 75 @Override
75   - public List<ProductBrandDO> getBrandList(ProductBrandListReqVO listVo) {
76   - return brandMapper.selectList(listVo);
  76 + public List<ProductBrandDO> getBrandList(ProductBrandListReqVO listReqVO) {
  77 + return brandMapper.selectList(listReqVO);
77 78 }
78 79  
79 80 @Override
80 81 public void validateProductBrand(Long id) {
81 82 if(getBrand(id) == null){
82   - throw exception(PRODUCT_BRAND_NOT_EXISTS);
  83 + throw exception(BRAND_NOT_EXISTS);
83 84 }
84 85 }
85 86  
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryService.java
... ... @@ -22,21 +22,21 @@ public interface ProductCategoryService {
22 22 * @param createReqVO 创建信息
23 23 * @return 编号
24 24 */
25   - Long createProductCategory(@Valid ProductCategoryCreateReqVO createReqVO);
  25 + Long createCategory(@Valid ProductCategoryCreateReqVO createReqVO);
26 26  
27 27 /**
28 28 * 更新商品分类
29 29 *
30 30 * @param updateReqVO 更新信息
31 31 */
32   - void updateProductCategory(@Valid ProductCategoryUpdateReqVO updateReqVO);
  32 + void updateCategory(@Valid ProductCategoryUpdateReqVO updateReqVO);
33 33  
34 34 /**
35 35 * 删除商品分类
36 36 *
37 37 * @param id 编号
38 38 */
39   - void deleteProductCategory(Long id);
  39 + void deleteCategory(Long id);
40 40  
41 41 /**
42 42 * 获得商品分类
... ... @@ -44,7 +44,7 @@ public interface ProductCategoryService {
44 44 * @param id 编号
45 45 * @return 商品分类
46 46 */
47   - ProductCategoryDO getProductCategory(Long id);
  47 + ProductCategoryDO getCategory(Long id);
48 48  
49 49 /**
50 50 * 获得商品分类列表
... ... @@ -52,7 +52,7 @@ public interface ProductCategoryService {
52 52 * @param ids 编号
53 53 * @return 商品分类列表
54 54 */
55   - List<ProductCategoryDO> getEnableProductCategoryList(Collection<Long> ids);
  55 + List<ProductCategoryDO> getEnableCategoryList(Collection<Long> ids);
56 56  
57 57 /**
58 58 * 获得商品分类列表
... ... @@ -60,20 +60,21 @@ public interface ProductCategoryService {
60 60 * @param listReqVO 查询条件
61 61 * @return 商品分类列表
62 62 */
63   - List<ProductCategoryDO> getEnableProductCategoryList(ProductCategoryListReqVO listReqVO);
  63 + List<ProductCategoryDO> getEnableCategoryList(ProductCategoryListReqVO listReqVO);
64 64  
65 65 /**
66   - * 验证选择的商品分类是否合法
  66 + * 验证选择的商品分类的级别是否合法
  67 + * 例如说,商品发布的时候,必须在第 3 级别
67 68 *
68 69 * @param id 分类编号
69 70 */
70   - void validateProductCategory(Long id);
  71 + void validateCategoryLevel(Long id);
71 72  
72 73 /**
73 74 * 获得开启状态的商品分类列表
74 75 *
75 76 * @return 商品分类列表
76 77 */
77   - List<ProductCategoryDO> getEnableProductCategoryList();
  78 + List<ProductCategoryDO> getEnableCategoryList();
78 79  
79 80 }
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImpl.java
... ... @@ -32,7 +32,7 @@ public class ProductCategoryServiceImpl implements ProductCategoryService {
32 32 private ProductCategoryMapper productCategoryMapper;
33 33  
34 34 @Override
35   - public Long createProductCategory(ProductCategoryCreateReqVO createReqVO) {
  35 + public Long createCategory(ProductCategoryCreateReqVO createReqVO) {
36 36 // 校验父分类存在
37 37 validateParentProductCategory(createReqVO.getParentId());
38 38  
... ... @@ -44,7 +44,7 @@ public class ProductCategoryServiceImpl implements ProductCategoryService {
44 44 }
45 45  
46 46 @Override
47   - public void updateProductCategory(ProductCategoryUpdateReqVO updateReqVO) {
  47 + public void updateCategory(ProductCategoryUpdateReqVO updateReqVO) {
48 48 // 校验分类是否存在
49 49 validateProductCategoryExists(updateReqVO.getId());
50 50 // 校验父分类存在
... ... @@ -56,12 +56,12 @@ public class ProductCategoryServiceImpl implements ProductCategoryService {
56 56 }
57 57  
58 58 @Override
59   - public void deleteProductCategory(Long id) {
  59 + public void deleteCategory(Long id) {
60 60 // 校验分类是否存在
61 61 validateProductCategoryExists(id);
62 62 // 校验是否还有子分类
63 63 if (productCategoryMapper.selectCountByParentId(id) > 0) {
64   - throw exception(PRODUCT_CATEGORY_EXISTS_CHILDREN);
  64 + throw exception(CATEGORY_EXISTS_CHILDREN);
65 65 }
66 66  
67 67 // 删除
... ... @@ -76,61 +76,69 @@ public class ProductCategoryServiceImpl implements ProductCategoryService {
76 76 // 父分类不存在
77 77 ProductCategoryDO category = productCategoryMapper.selectById(id);
78 78 if (category == null) {
79   - throw exception(PRODUCT_CATEGORY_PARENT_NOT_EXISTS);
  79 + throw exception(CATEGORY_PARENT_NOT_EXISTS);
80 80 }
81 81 // 父分类不能是二级分类
82 82 if (Objects.equals(id, ProductCategoryDO.PARENT_ID_NULL)) {
83   - throw exception(PRODUCT_CATEGORY_PARENT_NOT_FIRST_LEVEL);
  83 + throw exception(CATEGORY_PARENT_NOT_FIRST_LEVEL);
84 84 }
85 85 }
86 86  
87 87 private void validateProductCategoryExists(Long id) {
88 88 ProductCategoryDO category = productCategoryMapper.selectById(id);
89 89 if (category == null) {
90   - throw exception(PRODUCT_CATEGORY_NOT_EXISTS);
  90 + throw exception(CATEGORY_NOT_EXISTS);
91 91 }
92 92 }
93 93  
94 94 @Override
95   - public void validateProductCategory(Long id) {
96   - Integer level = categoryLevel(id, 1);
  95 + public void validateCategoryLevel(Long id) {
  96 + Integer level = getProductCategoryLevel(id, 1);
97 97 if(level < 3){
98   - throw exception(PRODUCT_CATEGORY_LEVEL);
  98 + throw exception(CATEGORY_LEVEL_ERROR);
99 99 }
100 100 }
101 101  
102   - // 校验分类级别
103   - private Integer categoryLevel(Long id, int level){
  102 + // TODO @Luowenfeng:建议使用 for 循环,避免递归
  103 + /**
  104 + * 获得商品分类的级别
  105 + *
  106 + * @param id 商品分类的编号
  107 + * @return 级别
  108 + */
  109 + private Integer getProductCategoryLevel(Long id, int level){
104 110 ProductCategoryDO category = productCategoryMapper.selectById(id);
105 111 if (category == null) {
106   - throw exception(PRODUCT_CATEGORY_NOT_EXISTS);
  112 + throw exception(CATEGORY_NOT_EXISTS);
107 113 }
  114 + // TODO Luowenfeng:去掉是否开启,它不影响级别哈
108 115 if (ObjectUtil.notEqual(category.getStatus(), CommonStatusEnum.ENABLE.getStatus())) {
109   - throw exception(PRODUCT_CATEGORY_DISABLED);
  116 + throw exception(CATEGORY_DISABLED);
110 117 }
111   - if(category.getParentId() == 0) {
  118 + // TODO Luowenfeng:不使用 0 直接比较哈,使用枚举
  119 + if (category.getParentId() == 0) {
112 120 return level;
113 121 }
114   - return categoryLevel(category.getParentId(), ++level);
  122 + return getProductCategoryLevel(category.getParentId(), ++level);
115 123 }
116 124  
117 125 @Override
118   - public ProductCategoryDO getProductCategory(Long id) {
  126 + public ProductCategoryDO getCategory(Long id) {
119 127 return productCategoryMapper.selectById(id);
120 128 }
121 129  
122 130 @Override
123   - public List<ProductCategoryDO> getEnableProductCategoryList(Collection<Long> ids) {
  131 + public List<ProductCategoryDO> getEnableCategoryList(Collection<Long> ids) {
124 132 return productCategoryMapper.selectBatchIds(ids);
125 133 }
126 134  
127 135 @Override
128   - public List<ProductCategoryDO> getEnableProductCategoryList(ProductCategoryListReqVO listReqVO) {
  136 + public List<ProductCategoryDO> getEnableCategoryList(ProductCategoryListReqVO listReqVO) {
129 137 return productCategoryMapper.selectList(listReqVO);
130 138 }
131 139  
132 140 @Override
133   - public List<ProductCategoryDO> getEnableProductCategoryList() {
  141 + public List<ProductCategoryDO> getEnableCategoryList() {
134 142 return productCategoryMapper.selectListByStatus(CommonStatusEnum.ENABLE.getStatus());
135 143 }
136 144  
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyService.java
1 1 package cn.iocoder.yudao.module.product.service.property;
2 2  
3   -import java.util.*;
4   -import javax.validation.*;
  3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 4 import cn.iocoder.yudao.module.product.controller.admin.property.vo.*;
6 5 import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO;
7   -import cn.iocoder.yudao.framework.common.pojo.PageResult;
  6 +
  7 +import javax.validation.Valid;
  8 +import java.util.Collection;
  9 +import java.util.List;
8 10  
9 11 /**
10 12 * 规格名称 Service 接口
... ... @@ -72,14 +74,16 @@ public interface ProductPropertyService {
72 74 * @param pageReqVO
73 75 * @return
74 76 */
75   - PageResult<ProductPropertyRespVO> getPropertyListPage(ProductPropertyPageReqVO pageReqVO);
  77 + PageResult<ProductPropertyAndValueRespVO> getPropertyListPage(ProductPropertyPageReqVO pageReqVO);
76 78  
77   - ProductPropertyRespVO getPropertyResp(Long id);
  79 + ProductPropertyAndValueRespVO getPropertyResp(Long id);
78 80  
79 81 /**
80   - * 根据数据名id集合查询属性名以及属性值的集合
81   - * @param propertyIds 属性名id集合
82   - * @return
  82 + * 根据规格属性编号的集合,获得对应的规格 + 规格值的集合
  83 + *
  84 + * @param ids 规格编号的集合
  85 + * @return 对应的规格 + 规格值的集合
83 86 */
84   - List<ProductPropertyRespVO> selectByIds(List<Long> propertyIds);
  87 + List<ProductPropertyAndValueRespVO> getPropertyAndValueList(Collection<Long> ids);
  88 +
85 89 }
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyServiceImpl.java
... ... @@ -108,11 +108,11 @@ public class ProductPropertyServiceImpl implements ProductPropertyService {
108 108 }
109 109  
110 110 @Override
111   - public PageResult<ProductPropertyRespVO> getPropertyListPage(ProductPropertyPageReqVO pageReqVO) {
  111 + public PageResult<ProductPropertyAndValueRespVO> getPropertyListPage(ProductPropertyPageReqVO pageReqVO) {
112 112 //获取属性列表
113 113 PageResult<ProductPropertyDO> pageResult = productPropertyMapper.selectPage(pageReqVO);
114   - PageResult<ProductPropertyRespVO> propertyRespVOPageResult = ProductPropertyConvert.INSTANCE.convertPage(pageResult);
115   - List<Long> propertyIds = propertyRespVOPageResult.getList().stream().map(ProductPropertyRespVO::getId).collect(Collectors.toList());
  114 + PageResult<ProductPropertyAndValueRespVO> propertyRespVOPageResult = ProductPropertyConvert.INSTANCE.convertPage(pageResult);
  115 + List<Long> propertyIds = propertyRespVOPageResult.getList().stream().map(ProductPropertyAndValueRespVO::getId).collect(Collectors.toList());
116 116  
117 117 //获取属性值列表
118 118 List<ProductPropertyValueDO> productPropertyValueDOList = productPropertyValueMapper.getPropertyValueListByPropertyId(propertyIds);
... ... @@ -121,7 +121,7 @@ public class ProductPropertyServiceImpl implements ProductPropertyService {
121 121 propertyRespVOPageResult.getList().forEach(x->{
122 122 Long propertyId = x.getId();
123 123 List<ProductPropertyValueRespVO> valueDOList = propertyValueRespVOList.stream().filter(v -> v.getPropertyId().equals(propertyId)).collect(Collectors.toList());
124   - x.setPropertyValueList(valueDOList);
  124 + x.setValues(valueDOList);
125 125 });
126 126 return propertyRespVOPageResult;
127 127 }
... ... @@ -131,25 +131,25 @@ public class ProductPropertyServiceImpl implements ProductPropertyService {
131 131 }
132 132  
133 133 @Override
134   - public ProductPropertyRespVO getPropertyResp(Long id) {
  134 + public ProductPropertyAndValueRespVO getPropertyResp(Long id) {
135 135 //查询规格
136 136 ProductPropertyDO property = getProperty(id);
137   - ProductPropertyRespVO propertyRespVO = ProductPropertyConvert.INSTANCE.convert(property);
  137 + ProductPropertyAndValueRespVO propertyRespVO = ProductPropertyConvert.INSTANCE.convert(property);
138 138 //查询属性值
139 139 List<ProductPropertyValueDO> valueDOList = productPropertyValueMapper.getPropertyValueListByPropertyId(Arrays.asList(id));
140 140 List<ProductPropertyValueRespVO> propertyValueRespVOS = ProductPropertyValueConvert.INSTANCE.convertList(valueDOList);
141 141 //组装
142   - propertyRespVO.setPropertyValueList(propertyValueRespVOS);
  142 + propertyRespVO.setValues(propertyValueRespVOS);
143 143 return propertyRespVO;
144 144 }
145 145  
146 146 @Override
147   - public List<ProductPropertyRespVO> selectByIds(List<Long> propertyIds) {
148   - List<ProductPropertyRespVO> productPropertyRespVO = ProductPropertyConvert.INSTANCE.convertList(productPropertyMapper.selectBatchIds(propertyIds));
  147 + public List<ProductPropertyAndValueRespVO> getPropertyAndValueList(Collection<Long> ids) {
  148 + List<ProductPropertyAndValueRespVO> productPropertyRespVO = ProductPropertyConvert.INSTANCE.convertList(productPropertyMapper.selectBatchIds(ids));
149 149 //查询属性值
150   - List<ProductPropertyValueDO> valueDOList = productPropertyValueMapper.getPropertyValueListByPropertyId(propertyIds);
  150 + List<ProductPropertyValueDO> valueDOList = productPropertyValueMapper.selectBatchIds(ids);
151 151 Map<Long, List<ProductPropertyValueDO>> propertyValuesMap = valueDOList.stream().collect(Collectors.groupingBy(ProductPropertyValueDO::getPropertyId));
152   - productPropertyRespVO.forEach(p -> p.setPropertyValueList(ProductPropertyValueConvert.INSTANCE.convertList(propertyValuesMap.get(p.getId()))));
  152 + productPropertyRespVO.forEach(p -> p.setValues(ProductPropertyValueConvert.INSTANCE.convertList(propertyValuesMap.get(p.getId()))));
153 153 return productPropertyRespVO;
154 154 }
155 155 }
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java
... ... @@ -11,14 +11,14 @@ import java.util.Collection;
11 11 import java.util.List;
12 12  
13 13 /**
14   - * 商品sku Service 接口
  14 + * 商品 SKU Service 接口
15 15 *
16 16 * @author 芋道源码
17 17 */
18 18 public interface ProductSkuService {
19 19  
20 20 /**
21   - * 创建商品sku
  21 + * 创建商品 SKU
22 22 *
23 23 * @param createReqVO 创建信息
24 24 * @return 编号
... ... @@ -68,14 +68,15 @@ public interface ProductSkuService {
68 68 *
69 69 * @param list sku组合的集合
70 70 */
71   - void validateProductSkus(List<ProductSkuCreateOrUpdateReqVO> list, Integer specType);
  71 + void validateSkus(List<ProductSkuCreateOrUpdateReqVO> list, Integer specType);
72 72  
73 73 /**
74 74 * 批量创建 SKU
75 75 *
  76 + * @param spuId 商品 SPU 编号
76 77 * @param list SKU 对象集合
77 78 */
78   - void createProductSkus(List<ProductSkuCreateOrUpdateReqVO> list, Long spuId);
  79 + void createSkus(Long spuId, List<ProductSkuCreateOrUpdateReqVO> list);
79 80  
80 81 /**
81 82 * 根据 SPU 编号,批量更新它的 SKU 信息
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java
1 1 package cn.iocoder.yudao.module.product.service.sku;
2 2  
3 3 import cn.hutool.core.collection.CollectionUtil;
  4 +import cn.hutool.core.util.ObjectUtil;
4 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 6 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
6   -import cn.iocoder.yudao.module.product.controller.admin.property.vo.ProductPropertyRespVO;
  7 +import cn.iocoder.yudao.module.product.controller.admin.property.vo.ProductPropertyAndValueRespVO;
7 8 import cn.iocoder.yudao.module.product.controller.admin.propertyvalue.vo.ProductPropertyValueRespVO;
8 9 import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuBaseVO;
9 10 import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO;
... ... @@ -24,11 +25,10 @@ import java.util.*;
24 25 import java.util.stream.Collectors;
25 26  
26 27 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
27   -import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.PROPERTY_NOT_EXISTS;
28   -import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS;
  28 +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.*;
29 29  
30 30 /**
31   - * 商品sku Service 实现类
  31 + * 商品 SKU Service 实现类
32 32 *
33 33 * @author 芋道源码
34 34 */
... ... @@ -90,48 +90,51 @@ public class ProductSkuServiceImpl implements ProductSkuService {
90 90 }
91 91  
92 92 @Override
93   - public void validateProductSkus(List<ProductSkuCreateOrUpdateReqVO> list, Integer specType) {
94   - // 多规格才需校验
95   - if (specType.equals(ProductSpuSpecTypeEnum.DISABLE.getType())) {
96   - List<ProductSkuBaseVO.Property> skuPropertyList = list.stream().flatMap(p -> Optional.of(p.getProperties()).orElse(new ArrayList<>()).stream()).collect(Collectors.toList());
97   - // 1、校验规格属性存在
98   - List<Long> propertyIds = CollectionUtils.convertList(skuPropertyList, ProductSkuBaseVO.Property::getPropertyId);
99   - List<ProductPropertyRespVO> propertyAndValueList = productPropertyService.selectByIds(propertyIds);
100   - if (propertyAndValueList.size() == propertyIds.size()) {
101   - throw exception(PROPERTY_NOT_EXISTS);
  93 + public void validateSkus(List<ProductSkuCreateOrUpdateReqVO> skus, Integer specType) {
  94 + // 非多规格,不需要校验
  95 + if (ObjectUtil.notEqual(specType, ProductSpuSpecTypeEnum.DISABLE.getType())) {
  96 + return;
  97 + }
  98 +
  99 + // 1、校验规格属性存在
  100 + // TODO @Luowenfeng:stream 的写法;不用改哈,就是说下可以酱紫写;
  101 + Set<Long> propertyIds = skus.stream().filter(p -> p.getProperties() != null).flatMap(p -> p.getProperties().stream()) // 遍历多个 Property 属性
  102 + .map(ProductSkuBaseVO.Property::getPropertyId).collect(Collectors.toSet()); // 将每个 Property 转换成对应的 propertyId,最后形成集合
  103 + List<ProductPropertyAndValueRespVO> propertyAndValueList = productPropertyService.getPropertyAndValueList(propertyIds);
  104 + if (propertyAndValueList.size() == propertyIds.size()) {
  105 + throw exception(PROPERTY_NOT_EXISTS);
  106 + }
  107 +
  108 + // 2. 校验,一个 SKU 下,没有重复的规格。校验方式是,遍历每个 SKU ,看看是否有重复的规格 propertyId
  109 + Map<Long, ProductPropertyValueRespVO> propertyValueMap = propertyAndValueList.stream().filter(p -> p.getValues() != null).flatMap(p -> p.getValues().stream())
  110 + .collect(Collectors.toMap(ProductPropertyValueRespVO::getId, value -> value)); // KEY:规格属性值的编号
  111 + skus.forEach(sku -> {
  112 + Set<Long> skuPropertyIds = CollectionUtils.convertSet(sku.getProperties(), propertyItem -> propertyValueMap.get(propertyItem.getValueId()).getPropertyId());
  113 + if (skuPropertyIds.size() != sku.getProperties().size()) {
  114 + throw exception(SKU_PROPERTIES_DUPLICATED);
102 115 }
103   - // 2. 校验,一个 Sku 下,没有重复的规格。校验方式是,遍历每个 Sku ,看看是否有重复的规格 attrId
104   - List<ProductPropertyValueRespVO> collect = propertyAndValueList.stream()
105   - .flatMap(v -> Optional.of(v.getPropertyValueList())
106   - .orElse(new ArrayList<>()).stream()).collect(Collectors.toList());
107   - Map<Long, ProductPropertyValueRespVO> propertyValueRespVOMap = CollectionUtils.convertMap(collect, ProductPropertyValueRespVO::getId);
108   - list.forEach(v -> {
109   - Set<Long> keys = v.getProperties().stream().map(k -> propertyValueRespVOMap.get(k.getValueId()).getPropertyId()).collect(Collectors.toSet());
110   - if (keys.size() != v.getProperties().size()) {
111   - throw exception(ErrorCodeConstants.SKU_PROPERTIES_DUPLICATED);
112   - }
113   - });
  116 + });
114 117  
115   - // 3. 再校验,每个 Sku 的规格值的数量,是一致的。
116   - int attrValueIdsSize = list.get(0).getProperties().size();
117   - for (int i = 1; i < list.size(); i++) {
118   - if (attrValueIdsSize != list.get(i).getProperties().size()) {
119   - throw exception(ErrorCodeConstants.PRODUCT_SPU_ATTR_NUMBERS_MUST_BE_EQUALS);
120   - }
  118 + // 3. 再校验,每个 Sku 的规格值的数量,是一致的。
  119 + int attrValueIdsSize = skus.get(0).getProperties().size();
  120 + for (int i = 1; i < skus.size(); i++) {
  121 + if (attrValueIdsSize != skus.get(i).getProperties().size()) {
  122 + throw exception(ErrorCodeConstants.SPU_ATTR_NUMBERS_MUST_BE_EQUALS);
121 123 }
  124 + }
122 125  
123   - // 4. 最后校验,每个 Sku 之间不是重复的
124   - Set<Set<Long>> skuAttrValues = new HashSet<>(); // 每个元素,都是一个 Sku 的 attrValueId 集合。这样,通过最外层的 Set ,判断是否有重复的.
125   - for (ProductSkuCreateOrUpdateReqVO sku : list) {
126   - if (!skuAttrValues.add(sku.getProperties().stream().map(ProductSkuBaseVO.Property::getValueId).collect(Collectors.toSet()))) { // 添加失败,说明重复
127   - throw exception(ErrorCodeConstants.PRODUCT_SPU_SKU_NOT_DUPLICATE);
128   - }
  126 + // 4. 最后校验,每个 Sku 之间不是重复的
  127 + Set<Set<Long>> skuAttrValues = new HashSet<>(); // 每个元素,都是一个 Sku 的 attrValueId 集合。这样,通过最外层的 Set ,判断是否有重复的.
  128 + for (ProductSkuCreateOrUpdateReqVO sku : skus) {
  129 + // TODO @Luowenfeng:可以使用 CollectionUtils.convertSet(),简化下面的 stream 操作
  130 + if (!skuAttrValues.add(sku.getProperties().stream().map(ProductSkuBaseVO.Property::getValueId).collect(Collectors.toSet()))) { // 添加失败,说明重复
  131 + throw exception(ErrorCodeConstants.SPU_SKU_NOT_DUPLICATE);
129 132 }
130 133 }
131 134 }
132 135  
133 136 @Override
134   - public void createProductSkus(List<ProductSkuCreateOrUpdateReqVO> skuCreateReqList, Long spuId) {
  137 + public void createSkus(Long spuId, List<ProductSkuCreateOrUpdateReqVO> skuCreateReqList) {
135 138 // 批量插入 SKU
136 139 List<ProductSkuDO> skuDOList = ProductSkuConvert.INSTANCE.convertSkuDOList(skuCreateReqList);
137 140 skuDOList.forEach(v -> v.setSpuId(spuId));
... ... @@ -140,13 +143,12 @@ public class ProductSkuServiceImpl implements ProductSkuService {
140 143  
141 144 @Override
142 145 public List<ProductSkuDO> getSkusBySpuId(Long spuId) {
143   - List<ProductSkuDO> productSkuDOS = productSkuMapper.selectBySpuIds(Collections.singletonList(spuId));
144   - return productSkuDOS;
  146 + return productSkuMapper.selectListBySpuIds(Collections.singletonList(spuId));
145 147 }
146 148  
147 149 @Override
148 150 public List<ProductSkuDO> getSkusBySpuIds(List<Long> spuIds) {
149   - return productSkuMapper.selectBySpuIds(spuIds);
  151 + return productSkuMapper.selectListBySpuIds(spuIds);
150 152 }
151 153  
152 154 @Override
... ... @@ -157,16 +159,16 @@ public class ProductSkuServiceImpl implements ProductSkuService {
157 159 @Override
158 160 @Transactional
159 161 public void updateProductSkus(Long spuId, List<ProductSkuCreateOrUpdateReqVO> skus) {
160   - // 查询 spu 下已经存在的 sku 的集合
161   - List<ProductSkuDO> existsSkus = productSkuMapper.selectBySpuId(spuId);
  162 + // 查询 SPU 下已经存在的 SKU 的集合
  163 + List<ProductSkuDO> existsSkus = productSkuMapper.selectListBySpuId(spuId);
162 164 Map<Long, ProductSkuDO> existsSkuMap = CollectionUtils.convertMap(existsSkus, ProductSkuDO::getId);
163 165  
164 166 // 拆分三个集合,新插入的、需要更新的、需要删除的
165 167 List<ProductSkuDO> insertSkus = new ArrayList<>();
166   - List<ProductSkuDO> updateSkus = new ArrayList<>();
  168 + List<ProductSkuDO> updateSkus = new ArrayList<>(); // TODO Luowenfeng:使用 Long 即可
167 169 List<ProductSkuDO> deleteSkus = new ArrayList<>();
168 170  
169   - // TODO @芋艿:是不是基于规格匹配会比较好。
  171 + // TODO @Luowenfeng:是不是基于规格匹配会比较好。可以参考下 onemall 的 ProductSpuServiceImpl 的 updateProductSpu 逻辑
170 172 List<ProductSkuDO> allUpdateSkus = ProductSkuConvert.INSTANCE.convertSkuDOList(skus);
171 173 allUpdateSkus.forEach(p -> {
172 174 if (p.getId() != null) {
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuService.java
... ... @@ -26,14 +26,14 @@ public interface ProductSpuService {
26 26 * @param createReqVO 创建信息
27 27 * @return 编号
28 28 */
29   - Long createProductSpu(@Valid ProductSpuCreateReqVO createReqVO);
  29 + Long createSpu(@Valid ProductSpuCreateReqVO createReqVO);
30 30  
31 31 /**
32 32 * 更新商品 SPU
33 33 *
34 34 * @param updateReqVO 更新信息
35 35 */
36   - void updateProductSpu(@Valid ProductSpuUpdateReqVO updateReqVO);
  36 + void updateSpu(@Valid ProductSpuUpdateReqVO updateReqVO);
37 37  
38 38 /**
39 39 * 删除商品spu
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java
... ... @@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.product.service.spu;
2 2  
3 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 4 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
5   -import cn.iocoder.yudao.module.product.controller.admin.property.vo.ProductPropertyRespVO;
  5 +import cn.iocoder.yudao.module.product.controller.admin.property.vo.ProductPropertyAndValueRespVO;
6 6 import cn.iocoder.yudao.module.product.controller.admin.property.vo.ProductPropertyViewRespVO;
7 7 import cn.iocoder.yudao.module.product.controller.admin.propertyvalue.vo.ProductPropertyValueRespVO;
8 8 import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuBaseVO;
... ... @@ -16,7 +16,6 @@ import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageReqVO;
16 16 import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageRespVO;
17 17 import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert;
18 18 import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert;
19   -import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
20 19 import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
21 20 import cn.iocoder.yudao.module.product.dal.mysql.spu.ProductSpuMapper;
22 21 import cn.iocoder.yudao.module.product.enums.spu.ProductSpuSpecTypeEnum;
... ... @@ -30,7 +29,6 @@ import org.springframework.validation.annotation.Validated;
30 29  
31 30 import javax.annotation.Resource;
32 31 import java.util.*;
33   -import java.util.function.Function;
34 32 import java.util.stream.Collectors;
35 33  
36 34 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
... ... @@ -62,14 +60,14 @@ public class ProductSpuServiceImpl implements ProductSpuService {
62 60  
63 61 @Override
64 62 @Transactional
65   - public Long createProductSpu(ProductSpuCreateReqVO createReqVO) {
  63 + public Long createSpu(ProductSpuCreateReqVO createReqVO) {
66 64 // 校验分类
67   - categoryService.validateProductCategory(createReqVO.getCategoryId());
  65 + categoryService.validateCategoryLevel(createReqVO.getCategoryId());
68 66 // 校验品牌
69 67 brandService.validateProductBrand(createReqVO.getBrandId());
70 68 // 校验SKU
71 69 List<ProductSkuCreateOrUpdateReqVO> skuCreateReqList = createReqVO.getSkus();
72   - productSkuService.validateProductSkus(skuCreateReqList, createReqVO.getSpecType());
  70 + productSkuService.validateSkus(skuCreateReqList, createReqVO.getSpecType());
73 71 // 插入 SPU
74 72 ProductSpuDO spu = ProductSpuConvert.INSTANCE.convert(createReqVO);
75 73 spu.setMarketPrice(CollectionUtils.getMaxValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getMarketPrice));
... ... @@ -78,24 +76,25 @@ public class ProductSpuServiceImpl implements ProductSpuService {
78 76 spu.setTotalStock(CollectionUtils.getSumValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getStock, Integer::sum));
79 77 ProductSpuMapper.insert(spu);
80 78 // 插入 SKU
81   - productSkuService.createProductSkus(skuCreateReqList, spu.getId());
  79 + productSkuService.createSkus(spu.getId(), skuCreateReqList);
82 80 // 返回
83 81 return spu.getId();
84 82 }
85 83  
86 84 @Override
87 85 @Transactional
88   - public void updateProductSpu(ProductSpuUpdateReqVO updateReqVO) {
  86 + public void updateSpu(ProductSpuUpdateReqVO updateReqVO) {
89 87 // 校验 SPU 是否存在
90 88 validateSpuExists(updateReqVO.getId());
91 89 // 校验分类
92   - categoryService.validateProductCategory(updateReqVO.getCategoryId());
  90 + categoryService.validateCategoryLevel(updateReqVO.getCategoryId());
93 91 // 校验品牌
94 92 brandService.validateProductBrand(updateReqVO.getBrandId());
95 93 // 校验SKU
96 94 List<ProductSkuCreateOrUpdateReqVO> skuCreateReqList = updateReqVO.getSkus();
97 95 // 多规格才需校验
98   - productSkuService.validateProductSkus(skuCreateReqList, updateReqVO.getSpecType());
  96 + productSkuService.validateSkus(skuCreateReqList, updateReqVO.getSpecType());
  97 +
99 98 // 更新 SPU
100 99 ProductSpuDO updateObj = ProductSpuConvert.INSTANCE.convert(updateReqVO);
101 100 updateObj.setMarketPrice(CollectionUtils.getMaxValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getMarketPrice));
... ... @@ -103,7 +102,7 @@ public class ProductSpuServiceImpl implements ProductSpuService {
103 102 updateObj.setMinPrice(CollectionUtils.getMinValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getPrice));
104 103 updateObj.setTotalStock(CollectionUtils.getSumValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getStock, Integer::sum));
105 104 ProductSpuMapper.updateById(updateObj);
106   - // 更新 SKU
  105 + // 批量更新 SKU
107 106 productSkuService.updateProductSkus(updateObj.getId(), updateReqVO.getSkus());
108 107 }
109 108  
... ... @@ -111,7 +110,7 @@ public class ProductSpuServiceImpl implements ProductSpuService {
111 110 @Transactional
112 111 public void deleteSpu(Long id) {
113 112 // 校验存在
114   - this.validateSpuExists(id);
  113 + validateSpuExists(id);
115 114 // 删除 SPU
116 115 ProductSpuMapper.deleteById(id);
117 116 // 删除关联的 SKU
... ... @@ -125,6 +124,7 @@ public class ProductSpuServiceImpl implements ProductSpuService {
125 124 }
126 125  
127 126 @Override
  127 + // TODO @芋艿:需要再 review 下
128 128 public SpuRespVO getSpu(Long id) {
129 129 ProductSpuDO spu = ProductSpuMapper.selectById(id);
130 130 SpuRespVO spuVO = ProductSpuConvert.INSTANCE.convert(spu);
... ... @@ -138,7 +138,7 @@ public class ProductSpuServiceImpl implements ProductSpuService {
138 138 properties.addAll(productSkuRespVO.getProperties());
139 139 }
140 140 Map<Long, List<ProductSkuBaseVO.Property>> propertyMaps = properties.stream().collect(Collectors.groupingBy(ProductSkuBaseVO.Property::getPropertyId));
141   - List<ProductPropertyRespVO> propertyAndValueList = productPropertyService.selectByIds(new ArrayList<>(propertyMaps.keySet()));
  141 + List<ProductPropertyAndValueRespVO> propertyAndValueList = productPropertyService.getPropertyAndValueList(new ArrayList<>(propertyMaps.keySet()));
142 142 // 装载组装过后的属性
143 143 List<ProductPropertyViewRespVO> productPropertyViews = new ArrayList<>();
144 144 propertyAndValueList.forEach(p -> {
... ... @@ -146,7 +146,7 @@ public class ProductSpuServiceImpl implements ProductSpuService {
146 146 productPropertyViewRespVO.setPropertyId(p.getId());
147 147 productPropertyViewRespVO.setName(p.getName());
148 148 List<ProductPropertyViewRespVO.Tuple2> propertyValues = new ArrayList<>();
149   - Map<Long, ProductPropertyValueRespVO> propertyValueMaps = p.getPropertyValueList().stream().collect(Collectors.toMap(ProductPropertyValueRespVO::getId, pv -> pv));
  149 + Map<Long, ProductPropertyValueRespVO> propertyValueMaps = p.getValues().stream().collect(Collectors.toMap(ProductPropertyValueRespVO::getId, pv -> pv));
150 150 propertyMaps.get(p.getId()).forEach(pv -> {
151 151 ProductPropertyViewRespVO.Tuple2 tuple2 = new ProductPropertyViewRespVO.Tuple2(pv.getValueId(), propertyValueMaps.get(pv.getValueId()).getName());
152 152 propertyValues.add(tuple2);
... ... @@ -162,7 +162,7 @@ public class ProductSpuServiceImpl implements ProductSpuService {
162 162 Long parentId = spuVO.getCategoryId();
163 163 categoryArray.addFirst(parentId);
164 164 while (parentId != 0) {
165   - parentId = categoryService.getProductCategory(parentId).getParentId();
  165 + parentId = categoryService.getCategory(parentId).getParentId();
166 166 if (parentId > 0) {
167 167 categoryArray.addFirst(parentId);
168 168 }
... ...
yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandServiceImplTest.java
... ... @@ -20,7 +20,7 @@ import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEq
20 20 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
21 21 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
22 22 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
23   -import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.PRODUCT_BRAND_NOT_EXISTS;
  23 +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.BRAND_NOT_EXISTS;
24 24 import static org.junit.jupiter.api.Assertions.*;
25 25  
26 26 /**
... ... @@ -74,7 +74,7 @@ public class ProductBrandServiceImplTest extends BaseDbUnitTest {
74 74 ProductBrandUpdateReqVO reqVO = randomPojo(ProductBrandUpdateReqVO.class);
75 75  
76 76 // 调用, 并断言异常
77   - assertServiceException(() -> brandService.updateBrand(reqVO), PRODUCT_BRAND_NOT_EXISTS);
  77 + assertServiceException(() -> brandService.updateBrand(reqVO), BRAND_NOT_EXISTS);
78 78 }
79 79  
80 80 @Test
... ... @@ -97,7 +97,7 @@ public class ProductBrandServiceImplTest extends BaseDbUnitTest {
97 97 Long id = randomLongId();
98 98  
99 99 // 调用, 并断言异常
100   - assertServiceException(() -> brandService.deleteBrand(id), PRODUCT_BRAND_NOT_EXISTS);
  100 + assertServiceException(() -> brandService.deleteBrand(id), BRAND_NOT_EXISTS);
101 101 }
102 102  
103 103 @Test
... ...
yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImplTest.java
... ... @@ -17,7 +17,7 @@ import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEq
17 17 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
18 18 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
19 19 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
20   -import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.PRODUCT_CATEGORY_NOT_EXISTS;
  20 +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.CATEGORY_NOT_EXISTS;
21 21 import static org.junit.jupiter.api.Assertions.*;
22 22  
23 23 /**
... ... @@ -43,7 +43,7 @@ public class ProductCategoryServiceImplTest extends BaseDbUnitTest {
43 43 productCategoryMapper.insert(parentProductCategory);
44 44  
45 45 // 调用
46   - Long categoryId = productCategoryService.createProductCategory(reqVO);
  46 + Long categoryId = productCategoryService.createCategory(reqVO);
47 47 // 断言
48 48 assertNotNull(categoryId);
49 49 // 校验记录的属性是否正确
... ... @@ -65,7 +65,7 @@ public class ProductCategoryServiceImplTest extends BaseDbUnitTest {
65 65 productCategoryMapper.insert(parentProductCategory);
66 66  
67 67 // 调用
68   - productCategoryService.updateProductCategory(reqVO);
  68 + productCategoryService.updateCategory(reqVO);
69 69 // 校验是否更新正确
70 70 ProductCategoryDO category = productCategoryMapper.selectById(reqVO.getId()); // 获取最新的
71 71 assertPojoEquals(reqVO, category);
... ... @@ -77,7 +77,7 @@ public class ProductCategoryServiceImplTest extends BaseDbUnitTest {
77 77 ProductCategoryUpdateReqVO reqVO = randomPojo(ProductCategoryUpdateReqVO.class);
78 78  
79 79 // 调用, 并断言异常
80   - assertServiceException(() -> productCategoryService.updateProductCategory(reqVO), PRODUCT_CATEGORY_NOT_EXISTS);
  80 + assertServiceException(() -> productCategoryService.updateCategory(reqVO), CATEGORY_NOT_EXISTS);
81 81 }
82 82  
83 83 @Test
... ... @@ -89,7 +89,7 @@ public class ProductCategoryServiceImplTest extends BaseDbUnitTest {
89 89 Long id = dbCategory.getId();
90 90  
91 91 // 调用
92   - productCategoryService.deleteProductCategory(id);
  92 + productCategoryService.deleteCategory(id);
93 93 // 校验数据不存在了
94 94 assertNull(productCategoryMapper.selectById(id));
95 95 }
... ... @@ -100,7 +100,7 @@ public class ProductCategoryServiceImplTest extends BaseDbUnitTest {
100 100 Long id = randomLongId();
101 101  
102 102 // 调用, 并断言异常
103   - assertServiceException(() -> productCategoryService.deleteProductCategory(id), PRODUCT_CATEGORY_NOT_EXISTS);
  103 + assertServiceException(() -> productCategoryService.deleteCategory(id), CATEGORY_NOT_EXISTS);
104 104 }
105 105  
106 106 @Test
... ... @@ -117,7 +117,7 @@ public class ProductCategoryServiceImplTest extends BaseDbUnitTest {
117 117 reqVO.setName("特曼");
118 118  
119 119 // 调用
120   - List<ProductCategoryDO> list = productCategoryService.getEnableProductCategoryList(reqVO);
  120 + List<ProductCategoryDO> list = productCategoryService.getEnableCategoryList(reqVO);
121 121 // 断言
122 122 assertEquals(1, list.size());
123 123 assertPojoEquals(dbCategory, list.get(0));
... ...
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 {
41 41 ProductSpuCreateReqVO reqVO = randomPojo(ProductSpuCreateReqVO.class);
42 42  
43 43 // 调用
44   - Long spuId = spuService.createProductSpu(reqVO);
  44 + Long spuId = spuService.createSpu(reqVO);
45 45 // 断言
46 46 assertNotNull(spuId);
47 47 // 校验记录的属性是否正确
... ... @@ -60,7 +60,7 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
60 60 });
61 61  
62 62 // 调用
63   - spuService.updateProductSpu(reqVO);
  63 + spuService.updateSpu(reqVO);
64 64 // 校验是否更新正确
65 65 ProductSpuDO spu = ProductSpuMapper.selectById(reqVO.getId()); // 获取最新的
66 66 assertPojoEquals(reqVO, spu);
... ... @@ -72,7 +72,7 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
72 72 ProductSpuUpdateReqVO reqVO = randomPojo(ProductSpuUpdateReqVO.class);
73 73  
74 74 // 调用, 并断言异常
75   - assertServiceException(() -> spuService.updateProductSpu(reqVO), SPU_NOT_EXISTS);
  75 + assertServiceException(() -> spuService.updateSpu(reqVO), SPU_NOT_EXISTS);
76 76 }
77 77  
78 78 @Test
... ...