mall:完善商品分类的后端接口
parent
1976571ae8
commit
6a0f713452
|
@ -3,16 +3,18 @@ package cn.iocoder.yudao.module.product.enums;
|
||||||
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
|
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* product 错误码枚举类
|
* Product 错误码枚举类
|
||||||
* <p>
|
*
|
||||||
* product 系统,使用 1-008-000-000 段
|
* product 系统,使用 1-008-000-000 段
|
||||||
*/
|
*/
|
||||||
public interface ErrorCodeConstants {
|
public interface ErrorCodeConstants {
|
||||||
|
|
||||||
// ========== 商品分类相关 1008001000============
|
// ========== 商品分类相关 1008001000 ============
|
||||||
ErrorCode CATEGORY_NOT_EXISTS = new ErrorCode(1008001000, "商品分类不存在");
|
ErrorCode PRODUCT_CATEGORY_NOT_EXISTS = new ErrorCode(1008001000, "商品分类不存在");
|
||||||
ErrorCode CATEGORY_PARENT_NOT_EXISTS = new ErrorCode(1008001001, "父分类不存在");
|
ErrorCode PRODUCT_CATEGORY_PARENT_NOT_EXISTS = new ErrorCode(1008001001, "父分类不存在");
|
||||||
ErrorCode CATEGORY_EXISTS_CHILDREN = new ErrorCode(1008001002, "存在子分类,无法删除");
|
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 ==========
|
// ========== 品牌相关编号 1008002000 ==========
|
||||||
ErrorCode BRAND_NOT_EXISTS = new ErrorCode(1008002000, "品牌不存在");
|
ErrorCode BRAND_NOT_EXISTS = new ErrorCode(1008002000, "品牌不存在");
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -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));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
|
||||||
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -11,7 +11,7 @@ import javax.validation.constraints.NotNull;
|
||||||
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
|
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
public class CategoryBaseVO {
|
public class ProductCategoryBaseVO {
|
||||||
|
|
||||||
@ApiModelProperty(value = "父分类编号", required = true, example = "1")
|
@ApiModelProperty(value = "父分类编号", required = true, example = "1")
|
||||||
@NotNull(message = "父分类编号不能为空")
|
@NotNull(message = "父分类编号不能为空")
|
||||||
|
@ -21,13 +21,9 @@ public class CategoryBaseVO {
|
||||||
@NotBlank(message = "分类名称不能为空")
|
@NotBlank(message = "分类名称不能为空")
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
@ApiModelProperty(value = "分类图标")
|
|
||||||
@NotBlank(message = "分类图标不能为空")
|
|
||||||
private String icon;
|
|
||||||
|
|
||||||
@ApiModelProperty(value = "分类图片", required = true)
|
@ApiModelProperty(value = "分类图片", required = true)
|
||||||
@NotBlank(message = "分类图片不能为空")
|
@NotBlank(message = "分类图片不能为空")
|
||||||
private String bannerUrl;
|
private String picUrl;
|
||||||
|
|
||||||
@ApiModelProperty(value = "分类排序", required = true, example = "1")
|
@ApiModelProperty(value = "分类排序", required = true, example = "1")
|
||||||
private Integer sort;
|
private Integer sort;
|
|
@ -1,14 +1,12 @@
|
||||||
package cn.iocoder.yudao.module.product.controller.admin.category.vo;
|
package cn.iocoder.yudao.module.product.controller.admin.category.vo;
|
||||||
|
|
||||||
import lombok.*;
|
import lombok.*;
|
||||||
import java.util.*;
|
|
||||||
import io.swagger.annotations.*;
|
import io.swagger.annotations.*;
|
||||||
import javax.validation.constraints.*;
|
|
||||||
|
|
||||||
@ApiModel("管理后台 - 商品分类创建 Request VO")
|
@ApiModel("管理后台 - 商品分类创建 Request VO")
|
||||||
@Data
|
@Data
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
@ToString(callSuper = true)
|
@ToString(callSuper = true)
|
||||||
public class CategoryCreateReqVO extends CategoryBaseVO {
|
public class ProductCategoryCreateReqVO extends ProductCategoryBaseVO {
|
||||||
|
|
||||||
}
|
}
|
|
@ -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;
|
||||||
|
|
||||||
|
}
|
|
@ -8,7 +8,7 @@ import io.swagger.annotations.*;
|
||||||
@Data
|
@Data
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
@ToString(callSuper = true)
|
@ToString(callSuper = true)
|
||||||
public class CategoryRespVO extends CategoryBaseVO {
|
public class ProductCategoryRespVO extends ProductCategoryBaseVO {
|
||||||
|
|
||||||
@ApiModelProperty(value = "分类编号", required = true, example = "2")
|
@ApiModelProperty(value = "分类编号", required = true, example = "2")
|
||||||
private Long id;
|
private Long id;
|
|
@ -1,7 +1,6 @@
|
||||||
package cn.iocoder.yudao.module.product.controller.admin.category.vo;
|
package cn.iocoder.yudao.module.product.controller.admin.category.vo;
|
||||||
|
|
||||||
import lombok.*;
|
import lombok.*;
|
||||||
import java.util.*;
|
|
||||||
import io.swagger.annotations.*;
|
import io.swagger.annotations.*;
|
||||||
import javax.validation.constraints.*;
|
import javax.validation.constraints.*;
|
||||||
|
|
||||||
|
@ -9,7 +8,7 @@ import javax.validation.constraints.*;
|
||||||
@Data
|
@Data
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
@ToString(callSuper = true)
|
@ToString(callSuper = true)
|
||||||
public class CategoryUpdateReqVO extends CategoryBaseVO {
|
public class ProductCategoryUpdateReqVO extends ProductCategoryBaseVO {
|
||||||
|
|
||||||
@ApiModelProperty(value = "分类编号", required = true, example = "2")
|
@ApiModelProperty(value = "分类编号", required = true, example = "2")
|
||||||
@NotNull(message = "分类编号不能为空")
|
@NotNull(message = "分类编号不能为空")
|
|
@ -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.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.module.product.controller.app.category.vo.AppCategoryListRespVO;
|
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.convert.category.CategoryConvert;
|
||||||
import cn.iocoder.yudao.module.product.dal.dataobject.category.CategoryDO;
|
import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO;
|
||||||
import cn.iocoder.yudao.module.product.service.category.CategoryService;
|
import cn.iocoder.yudao.module.product.service.category.ProductCategoryService;
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
@ -25,13 +25,13 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||||
public class AppCategoryController {
|
public class AppCategoryController {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private CategoryService categoryService;
|
private ProductCategoryService categoryService;
|
||||||
|
|
||||||
@GetMapping("/list")
|
@GetMapping("/list")
|
||||||
@ApiOperation("获得商品分类列表")
|
@ApiOperation("获得商品分类列表")
|
||||||
public CommonResult<List<AppCategoryListRespVO>> listByQuery() {
|
public CommonResult<List<AppCategoryListRespVO>> listByQuery() {
|
||||||
List<CategoryDO> list = categoryService.getCategoryList();
|
List<ProductCategoryDO> list = categoryService.getEnableProductCategoryList();
|
||||||
list.sort(Comparator.comparing(CategoryDO::getSort));
|
list.sort(Comparator.comparing(ProductCategoryDO::getSort));
|
||||||
return success(CategoryConvert.INSTANCE.convertList03(list));
|
return success(CategoryConvert.INSTANCE.convertList03(list));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
package cn.iocoder.yudao.module.product.convert.category;
|
package cn.iocoder.yudao.module.product.convert.category;
|
||||||
|
|
||||||
import java.util.*;
|
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.framework.common.pojo.PageResult;
|
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.controller.app.category.vo.AppCategoryListRespVO;
|
||||||
|
import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO;
|
||||||
import org.mapstruct.Mapper;
|
import org.mapstruct.Mapper;
|
||||||
import org.mapstruct.factory.Mappers;
|
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
|
* 商品分类 Convert
|
||||||
|
@ -20,17 +20,13 @@ public interface CategoryConvert {
|
||||||
|
|
||||||
CategoryConvert INSTANCE = Mappers.getMapper(CategoryConvert.class);
|
CategoryConvert INSTANCE = Mappers.getMapper(CategoryConvert.class);
|
||||||
|
|
||||||
CategoryDO convert(CategoryCreateReqVO bean);
|
ProductCategoryDO convert(ProductCategoryCreateReqVO bean);
|
||||||
|
|
||||||
CategoryDO convert(CategoryUpdateReqVO bean);
|
ProductCategoryDO convert(ProductCategoryUpdateReqVO bean);
|
||||||
|
|
||||||
CategoryRespVO convert(CategoryDO bean);
|
ProductCategoryRespVO convert(ProductCategoryDO bean);
|
||||||
|
|
||||||
List<CategoryRespVO> convertList(List<CategoryDO> list);
|
List<ProductCategoryRespVO> convertList(List<ProductCategoryDO> list);
|
||||||
|
|
||||||
PageResult<CategoryRespVO> convertPage(PageResult<CategoryDO> page);
|
List<AppCategoryListRespVO> convertList03(List<ProductCategoryDO> list);
|
||||||
|
|
||||||
List<CategoryExcelVO> convertList02(List<CategoryDO> list);
|
|
||||||
|
|
||||||
List<AppCategoryListRespVO> convertList03(List<CategoryDO> list);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,10 +6,13 @@ import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import lombok.*;
|
import lombok.*;
|
||||||
|
|
||||||
// TODO @JeromeSoar:Product 前缀
|
|
||||||
/**
|
/**
|
||||||
* 商品分类 DO
|
* 商品分类 DO
|
||||||
*
|
*
|
||||||
|
* 商品分类一共两级:
|
||||||
|
* 1)一级分类:{@link #parentId} 等于 0
|
||||||
|
* 2)二级分类:{@link #parentId} 等于父分类
|
||||||
|
*
|
||||||
* @author 芋道源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
@TableName("product_category")
|
@TableName("product_category")
|
||||||
|
@ -19,7 +22,12 @@ import lombok.*;
|
||||||
@Builder
|
@Builder
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@AllArgsConstructor
|
@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 name;
|
||||||
/**
|
/**
|
||||||
* 分类图标
|
* 分类图片
|
||||||
*/
|
|
||||||
private String icon;
|
|
||||||
/**
|
|
||||||
* 分类 Banner 图片
|
|
||||||
*
|
*
|
||||||
* 第一层的商品分类,会有该字段,用于用户 App 展示
|
* 一级分类:推荐 200 x 100 分辨率
|
||||||
|
* 二级分类:推荐 100 x 100 分辨率
|
||||||
*/
|
*/
|
||||||
private String bannerUrl;
|
private String picUrl;
|
||||||
/**
|
/**
|
||||||
* 分类排序
|
* 分类排序
|
||||||
*/
|
*/
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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();
|
|
||||||
}
|
|
|
@ -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());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
|
@ -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();
|
||||||
|
|
||||||
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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.sku.ProductSkuDO;
|
||||||
import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
|
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.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.property.ProductPropertyService;
|
||||||
import cn.iocoder.yudao.module.product.service.sku.ProductSkuService;
|
import cn.iocoder.yudao.module.product.service.sku.ProductSkuService;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
@ -42,7 +42,7 @@ public class ProductSpuServiceImpl implements ProductSpuService {
|
||||||
private ProductSpuMapper ProductSpuMapper;
|
private ProductSpuMapper ProductSpuMapper;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private CategoryService categoryService;
|
private ProductCategoryService categoryService;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private ProductSkuService productSkuService;
|
private ProductSkuService productSkuService;
|
||||||
|
@ -54,7 +54,7 @@ public class ProductSpuServiceImpl implements ProductSpuService {
|
||||||
@Transactional
|
@Transactional
|
||||||
public Long createSpu(ProductSpuCreateReqVO createReqVO) {
|
public Long createSpu(ProductSpuCreateReqVO createReqVO) {
|
||||||
// 校验分类
|
// 校验分类
|
||||||
categoryService.validatedCategoryById(createReqVO.getCategoryId());
|
categoryService.validateProductCategory(createReqVO.getCategoryId());
|
||||||
// 校验SKU
|
// 校验SKU
|
||||||
List<ProductSkuCreateReqVO> skuCreateReqList = createReqVO.getSkus();
|
List<ProductSkuCreateReqVO> skuCreateReqList = createReqVO.getSkus();
|
||||||
productSkuService.validateSkus(skuCreateReqList);
|
productSkuService.validateSkus(skuCreateReqList);
|
||||||
|
@ -78,7 +78,7 @@ public class ProductSpuServiceImpl implements ProductSpuService {
|
||||||
// 校验 spu 是否存在
|
// 校验 spu 是否存在
|
||||||
this.validateSpuExists(updateReqVO.getId());
|
this.validateSpuExists(updateReqVO.getId());
|
||||||
// 校验分类
|
// 校验分类
|
||||||
categoryService.validatedCategoryById(updateReqVO.getCategoryId());
|
categoryService.validateProductCategory(updateReqVO.getCategoryId());
|
||||||
// 校验SKU
|
// 校验SKU
|
||||||
List<ProductSkuCreateReqVO> skuCreateReqList = updateReqVO.getSkus();
|
List<ProductSkuCreateReqVO> skuCreateReqList = updateReqVO.getSkus();
|
||||||
productSkuService.validateSkus(skuCreateReqList);
|
productSkuService.validateSkus(skuCreateReqList);
|
||||||
|
@ -142,7 +142,7 @@ public class ProductSpuServiceImpl implements ProductSpuService {
|
||||||
Long parentId = spuVO.getCategoryId();
|
Long parentId = spuVO.getCategoryId();
|
||||||
categoryArray.addFirst(parentId);
|
categoryArray.addFirst(parentId);
|
||||||
while (parentId != 0) {
|
while (parentId != 0) {
|
||||||
parentId = categoryService.getCategory(parentId).getParentId();
|
parentId = categoryService.getProductCategory(parentId).getParentId();
|
||||||
if (parentId > 0) {
|
if (parentId > 0) {
|
||||||
categoryArray.addFirst(parentId);
|
categoryArray.addFirst(parentId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -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));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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
|
|
@ -0,0 +1,4 @@
|
||||||
|
<configuration>
|
||||||
|
<!-- 引用 Spring Boot 的 logback 基础配置 -->
|
||||||
|
<include resource="org/springframework/boot/logging/logback/defaults.xml" />
|
||||||
|
</configuration>
|
|
@ -2,8 +2,7 @@ CREATE TABLE IF NOT EXISTS "product_category" (
|
||||||
"id" bigint(20) NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
"id" bigint(20) NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
||||||
"parent_id" bigint(20) NOT NULL,
|
"parent_id" bigint(20) NOT NULL,
|
||||||
"name" varchar(255) NOT NULL,
|
"name" varchar(255) NOT NULL,
|
||||||
"icon" varchar(100),
|
"pic_url" varchar(255) NOT NULL,
|
||||||
"banner_url" varchar(255) NOT NULL,
|
|
||||||
"sort" int(11) NOT NULL,
|
"sort" int(11) NOT NULL,
|
||||||
"description" varchar(1024) NOT NULL,
|
"description" varchar(1024) NOT NULL,
|
||||||
"status" tinyint(4) NOT NULL,
|
"status" tinyint(4) NOT NULL,
|
||||||
|
@ -12,7 +11,6 @@ CREATE TABLE IF NOT EXISTS "product_category" (
|
||||||
"updater" varchar(64) DEFAULT '',
|
"updater" varchar(64) DEFAULT '',
|
||||||
"update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
"update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
"deleted" bit NOT NULL DEFAULT FALSE,
|
"deleted" bit NOT NULL DEFAULT FALSE,
|
||||||
"tenant_id" bigint(20) NOT NULL,
|
|
||||||
PRIMARY KEY ("id")
|
PRIMARY KEY ("id")
|
||||||
) COMMENT '商品分类';
|
) COMMENT '商品分类';
|
||||||
|
|
||||||
|
@ -29,6 +27,5 @@ CREATE TABLE IF NOT EXISTS "product_brand" (
|
||||||
"updater" varchar(64) DEFAULT '',
|
"updater" varchar(64) DEFAULT '',
|
||||||
"update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
"update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
"deleted" bit NOT NULL DEFAULT FALSE,
|
"deleted" bit NOT NULL DEFAULT FALSE,
|
||||||
"tenant_id" bigint(20) NOT NULL,
|
|
||||||
PRIMARY KEY ("id")
|
PRIMARY KEY ("id")
|
||||||
) COMMENT '品牌';
|
) COMMENT '品牌';
|
||||||
|
|
Loading…
Reference in New Issue