Browse Source

mall:完善商品分类的后端接口

YunaiV 2 years ago
parent
commit
6a0f713452
27 changed files with 556 additions and 723 deletions
  1. 8 6
      yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/ErrorCodeConstants.java
  2. 0 92
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/CategoryController.java
  3. 76 0
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/ProductCategoryController.java
  4. 0 47
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryExcelVO.java
  5. 0 26
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryExportReqVO.java
  6. 0 31
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryPageReqVO.java
  7. 0 25
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryTreeListReqVO.java
  8. 2 6
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/ProductCategoryBaseVO.java
  9. 1 3
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/ProductCategoryCreateReqVO.java
  10. 14 0
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/ProductCategoryListReqVO.java
  11. 1 1
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/ProductCategoryRespVO.java
  12. 1 2
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/ProductCategoryUpdateReqVO.java
  13. 5 5
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/category/AppCategoryController.java
  14. 11 15
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/category/CategoryConvert.java
  15. 14 9
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/category/ProductCategoryDO.java
  16. 0 40
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/category/CategoryMapper.java
  17. 33 0
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/category/ProductCategoryMapper.java
  18. 0 94
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/CategoryService.java
  19. 0 120
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/CategoryServiceImpl.java
  20. 79 0
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryService.java
  21. 125 0
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImpl.java
  22. 5 5
      yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java
  23. 0 192
      yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/category/CategoryServiceImplTest.java
  24. 126 0
      yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImplTest.java
  25. 50 0
      yudao-module-mall/yudao-module-product-biz/src/test/resources/application-unit-test.yaml
  26. 4 0
      yudao-module-mall/yudao-module-product-biz/src/test/resources/logback.xml
  27. 1 4
      yudao-module-mall/yudao-module-product-biz/src/test/resources/sql/create_tables.sql

+ 8 - 6
yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/ErrorCodeConstants.java

@@ -3,16 +3,18 @@ package cn.iocoder.yudao.module.product.enums;
 import cn.iocoder.yudao.framework.common.exception.ErrorCode;
 
 /**
- * product 错误码枚举类
- * <p>
+ * Product 错误码枚举类
+ *
  * product 系统,使用 1-008-000-000 段
  */
 public interface ErrorCodeConstants {
 
-    // ========== 商品分类相关  1008001000============
-    ErrorCode CATEGORY_NOT_EXISTS = new ErrorCode(1008001000, "商品分类不存在");
-    ErrorCode CATEGORY_PARENT_NOT_EXISTS = new ErrorCode(1008001001, "父分类不存在");
-    ErrorCode CATEGORY_EXISTS_CHILDREN = new ErrorCode(1008001002, "存在子分类,无法删除");
+    // ========== 商品分类相关 1008001000 ============
+    ErrorCode PRODUCT_CATEGORY_NOT_EXISTS = new ErrorCode(1008001000, "商品分类不存在");
+    ErrorCode PRODUCT_CATEGORY_PARENT_NOT_EXISTS = new ErrorCode(1008001001, "父分类不存在");
+    ErrorCode PRODUCT_CATEGORY_PARENT_NOT_FIRST_LEVEL = new ErrorCode(1008001002, "父分类不能是二级分类");
+    ErrorCode PRODUCT_CATEGORY_EXISTS_CHILDREN = new ErrorCode(1008001003, "存在子分类,无法删除");
+    ErrorCode PRODUCT_CATEGORY_DISABLED = new ErrorCode(1008001004, "商品分类({})已禁用,无法使用");
 
     // ========== 品牌相关编号 1008002000 ==========
     ErrorCode BRAND_NOT_EXISTS = new ErrorCode(1008002000, "品牌不存在");

+ 0 - 92
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/CategoryController.java

@@ -1,92 +0,0 @@
-package cn.iocoder.yudao.module.product.controller.admin.category;
-
-import cn.iocoder.yudao.framework.common.pojo.CommonResult;
-import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
-import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
-import cn.iocoder.yudao.module.product.controller.admin.category.vo.*;
-import cn.iocoder.yudao.module.product.convert.category.CategoryConvert;
-import cn.iocoder.yudao.module.product.dal.dataobject.category.CategoryDO;
-import cn.iocoder.yudao.module.product.service.category.CategoryService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiImplicitParam;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.*;
-
-import javax.annotation.Resource;
-import javax.servlet.http.HttpServletResponse;
-import javax.validation.Valid;
-import java.io.IOException;
-import java.util.Comparator;
-import java.util.List;
-
-import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
-import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
-
-@Api(tags = "管理后台 - 商品分类")
-@RestController
-@RequestMapping("/product/category")
-@Validated
-public class CategoryController {
-
-    @Resource
-    private CategoryService categoryService;
-
-    @PostMapping("/create")
-    @ApiOperation("创建商品分类")
-    @PreAuthorize("@ss.hasPermission('product:category:create')")
-    public CommonResult<Long> createCategory(@Valid @RequestBody CategoryCreateReqVO createReqVO) {
-        return success(categoryService.createCategory(createReqVO));
-    }
-
-    @PutMapping("/update")
-    @ApiOperation("更新商品分类")
-    @PreAuthorize("@ss.hasPermission('product:category:update')")
-    public CommonResult<Boolean> updateCategory(@Valid @RequestBody CategoryUpdateReqVO updateReqVO) {
-        categoryService.updateCategory(updateReqVO);
-        return success(true);
-    }
-
-    @DeleteMapping("/delete")
-    @ApiOperation("删除商品分类")
-    @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
-    @PreAuthorize("@ss.hasPermission('product:category:delete')")
-    public CommonResult<Boolean> deleteCategory(@RequestParam("id") Long id) {
-        categoryService.deleteCategory(id);
-        return success(true);
-    }
-
-    @GetMapping("/get")
-    @ApiOperation("获得商品分类")
-    @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
-    @PreAuthorize("@ss.hasPermission('product:category:query')")
-    public CommonResult<CategoryRespVO> getCategory(@RequestParam("id") Long id) {
-        CategoryDO category = categoryService.getCategory(id);
-        return success(CategoryConvert.INSTANCE.convert(category));
-    }
-
-    // TODO @JeromeSoar:这应该是个 app 的接口,提供商品分类的树结构。这个调整下,后端只返回列表,前端构建 tree。注意,不需要返回创建时间、是否开启等无关字段。
-    // TODO @YunaiV: 这个是在管理端展示了一个类似菜单的分类树列表, treeListReqVO 只是查询参数的封装命名,返给前端的是列表数据。PS: 这里 /page 接口没有使用到。
-    @GetMapping("/listByQuery")
-    @ApiOperation("获得商品分类列表")
-    @PreAuthorize("@ss.hasPermission('product:category:query')")
-    public CommonResult<List<CategoryRespVO>> listByQuery(@Valid CategoryTreeListReqVO treeListReqVO) {
-        List<CategoryDO> list = categoryService.getCategoryTreeList(treeListReqVO);
-        list.sort(Comparator.comparing(CategoryDO::getSort));
-        return success(CategoryConvert.INSTANCE.convertList(list));
-    }
-    
-    @GetMapping("/export-excel")
-    @ApiOperation("导出商品分类 Excel")
-    @PreAuthorize("@ss.hasPermission('product:category:export')")
-    @OperateLog(type = EXPORT)
-    public void exportCategoryExcel(@Valid CategoryExportReqVO exportReqVO,
-              HttpServletResponse response) throws IOException {
-        List<CategoryDO> list = categoryService.getCategoryList(exportReqVO);
-        // 导出 Excel
-        List<CategoryExcelVO> datas = CategoryConvert.INSTANCE.convertList02(list);
-        ExcelUtils.write(response, "商品分类.xls", "数据", CategoryExcelVO.class, datas);
-    }
-
-}

+ 76 - 0
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/ProductCategoryController.java

@@ -0,0 +1,76 @@
+package cn.iocoder.yudao.module.product.controller.admin.category;
+
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryRespVO;
+import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryListReqVO;
+import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryCreateReqVO;
+import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryUpdateReqVO;
+import cn.iocoder.yudao.module.product.convert.category.CategoryConvert;
+import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO;
+import cn.iocoder.yudao.module.product.service.category.ProductCategoryService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import javax.validation.Valid;
+import java.util.Comparator;
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+@Api(tags = "管理后台 - 商品分类")
+@RestController
+@RequestMapping("/product/category")
+@Validated
+public class ProductCategoryController {
+
+    @Resource
+    private ProductCategoryService categoryService;
+
+    @PostMapping("/create")
+    @ApiOperation("创建商品分类")
+    @PreAuthorize("@ss.hasPermission('product:category:create')")
+    public CommonResult<Long> createProductCategory(@Valid @RequestBody ProductCategoryCreateReqVO createReqVO) {
+        return success(categoryService.createProductCategory(createReqVO));
+    }
+
+    @PutMapping("/update")
+    @ApiOperation("更新商品分类")
+    @PreAuthorize("@ss.hasPermission('product:category:update')")
+    public CommonResult<Boolean> updateProductCategory(@Valid @RequestBody ProductCategoryUpdateReqVO updateReqVO) {
+        categoryService.updateProductCategory(updateReqVO);
+        return success(true);
+    }
+
+    @DeleteMapping("/delete")
+    @ApiOperation("删除商品分类")
+    @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
+    @PreAuthorize("@ss.hasPermission('product:category:delete')")
+    public CommonResult<Boolean> deleteProductCategory(@RequestParam("id") Long id) {
+        categoryService.deleteProductCategory(id);
+        return success(true);
+    }
+
+    @GetMapping("/get")
+    @ApiOperation("获得商品分类")
+    @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
+    @PreAuthorize("@ss.hasPermission('product:category:query')")
+    public CommonResult<ProductCategoryRespVO> getProductCategory(@RequestParam("id") Long id) {
+        ProductCategoryDO category = categoryService.getProductCategory(id);
+        return success(CategoryConvert.INSTANCE.convert(category));
+    }
+
+    @GetMapping("/list")
+    @ApiOperation("获得商品分类列表")
+    @PreAuthorize("@ss.hasPermission('product:category:query')")
+    public CommonResult<List<ProductCategoryRespVO>> getProductCategoryList(@Valid ProductCategoryListReqVO treeListReqVO) {
+        List<ProductCategoryDO> list = categoryService.getEnableProductCategoryList(treeListReqVO);
+        list.sort(Comparator.comparing(ProductCategoryDO::getSort));
+        return success(CategoryConvert.INSTANCE.convertList(list));
+    }
+
+}

+ 0 - 47
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryExcelVO.java

@@ -1,47 +0,0 @@
-package cn.iocoder.yudao.module.product.controller.admin.category.vo;
-
-import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
-import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
-import com.alibaba.excel.annotation.ExcelProperty;
-import lombok.Data;
-
-import java.util.Date;
-
-
-/**
- * 商品分类 Excel VO
- *
- * @author 芋道源码
- */
-@Data
-public class CategoryExcelVO {
-
-    @ExcelProperty("分类编号")
-    private Long id;
-
-    @ExcelProperty("父分类编号")
-    private Long parentId;
-
-    @ExcelProperty("分类名称")
-    private String name;
-
-    @ExcelProperty("分类图标")
-    private String icon;
-
-    @ExcelProperty("分类图片")
-    private String bannerUrl;
-
-    @ExcelProperty("分类排序")
-    private Integer sort;
-
-    @ExcelProperty("分类描述")
-    private String description;
-
-    @ExcelProperty(value = "开启状态", converter = DictConvert.class)
-    @DictFormat("common_status") // TODO 代码优化:建议设置到对应的 XXXDictTypeConstants 枚举类中
-    private Integer status;
-
-    @ExcelProperty("创建时间")
-    private Date createTime;
-
-}

+ 0 - 26
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryExportReqVO.java

@@ -1,26 +0,0 @@
-package cn.iocoder.yudao.module.product.controller.admin.category.vo;
-
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-import org.springframework.format.annotation.DateTimeFormat;
-
-import java.util.Date;
-
-import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
-
-@ApiModel(value = "管理后台 - 商品分类 Excel 导出 Request VO", description = "参数和 CategoryPageReqVO 是一致的")
-@Data
-public class CategoryExportReqVO {
-
-    @ApiModelProperty(value = "分类名称", example = "办公文具")
-    private String name;
-
-    @ApiModelProperty(value = "开启状态", example = "0")
-    private Integer status;
-
-    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
-    @ApiModelProperty(value = "创建时间")
-    private Date[] createTime;
-
-}

+ 0 - 31
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryPageReqVO.java

@@ -1,31 +0,0 @@
-package cn.iocoder.yudao.module.product.controller.admin.category.vo;
-
-import cn.iocoder.yudao.framework.common.pojo.PageParam;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.ToString;
-import org.springframework.format.annotation.DateTimeFormat;
-
-import java.util.Date;
-
-import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
-
-@ApiModel("管理后台 - 商品分类分页 Request VO")
-@Data
-@EqualsAndHashCode(callSuper = true)
-@ToString(callSuper = true)
-public class CategoryPageReqVO extends PageParam {
-
-    @ApiModelProperty(value = "分类名称", example = "办公文具")
-    private String name;
-
-    @ApiModelProperty(value = "开启状态", example = "0")
-    private Integer status;
-
-    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
-    @ApiModelProperty(value = "创建时间")
-    private Date[] createTime;
-
-}

+ 0 - 25
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryTreeListReqVO.java

@@ -1,25 +0,0 @@
-package cn.iocoder.yudao.module.product.controller.admin.category.vo;
-
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-import org.springframework.format.annotation.DateTimeFormat;
-
-import java.util.Date;
-
-import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
-
-@Data
-@ApiModel(value = "管理后台 - 商品分类列表查询 Request VO", description = "参数和 CategoryPageReqVO 是一致的")
-public class CategoryTreeListReqVO extends CategoryExportReqVO {
-
-    @ApiModelProperty(value = "分类名称", example = "办公文具")
-    private String name;
-
-    @ApiModelProperty(value = "开启状态", example = "0")
-    private Integer status;
-
-    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
-    @ApiModelProperty(value = "创建时间")
-    private Date[] createTime;
-}

+ 2 - 6
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryBaseVO.java → yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/ProductCategoryBaseVO.java

@@ -11,7 +11,7 @@ import javax.validation.constraints.NotNull;
 * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
 */
 @Data
-public class CategoryBaseVO {
+public class ProductCategoryBaseVO {
 
     @ApiModelProperty(value = "父分类编号", required = true, example = "1")
     @NotNull(message = "父分类编号不能为空")
@@ -21,13 +21,9 @@ public class CategoryBaseVO {
     @NotBlank(message = "分类名称不能为空")
     private String name;
 
-    @ApiModelProperty(value = "分类图标")
-    @NotBlank(message = "分类图标不能为空")
-    private String icon;
-
     @ApiModelProperty(value = "分类图片", required = true)
     @NotBlank(message = "分类图片不能为空")
-    private String bannerUrl;
+    private String picUrl;
 
     @ApiModelProperty(value = "分类排序", required = true, example = "1")
     private Integer sort;

+ 1 - 3
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryCreateReqVO.java → yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/ProductCategoryCreateReqVO.java

@@ -1,14 +1,12 @@
 package cn.iocoder.yudao.module.product.controller.admin.category.vo;
 
 import lombok.*;
-import java.util.*;
 import io.swagger.annotations.*;
-import javax.validation.constraints.*;
 
 @ApiModel("管理后台 - 商品分类创建 Request VO")
 @Data
 @EqualsAndHashCode(callSuper = true)
 @ToString(callSuper = true)
-public class CategoryCreateReqVO extends CategoryBaseVO {
+public class ProductCategoryCreateReqVO extends ProductCategoryBaseVO {
 
 }

+ 14 - 0
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/ProductCategoryListReqVO.java

@@ -0,0 +1,14 @@
+package cn.iocoder.yudao.module.product.controller.admin.category.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+@ApiModel(value = "管理后台 - 商品分类列表查询 Request VO")
+@Data
+public class ProductCategoryListReqVO {
+
+    @ApiModelProperty(value = "分类名称", example = "办公文具")
+    private String name;
+
+}

+ 1 - 1
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryRespVO.java → yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/ProductCategoryRespVO.java

@@ -8,7 +8,7 @@ import io.swagger.annotations.*;
 @Data
 @EqualsAndHashCode(callSuper = true)
 @ToString(callSuper = true)
-public class CategoryRespVO extends CategoryBaseVO {
+public class ProductCategoryRespVO extends ProductCategoryBaseVO {
 
     @ApiModelProperty(value = "分类编号", required = true, example = "2")
     private Long id;

+ 1 - 2
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/CategoryUpdateReqVO.java → yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/ProductCategoryUpdateReqVO.java

@@ -1,7 +1,6 @@
 package cn.iocoder.yudao.module.product.controller.admin.category.vo;
 
 import lombok.*;
-import java.util.*;
 import io.swagger.annotations.*;
 import javax.validation.constraints.*;
 
@@ -9,7 +8,7 @@ import javax.validation.constraints.*;
 @Data
 @EqualsAndHashCode(callSuper = true)
 @ToString(callSuper = true)
-public class CategoryUpdateReqVO extends CategoryBaseVO {
+public class ProductCategoryUpdateReqVO extends ProductCategoryBaseVO {
 
     @ApiModelProperty(value = "分类编号", required = true, example = "2")
     @NotNull(message = "分类编号不能为空")

+ 5 - 5
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/category/AppCategoryController.java

@@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.product.controller.app.category;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.module.product.controller.app.category.vo.AppCategoryListRespVO;
 import cn.iocoder.yudao.module.product.convert.category.CategoryConvert;
-import cn.iocoder.yudao.module.product.dal.dataobject.category.CategoryDO;
-import cn.iocoder.yudao.module.product.service.category.CategoryService;
+import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO;
+import cn.iocoder.yudao.module.product.service.category.ProductCategoryService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import org.springframework.validation.annotation.Validated;
@@ -25,13 +25,13 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
 public class AppCategoryController {
 
     @Resource
-    private CategoryService categoryService;
+    private ProductCategoryService categoryService;
 
     @GetMapping("/list")
     @ApiOperation("获得商品分类列表")
     public CommonResult<List<AppCategoryListRespVO>> listByQuery() {
-        List<CategoryDO> list = categoryService.getCategoryList();
-        list.sort(Comparator.comparing(CategoryDO::getSort));
+        List<ProductCategoryDO> list = categoryService.getEnableProductCategoryList();
+        list.sort(Comparator.comparing(ProductCategoryDO::getSort));
         return success(CategoryConvert.INSTANCE.convertList03(list));
     }
 

+ 11 - 15
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/category/CategoryConvert.java

@@ -1,14 +1,14 @@
 package cn.iocoder.yudao.module.product.convert.category;
 
-import java.util.*;
-
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
-
+import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryCreateReqVO;
+import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryRespVO;
+import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryUpdateReqVO;
 import cn.iocoder.yudao.module.product.controller.app.category.vo.AppCategoryListRespVO;
+import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO;
 import org.mapstruct.Mapper;
 import org.mapstruct.factory.Mappers;
-import cn.iocoder.yudao.module.product.controller.admin.category.vo.*;
-import cn.iocoder.yudao.module.product.dal.dataobject.category.CategoryDO;
+
+import java.util.List;
 
 /**
  * 商品分类 Convert
@@ -20,17 +20,13 @@ public interface CategoryConvert {
 
     CategoryConvert INSTANCE = Mappers.getMapper(CategoryConvert.class);
 
-    CategoryDO convert(CategoryCreateReqVO bean);
-
-    CategoryDO convert(CategoryUpdateReqVO bean);
-
-    CategoryRespVO convert(CategoryDO bean);
+    ProductCategoryDO convert(ProductCategoryCreateReqVO bean);
 
-    List<CategoryRespVO> convertList(List<CategoryDO> list);
+    ProductCategoryDO convert(ProductCategoryUpdateReqVO bean);
 
-    PageResult<CategoryRespVO> convertPage(PageResult<CategoryDO> page);
+    ProductCategoryRespVO convert(ProductCategoryDO bean);
 
-    List<CategoryExcelVO> convertList02(List<CategoryDO> list);
+    List<ProductCategoryRespVO> convertList(List<ProductCategoryDO> list);
 
-    List<AppCategoryListRespVO> convertList03(List<CategoryDO> list);
+    List<AppCategoryListRespVO> convertList03(List<ProductCategoryDO> list);
 }

+ 14 - 9
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/category/CategoryDO.java → yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/category/ProductCategoryDO.java

@@ -6,10 +6,13 @@ import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.*;
 
-// TODO @JeromeSoar:Product 前缀
 /**
  * 商品分类 DO
  *
+ * 商品分类一共两级:
+ * 1)一级分类:{@link #parentId} 等于 0
+ * 2)二级分类:{@link #parentId} 等于父分类
+ *
  * @author 芋道源码
  */
 @TableName("product_category")
@@ -19,7 +22,12 @@ import lombok.*;
 @Builder
 @NoArgsConstructor
 @AllArgsConstructor
-public class CategoryDO extends BaseDO {
+public class ProductCategoryDO extends BaseDO {
+
+    /**
+     * 父分类编号 - 根分类
+     */
+    public static final Long PARENT_ID_NULL = 0L;
 
     /**
      * 分类编号
@@ -35,15 +43,12 @@ public class CategoryDO extends BaseDO {
      */
     private String name;
     /**
-     * 分类图标
-     */
-    private String icon;
-    /**
-     * 分类 Banner 图片
+     * 分类图片
      *
-     * 第一层的商品分类,会有该字段,用于用户 App 展示
+     * 一级分类:推荐 200 x 100 分辨率
+     * 二级分类:推荐 100 x 100 分辨率
      */
-    private String bannerUrl;
+    private String picUrl;
     /**
      * 分类排序
      */

+ 0 - 40
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/category/CategoryMapper.java

@@ -1,40 +0,0 @@
-package cn.iocoder.yudao.module.product.dal.mysql.category;
-
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
-import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
-import cn.iocoder.yudao.module.product.controller.admin.category.vo.CategoryExportReqVO;
-import cn.iocoder.yudao.module.product.controller.admin.category.vo.CategoryPageReqVO;
-import cn.iocoder.yudao.module.product.dal.dataobject.category.CategoryDO;
-import org.apache.ibatis.annotations.Mapper;
-
-import java.util.List;
-
-/**
- * 商品分类 Mapper
- *
- * @author 芋道源码
- */
-@Mapper
-public interface CategoryMapper extends BaseMapperX<CategoryDO> {
-
-    default PageResult<CategoryDO> selectPage(CategoryPageReqVO reqVO) {
-        return selectPage(reqVO, new LambdaQueryWrapperX<CategoryDO>()
-                .likeIfPresent(CategoryDO::getName, reqVO.getName())
-                .eqIfPresent(CategoryDO::getStatus, reqVO.getStatus())
-                .betweenIfPresent(CategoryDO::getCreateTime, reqVO.getCreateTime())
-                .orderByDesc(CategoryDO::getId));
-    }
-
-    default List<CategoryDO> selectList(CategoryExportReqVO reqVO) {
-        return selectList(new LambdaQueryWrapperX<CategoryDO>()
-                .likeIfPresent(CategoryDO::getName, reqVO.getName())
-                .eqIfPresent(CategoryDO::getStatus, reqVO.getStatus())
-                .betweenIfPresent(CategoryDO::getCreateTime, reqVO.getCreateTime())
-                .orderByDesc(CategoryDO::getId));
-    }
-
-    default Long selectCountByParentId(Long parentId) {
-        return selectCount(CategoryDO::getParentId, parentId);
-    }
-}

+ 33 - 0
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/category/ProductCategoryMapper.java

@@ -0,0 +1,33 @@
+package cn.iocoder.yudao.module.product.dal.mysql.category;
+
+import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryListReqVO;
+import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+/**
+ * 商品分类 Mapper
+ *
+ * @author 芋道源码
+ */
+@Mapper
+public interface ProductCategoryMapper extends BaseMapperX<ProductCategoryDO> {
+
+    default List<ProductCategoryDO> selectList(ProductCategoryListReqVO listReqVO) {
+        return selectList(new LambdaQueryWrapperX<ProductCategoryDO>()
+                .likeIfPresent(ProductCategoryDO::getName, listReqVO.getName())
+                .orderByDesc(ProductCategoryDO::getId));
+    }
+
+    default Long selectCountByParentId(Long parentId) {
+        return selectCount(ProductCategoryDO::getParentId, parentId);
+    }
+
+    default List<ProductCategoryDO> selectListByStatus(Integer status) {
+        return selectList(ProductCategoryDO::getStatus, status);
+    }
+
+}

+ 0 - 94
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/CategoryService.java

@@ -1,94 +0,0 @@
-package cn.iocoder.yudao.module.product.service.category;
-
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.module.product.controller.admin.category.vo.*;
-import cn.iocoder.yudao.module.product.controller.app.category.vo.AppCategoryListRespVO;
-import cn.iocoder.yudao.module.product.dal.dataobject.category.CategoryDO;
-
-import javax.validation.Valid;
-import java.util.Collection;
-import java.util.List;
-
-// TODO @JeromeSoar:需要 Product 前缀
-/**
- * 商品分类 Service 接口
- *
- * @author 芋道源码
- */
-public interface CategoryService {
-
-    /**
-     * 创建商品分类
-     *
-     * @param createReqVO 创建信息
-     * @return 编号
-     */
-    Long createCategory(@Valid CategoryCreateReqVO createReqVO);
-
-    /**
-     * 更新商品分类
-     *
-     * @param updateReqVO 更新信息
-     */
-    void updateCategory(@Valid CategoryUpdateReqVO updateReqVO);
-
-    /**
-     * 删除商品分类
-     *
-     * @param id 编号
-     */
-    void deleteCategory(Long id);
-
-    /**
-     * 获得商品分类
-     *
-     * @param id 编号
-     * @return 商品分类
-     */
-    CategoryDO getCategory(Long id);
-
-    /**
-     * 获得商品分类列表
-     *
-     * @param ids 编号
-     * @return 商品分类列表
-     */
-    List<CategoryDO> getCategoryList(Collection<Long> ids);
-
-    /**
-     * 获得商品分类分页
-     *
-     * @param pageReqVO 分页查询
-     * @return 商品分类分页
-     */
-    PageResult<CategoryDO> getCategoryPage(CategoryPageReqVO pageReqVO);
-
-    /**
-     * 获得商品分类列表, 用于 Excel 导出
-     *
-     * @param exportReqVO 查询条件
-     * @return 商品分类列表
-     */
-    List<CategoryDO> getCategoryList(CategoryExportReqVO exportReqVO);
-
-    /**
-     * 获得商品分类列表
-     *
-     * @param treeListReqVO 查询条件
-     * @return 商品分类列表
-     */
-    List<CategoryDO> getCategoryTreeList(CategoryTreeListReqVO treeListReqVO);
-
-    /**
-     *  验证选择的分类的合法性
-     * @param categoryId 分类id
-     */
-    void validatedCategoryById(Long categoryId);
-
-    /**
-     * app端获得商品分类列表
-     *
-     * @return 商品分类列表
-     */
-    List<CategoryDO> getCategoryList();
-}

+ 0 - 120
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/CategoryServiceImpl.java

@@ -1,120 +0,0 @@
-package cn.iocoder.yudao.module.product.service.category;
-
-import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
-import cn.iocoder.yudao.framework.common.exception.ErrorCode;
-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.category.vo.*;
-import cn.iocoder.yudao.module.product.convert.category.CategoryConvert;
-import cn.iocoder.yudao.module.product.dal.dataobject.category.CategoryDO;
-import cn.iocoder.yudao.module.product.dal.mysql.category.CategoryMapper;
-import org.springframework.stereotype.Service;
-import org.springframework.validation.annotation.Validated;
-
-import javax.annotation.Resource;
-import java.util.Collection;
-import java.util.List;
-import java.util.stream.Collectors;
-
-import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
-import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.*;
-
-/**
- * 商品分类 Service 实现类
- *
- * @author 芋道源码
- */
-@Service
-@Validated
-public class CategoryServiceImpl implements CategoryService {
-
-    @Resource
-    private CategoryMapper categoryMapper;
-
-    @Override
-    public Long createCategory(CategoryCreateReqVO createReqVO) {
-        // 校验父分类存在
-        this.validateCategoryExists(createReqVO.getParentId(), CATEGORY_PARENT_NOT_EXISTS);
-        // 插入
-        CategoryDO category = CategoryConvert.INSTANCE.convert(createReqVO);
-        categoryMapper.insert(category);
-        // 返回
-        return category.getId();
-    }
-
-    @Override
-    public void updateCategory(CategoryUpdateReqVO updateReqVO) {
-        // 校验父分类存在
-        this.validateCategoryExists(updateReqVO.getParentId(), CATEGORY_PARENT_NOT_EXISTS);
-        // 校验分类是否存在
-        this.validateCategoryExists(updateReqVO.getId(), CATEGORY_NOT_EXISTS);
-        // 更新
-        CategoryDO updateObj = CategoryConvert.INSTANCE.convert(updateReqVO);
-        categoryMapper.updateById(updateObj);
-    }
-
-    @Override
-    public void deleteCategory(Long id) {
-        // TODO 芋艿 补充只有不存在商品才可以删除
-        // 校验分类是否存在
-        CategoryDO categoryDO = this.validateCategoryExists(id, CATEGORY_NOT_EXISTS);
-        // 校验是否还有子分类
-        if (categoryMapper.selectCountByParentId(categoryDO.getParentId()) > 0) {
-            throw ServiceExceptionUtil.exception(CATEGORY_EXISTS_CHILDREN);
-        }
-        // 删除
-        categoryMapper.deleteById(id);
-    }
-
-    private CategoryDO validateCategoryExists(Long id, ErrorCode errorCode) {
-        // TODO franky:0 要枚举哈
-        if (id == 0) {
-            return new CategoryDO().setId(id);
-        }
-        CategoryDO categoryDO = categoryMapper.selectById(id);
-        if (categoryDO == null) {
-            throw exception(errorCode);
-        }
-        return categoryDO;
-    }
-
-    @Override
-    public void validatedCategoryById(Long categoryId) {
-        this.validateCategoryExists(categoryId, CATEGORY_NOT_EXISTS);
-    }
-
-    @Override
-    public CategoryDO getCategory(Long id) {
-        return categoryMapper.selectById(id);
-    }
-
-    @Override
-    public List<CategoryDO> getCategoryList(Collection<Long> ids) {
-        return categoryMapper.selectBatchIds(ids);
-    }
-
-    @Override
-    public PageResult<CategoryDO> getCategoryPage(CategoryPageReqVO pageReqVO) {
-        return categoryMapper.selectPage(pageReqVO);
-    }
-
-    @Override
-    public List<CategoryDO> getCategoryList(CategoryExportReqVO exportReqVO) {
-        return categoryMapper.selectList(exportReqVO);
-    }
-
-    @Override
-    public List<CategoryDO> getCategoryTreeList(CategoryTreeListReqVO treeListReqVO) {
-        return categoryMapper.selectList(treeListReqVO);
-    }
-
-    @Override
-    public List<CategoryDO> getCategoryList() {
-        return categoryMapper.selectList()
-                .stream()
-                .filter(v->v.getStatus().equals(CommonStatusEnum.ENABLE.getStatus()))
-                .collect(Collectors.toList());
-    }
-
-
-}

+ 79 - 0
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryService.java

@@ -0,0 +1,79 @@
+package cn.iocoder.yudao.module.product.service.category;
+
+import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryCreateReqVO;
+import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryListReqVO;
+import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryUpdateReqVO;
+import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO;
+
+import javax.validation.Valid;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 商品分类 Service 接口
+ *
+ * @author 芋道源码
+ */
+public interface ProductCategoryService {
+
+    /**
+     * 创建商品分类
+     *
+     * @param createReqVO 创建信息
+     * @return 编号
+     */
+    Long createProductCategory(@Valid ProductCategoryCreateReqVO createReqVO);
+
+    /**
+     * 更新商品分类
+     *
+     * @param updateReqVO 更新信息
+     */
+    void updateProductCategory(@Valid ProductCategoryUpdateReqVO updateReqVO);
+
+    /**
+     * 删除商品分类
+     *
+     * @param id 编号
+     */
+    void deleteProductCategory(Long id);
+
+    /**
+     * 获得商品分类
+     *
+     * @param id 编号
+     * @return 商品分类
+     */
+    ProductCategoryDO getProductCategory(Long id);
+
+    /**
+     * 获得商品分类列表
+     *
+     * @param ids 编号
+     * @return 商品分类列表
+     */
+    List<ProductCategoryDO> getEnableProductCategoryList(Collection<Long> ids);
+
+    /**
+     * 获得商品分类列表
+     *
+     * @param listReqVO 查询条件
+     * @return 商品分类列表
+     */
+    List<ProductCategoryDO> getEnableProductCategoryList(ProductCategoryListReqVO listReqVO);
+
+    /**
+     * 验证选择的商品分类是否合法
+     *
+     * @param id 分类编号
+     */
+    void validateProductCategory(Long id);
+
+    /**
+     * 获得开启状态的商品分类列表
+     *
+     * @return 商品分类列表
+     */
+    List<ProductCategoryDO> getEnableProductCategoryList();
+
+}

+ 125 - 0
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImpl.java

@@ -0,0 +1,125 @@
+package cn.iocoder.yudao.module.product.service.category;
+
+import cn.hutool.core.util.ObjectUtil;
+import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
+import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryCreateReqVO;
+import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryListReqVO;
+import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryUpdateReqVO;
+import cn.iocoder.yudao.module.product.convert.category.CategoryConvert;
+import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO;
+import cn.iocoder.yudao.module.product.dal.mysql.category.ProductCategoryMapper;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+import javax.annotation.Resource;
+import java.util.Collection;
+import java.util.List;
+import java.util.Objects;
+
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.*;
+
+/**
+ * 商品分类 Service 实现类
+ *
+ * @author 芋道源码
+ */
+@Service
+@Validated
+public class ProductCategoryServiceImpl implements ProductCategoryService {
+
+    @Resource
+    private ProductCategoryMapper productCategoryMapper;
+
+    @Override
+    public Long createProductCategory(ProductCategoryCreateReqVO createReqVO) {
+        // 校验父分类存在
+        validateParentProductCategory(createReqVO.getParentId());
+
+        // 插入
+        ProductCategoryDO category = CategoryConvert.INSTANCE.convert(createReqVO);
+        productCategoryMapper.insert(category);
+        // 返回
+        return category.getId();
+    }
+
+    @Override
+    public void updateProductCategory(ProductCategoryUpdateReqVO updateReqVO) {
+        // 校验分类是否存在
+        validateProductCategoryExists(updateReqVO.getId());
+        // 校验父分类存在
+        validateParentProductCategory(updateReqVO.getParentId());
+
+        // 更新
+        ProductCategoryDO updateObj = CategoryConvert.INSTANCE.convert(updateReqVO);
+        productCategoryMapper.updateById(updateObj);
+    }
+
+    @Override
+    public void deleteProductCategory(Long id) {
+        // 校验分类是否存在
+        validateProductCategoryExists(id);
+        // 校验是否还有子分类
+        if (productCategoryMapper.selectCountByParentId(id) > 0) {
+            throw exception(PRODUCT_CATEGORY_EXISTS_CHILDREN);
+        }
+
+        // 删除
+        productCategoryMapper.deleteById(id);
+    }
+
+    private void validateParentProductCategory(Long id) {
+        // 如果是根分类,无需验证
+        if (Objects.equals(id, ProductCategoryDO.PARENT_ID_NULL)) {
+            return;
+        }
+        // 父分类不存在
+        ProductCategoryDO category = productCategoryMapper.selectById(id);
+        if (category == null) {
+            throw exception(PRODUCT_CATEGORY_PARENT_NOT_EXISTS);
+        }
+        // 父分类不能是二级分类
+        if (Objects.equals(id, ProductCategoryDO.PARENT_ID_NULL)) {
+            throw exception(PRODUCT_CATEGORY_PARENT_NOT_FIRST_LEVEL);
+        }
+    }
+
+    private void validateProductCategoryExists(Long id) {
+        ProductCategoryDO category = productCategoryMapper.selectById(id);
+        if (category == null) {
+            throw exception(PRODUCT_CATEGORY_NOT_EXISTS);
+        }
+    }
+
+    @Override
+    public void validateProductCategory(Long id) {
+        ProductCategoryDO category = productCategoryMapper.selectById(id);
+        if (category == null) {
+            throw exception(PRODUCT_CATEGORY_NOT_EXISTS);
+        }
+        if (ObjectUtil.notEqual(category.getStatus(), CommonStatusEnum.ENABLE.getStatus())) {
+            throw exception(PRODUCT_CATEGORY_DISABLED);
+        }
+    }
+
+    @Override
+    public ProductCategoryDO getProductCategory(Long id) {
+        return productCategoryMapper.selectById(id);
+    }
+
+    @Override
+    public List<ProductCategoryDO> getEnableProductCategoryList(Collection<Long> ids) {
+        return productCategoryMapper.selectBatchIds(ids);
+    }
+
+    @Override
+    public List<ProductCategoryDO> getEnableProductCategoryList(ProductCategoryListReqVO listReqVO) {
+        return productCategoryMapper.selectList(listReqVO);
+    }
+
+    @Override
+    public List<ProductCategoryDO> getEnableProductCategoryList() {
+        return productCategoryMapper.selectListByStatus(CommonStatusEnum.ENABLE.getStatus());
+    }
+
+}

+ 5 - 5
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java

@@ -15,7 +15,7 @@ import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert;
 import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
 import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
 import cn.iocoder.yudao.module.product.dal.mysql.spu.ProductSpuMapper;
-import cn.iocoder.yudao.module.product.service.category.CategoryService;
+import cn.iocoder.yudao.module.product.service.category.ProductCategoryService;
 import cn.iocoder.yudao.module.product.service.property.ProductPropertyService;
 import cn.iocoder.yudao.module.product.service.sku.ProductSkuService;
 import org.springframework.stereotype.Service;
@@ -42,7 +42,7 @@ public class ProductSpuServiceImpl implements ProductSpuService {
     private ProductSpuMapper ProductSpuMapper;
 
     @Resource
-    private CategoryService categoryService;
+    private ProductCategoryService categoryService;
 
     @Resource
     private ProductSkuService productSkuService;
@@ -54,7 +54,7 @@ public class ProductSpuServiceImpl implements ProductSpuService {
     @Transactional
     public Long createSpu(ProductSpuCreateReqVO createReqVO) {
         // 校验分类
-        categoryService.validatedCategoryById(createReqVO.getCategoryId());
+        categoryService.validateProductCategory(createReqVO.getCategoryId());
         // 校验SKU
         List<ProductSkuCreateReqVO> skuCreateReqList = createReqVO.getSkus();
         productSkuService.validateSkus(skuCreateReqList);
@@ -78,7 +78,7 @@ public class ProductSpuServiceImpl implements ProductSpuService {
         // 校验 spu 是否存在
         this.validateSpuExists(updateReqVO.getId());
         // 校验分类
-        categoryService.validatedCategoryById(updateReqVO.getCategoryId());
+        categoryService.validateProductCategory(updateReqVO.getCategoryId());
         // 校验SKU
         List<ProductSkuCreateReqVO> skuCreateReqList = updateReqVO.getSkus();
         productSkuService.validateSkus(skuCreateReqList);
@@ -142,7 +142,7 @@ public class ProductSpuServiceImpl implements ProductSpuService {
                 Long parentId = spuVO.getCategoryId();
                 categoryArray.addFirst(parentId);
                 while (parentId != 0) {
-                    parentId = categoryService.getCategory(parentId).getParentId();
+                    parentId = categoryService.getProductCategory(parentId).getParentId();
                     if (parentId > 0) {
                         categoryArray.addFirst(parentId);
                     }

+ 0 - 192
yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/category/CategoryServiceImplTest.java

@@ -1,192 +0,0 @@
-package cn.iocoder.yudao.module.product.service.category;
-
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
-import cn.iocoder.yudao.module.product.controller.admin.category.vo.CategoryCreateReqVO;
-import cn.iocoder.yudao.module.product.controller.admin.category.vo.CategoryExportReqVO;
-import cn.iocoder.yudao.module.product.controller.admin.category.vo.CategoryPageReqVO;
-import cn.iocoder.yudao.module.product.controller.admin.category.vo.CategoryUpdateReqVO;
-import cn.iocoder.yudao.module.product.dal.dataobject.category.CategoryDO;
-import cn.iocoder.yudao.module.product.dal.mysql.category.CategoryMapper;
-import org.junit.jupiter.api.Disabled;
-import org.junit.jupiter.api.Test;
-import org.springframework.context.annotation.Import;
-
-import javax.annotation.Resource;
-import java.util.List;
-
-import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
-import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
-import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
-import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
-import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
-import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.CATEGORY_NOT_EXISTS;
-import static org.junit.jupiter.api.Assertions.*;
-
-/**
- * {@link CategoryServiceImpl} 的单元测试类
- *
- * @author 芋道源码
- */
-@Import(CategoryServiceImpl.class)
-public class CategoryServiceImplTest extends BaseDbUnitTest {
-
-    @Resource
-    private CategoryServiceImpl categoryService;
-
-    @Resource
-    private CategoryMapper categoryMapper;
-
-    @Test
-    public void testCreateCategory_success() {
-        // 准备参数
-        CategoryCreateReqVO reqVO = randomPojo(CategoryCreateReqVO.class);
-
-        // 调用
-        Long categoryId = categoryService.createCategory(reqVO);
-        // 断言
-        assertNotNull(categoryId);
-        // 校验记录的属性是否正确
-        CategoryDO category = categoryMapper.selectById(categoryId);
-        assertPojoEquals(reqVO, category);
-    }
-
-    @Test
-    public void testUpdateCategory_success() {
-        // mock 数据
-        CategoryDO dbCategory = randomPojo(CategoryDO.class);
-        categoryMapper.insert(dbCategory);// @Sql: 先插入出一条存在的数据
-        // 准备参数
-        CategoryUpdateReqVO reqVO = randomPojo(CategoryUpdateReqVO.class, o -> {
-            o.setId(dbCategory.getId()); // 设置更新的 ID
-        });
-
-        // 调用
-        categoryService.updateCategory(reqVO);
-        // 校验是否更新正确
-        CategoryDO category = categoryMapper.selectById(reqVO.getId()); // 获取最新的
-        assertPojoEquals(reqVO, category);
-    }
-
-    @Test
-    public void testUpdateCategory_notExists() {
-        // 准备参数
-        CategoryUpdateReqVO reqVO = randomPojo(CategoryUpdateReqVO.class);
-
-        // 调用, 并断言异常
-        assertServiceException(() -> categoryService.updateCategory(reqVO), CATEGORY_NOT_EXISTS);
-    }
-
-    @Test
-    public void testDeleteCategory_success() {
-        // mock 数据
-        CategoryDO dbCategory = randomPojo(CategoryDO.class);
-        categoryMapper.insert(dbCategory);// @Sql: 先插入出一条存在的数据
-        // 准备参数
-        Long id = dbCategory.getId();
-
-        // 调用
-        categoryService.deleteCategory(id);
-        // 校验数据不存在了
-        assertNull(categoryMapper.selectById(id));
-    }
-
-    @Test
-    public void testDeleteCategory_notExists() {
-        // 准备参数
-        Long id = randomLongId();
-
-        // 调用, 并断言异常
-        assertServiceException(() -> categoryService.deleteCategory(id), CATEGORY_NOT_EXISTS);
-    }
-
-    @Test
-    @Disabled  // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
-    public void testGetCategoryPage() {
-        // mock 数据
-        CategoryDO dbCategory = randomPojo(CategoryDO.class, o -> { // 等会查询到
-            o.setParentId(null);
-            o.setName(null);
-            o.setIcon(null);
-            o.setBannerUrl(null);
-            o.setSort(null);
-            o.setDescription(null);
-            o.setStatus(null);
-            o.setCreateTime(null);
-        });
-        categoryMapper.insert(dbCategory);
-        // 测试 pid 不匹配
-        categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setParentId(null)));
-        // 测试 name 不匹配
-        categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setName(null)));
-        // 测试 icon 不匹配
-        categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setIcon(null)));
-        // 测试 bannerUrl 不匹配
-        categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setBannerUrl(null)));
-        // 测试 sort 不匹配
-        categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setSort(null)));
-        // 测试 description 不匹配
-        categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setDescription(null)));
-        // 测试 status 不匹配
-        categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setStatus(null)));
-        // 测试 createTime 不匹配
-        categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setCreateTime(null)));
-        // 准备参数
-        CategoryPageReqVO reqVO = new CategoryPageReqVO();
-        reqVO.setName(null);
-        reqVO.setStatus(null);
-        reqVO.setCreateTime(null);
-
-        // 调用
-        PageResult<CategoryDO> pageResult = categoryService.getCategoryPage(reqVO);
-        // 断言
-        assertEquals(1, pageResult.getTotal());
-        assertEquals(1, pageResult.getList().size());
-        assertPojoEquals(dbCategory, pageResult.getList().get(0));
-    }
-
-    @Test
-    @Disabled  // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
-    public void testGetCategoryList() {
-        // mock 数据
-        CategoryDO dbCategory = randomPojo(CategoryDO.class, o -> { // 等会查询到
-            o.setParentId(null);
-            o.setName(null);
-            o.setIcon(null);
-            o.setBannerUrl(null);
-            o.setSort(null);
-            o.setDescription(null);
-            o.setStatus(null);
-            o.setCreateTime(null);
-        });
-        categoryMapper.insert(dbCategory);
-        // 测试 pid 不匹配
-        categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setParentId(null)));
-        // 测试 name 不匹配
-        categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setName(null)));
-        // 测试 icon 不匹配
-        categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setIcon(null)));
-        // 测试 bannerUrl 不匹配
-        categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setBannerUrl(null)));
-        // 测试 sort 不匹配
-        categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setSort(null)));
-        // 测试 description 不匹配
-        categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setDescription(null)));
-        // 测试 status 不匹配
-        categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setStatus(null)));
-        // 测试 createTime 不匹配
-        categoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setCreateTime(null)));
-        // 准备参数
-        CategoryExportReqVO reqVO = new CategoryExportReqVO();
-        reqVO.setName(null);
-        reqVO.setStatus(null);
-        reqVO.setCreateTime(null);
-
-        // 调用
-        List<CategoryDO> list = categoryService.getCategoryList(reqVO);
-        // 断言
-        assertEquals(1, list.size());
-        assertPojoEquals(dbCategory, list.get(0));
-    }
-
-}

+ 126 - 0
yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImplTest.java

@@ -0,0 +1,126 @@
+package cn.iocoder.yudao.module.product.service.category;
+
+import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
+import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryCreateReqVO;
+import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryListReqVO;
+import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryUpdateReqVO;
+import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO;
+import cn.iocoder.yudao.module.product.dal.mysql.category.ProductCategoryMapper;
+import org.junit.jupiter.api.Test;
+import org.springframework.context.annotation.Import;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
+import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
+import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
+import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
+import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
+import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.PRODUCT_CATEGORY_NOT_EXISTS;
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ * {@link ProductCategoryServiceImpl} 的单元测试类
+ *
+ * @author 芋道源码
+ */
+@Import(ProductCategoryServiceImpl.class)
+public class ProductCategoryServiceImplTest extends BaseDbUnitTest {
+
+    @Resource
+    private ProductCategoryServiceImpl productCategoryService;
+
+    @Resource
+    private ProductCategoryMapper productCategoryMapper;
+
+    @Test
+    public void testCreateCategory_success() {
+        // 准备参数
+        ProductCategoryCreateReqVO reqVO = randomPojo(ProductCategoryCreateReqVO.class);
+        // mock 父类
+        ProductCategoryDO parentProductCategory = randomPojo(ProductCategoryDO.class, o -> o.setId(reqVO.getParentId()));
+        productCategoryMapper.insert(parentProductCategory);
+
+        // 调用
+        Long categoryId = productCategoryService.createProductCategory(reqVO);
+        // 断言
+        assertNotNull(categoryId);
+        // 校验记录的属性是否正确
+        ProductCategoryDO category = productCategoryMapper.selectById(categoryId);
+        assertPojoEquals(reqVO, category);
+    }
+
+    @Test
+    public void testUpdateCategory_success() {
+        // mock 数据
+        ProductCategoryDO dbCategory = randomPojo(ProductCategoryDO.class);
+        productCategoryMapper.insert(dbCategory);// @Sql: 先插入出一条存在的数据
+        // 准备参数
+        ProductCategoryUpdateReqVO reqVO = randomPojo(ProductCategoryUpdateReqVO.class, o -> {
+            o.setId(dbCategory.getId()); // 设置更新的 ID
+        });
+        // mock 父类
+        ProductCategoryDO parentProductCategory = randomPojo(ProductCategoryDO.class, o -> o.setId(reqVO.getParentId()));
+        productCategoryMapper.insert(parentProductCategory);
+
+        // 调用
+        productCategoryService.updateProductCategory(reqVO);
+        // 校验是否更新正确
+        ProductCategoryDO category = productCategoryMapper.selectById(reqVO.getId()); // 获取最新的
+        assertPojoEquals(reqVO, category);
+    }
+
+    @Test
+    public void testUpdateCategory_notExists() {
+        // 准备参数
+        ProductCategoryUpdateReqVO reqVO = randomPojo(ProductCategoryUpdateReqVO.class);
+
+        // 调用, 并断言异常
+        assertServiceException(() -> productCategoryService.updateProductCategory(reqVO), PRODUCT_CATEGORY_NOT_EXISTS);
+    }
+
+    @Test
+    public void testDeleteCategory_success() {
+        // mock 数据
+        ProductCategoryDO dbCategory = randomPojo(ProductCategoryDO.class);
+        productCategoryMapper.insert(dbCategory);// @Sql: 先插入出一条存在的数据
+        // 准备参数
+        Long id = dbCategory.getId();
+
+        // 调用
+        productCategoryService.deleteProductCategory(id);
+        // 校验数据不存在了
+        assertNull(productCategoryMapper.selectById(id));
+    }
+
+    @Test
+    public void testDeleteCategory_notExists() {
+        // 准备参数
+        Long id = randomLongId();
+
+        // 调用, 并断言异常
+        assertServiceException(() -> productCategoryService.deleteProductCategory(id), PRODUCT_CATEGORY_NOT_EXISTS);
+    }
+
+    @Test
+    public void testGetCategoryList() {
+        // mock 数据
+        ProductCategoryDO dbCategory = randomPojo(ProductCategoryDO.class, o -> { // 等会查询到
+            o.setName("奥特曼");
+        });
+        productCategoryMapper.insert(dbCategory);
+        // 测试 name 不匹配
+        productCategoryMapper.insert(cloneIgnoreId(dbCategory, o -> o.setName("奥特块")));
+        // 准备参数
+        ProductCategoryListReqVO reqVO = new ProductCategoryListReqVO();
+        reqVO.setName("特曼");
+
+        // 调用
+        List<ProductCategoryDO> list = productCategoryService.getEnableProductCategoryList(reqVO);
+        // 断言
+        assertEquals(1, list.size());
+        assertPojoEquals(dbCategory, list.get(0));
+    }
+
+}

+ 50 - 0
yudao-module-mall/yudao-module-product-biz/src/test/resources/application-unit-test.yaml

@@ -0,0 +1,50 @@
+spring:
+  main:
+    lazy-initialization: true # 开启懒加载,加快速度
+    banner-mode: off # 单元测试,禁用 Banner
+
+--- #################### 数据库相关配置 ####################
+
+spring:
+  # 数据源配置项
+  datasource:
+    name: ruoyi-vue-pro
+    url: jdbc:h2:mem:testdb;MODE=MYSQL;DATABASE_TO_UPPER=false; # MODE 使用 MySQL 模式;DATABASE_TO_UPPER 配置表和字段使用小写
+    driver-class-name: org.h2.Driver
+    username: sa
+    password:
+    druid:
+      async-init: true # 单元测试,异步初始化 Druid 连接池,提升启动速度
+      initial-size: 1 # 单元测试,配置为 1,提升启动速度
+  sql:
+    init:
+      schema-locations: classpath:/sql/create_tables.sql
+
+  # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优
+  redis:
+    host: 127.0.0.1 # 地址
+    port: 16379 # 端口(单元测试,使用 16379 端口)
+    database: 0 # 数据库索引
+
+mybatis-plus:
+  lazy-initialization: true # 单元测试,设置 MyBatis Mapper 延迟加载,加速每个单元测试
+  type-aliases-package: ${yudao.info.base-package}.module.*.dal.dataobject
+
+--- #################### 定时任务相关配置 ####################
+
+--- #################### 配置中心相关配置 ####################
+
+--- #################### 服务保障相关配置 ####################
+
+# Lock4j 配置项(单元测试,禁用 Lock4j)
+
+# Resilience4j 配置项
+
+--- #################### 监控相关配置 ####################
+
+--- #################### 芋道相关配置 ####################
+
+# 芋道配置项,设置当前项目所有自定义的配置
+yudao:
+  info:
+    base-package: cn.iocoder.yudao

+ 4 - 0
yudao-module-mall/yudao-module-product-biz/src/test/resources/logback.xml

@@ -0,0 +1,4 @@
+<configuration>
+    <!-- 引用 Spring Boot 的 logback 基础配置 -->
+    <include resource="org/springframework/boot/logging/logback/defaults.xml" />
+</configuration>

+ 1 - 4
yudao-module-mall/yudao-module-product-biz/src/test/resources/sql/create_tables.sql

@@ -2,8 +2,7 @@ CREATE TABLE IF NOT EXISTS "product_category" (
     "id" bigint(20) NOT NULL GENERATED BY DEFAULT AS IDENTITY,
     "parent_id" bigint(20) NOT NULL,
     "name" varchar(255) NOT NULL,
-    "icon" varchar(100),
-    "banner_url" varchar(255) NOT NULL,
+    "pic_url" varchar(255) NOT NULL,
     "sort" int(11) NOT NULL,
     "description" varchar(1024) NOT NULL,
     "status" tinyint(4) NOT NULL,
@@ -12,7 +11,6 @@ CREATE TABLE IF NOT EXISTS "product_category" (
     "updater" varchar(64) DEFAULT '',
     "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
     "deleted" bit NOT NULL DEFAULT FALSE,
-    "tenant_id" bigint(20) NOT NULL,
     PRIMARY KEY ("id")
 ) COMMENT '商品分类';
 
@@ -29,6 +27,5 @@ CREATE TABLE IF NOT EXISTS "product_brand" (
     "updater" varchar(64) DEFAULT '',
     "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
     "deleted" bit NOT NULL DEFAULT FALSE,
-    "tenant_id" bigint(20) NOT NULL,
     PRIMARY KEY ("id")
 ) COMMENT '品牌';