Commit 2f9eef589b68bffe1ab19a7b68d4a101ecbc5e6e

Authored by YunaiV
1 parent 5474ae87

product:优化商品分类的代码

yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/ErrorCodeConstants.java
@@ -15,7 +15,6 @@ public interface ErrorCodeConstants { @@ -15,7 +15,6 @@ public interface ErrorCodeConstants {
15 ErrorCode CATEGORY_PARENT_NOT_FIRST_LEVEL = new ErrorCode(1008001002, "父分类不能是二级分类"); 15 ErrorCode CATEGORY_PARENT_NOT_FIRST_LEVEL = new ErrorCode(1008001002, "父分类不能是二级分类");
16 ErrorCode CATEGORY_EXISTS_CHILDREN = new ErrorCode(1008001003, "存在子分类,无法删除"); 16 ErrorCode CATEGORY_EXISTS_CHILDREN = new ErrorCode(1008001003, "存在子分类,无法删除");
17 ErrorCode CATEGORY_DISABLED = new ErrorCode(1008001004, "商品分类({})已禁用,无法使用"); 17 ErrorCode CATEGORY_DISABLED = new ErrorCode(1008001004, "商品分类({})已禁用,无法使用");
18 - ErrorCode CATEGORY_LEVEL_ERROR = new ErrorCode(1008001005, "商品分类不正确,原因:必须使用第三级的商品分类下");  
19 18
20 // ========== 商品品牌相关编号 1008002000 ========== 19 // ========== 商品品牌相关编号 1008002000 ==========
21 ErrorCode BRAND_NOT_EXISTS = new ErrorCode(1008002000, "品牌不存在"); 20 ErrorCode BRAND_NOT_EXISTS = new ErrorCode(1008002000, "品牌不存在");
@@ -33,6 +32,7 @@ public interface ErrorCodeConstants { @@ -33,6 +32,7 @@ public interface ErrorCodeConstants {
33 32
34 // ========== 商品 SPU 1008005000 ========== 33 // ========== 商品 SPU 1008005000 ==========
35 ErrorCode SPU_NOT_EXISTS = new ErrorCode(1008005000, "商品 SPU 不存在"); 34 ErrorCode SPU_NOT_EXISTS = new ErrorCode(1008005000, "商品 SPU 不存在");
  35 + ErrorCode SPU_SAVE_FAIL_CATEGORY_LEVEL_ERROR = new ErrorCode(1008005001, "商品分类不正确,原因:必须使用第三级的商品分类下");
36 36
37 // ========== 商品 SKU 1008006000 ========== 37 // ========== 商品 SKU 1008006000 ==========
38 ErrorCode SKU_NOT_EXISTS = new ErrorCode(1008006000, "商品 SKU 不存在"); 38 ErrorCode SKU_NOT_EXISTS = new ErrorCode(1008006000, "商品 SKU 不存在");
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryService.java
@@ -6,7 +6,6 @@ import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCateg @@ -6,7 +6,6 @@ import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCateg
6 import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO; 6 import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO;
7 7
8 import javax.validation.Valid; 8 import javax.validation.Valid;
9 -import java.util.Collection;  
10 import java.util.List; 9 import java.util.List;
11 10
12 /** 11 /**
@@ -47,28 +46,27 @@ public interface ProductCategoryService { @@ -47,28 +46,27 @@ public interface ProductCategoryService {
47 ProductCategoryDO getCategory(Long id); 46 ProductCategoryDO getCategory(Long id);
48 47
49 /** 48 /**
50 - * 获得商品分类列表 49 + * 校验商品分类
51 * 50 *
52 - * @param ids 编号  
53 - * @return 商品分类列表 51 + * @param id 分类编号
54 */ 52 */
55 - List<ProductCategoryDO> getEnableCategoryList(Collection<Long> ids); 53 + void validateCategory(Long id);
56 54
57 /** 55 /**
58 - * 获得商品分类列表 56 + * 获得商品分类的层级
59 * 57 *
60 - * @param listReqVO 查询条件  
61 - * @return 商品分类列表 58 + * @param id 编号
  59 + * @return 商品分类的层级
62 */ 60 */
63 - List<ProductCategoryDO> getEnableCategoryList(ProductCategoryListReqVO listReqVO); 61 + Integer getCategoryLevel(Long id);
64 62
65 /** 63 /**
66 - * 验证选择的商品分类的级别是否合法  
67 - * 例如说,商品发布的时候,必须在第 3 级别 64 + * 获得商品分类列表
68 * 65 *
69 - * @param id 分类编号 66 + * @param listReqVO 查询条件
  67 + * @return 商品分类列表
70 */ 68 */
71 - void validateCategoryLevel(Long id); 69 + List<ProductCategoryDO> getEnableCategoryList(ProductCategoryListReqVO listReqVO);
72 70
73 /** 71 /**
74 * 获得开启状态的商品分类列表 72 * 获得开启状态的商品分类列表
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImpl.java
@@ -11,7 +11,6 @@ import org.springframework.stereotype.Service; @@ -11,7 +11,6 @@ import org.springframework.stereotype.Service;
11 import org.springframework.validation.annotation.Validated; 11 import org.springframework.validation.annotation.Validated;
12 12
13 import javax.annotation.Resource; 13 import javax.annotation.Resource;
14 -import java.util.Collection;  
15 import java.util.List; 14 import java.util.List;
16 import java.util.Objects; 15 import java.util.Objects;
17 16
@@ -91,30 +90,39 @@ public class ProductCategoryServiceImpl implements ProductCategoryService { @@ -91,30 +90,39 @@ public class ProductCategoryServiceImpl implements ProductCategoryService {
91 } 90 }
92 91
93 @Override 92 @Override
94 - public void validateCategoryLevel(Long id) {  
95 - // TODO @芋艿:在看看,杂能优化下  
96 - Long parentId = id;  
97 - int i = 2;  
98 - for (; i >= 0; --i) {  
99 - ProductCategoryDO category = productCategoryMapper.selectById(parentId);  
100 - parentId = category.getParentId();  
101 - if(Objects.equals(parentId, ProductCategoryDO.PARENT_ID_NULL)){  
102 - break;  
103 - }  
104 - }  
105 - if (!Objects.equals(parentId, ProductCategoryDO.PARENT_ID_NULL) || i != 0) {  
106 - throw exception(CATEGORY_LEVEL_ERROR);  
107 - } 93 + public ProductCategoryDO getCategory(Long id) {
  94 + return productCategoryMapper.selectById(id);
108 } 95 }
109 96
110 @Override 97 @Override
111 - public ProductCategoryDO getCategory(Long id) {  
112 - return productCategoryMapper.selectById(id); 98 + public void validateCategory(Long id) {
  99 + ProductCategoryDO category = productCategoryMapper.selectById(id);
  100 + if (category == null) {
  101 + throw exception(CATEGORY_NOT_EXISTS);
  102 + }
  103 + if (Objects.equals(category.getStatus(), CommonStatusEnum.ENABLE.getStatus())) {
  104 + throw exception(CATEGORY_DISABLED, category.getName());
  105 + }
113 } 106 }
114 107
115 @Override 108 @Override
116 - public List<ProductCategoryDO> getEnableCategoryList(Collection<Long> ids) {  
117 - return productCategoryMapper.selectBatchIds(ids); 109 + public Integer getCategoryLevel(Long id) {
  110 + if (Objects.equals(id, ProductCategoryDO.PARENT_ID_NULL)) {
  111 + return 0;
  112 + }
  113 + int level = 1;
  114 + for (int i = 0; i < 100; i++) {
  115 + ProductCategoryDO category = productCategoryMapper.selectById(id);
  116 + // 如果没有父节点,break 结束
  117 + if (category == null
  118 + || Objects.equals(category.getParentId(), ProductCategoryDO.PARENT_ID_NULL)) {
  119 + break;
  120 + }
  121 + // 继续递归父节点
  122 + level++;
  123 + id = category.getParentId();
  124 + }
  125 + return level;
118 } 126 }
119 127
120 @Override 128 @Override
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java
@@ -36,6 +36,7 @@ import java.util.stream.Collectors; @@ -36,6 +36,7 @@ import java.util.stream.Collectors;
36 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 36 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
37 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; 37 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
38 import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS; 38 import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS;
  39 +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_SAVE_FAIL_CATEGORY_LEVEL_ERROR;
39 40
40 /** 41 /**
41 * 商品 SPU Service 实现类 42 * 商品 SPU Service 实现类
@@ -66,7 +67,7 @@ public class ProductSpuServiceImpl implements ProductSpuService { @@ -66,7 +67,7 @@ public class ProductSpuServiceImpl implements ProductSpuService {
66 @Transactional 67 @Transactional
67 public Long createSpu(ProductSpuCreateReqVO createReqVO) { 68 public Long createSpu(ProductSpuCreateReqVO createReqVO) {
68 // 校验分类 69 // 校验分类
69 - categoryService.validateCategoryLevel(createReqVO.getCategoryId()); 70 + validateCategory(createReqVO.getCategoryId());
70 // 校验品牌 71 // 校验品牌
71 brandService.validateProductBrand(createReqVO.getBrandId()); 72 brandService.validateProductBrand(createReqVO.getBrandId());
72 // 校验SKU 73 // 校验SKU
@@ -91,7 +92,7 @@ public class ProductSpuServiceImpl implements ProductSpuService { @@ -91,7 +92,7 @@ public class ProductSpuServiceImpl implements ProductSpuService {
91 // 校验 SPU 是否存在 92 // 校验 SPU 是否存在
92 validateSpuExists(updateReqVO.getId()); 93 validateSpuExists(updateReqVO.getId());
93 // 校验分类 94 // 校验分类
94 - categoryService.validateCategoryLevel(updateReqVO.getCategoryId()); 95 + validateCategory(updateReqVO.getCategoryId());
95 // 校验品牌 96 // 校验品牌
96 brandService.validateProductBrand(updateReqVO.getBrandId()); 97 brandService.validateProductBrand(updateReqVO.getBrandId());
97 // 校验SKU 98 // 校验SKU
@@ -109,6 +110,19 @@ public class ProductSpuServiceImpl implements ProductSpuService { @@ -109,6 +110,19 @@ public class ProductSpuServiceImpl implements ProductSpuService {
109 productSkuService.updateSkus(updateObj.getId(), updateObj.getName(), updateReqVO.getSkus()); 110 productSkuService.updateSkus(updateObj.getId(), updateObj.getName(), updateReqVO.getSkus());
110 } 111 }
111 112
  113 + /**
  114 + * 校验商品分类是否合法
  115 + *
  116 + * @param id 商品分类编号
  117 + */
  118 + private void validateCategory(Long id) {
  119 + categoryService.validateCategory(id);
  120 + // 校验层级
  121 + if (categoryService.getCategoryLevel(id) != 3) {
  122 + throw exception(SPU_SAVE_FAIL_CATEGORY_LEVEL_ERROR);
  123 + }
  124 + }
  125 +
112 @Override 126 @Override
113 @Transactional 127 @Transactional
114 public void deleteSpu(Long id) { 128 public void deleteSpu(Long id) {
yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImplTest.java
@@ -104,6 +104,25 @@ public class ProductCategoryServiceImplTest extends BaseDbUnitTest { @@ -104,6 +104,25 @@ public class ProductCategoryServiceImplTest extends BaseDbUnitTest {
104 } 104 }
105 105
106 @Test 106 @Test
  107 + public void testGetCategoryLevel() {
  108 + // mock 数据
  109 + ProductCategoryDO category1 = randomPojo(ProductCategoryDO.class,
  110 + o -> o.setParentId(ProductCategoryDO.PARENT_ID_NULL));
  111 + productCategoryMapper.insert(category1);
  112 + ProductCategoryDO category2 = randomPojo(ProductCategoryDO.class,
  113 + o -> o.setParentId(category1.getId()));
  114 + productCategoryMapper.insert(category2);
  115 + ProductCategoryDO category3 = randomPojo(ProductCategoryDO.class,
  116 + o -> o.setParentId(category2.getId()));
  117 + productCategoryMapper.insert(category3);
  118 +
  119 + // 调用,并断言
  120 + assertEquals(productCategoryService.getCategoryLevel(category1.getId()), 1);
  121 + assertEquals(productCategoryService.getCategoryLevel(category2.getId()), 2);
  122 + assertEquals(productCategoryService.getCategoryLevel(category3.getId()), 3);
  123 + }
  124 +
  125 + @Test
107 public void testGetCategoryList() { 126 public void testGetCategoryList() {
108 // mock 数据 127 // mock 数据
109 ProductCategoryDO dbCategory = randomPojo(ProductCategoryDO.class, o -> { // 等会查询到 128 ProductCategoryDO dbCategory = randomPojo(ProductCategoryDO.class, o -> { // 等会查询到
yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java
@@ -187,9 +187,9 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest { @@ -187,9 +187,9 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
187 }); 187 });
188 188
189 Mockito.when(productSkuService.getSkusBySpuId(createReqVO.getId())).thenReturn(productSkuDOS); 189 Mockito.when(productSkuService.getSkusBySpuId(createReqVO.getId())).thenReturn(productSkuDOS);
190 - Mockito.when(productPropertyValueService.getPropertyValueListByPropertyId(new ArrayList<>(collect.keySet()))).thenReturn(productPropertyValueRespVO);  
191 - Mockito.when(productPropertyService.getPropertyVOList(new ArrayList<>(collect.keySet()))).thenReturn(productPropertyRespVOS);  
192 - 190 +// Mockito.when(productPropertyValueService.getPropertyValueListByPropertyId(new ArrayList<>(collect.keySet()))).thenReturn(productPropertyValueRespVO);
  191 +// Mockito.when(productPropertyService.getPropertyVOList(new ArrayList<>(collect.keySet()))).thenReturn(productPropertyRespVOS);
  192 +//
193 // 调用 193 // 调用
194 ProductSpuDetailRespVO spuDetail = productSpuService.getSpuDetail(createReqVO.getId()); 194 ProductSpuDetailRespVO spuDetail = productSpuService.getSpuDetail(createReqVO.getId());
195 195
yudao-module-mall/yudao-module-product-biz/src/test/resources/sql/create_tables.sql
@@ -52,3 +52,19 @@ CREATE TABLE IF NOT EXISTS `product_spu` ( @@ -52,3 +52,19 @@ CREATE TABLE IF NOT EXISTS `product_spu` (
52 `deleted` bit(1) NOT NULL DEFAULT 0 COMMENT '是否删除', 52 `deleted` bit(1) NOT NULL DEFAULT 0 COMMENT '是否删除',
53 PRIMARY KEY (`id`) 53 PRIMARY KEY (`id`)
54 ) COMMENT '商品spu'; 54 ) COMMENT '商品spu';
  55 +
  56 +CREATE TABLE IF NOT EXISTS `product_category` (
  57 + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '分类编号',
  58 + `parent_id` bigint DEFAULT NULL COMMENT '父分类编号',
  59 + `name` varchar(128) NOT NULL COMMENT '分类名称',
  60 + `description` varchar(128) NOT NULL COMMENT '分类描述',
  61 + `pic_url` varchar DEFAULT NULL COMMENT '分类图片',
  62 + `sort` int NOT NULL DEFAULT '0' COMMENT '排序字段',
  63 + `status` bit(1) DEFAULT NULL COMMENT '状态',
  64 + `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  65 + `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  66 + `creator` varchar DEFAULT NULL COMMENT '创建人',
  67 + `updater` varchar DEFAULT NULL COMMENT '更新人',
  68 + `deleted` bit(1) NOT NULL DEFAULT 0 COMMENT '是否删除',
  69 + PRIMARY KEY (`id`)
  70 +) COMMENT '商品分类';
yudao-ui-app/pages/category/category.vue
@@ -34,7 +34,7 @@ @@ -34,7 +34,7 @@
34 <u-grid-item v-for="(subItem, subIndex) in item.children" :key="subItem.id"> 34 <u-grid-item v-for="(subItem, subIndex) in item.children" :key="subItem.id">
35 <view class="sub-category-item" @click="handleCategory(item, subIndex)"> 35 <view class="sub-category-item" @click="handleCategory(item, subIndex)">
36 <u-icon name="photo" :size="80" v-if="subItem.picUrl === null"></u-icon> 36 <u-icon name="photo" :size="80" v-if="subItem.picUrl === null"></u-icon>
37 - <image :src="item.picUrl" v-if="subItem.picUrl != null" mode='widthFix' /> 37 + <image :src="subItem.picUrl" v-if="subItem.picUrl != null" mode='widthFix' />
38 <text class="sub-category-title">{{ subItem.name }}</text> 38 <text class="sub-category-title">{{ subItem.name }}</text>
39 </view> 39 </view>
40 </u-grid-item> 40 </u-grid-item>