Commit c62da6a056331a8202c4d46d90a29a98ebc4f139

Authored by YunaiV
1 parent fb7915c9

mall:review 商品接口

Showing 23 changed files with 83 additions and 80 deletions
yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/DictTypeConstants.java
@@ -2,9 +2,12 @@ package cn.iocoder.yudao.module.product.enums; @@ -2,9 +2,12 @@ package cn.iocoder.yudao.module.product.enums;
2 2
3 /** 3 /**
4 * product 字典类型的枚举类 4 * product 字典类型的枚举类
  5 + *
5 * @author HUIHUI 6 * @author HUIHUI
6 */ 7 */
7 public interface DictTypeConstants { 8 public interface DictTypeConstants {
  9 +
8 String PRODUCT_UNIT = "product_unit"; // 商品单位 10 String PRODUCT_UNIT = "product_unit"; // 商品单位
9 String PRODUCT_SPU_STATUS = "product_spu_status"; // 商品 SPU 状态 11 String PRODUCT_SPU_STATUS = "product_spu_status"; // 商品 SPU 状态
  12 +
10 } 13 }
yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/ProductConstants.java
@@ -5,8 +5,9 @@ package cn.iocoder.yudao.module.product.enums; @@ -5,8 +5,9 @@ package cn.iocoder.yudao.module.product.enums;
5 * 5 *
6 * @author HUIHUI 6 * @author HUIHUI
7 */ 7 */
8 -  
9 public interface ProductConstants { 8 public interface ProductConstants {
  9 +
  10 + // TODO @puhui999:这个变量,可以放到 CategoryDO 的实体里
10 /** 11 /**
11 * 父分类编号 - 根分类 12 * 父分类编号 - 根分类
12 */ 13 */
@@ -15,14 +16,18 @@ public interface ProductConstants { @@ -15,14 +16,18 @@ public interface ProductConstants {
15 * 限定分类层级 16 * 限定分类层级
16 */ 17 */
17 int CATEGORY_LEVEL = 2; 18 int CATEGORY_LEVEL = 2;
  19 +
  20 + // TODO @puhui999:这个变量,必要项不大哈
18 /** 21 /**
19 * SPU 分页 tab 个数 22 * SPU 分页 tab 个数
20 */ 23 */
21 int SPU_TAB_COUNTS = 5; 24 int SPU_TAB_COUNTS = 5;
  25 +
22 /** 26 /**
23 * 警戒库存 TODO 警戒库存暂时为 10,后期需要使用常量或者数据库配置替换 27 * 警戒库存 TODO 警戒库存暂时为 10,后期需要使用常量或者数据库配置替换
24 */ 28 */
25 int ALERT_STOCK = 10; 29 int ALERT_STOCK = 10;
  30 +
26 /** 31 /**
27 * 默认商品销量 TODO 默认商品销量为零 32 * 默认商品销量 TODO 默认商品销量为零
28 */ 33 */
@@ -31,4 +36,5 @@ public interface ProductConstants { @@ -31,4 +36,5 @@ public interface ProductConstants {
31 * 默认善品浏览量 TODO 默认浏览量为零 36 * 默认善品浏览量 TODO 默认浏览量为零
32 */ 37 */
33 Integer BROWSE_COUNT = 0; 38 Integer BROWSE_COUNT = 0;
  39 +
34 } 40 }
yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/spu/ProductSpuPageTabEnum.java
@@ -6,7 +6,7 @@ import lombok.Getter; @@ -6,7 +6,7 @@ import lombok.Getter;
6 6
7 import java.util.Arrays; 7 import java.util.Arrays;
8 8
9 -// TODO @puhui999:中英文之间要有空格; 商品 spu Tab 标签枚举;这个类可以改成 ProductSpuPageTabEnum 会更好一点哈;分页 Tab 的意思; 9 +// TODO @puhui999:这种非关键的枚举,要不直接写在 ProductSpuPageReqVO 里。类似 public static final Integer TAB_TYPE_FOR_SALE = 0; // 出售中商品
10 /** 10 /**
11 * 商品 spu Tabs 标签枚举类型 11 * 商品 spu Tabs 标签枚举类型
12 * 12 *
@@ -21,6 +21,7 @@ public enum ProductSpuPageTabEnum implements IntArrayValuable { @@ -21,6 +21,7 @@ public enum ProductSpuPageTabEnum implements IntArrayValuable {
21 SOLD_OUT(2,"已售空商品"), 21 SOLD_OUT(2,"已售空商品"),
22 ALERT_STOCK(3,"警戒库存"), 22 ALERT_STOCK(3,"警戒库存"),
23 RECYCLE_BIN(4,"商品回收站"); 23 RECYCLE_BIN(4,"商品回收站");
  24 +
24 public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ProductSpuPageTabEnum::getType).toArray(); 25 public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ProductSpuPageTabEnum::getType).toArray();
25 /** 26 /**
26 * 状态 27 * 状态
@@ -35,4 +36,5 @@ public enum ProductSpuPageTabEnum implements IntArrayValuable { @@ -35,4 +36,5 @@ public enum ProductSpuPageTabEnum implements IntArrayValuable {
35 public int[] array() { 36 public int[] array() {
36 return ARRAYS; 37 return ARRAYS;
37 } 38 }
  39 +
38 } 40 }
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/ProductBrandController.java
@@ -61,7 +61,7 @@ public class ProductBrandController { @@ -61,7 +61,7 @@ public class ProductBrandController {
61 public CommonResult<ProductBrandRespVO> getBrand(@RequestParam("id") Long id) { 61 public CommonResult<ProductBrandRespVO> getBrand(@RequestParam("id") Long id) {
62 ProductBrandDO brand = brandService.getBrand(id); 62 ProductBrandDO brand = brandService.getBrand(id);
63 return success(ProductBrandConvert.INSTANCE.convert(brand)); 63 return success(ProductBrandConvert.INSTANCE.convert(brand));
64 - } 64 + } // TODO @puhui999:方法和方法之间,要有空行。
65 @GetMapping("/list-all-simple") 65 @GetMapping("/list-all-simple")
66 @Operation(summary = "获取品牌精简信息列表", description = "主要用于前端的下拉选项") 66 @Operation(summary = "获取品牌精简信息列表", description = "主要用于前端的下拉选项")
67 public CommonResult<List<ProductBrandSimpleRespVO>> getSimpleUserList() { 67 public CommonResult<List<ProductBrandSimpleRespVO>> getSimpleUserList() {
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/vo/ProductBrandSimpleRespVO.java
@@ -5,6 +5,7 @@ import lombok.AllArgsConstructor; @@ -5,6 +5,7 @@ import lombok.AllArgsConstructor;
5 import lombok.Data; 5 import lombok.Data;
6 import lombok.NoArgsConstructor; 6 import lombok.NoArgsConstructor;
7 7
  8 +// TODO @puhui999:class 类的开始和结束,都要有一个空行哈。
8 @Schema(description = "管理后台 - 品牌精简信息 Response VO") 9 @Schema(description = "管理后台 - 品牌精简信息 Response VO")
9 @Data 10 @Data
10 @NoArgsConstructor 11 @NoArgsConstructor
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuBaseVO.java
1 package cn.iocoder.yudao.module.product.controller.admin.sku.vo; 1 package cn.iocoder.yudao.module.product.controller.admin.sku.vo;
2 2
3 -import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO;  
4 -import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO;  
5 import io.swagger.v3.oas.annotations.media.Schema; 3 import io.swagger.v3.oas.annotations.media.Schema;
6 import lombok.AllArgsConstructor; 4 import lombok.AllArgsConstructor;
7 import lombok.Data; 5 import lombok.Data;
@@ -57,6 +55,7 @@ public class ProductSkuBaseVO { @@ -57,6 +55,7 @@ public class ProductSkuBaseVO {
57 @Schema(description = "二级分销的佣金,单位:分", example = "1024") 55 @Schema(description = "二级分销的佣金,单位:分", example = "1024")
58 private Integer subCommissionSecondPrice; 56 private Integer subCommissionSecondPrice;
59 57
  58 + // TODO @puhui999:这里要写 swagger 注解哈
60 /** 59 /**
61 * 商品属性 60 * 商品属性
62 */ 61 */
@@ -67,27 +66,19 @@ public class ProductSkuBaseVO { @@ -67,27 +66,19 @@ public class ProductSkuBaseVO {
67 66
68 /** 67 /**
69 * 属性编号 68 * 属性编号
70 - * 关联 {@link ProductPropertyDO#getId()}  
71 */ 69 */
72 private Long propertyId; 70 private Long propertyId;
73 /** 71 /**
74 * 属性名字 72 * 属性名字
75 - * 冗余 {@link ProductPropertyDO#getName()}  
76 - *  
77 - * 注意:每次属性名字发生变化时,需要更新该冗余  
78 */ 73 */
79 private String propertyName; 74 private String propertyName;
80 75
81 /** 76 /**
82 * 属性值编号 77 * 属性值编号
83 - * 关联 {@link ProductPropertyValueDO#getId()}  
84 */ 78 */
85 private Long valueId; 79 private Long valueId;
86 /** 80 /**
87 * 属性值名字 81 * 属性值名字
88 - * 冗余 {@link ProductPropertyValueDO#getName()}  
89 - *  
90 - * 注意:每次属性值名字发生变化时,需要更新该冗余  
91 */ 82 */
92 private String valueName; 83 private String valueName;
93 84
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuCreateOrUpdateReqVO.java
1 package cn.iocoder.yudao.module.product.controller.admin.sku.vo; 1 package cn.iocoder.yudao.module.product.controller.admin.sku.vo;
2 2
3 import io.swagger.v3.oas.annotations.media.Schema; 3 import io.swagger.v3.oas.annotations.media.Schema;
4 -import lombok.*; 4 +import lombok.Data;
  5 +import lombok.EqualsAndHashCode;
  6 +import lombok.ToString;
5 7
6 -import javax.validation.constraints.NotNull;  
7 import java.util.List; 8 import java.util.List;
8 9
9 @Schema(description = "管理后台 - 商品 SKU 创建/更新 Request VO") 10 @Schema(description = "管理后台 - 商品 SKU 创建/更新 Request VO")
@@ -12,6 +13,7 @@ import java.util.List; @@ -12,6 +13,7 @@ import java.util.List;
12 @ToString(callSuper = true) 13 @ToString(callSuper = true)
13 public class ProductSkuCreateOrUpdateReqVO extends ProductSkuBaseVO { 14 public class ProductSkuCreateOrUpdateReqVO extends ProductSkuBaseVO {
14 15
  16 + // TODO @puhui999:是不是可以抽到父类里?
15 /** 17 /**
16 * 属性数组 18 * 属性数组
17 */ 19 */
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.java
@@ -2,14 +2,11 @@ package cn.iocoder.yudao.module.product.controller.admin.spu; @@ -2,14 +2,11 @@ package cn.iocoder.yudao.module.product.controller.admin.spu;
2 2
3 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 3 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 import cn.iocoder.yudao.framework.common.pojo.PageResult; 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 -import cn.iocoder.yudao.framework.common.util.collection.MapUtils;  
6 import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; 5 import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
7 import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; 6 import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
8 import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*; 7 import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*;
9 import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert; 8 import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert;
10 import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; 9 import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
11 -import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService;  
12 -import cn.iocoder.yudao.module.product.service.sku.ProductSkuService;  
13 import cn.iocoder.yudao.module.product.service.spu.ProductSpuService; 10 import cn.iocoder.yudao.module.product.service.spu.ProductSpuService;
14 import io.swagger.v3.oas.annotations.Operation; 11 import io.swagger.v3.oas.annotations.Operation;
15 import io.swagger.v3.oas.annotations.Parameter; 12 import io.swagger.v3.oas.annotations.Parameter;
@@ -22,14 +19,10 @@ import javax.annotation.Resource; @@ -22,14 +19,10 @@ import javax.annotation.Resource;
22 import javax.servlet.http.HttpServletResponse; 19 import javax.servlet.http.HttpServletResponse;
23 import javax.validation.Valid; 20 import javax.validation.Valid;
24 import java.io.IOException; 21 import java.io.IOException;
25 -import java.util.ArrayList;  
26 -import java.util.Collection;  
27 import java.util.List; 22 import java.util.List;
28 import java.util.Map; 23 import java.util.Map;
29 24
30 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 25 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
31 -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;  
32 -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;  
33 import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; 26 import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
34 27
35 /** 28 /**
@@ -101,7 +94,7 @@ public class ProductSpuController { @@ -101,7 +94,7 @@ public class ProductSpuController {
101 return success(ProductSpuConvert.INSTANCE.convertPage(productSpuService.getSpuPage(pageVO))); 94 return success(ProductSpuConvert.INSTANCE.convertPage(productSpuService.getSpuPage(pageVO)));
102 } 95 }
103 96
104 - // TODO @tuihui999:get-count;另外,url 使用 - 拆分 fix 97 + // TODO @puhui999:方法名改成 getSpuCount,只是用于 tab 哈,这样更抽象一点。
105 @GetMapping("/get-count") 98 @GetMapping("/get-count")
106 @Operation(summary = "获得商品 SPU 分页 tab count") 99 @Operation(summary = "获得商品 SPU 分页 tab count")
107 @PreAuthorize("@ss.hasPermission('product:spu:query')") 100 @PreAuthorize("@ss.hasPermission('product:spu:query')")
@@ -110,7 +103,7 @@ public class ProductSpuController { @@ -110,7 +103,7 @@ public class ProductSpuController {
110 } 103 }
111 104
112 @GetMapping("/export") 105 @GetMapping("/export")
113 - @Operation(summary = "导出用户") 106 + @Operation(summary = "导出商品")
114 @PreAuthorize("@ss.hasPermission('product:spu:export')") 107 @PreAuthorize("@ss.hasPermission('product:spu:export')")
115 @OperateLog(type = EXPORT) 108 @OperateLog(type = EXPORT)
116 public void exportUserList(@Validated ProductSpuExportReqVO reqVO, 109 public void exportUserList(@Validated ProductSpuExportReqVO reqVO,
@@ -118,6 +111,7 @@ public class ProductSpuController { @@ -118,6 +111,7 @@ public class ProductSpuController {
118 List<ProductSpuDO> spuList = productSpuService.getSpuList(reqVO); 111 List<ProductSpuDO> spuList = productSpuService.getSpuList(reqVO);
119 // 导出 Excel 112 // 导出 Excel
120 List<ProductSpuExcelVO> datas = ProductSpuConvert.INSTANCE.convertList03(spuList); 113 List<ProductSpuExcelVO> datas = ProductSpuConvert.INSTANCE.convertList03(spuList);
121 - ExcelUtils.write(response, "商品spu.xls", "数据", ProductSpuExcelVO.class, datas); 114 + ExcelUtils.write(response, "商品列表.xls", "数据", ProductSpuExcelVO.class, datas);
122 } 115 }
  116 +
123 } 117 }
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuBaseVO.java
1 package cn.iocoder.yudao.module.product.controller.admin.spu.vo; 1 package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
2 2
3 -import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;  
4 import io.swagger.v3.oas.annotations.media.Schema; 3 import io.swagger.v3.oas.annotations.media.Schema;
5 import lombok.Data; 4 import lombok.Data;
6 5
@@ -97,14 +96,14 @@ public class ProductSpuBaseVO { @@ -97,14 +96,14 @@ public class ProductSpuBaseVO {
97 @NotNull(message = "商品赠送积分不能为空") 96 @NotNull(message = "商品赠送积分不能为空")
98 private Integer giveIntegral; 97 private Integer giveIntegral;
99 98
100 - @Schema(description = "赠送的优惠劵编号的数组") // TODO 这块前端还未实现 99 + @Schema(description = "赠送的优惠劵编号的数组", example = "[1, 10]") // TODO 这块前端还未实现
101 private List<Long> giveCouponTemplateIds; 100 private List<Long> giveCouponTemplateIds;
102 101
103 - @Schema(description = "分销类型", example = "true") 102 + @Schema(description = "分销类型", required = true, example = "true")
104 @NotNull(message = "商品分销类型不能为空") 103 @NotNull(message = "商品分销类型不能为空")
105 private Boolean subCommissionType; 104 private Boolean subCommissionType;
106 105
107 - @Schema(description = "活动展示顺序", example = "[1、3、2、4、5]") // TODO 这块前端还未实现 106 + @Schema(description = "活动展示顺序", example = "[1, 3, 2, 4, 5]") // TODO 这块前端还未实现
108 private List<Integer> activityOrders; 107 private List<Integer> activityOrders;
109 108
110 // ========== 统计相关字段 ========= 109 // ========== 统计相关字段 =========
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuDetailRespVO.java
@@ -6,7 +6,6 @@ import lombok.Data; @@ -6,7 +6,6 @@ import lombok.Data;
6 import lombok.EqualsAndHashCode; 6 import lombok.EqualsAndHashCode;
7 import lombok.ToString; 7 import lombok.ToString;
8 8
9 -import java.time.LocalDateTime;  
10 import java.util.List; 9 import java.util.List;
11 10
12 /** 11 /**
@@ -21,7 +20,9 @@ import java.util.List; @@ -21,7 +20,9 @@ import java.util.List;
21 @ToString(callSuper = true) 20 @ToString(callSuper = true)
22 public class ProductSpuDetailRespVO extends ProductSpuBaseVO { 21 public class ProductSpuDetailRespVO extends ProductSpuBaseVO {
23 22
24 - @Schema(description = "spuId") 23 + // TODO @puhui999:swagger 的 required 和 example 写下
  24 +
  25 + @Schema(description = "商品 SPU 编号")
25 private Long id; 26 private Long id;
26 27
27 @Schema(description = "商品销量") 28 @Schema(description = "商品销量")
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuExportReqVO.java
@@ -11,11 +11,13 @@ import org.springframework.format.annotation.DateTimeFormat; @@ -11,11 +11,13 @@ import org.springframework.format.annotation.DateTimeFormat;
11 import java.time.LocalDateTime; 11 import java.time.LocalDateTime;
12 12
13 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; 13 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
  14 +
14 @Schema(description = "管理后台 - 商品Spu导出 Request VO,参数和 ProductSpuPageReqVO 是一致的") 15 @Schema(description = "管理后台 - 商品Spu导出 Request VO,参数和 ProductSpuPageReqVO 是一致的")
15 @Data 16 @Data
16 @NoArgsConstructor 17 @NoArgsConstructor
17 @AllArgsConstructor 18 @AllArgsConstructor
18 public class ProductSpuExportReqVO { 19 public class ProductSpuExportReqVO {
  20 +
19 @Schema(description = "商品名称", example = "yutou") 21 @Schema(description = "商品名称", example = "yutou")
20 private String name; 22 private String name;
21 23
@@ -29,4 +31,5 @@ public class ProductSpuExportReqVO { @@ -29,4 +31,5 @@ public class ProductSpuExportReqVO {
29 @Schema(description = "创建时间", example = "[2022-07-01 00:00:00,2022-07-01 23:59:59]") 31 @Schema(description = "创建时间", example = "[2022-07-01 00:00:00,2022-07-01 23:59:59]")
30 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) 32 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
31 private LocalDateTime[] createTime; 33 private LocalDateTime[] createTime;
  34 +
32 } 35 }
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuRespVO.java
1 package cn.iocoder.yudao.module.product.controller.admin.spu.vo; 1 package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
2 2
3 -import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;  
4 import io.swagger.v3.oas.annotations.media.Schema; 3 import io.swagger.v3.oas.annotations.media.Schema;
5 import lombok.Data; 4 import lombok.Data;
6 import lombok.EqualsAndHashCode; 5 import lombok.EqualsAndHashCode;
@@ -19,6 +18,8 @@ import java.time.LocalDateTime; @@ -19,6 +18,8 @@ import java.time.LocalDateTime;
19 @ToString(callSuper = true) 18 @ToString(callSuper = true)
20 public class ProductSpuRespVO extends ProductSpuBaseVO { 19 public class ProductSpuRespVO extends ProductSpuBaseVO {
21 20
  21 + // TODO @puhui999:swagger 的 required 和 example 写下
  22 +
22 @Schema(description = "spuId") 23 @Schema(description = "spuId")
23 private Long id; 24 private Long id;
24 25
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuSimpleRespVO.java
1 package cn.iocoder.yudao.module.product.controller.admin.spu.vo; 1 package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
2 2
3 -import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;  
4 import io.swagger.v3.oas.annotations.media.Schema; 3 import io.swagger.v3.oas.annotations.media.Schema;
5 import lombok.Data; 4 import lombok.Data;
6 -import lombok.EqualsAndHashCode;  
7 import lombok.ToString; 5 import lombok.ToString;
8 6
9 /** 7 /**
@@ -16,6 +14,8 @@ import lombok.ToString; @@ -16,6 +14,8 @@ import lombok.ToString;
16 @ToString(callSuper = true) 14 @ToString(callSuper = true)
17 public class ProductSpuSimpleRespVO { 15 public class ProductSpuSimpleRespVO {
18 16
  17 + // TODO @puhui999:swagger 的 required 和 example 写下
  18 +
19 @Schema(description = "主键") 19 @Schema(description = "主键")
20 private Long id; 20 private Long id;
21 21
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuUpdateReqVO.java
@@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.product.controller.admin.spu.vo; @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
2 2
3 import cn.iocoder.yudao.framework.common.validation.InEnum; 3 import cn.iocoder.yudao.framework.common.validation.InEnum;
4 import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO; 4 import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO;
5 -import cn.iocoder.yudao.module.product.enums.spu.ProductSpuPageTabEnum;  
6 import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum; 5 import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;
7 import io.swagger.v3.oas.annotations.media.Schema; 6 import io.swagger.v3.oas.annotations.media.Schema;
8 import lombok.Data; 7 import lombok.Data;
@@ -11,7 +10,6 @@ import lombok.ToString; @@ -11,7 +10,6 @@ import lombok.ToString;
11 10
12 import javax.validation.Valid; 11 import javax.validation.Valid;
13 import javax.validation.constraints.NotNull; 12 import javax.validation.constraints.NotNull;
14 -import java.time.LocalDateTime;  
15 import java.util.List; 13 import java.util.List;
16 14
17 /** 15 /**
@@ -25,6 +23,8 @@ import java.util.List; @@ -25,6 +23,8 @@ import java.util.List;
25 @ToString(callSuper = true) 23 @ToString(callSuper = true)
26 public class ProductSpuUpdateReqVO extends ProductSpuBaseVO { 24 public class ProductSpuUpdateReqVO extends ProductSpuBaseVO {
27 25
  26 + // TODO @puhui999:swagger 的 required 和 example 写下
  27 +
28 @Schema(description = "商品编号", required = true, example = "1") 28 @Schema(description = "商品编号", required = true, example = "1")
29 @NotNull(message = "商品编号不能为空") 29 @NotNull(message = "商品编号不能为空")
30 private Long id; 30 private Long id;
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/brand/ProductBrandConvert.java
@@ -26,7 +26,9 @@ public interface ProductBrandConvert { @@ -26,7 +26,9 @@ public interface ProductBrandConvert {
26 ProductBrandDO convert(ProductBrandUpdateReqVO bean); 26 ProductBrandDO convert(ProductBrandUpdateReqVO bean);
27 27
28 ProductBrandRespVO convert(ProductBrandDO bean); 28 ProductBrandRespVO convert(ProductBrandDO bean);
  29 +
29 List<ProductBrandSimpleRespVO> convertList1(List<ProductBrandDO> list); 30 List<ProductBrandSimpleRespVO> convertList1(List<ProductBrandDO> list);
  31 +
30 List<ProductBrandRespVO> convertList(List<ProductBrandDO> list); 32 List<ProductBrandRespVO> convertList(List<ProductBrandDO> list);
31 33
32 PageResult<ProductBrandRespVO> convertPage(PageResult<ProductBrandDO> page); 34 PageResult<ProductBrandRespVO> convertPage(PageResult<ProductBrandDO> page);
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java
1 package cn.iocoder.yudao.module.product.convert.spu; 1 package cn.iocoder.yudao.module.product.convert.spu;
2 -import java.time.LocalDateTime;  
3 2
4 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
5 import cn.hutool.core.util.StrUtil; 4 import cn.hutool.core.util.StrUtil;
@@ -10,8 +9,8 @@ import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuRespVO; @@ -10,8 +9,8 @@ import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuRespVO;
10 import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*; 9 import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*;
11 import cn.iocoder.yudao.module.product.controller.app.property.vo.value.AppProductPropertyValueDetailRespVO; 10 import cn.iocoder.yudao.module.product.controller.app.property.vo.value.AppProductPropertyValueDetailRespVO;
12 import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuDetailRespVO; 11 import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuDetailRespVO;
13 -import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO;  
14 import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageItemRespVO; 12 import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageItemRespVO;
  13 +import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO;
15 import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert; 14 import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert;
16 import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; 15 import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
17 import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; 16 import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
@@ -52,6 +51,8 @@ public interface ProductSpuConvert { @@ -52,6 +51,8 @@ public interface ProductSpuConvert {
52 List<ProductSpuRespDTO> convertList2(List<ProductSpuDO> list); 51 List<ProductSpuRespDTO> convertList2(List<ProductSpuDO> list);
53 52
54 List<ProductSpuSimpleRespVO> convertList02(List<ProductSpuDO> list); 53 List<ProductSpuSimpleRespVO> convertList02(List<ProductSpuDO> list);
  54 +
  55 + // TODO @puhui999:部分属性,可以通过 mapstruct 的 @Mapping(source = , target = , ) 映射转换,可以查下文档
55 default List<ProductSpuExcelVO> convertList03(List<ProductSpuDO> list){ 56 default List<ProductSpuExcelVO> convertList03(List<ProductSpuDO> list){
56 ArrayList<ProductSpuExcelVO> spuExcelVOs = new ArrayList<>(); 57 ArrayList<ProductSpuExcelVO> spuExcelVOs = new ArrayList<>();
57 list.forEach((spu)->{ 58 list.forEach((spu)->{
@@ -95,6 +96,7 @@ public interface ProductSpuConvert { @@ -95,6 +96,7 @@ public interface ProductSpuConvert {
95 } 96 }
96 ProductSpuDetailRespVO convert03(ProductSpuDO spu); 97 ProductSpuDetailRespVO convert03(ProductSpuDO spu);
97 98
  99 + // TODO @puhui999:下面两个没用到,是不是删除呀?
98 List<ProductSkuRespVO> convertList04(List<ProductSkuDO> skus); 100 List<ProductSkuRespVO> convertList04(List<ProductSkuDO> skus);
99 101
100 ProductPropertyValueDetailRespVO convert04(ProductPropertyValueDetailRespBO propertyValue); 102 ProductPropertyValueDetailRespVO convert04(ProductPropertyValueDetailRespBO propertyValue);
@@ -142,11 +144,13 @@ public interface ProductSpuConvert { @@ -142,11 +144,13 @@ public interface ProductSpuConvert {
142 144
143 AppProductPropertyValueDetailRespVO convertForGetSpuDetail(ProductPropertyValueDetailRespBO propertyValue); 145 AppProductPropertyValueDetailRespVO convertForGetSpuDetail(ProductPropertyValueDetailRespBO propertyValue);
144 146
145 - default ProductSpuDetailRespVO convertForSpuDetailRespVO(ProductSpuDO spu, List<ProductSkuDO> skus, Function<Set<Long>, List<ProductPropertyValueDetailRespBO>> func) { 147 + default ProductSpuDetailRespVO convertForSpuDetailRespVO(ProductSpuDO spu, List<ProductSkuDO> skus,
  148 + Function<Set<Long>, List<ProductPropertyValueDetailRespBO>> func) {
146 ProductSpuDetailRespVO productSpuDetailRespVO = convert03(spu); 149 ProductSpuDetailRespVO productSpuDetailRespVO = convert03(spu);
  150 + // TODO @puhui999:if return 哈,减少嵌套层数。
147 if (CollUtil.isNotEmpty(skus)) { 151 if (CollUtil.isNotEmpty(skus)) {
148 List<ProductSkuRespVO> skuVOs = ProductSkuConvert.INSTANCE.convertList(skus); 152 List<ProductSkuRespVO> skuVOs = ProductSkuConvert.INSTANCE.convertList(skus);
149 - // fix:统一模型,即使是单规格,也查询下,如若Properties为空报错则为单属性不做处理 153 + // fix:统一模型,即使是单规格,也查询下,如若 Properties 为空报错则为单属性不做处理
150 try { 154 try {
151 // 获取所有的属性值 id 155 // 获取所有的属性值 id
152 Set<Long> valueIds = skus.stream().flatMap(p -> p.getProperties().stream()) 156 Set<Long> valueIds = skus.stream().flatMap(p -> p.getProperties().stream())
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/brand/ProductBrandMapper.java
@@ -31,6 +31,7 @@ public interface ProductBrandMapper extends BaseMapperX&lt;ProductBrandDO&gt; { @@ -31,6 +31,7 @@ public interface ProductBrandMapper extends BaseMapperX&lt;ProductBrandDO&gt; {
31 return selectOne(ProductBrandDO::getName, name); 31 return selectOne(ProductBrandDO::getName, name);
32 } 32 }
33 33
  34 + // TODO @puhui999:) { 中间要有空格哈。
34 default List<ProductBrandDO> selectListByStatus(Integer status){ 35 default List<ProductBrandDO> selectListByStatus(Integer status){
35 return selectList(ProductBrandDO::getStatus,status); 36 return selectList(ProductBrandDO::getStatus,status);
36 } 37 }
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/spu/ProductSpuMapper.java
@@ -10,13 +10,10 @@ import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuPageReq @@ -10,13 +10,10 @@ import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuPageReq
10 import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO; 10 import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO;
11 import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; 11 import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
12 import cn.iocoder.yudao.module.product.enums.ProductConstants; 12 import cn.iocoder.yudao.module.product.enums.ProductConstants;
13 -import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;  
14 import cn.iocoder.yudao.module.product.enums.spu.ProductSpuPageTabEnum; 13 import cn.iocoder.yudao.module.product.enums.spu.ProductSpuPageTabEnum;
15 -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 14 +import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;
16 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; 15 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
17 -import com.baomidou.mybatisplus.core.toolkit.support.SFunction;  
18 import org.apache.ibatis.annotations.Mapper; 16 import org.apache.ibatis.annotations.Mapper;
19 -import org.apache.poi.ss.formula.functions.T;  
20 17
21 import java.util.List; 18 import java.util.List;
22 import java.util.Objects; 19 import java.util.Objects;
@@ -26,7 +23,7 @@ import java.util.Set; @@ -26,7 +23,7 @@ import java.util.Set;
26 public interface ProductSpuMapper extends BaseMapperX<ProductSpuDO> { 23 public interface ProductSpuMapper extends BaseMapperX<ProductSpuDO> {
27 24
28 /** 25 /**
29 - * 获取 商品 SPU 分页列表数据 26 + * 获取商品 SPU 分页列表数据
30 * 27 *
31 * @param reqVO 分页请求参数 28 * @param reqVO 分页请求参数
32 * @return 商品 SPU 分页列表数据 29 * @return 商品 SPU 分页列表数据
@@ -43,11 +40,14 @@ public interface ProductSpuMapper extends BaseMapperX&lt;ProductSpuDO&gt; { @@ -43,11 +40,14 @@ public interface ProductSpuMapper extends BaseMapperX&lt;ProductSpuDO&gt; {
43 } 40 }
44 41
45 /** 42 /**
46 - * 获取库存小于value且状态不等于status的的个数 43 + * 获取库存小于 value ,且状态不等于 status 的的个数
  44 + *
  45 + * @return 个数
47 */ 46 */
48 default Long selectCountByStockAndStatus() { 47 default Long selectCountByStockAndStatus() {
49 LambdaQueryWrapperX<ProductSpuDO> queryWrapper = new LambdaQueryWrapperX<>(); 48 LambdaQueryWrapperX<ProductSpuDO> queryWrapper = new LambdaQueryWrapperX<>();
50 queryWrapper.le(ProductSpuDO::getStock, ProductConstants.ALERT_STOCK) 49 queryWrapper.le(ProductSpuDO::getStock, ProductConstants.ALERT_STOCK)
  50 + // TODO @puhui999:IN 另外两个状态,会不会好点哈。尽量不用 !=
51 // 如果库存触发警戒库存且状态为回收站的话则不计入触发警戒库存的个数 51 // 如果库存触发警戒库存且状态为回收站的话则不计入触发警戒库存的个数
52 .and(q -> q.ne(ProductSpuDO::getStatus, ProductSpuStatusEnum.RECYCLE.getStatus())); 52 .and(q -> q.ne(ProductSpuDO::getStatus, ProductSpuStatusEnum.RECYCLE.getStatus()));
53 return selectCount(queryWrapper); 53 return selectCount(queryWrapper);
@@ -111,6 +111,7 @@ public interface ProductSpuMapper extends BaseMapperX&lt;ProductSpuDO&gt; { @@ -111,6 +111,7 @@ public interface ProductSpuMapper extends BaseMapperX&lt;ProductSpuDO&gt; {
111 return selectList(queryWrapper); 111 return selectList(queryWrapper);
112 } 112 }
113 113
  114 + // TODO @puhui999:应该不太适合 validate 验证,应该是补充条件,例如说 appendTabQuery
114 /** 115 /**
115 * 验证选项卡类型构建条件 116 * 验证选项卡类型构建条件
116 * 117 *
@@ -118,8 +119,8 @@ public interface ProductSpuMapper extends BaseMapperX&lt;ProductSpuDO&gt; { @@ -118,8 +119,8 @@ public interface ProductSpuMapper extends BaseMapperX&lt;ProductSpuDO&gt; {
118 * @param queryWrapper 查询条件 119 * @param queryWrapper 查询条件
119 */ 120 */
120 static void validateTabType(Integer tabType, LambdaQueryWrapperX<ProductSpuDO> queryWrapper) { 121 static void validateTabType(Integer tabType, LambdaQueryWrapperX<ProductSpuDO> queryWrapper) {
  122 + // 出售中商品 TODO puhui999:这样好点
121 if (ObjectUtil.equals(ProductSpuPageTabEnum.FOR_SALE.getType(), tabType)) { 123 if (ObjectUtil.equals(ProductSpuPageTabEnum.FOR_SALE.getType(), tabType)) {
122 - // 出售中商品  
123 queryWrapper.eqIfPresent(ProductSpuDO::getStatus, ProductSpuStatusEnum.ENABLE.getStatus()); 124 queryWrapper.eqIfPresent(ProductSpuDO::getStatus, ProductSpuStatusEnum.ENABLE.getStatus());
124 } 125 }
125 if (ObjectUtil.equals(ProductSpuPageTabEnum.IN_WAREHOUSE.getType(), tabType)) { 126 if (ObjectUtil.equals(ProductSpuPageTabEnum.IN_WAREHOUSE.getType(), tabType)) {
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImpl.java
@@ -111,6 +111,7 @@ public class ProductCategoryServiceImpl implements ProductCategoryService { @@ -111,6 +111,7 @@ public class ProductCategoryServiceImpl implements ProductCategoryService {
111 if (Objects.equals(id, ProductConstants.PARENT_ID_NULL)) { 111 if (Objects.equals(id, ProductConstants.PARENT_ID_NULL)) {
112 return 0; 112 return 0;
113 } 113 }
  114 + // TODO @puhui999:for 的原因,是因为避免脏数据,导致可能的死循环。一般不会超过 100 层哈
114 int level = 1; 115 int level = 1;
115 // fix: 循环次数不确定改为while循环 116 // fix: 循环次数不确定改为while循环
116 while (true){ 117 while (true){
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java
1 package cn.iocoder.yudao.module.product.service.spu; 1 package cn.iocoder.yudao.module.product.service.spu;
2 2
3 -import cn.hutool.core.collection.CollUtil;  
4 import cn.hutool.core.util.ObjectUtil; 3 import cn.hutool.core.util.ObjectUtil;
5 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 4 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
6 import cn.iocoder.yudao.framework.common.pojo.PageResult; 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
7 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; 6 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
8 -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;  
9 import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryListReqVO; 7 import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryListReqVO;
10 import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO; 8 import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO;
11 -import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuRespVO;  
12 import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*; 9 import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*;
13 import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO; 10 import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO;
14 -import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert;  
15 import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert; 11 import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert;
16 import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO; 12 import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO;
17 import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; 13 import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
18 import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; 14 import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
19 import cn.iocoder.yudao.module.product.dal.mysql.spu.ProductSpuMapper; 15 import cn.iocoder.yudao.module.product.dal.mysql.spu.ProductSpuMapper;
20 import cn.iocoder.yudao.module.product.enums.ProductConstants; 16 import cn.iocoder.yudao.module.product.enums.ProductConstants;
21 -import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;  
22 import cn.iocoder.yudao.module.product.enums.spu.ProductSpuPageTabEnum; 17 import cn.iocoder.yudao.module.product.enums.spu.ProductSpuPageTabEnum;
  18 +import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;
23 import cn.iocoder.yudao.module.product.service.brand.ProductBrandService; 19 import cn.iocoder.yudao.module.product.service.brand.ProductBrandService;
24 import cn.iocoder.yudao.module.product.service.category.ProductCategoryService; 20 import cn.iocoder.yudao.module.product.service.category.ProductCategoryService;
25 import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService; 21 import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService;
26 -import cn.iocoder.yudao.module.product.service.property.bo.ProductPropertyValueDetailRespBO;  
27 import cn.iocoder.yudao.module.product.service.sku.ProductSkuService; 22 import cn.iocoder.yudao.module.product.service.sku.ProductSkuService;
28 import org.springframework.context.annotation.Lazy; 23 import org.springframework.context.annotation.Lazy;
29 import org.springframework.stereotype.Service; 24 import org.springframework.stereotype.Service;
@@ -32,7 +27,6 @@ import org.springframework.validation.annotation.Validated; @@ -32,7 +27,6 @@ import org.springframework.validation.annotation.Validated;
32 27
33 import javax.annotation.Resource; 28 import javax.annotation.Resource;
34 import java.util.*; 29 import java.util.*;
35 -import java.util.stream.Collectors;  
36 30
37 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 31 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
38 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.getSumValue; 32 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.getSumValue;
@@ -63,11 +57,11 @@ public class ProductSpuServiceImpl implements ProductSpuService { @@ -63,11 +57,11 @@ public class ProductSpuServiceImpl implements ProductSpuService {
63 @Override 57 @Override
64 @Transactional(rollbackFor = Exception.class) 58 @Transactional(rollbackFor = Exception.class)
65 public Long createSpu(ProductSpuCreateReqVO createReqVO) { 59 public Long createSpu(ProductSpuCreateReqVO createReqVO) {
66 - // 校验分类 TODO puhui999:暂不清楚为什么只能选择第三层的结点;芋艿:改成二级分类,因为商品只能放在叶子节点级别;fix 60 + // 校验分类、品牌
67 validateCategory(createReqVO.getCategoryId()); 61 validateCategory(createReqVO.getCategoryId());
68 brandService.validateProductBrand(createReqVO.getBrandId()); 62 brandService.validateProductBrand(createReqVO.getBrandId());
69 - List<ProductSkuCreateOrUpdateReqVO> skuSaveReqList = createReqVO.getSkus();  
70 // 校验 SKU 63 // 校验 SKU
  64 + List<ProductSkuCreateOrUpdateReqVO> skuSaveReqList = createReqVO.getSkus();
71 productSkuService.validateSkuList(skuSaveReqList, createReqVO.getSpecType()); 65 productSkuService.validateSkuList(skuSaveReqList, createReqVO.getSpecType());
72 ProductSpuDO spu = ProductSpuConvert.INSTANCE.convert(createReqVO); 66 ProductSpuDO spu = ProductSpuConvert.INSTANCE.convert(createReqVO);
73 // 初始化 SPU 中 SKU 相关属性 67 // 初始化 SPU 中 SKU 相关属性
@@ -86,13 +80,13 @@ public class ProductSpuServiceImpl implements ProductSpuService { @@ -86,13 +80,13 @@ public class ProductSpuServiceImpl implements ProductSpuService {
86 public void updateSpu(ProductSpuUpdateReqVO updateReqVO) { 80 public void updateSpu(ProductSpuUpdateReqVO updateReqVO) {
87 // 校验 SPU 是否存在 81 // 校验 SPU 是否存在
88 validateSpuExists(updateReqVO.getId()); 82 validateSpuExists(updateReqVO.getId());
89 - // 校验分类 83 + // 校验分类、品牌
90 validateCategory(updateReqVO.getCategoryId()); 84 validateCategory(updateReqVO.getCategoryId());
91 - // 校验品牌  
92 brandService.validateProductBrand(updateReqVO.getBrandId()); 85 brandService.validateProductBrand(updateReqVO.getBrandId());
93 // 校验SKU 86 // 校验SKU
94 List<ProductSkuCreateOrUpdateReqVO> skuSaveReqList = updateReqVO.getSkus(); 87 List<ProductSkuCreateOrUpdateReqVO> skuSaveReqList = updateReqVO.getSkus();
95 productSkuService.validateSkuList(skuSaveReqList, updateReqVO.getSpecType()); 88 productSkuService.validateSkuList(skuSaveReqList, updateReqVO.getSpecType());
  89 + // TODO @puhui999:可以校验逻辑,和更新逻辑,中间有个空行,这样会发现,哟 这里到了关键逻辑啦,更有层次感
96 // 更新 SPU 90 // 更新 SPU
97 ProductSpuDO updateObj = ProductSpuConvert.INSTANCE.convert(updateReqVO); 91 ProductSpuDO updateObj = ProductSpuConvert.INSTANCE.convert(updateReqVO);
98 initSpuFromSkus(updateObj, skuSaveReqList); 92 initSpuFromSkus(updateObj, skuSaveReqList);
@@ -111,17 +105,19 @@ public class ProductSpuServiceImpl implements ProductSpuService { @@ -111,17 +105,19 @@ public class ProductSpuServiceImpl implements ProductSpuService {
111 private void initSpuFromSkus(ProductSpuDO spu, List<ProductSkuCreateOrUpdateReqVO> skus) { 105 private void initSpuFromSkus(ProductSpuDO spu, List<ProductSkuCreateOrUpdateReqVO> skus) {
112 // 断言,避免告警 106 // 断言,避免告警
113 assert skus.size() > 0; 107 assert skus.size() > 0;
114 - // 获取sku单价最低的商品 108 + // 获取 sku 单价最低的商品
  109 + // TODO @puhui999:vo 改成 sku 会更好。vo dto 只是我们用来区分的,如果能区分的情况下,用更明确的名字会更好。
  110 +// CollectionUtils.getMinValue(); TODO @puhui999:可以用这个方法,常见的 stream 操作,封装成方法,让逻辑更简洁
115 ProductSkuCreateOrUpdateReqVO vo = skus.stream().min(Comparator.comparing(ProductSkuCreateOrUpdateReqVO::getPrice)).get(); 111 ProductSkuCreateOrUpdateReqVO vo = skus.stream().min(Comparator.comparing(ProductSkuCreateOrUpdateReqVO::getPrice)).get();
116 - // sku单价最低的商品的价格 112 + // sku 单价最低的商品的价格
117 spu.setPrice(vo.getPrice()); 113 spu.setPrice(vo.getPrice());
118 - // sku单价最低的商品的市场价格 114 + // sku 单价最低的商品的市场价格
119 spu.setMarketPrice(vo.getMarketPrice()); 115 spu.setMarketPrice(vo.getMarketPrice());
120 // sku单价最低的商品的成本价格 116 // sku单价最低的商品的成本价格
121 spu.setCostPrice(vo.getCostPrice()); 117 spu.setCostPrice(vo.getCostPrice());
122 // sku单价最低的商品的条形码 118 // sku单价最低的商品的条形码
123 spu.setBarCode(vo.getBarCode()); 119 spu.setBarCode(vo.getBarCode());
124 - // skus库存总数 120 + // skus 库存总数
125 spu.setStock(getSumValue(skus, ProductSkuCreateOrUpdateReqVO::getStock, Integer::sum)); 121 spu.setStock(getSumValue(skus, ProductSkuCreateOrUpdateReqVO::getStock, Integer::sum));
126 // 若是 spu 已有状态则不处理 122 // 若是 spu 已有状态则不处理
127 if (spu.getStatus() == null) { 123 if (spu.getStatus() == null) {
@@ -233,6 +229,7 @@ public class ProductSpuServiceImpl implements ProductSpuService { @@ -233,6 +229,7 @@ public class ProductSpuServiceImpl implements ProductSpuService {
233 } 229 }
234 // 查询商品 SKU 230 // 查询商品 SKU
235 List<ProductSkuDO> skus = productSkuService.getSkuListBySpuId(spu.getId()); 231 List<ProductSkuDO> skus = productSkuService.getSkuListBySpuId(spu.getId());
  232 + // TODO @puhui999:感觉还是查询好 productPropertyValueService,然后 propertyId 可以交给 convert 处理下即可。
236 return ProductSpuConvert.INSTANCE.convertForSpuDetailRespVO(spu, skus, productPropertyValueService::getPropertyValueDetailList); 233 return ProductSpuConvert.INSTANCE.convertForSpuDetailRespVO(spu, skus, productPropertyValueService::getPropertyValueDetailList);
237 } 234 }
238 235
@@ -249,7 +246,6 @@ public class ProductSpuServiceImpl implements ProductSpuService { @@ -249,7 +246,6 @@ public class ProductSpuServiceImpl implements ProductSpuService {
249 246
250 @Override 247 @Override
251 public Map<Integer, Long> getTabsCount() { 248 public Map<Integer, Long> getTabsCount() {
252 - // TODO @puhui999:map =》;尽量避免出现 map 这种命名,无命名含义哈 fix  
253 Map<Integer, Long> counts = new HashMap<>(ProductConstants.SPU_TAB_COUNTS); 249 Map<Integer, Long> counts = new HashMap<>(ProductConstants.SPU_TAB_COUNTS);
254 // 查询销售中的商品数量 250 // 查询销售中的商品数量
255 counts.put(ProductSpuPageTabEnum.FOR_SALE.getType(), productSpuMapper.selectCount(ProductSpuDO::getStatus, ProductSpuStatusEnum.ENABLE.getStatus())); 251 counts.put(ProductSpuPageTabEnum.FOR_SALE.getType(), productSpuMapper.selectCount(ProductSpuDO::getStatus, ProductSpuStatusEnum.ENABLE.getStatus()));
@@ -258,8 +254,6 @@ public class ProductSpuServiceImpl implements ProductSpuService { @@ -258,8 +254,6 @@ public class ProductSpuServiceImpl implements ProductSpuService {
258 // 查询售空的商品数量 254 // 查询售空的商品数量
259 counts.put(ProductSpuPageTabEnum.SOLD_OUT.getType(), productSpuMapper.selectCount(ProductSpuDO::getStock, 0)); 255 counts.put(ProductSpuPageTabEnum.SOLD_OUT.getType(), productSpuMapper.selectCount(ProductSpuDO::getStock, 0));
260 // 查询触发警戒库存的商品数量 256 // 查询触发警戒库存的商品数量
261 - // TODO @puhui999:要有空格;, productSpuMapper fix  
262 - // TODO @puhui999:Service 不要有 Mapper 的逻辑;想想咋抽象一下哈 fix:调整为在 productSpuMapper 中书写逻辑  
263 counts.put(ProductSpuPageTabEnum.ALERT_STOCK.getType(), productSpuMapper.selectCountByStockAndStatus()); 257 counts.put(ProductSpuPageTabEnum.ALERT_STOCK.getType(), productSpuMapper.selectCountByStockAndStatus());
264 // 查询回收站中的商品数量 258 // 查询回收站中的商品数量
265 counts.put(ProductSpuPageTabEnum.RECYCLE_BIN.getType(), productSpuMapper.selectCount(ProductSpuDO::getStatus, ProductSpuStatusEnum.RECYCLE.getStatus())); 259 counts.put(ProductSpuPageTabEnum.RECYCLE_BIN.getType(), productSpuMapper.selectCount(ProductSpuDO::getStatus, ProductSpuStatusEnum.RECYCLE.getStatus()));
yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImplTest.java
@@ -40,10 +40,7 @@ public class ProductCategoryServiceImplTest extends BaseDbUnitTest { @@ -40,10 +40,7 @@ public class ProductCategoryServiceImplTest extends BaseDbUnitTest {
40 @Test 40 @Test
41 public void testCreateCategory_success() { 41 public void testCreateCategory_success() {
42 // 准备参数 42 // 准备参数
43 - ProductCategoryCreateReqVO reqVO = randomPojo(ProductCategoryCreateReqVO.class,o -> {  
44 - // 设置PC端图片可为空 TODO 数据库没有这个字段  
45 - //o.setBigPicUrl(null);  
46 - }); 43 + ProductCategoryCreateReqVO reqVO = randomPojo(ProductCategoryCreateReqVO.class);
47 44
48 // mock 父类 45 // mock 父类
49 ProductCategoryDO parentProductCategory = randomPojo(ProductCategoryDO.class, o -> { 46 ProductCategoryDO parentProductCategory = randomPojo(ProductCategoryDO.class, o -> {
yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceTest.java
1 package cn.iocoder.yudao.module.product.service.sku; 1 package cn.iocoder.yudao.module.product.service.sku;
2 2
3 import cn.hutool.core.util.RandomUtil; 3 import cn.hutool.core.util.RandomUtil;
4 -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;  
5 import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; 4 import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
6 import cn.iocoder.yudao.framework.test.core.util.AssertUtils; 5 import cn.iocoder.yudao.framework.test.core.util.AssertUtils;
7 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO; 6 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO;
@@ -50,6 +49,7 @@ public class ProductSkuServiceTest extends BaseDbUnitTest { @@ -50,6 +49,7 @@ public class ProductSkuServiceTest extends BaseDbUnitTest {
50 @MockBean 49 @MockBean
51 private ProductPropertyValueService productPropertyValueService; 50 private ProductPropertyValueService productPropertyValueService;
52 51
  52 + // TODO @puhui999:是不是可以删除这 2 方法
53 public Long generateId() { 53 public Long generateId() {
54 return RandomUtil.randomLong(100000, 999999); 54 return RandomUtil.randomLong(100000, 999999);
55 } 55 }
yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java
@@ -6,13 +6,12 @@ import cn.hutool.core.util.RandomUtil; @@ -6,13 +6,12 @@ import cn.hutool.core.util.RandomUtil;
6 import cn.iocoder.yudao.framework.common.exception.ServiceException; 6 import cn.iocoder.yudao.framework.common.exception.ServiceException;
7 import cn.iocoder.yudao.framework.common.pojo.PageResult; 7 import cn.iocoder.yudao.framework.common.pojo.PageResult;
8 import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; 8 import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
9 -import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryCreateReqVO;  
10 import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO; 9 import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO;
11 -import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*;  
12 -import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO; 10 +import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuCreateReqVO;
  11 +import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuPageReqVO;
  12 +import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuRespVO;
  13 +import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuUpdateReqVO;
13 import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert; 14 import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert;
14 -import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO;  
15 -import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;  
16 import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; 15 import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
17 import cn.iocoder.yudao.module.product.dal.mysql.spu.ProductSpuMapper; 16 import cn.iocoder.yudao.module.product.dal.mysql.spu.ProductSpuMapper;
18 import cn.iocoder.yudao.module.product.enums.spu.ProductSpuPageTabEnum; 17 import cn.iocoder.yudao.module.product.enums.spu.ProductSpuPageTabEnum;
@@ -23,21 +22,20 @@ import cn.iocoder.yudao.module.product.service.property.ProductPropertyService; @@ -23,21 +22,20 @@ import cn.iocoder.yudao.module.product.service.property.ProductPropertyService;
23 import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService; 22 import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService;
24 import cn.iocoder.yudao.module.product.service.sku.ProductSkuServiceImpl; 23 import cn.iocoder.yudao.module.product.service.sku.ProductSkuServiceImpl;
25 import com.google.common.collect.Lists; 24 import com.google.common.collect.Lists;
26 -import org.apache.poi.ss.formula.functions.T;  
27 import org.junit.jupiter.api.Assertions; 25 import org.junit.jupiter.api.Assertions;
28 -import org.junit.jupiter.api.Disabled;  
29 import org.junit.jupiter.api.Test; 26 import org.junit.jupiter.api.Test;
30 -import org.mockito.Mockito;  
31 import org.springframework.boot.test.mock.mockito.MockBean; 27 import org.springframework.boot.test.mock.mockito.MockBean;
32 import org.springframework.context.annotation.Import; 28 import org.springframework.context.annotation.Import;
33 29
34 import javax.annotation.Resource; 30 import javax.annotation.Resource;
35 import java.math.RoundingMode; 31 import java.math.RoundingMode;
36 -import java.util.*; 32 +import java.util.ArrayList;
  33 +import java.util.Date;
  34 +import java.util.List;
  35 +import java.util.Map;
37 import java.util.stream.Collectors; 36 import java.util.stream.Collectors;
38 import java.util.stream.Stream; 37 import java.util.stream.Stream;
39 38
40 -import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;  
41 import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; 39 import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
42 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; 40 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
43 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; 41 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
@@ -83,6 +81,8 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest { @@ -83,6 +81,8 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
83 81
84 public int generaInt(){return RandomUtil.randomInt(1,9999999);} 82 public int generaInt(){return RandomUtil.randomInt(1,9999999);}
85 83
  84 + // TODO @芋艿:单测后续 review 哈
  85 +
86 @Test 86 @Test
87 public void testCreateSpu_success() { 87 public void testCreateSpu_success() {
88 // 准备参数 88 // 准备参数