().le(leField, value).ge(geField, value));
+ }
+
/**
* 逐条插入,适合少量数据插入,或者对性能要求不高的场景
- *
+ *
* 如果大量,请使用 {@link com.baomidou.mybatisplus.extension.service.impl.ServiceImpl#saveBatch(Collection)} 方法
* 使用示例,可见 RoleMenuBatchInsertMapper、UserRoleBatchInsertMapper 类
*
diff --git a/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/util/AssertUtils.java b/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/util/AssertUtils.java
index c18bd248c..e98f4980f 100644
--- a/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/util/AssertUtils.java
+++ b/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/util/AssertUtils.java
@@ -33,6 +33,10 @@ public class AssertUtils {
public static void assertPojoEquals(Object expected, Object actual, String... ignoreFields) {
Field[] expectedFields = ReflectUtil.getFields(expected.getClass());
Arrays.stream(expectedFields).forEach(expectedField -> {
+ // 忽略 jacoco 自动生成的 $jacocoData 属性的情况
+ if (expectedField.isSynthetic()) {
+ return;
+ }
// 如果是忽略的属性,则不进行比对
if (ArrayUtil.contains(ignoreFields, expectedField.getName())) {
return;
diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/core/databind/LocalTimeJson.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/core/databind/LocalTimeJson.java
new file mode 100644
index 000000000..f9ff37511
--- /dev/null
+++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/core/databind/LocalTimeJson.java
@@ -0,0 +1,21 @@
+package cn.iocoder.yudao.framework.jackson.core.databind;
+
+import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
+import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
+
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_HOUR_MINUTE_SECOND;
+
+public class LocalTimeJson {
+
+ public static final LocalTimeSerializer SERIALIZER = new LocalTimeSerializer(DateTimeFormatter
+ .ofPattern(FORMAT_HOUR_MINUTE_SECOND)
+ .withZone(ZoneId.systemDefault()));
+
+ public static final LocalTimeDeserializer DESERIALIZABLE = new LocalTimeDeserializer(DateTimeFormatter
+ .ofPattern(FORMAT_HOUR_MINUTE_SECOND)
+ .withZone(ZoneId.systemDefault()));
+
+}
diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenBuilder.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenBuilder.java
index 90f5816f3..8293ffef0 100644
--- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenBuilder.java
+++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenBuilder.java
@@ -18,6 +18,8 @@ import org.springframework.stereotype.Component;
import java.util.*;
import static cn.hutool.core.text.CharSequenceUtil.*;
+import static cn.hutool.core.util.RandomUtil.randomEle;
+import static cn.hutool.core.util.RandomUtil.randomInt;
/**
* 代码生成器的 Builder,负责:
@@ -128,6 +130,7 @@ public class CodegenBuilder {
// 初始化 Column 列的默认字段
processColumnOperation(column); // 处理 CRUD 相关的字段的默认值
processColumnUI(column); // 处理 UI 相关的字段的默认值
+ processColumnExample(column); // 处理字段的 swagger example 示例
}
return columns;
}
@@ -169,4 +172,42 @@ public class CodegenBuilder {
}
}
+ /**
+ * 处理字段的 swagger example 示例
+ *
+ * @param column 字段
+ */
+ private void processColumnExample(CodegenColumnDO column) {
+ // id、price、count 等可能是整数的后缀
+ if (StrUtil.endWithAnyIgnoreCase(column.getJavaField(), "id", "price", "count")) {
+ column.setExample(String.valueOf(randomInt(1, Short.MAX_VALUE)));
+ return;
+ }
+ // name
+ if (StrUtil.endWithIgnoreCase(column.getJavaField(), "name")) {
+ column.setExample(randomEle(new String[]{"张三", "李四", "王五", "赵六", "芋艿"}));
+ return;
+ }
+ // status
+ if (StrUtil.endWithAnyIgnoreCase(column.getJavaField(), "status", "type")) {
+ column.setExample(randomEle(new String[]{"1", "2"}));
+ return;
+ }
+ // url
+ if (StrUtil.endWithIgnoreCase(column.getColumnName(), "url")) {
+ column.setExample("https://www.iocoder.cn");
+ return;
+ }
+ // reason
+ if (StrUtil.endWithIgnoreCase(column.getColumnName(), "reason")) {
+ column.setExample(randomEle(new String[]{"不喜欢", "不对", "不好", "不香"}));
+ return;
+ }
+ // description、memo、remark
+ if (StrUtil.endWithAnyIgnoreCase(column.getColumnName(), "description", "memo", "remark")) {
+ column.setExample(randomEle(new String[]{"你猜", "随便", "你说的对"}));
+ return;
+ }
+ }
+
}
diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/property/ProductPropertyValueApi.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/property/ProductPropertyValueApi.java
new file mode 100644
index 000000000..83269f91d
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/property/ProductPropertyValueApi.java
@@ -0,0 +1,23 @@
+package cn.iocoder.yudao.module.product.api.property;
+
+import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 商品属性值 API 接口
+ *
+ * @author 芋道源码
+ */
+public interface ProductPropertyValueApi {
+
+ /**
+ * 根据编号数组,获得属性值列表
+ *
+ * @param ids 编号数组
+ * @return 属性值明细列表
+ */
+ List getPropertyValueDetailList(Collection ids);
+
+}
diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/property/dto/ProductPropertyValueDetailRespDTO.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/property/dto/ProductPropertyValueDetailRespDTO.java
new file mode 100644
index 000000000..2a1ab71a9
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/property/dto/ProductPropertyValueDetailRespDTO.java
@@ -0,0 +1,33 @@
+package cn.iocoder.yudao.module.product.api.property.dto;
+
+import lombok.Data;
+
+/**
+ * 商品属性项的明细 Response DTO
+ *
+ * @author 芋道源码
+ */
+@Data
+public class ProductPropertyValueDetailRespDTO {
+
+ /**
+ * 属性的编号
+ */
+ private Long propertyId;
+
+ /**
+ * 属性的名称
+ */
+ private String propertyName;
+
+ /**
+ * 属性值的编号
+ */
+ private Long valueId;
+
+ /**
+ * 属性值的名称
+ */
+ private String valueName;
+
+}
diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/ProductSkuRespDTO.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/ProductSkuRespDTO.java
index 4b324149b..aaaf767f2 100644
--- a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/ProductSkuRespDTO.java
+++ b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/ProductSkuRespDTO.java
@@ -18,17 +18,17 @@ public class ProductSkuRespDTO {
* 商品 SKU 编号,自增
*/
private Long id;
- /**
- * 商品 SKU 名字
- */
- private String name;
/**
* SPU 编号
*/
private Long spuId;
+ /**
+ * SPU 名字
+ */
+ private String spuName;
/**
- * 规格值数组,JSON 格式
+ * 属性数组,JSON 格式
*/
private List properties;
/**
diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/ErrorCodeConstants.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/ErrorCodeConstants.java
index 86875b119..4adad0afc 100644
--- a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/ErrorCodeConstants.java
+++ b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/ErrorCodeConstants.java
@@ -15,28 +15,30 @@ public interface ErrorCodeConstants {
ErrorCode CATEGORY_PARENT_NOT_FIRST_LEVEL = new ErrorCode(1008001002, "父分类不能是二级分类");
ErrorCode CATEGORY_EXISTS_CHILDREN = new ErrorCode(1008001003, "存在子分类,无法删除");
ErrorCode CATEGORY_DISABLED = new ErrorCode(1008001004, "商品分类({})已禁用,无法使用");
- ErrorCode CATEGORY_LEVEL_ERROR = new ErrorCode(1008001005, "商品分类不正确,原因:必须使用第三级的商品分类下");
// ========== 商品品牌相关编号 1008002000 ==========
ErrorCode BRAND_NOT_EXISTS = new ErrorCode(1008002000, "品牌不存在");
ErrorCode BRAND_DISABLED = new ErrorCode(1008002001, "品牌不存在");
ErrorCode BRAND_NAME_EXISTS = new ErrorCode(1008002002, "品牌名称已存在");
- // ========== 商品规格名称 1008003000 ==========
- ErrorCode PROPERTY_NOT_EXISTS = new ErrorCode(1008003000, "规格名称不存在");
- ErrorCode PROPERTY_EXISTS = new ErrorCode(1008003001, "规格名称已存在");
+ // ========== 商品属性项 1008003000 ==========
+ ErrorCode PROPERTY_NOT_EXISTS = new ErrorCode(1008003000, "属性项不存在");
+ ErrorCode PROPERTY_EXISTS = new ErrorCode(1008003001, "属性项的名称已存在");
+ ErrorCode PROPERTY_DELETE_FAIL_VALUE_EXISTS = new ErrorCode(1008003002, "属性项下存在属性值,无法删除");
- // ========== 规格值 1008004000 ==========
- ErrorCode PROPERTY_VALUE_NOT_EXISTS = new ErrorCode(1008004000, "规格值不存在");
- ErrorCode PROPERTY_VALUE_EXISTS = new ErrorCode(1008004001, "规格值已存在");
+ // ========== 商品属性值 1008004000 ==========
+ ErrorCode PROPERTY_VALUE_NOT_EXISTS = new ErrorCode(1008004000, "属性值不存在");
+ ErrorCode PROPERTY_VALUE_EXISTS = new ErrorCode(1008004001, "属性值的名称已存在");
// ========== 商品 SPU 1008005000 ==========
ErrorCode SPU_NOT_EXISTS = new ErrorCode(1008005000, "商品 SPU 不存在");
+ ErrorCode SPU_SAVE_FAIL_CATEGORY_LEVEL_ERROR = new ErrorCode(1008005001, "商品分类不正确,原因:必须使用第三级的商品分类下");
+ ErrorCode SPU_NOT_ENABLE = new ErrorCode(1008005002, "商品 SPU 不处于上架状态");
// ========== 商品 SKU 1008006000 ==========
ErrorCode SKU_NOT_EXISTS = new ErrorCode(1008006000, "商品 SKU 不存在");
ErrorCode SKU_PROPERTIES_DUPLICATED = new ErrorCode(1008006001, "商品 SKU 的属性组合存在重复");
- ErrorCode SPU_ATTR_NUMBERS_MUST_BE_EQUALS = new ErrorCode(1008006002, "一个 SPU 下的每个 SKU,其规格数必须一致");
+ ErrorCode SPU_ATTR_NUMBERS_MUST_BE_EQUALS = new ErrorCode(1008006002, "一个 SPU 下的每个 SKU,其属性项必须一致");
ErrorCode SPU_SKU_NOT_DUPLICATE = new ErrorCode(1008006003, "一个 SPU 下的每个 SKU,必须不重复");
ErrorCode SKU_STOCK_NOT_ENOUGH = new ErrorCode(1008006004, "商品 SKU 库存不足");
diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/spu/ProductSpuSpecTypeEnum.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/spu/ProductSpuSpecTypeEnum.java
index 30ece744d..fbc227b53 100644
--- a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/spu/ProductSpuSpecTypeEnum.java
+++ b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/spu/ProductSpuSpecTypeEnum.java
@@ -21,11 +21,11 @@ public enum ProductSpuSpecTypeEnum implements IntArrayValuable {
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ProductSpuSpecTypeEnum::getType).toArray();
/**
- * 规格
+ * 规格类型
*/
private final Integer type;
/**
- * 规格名
+ * 规格名称
*/
private final String name;
diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/spu/ProductSpuStatusEnum.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/spu/ProductSpuStatusEnum.java
index 6b7f03ac2..2223cf23d 100644
--- a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/spu/ProductSpuStatusEnum.java
+++ b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/spu/ProductSpuStatusEnum.java
@@ -35,4 +35,14 @@ public enum ProductSpuStatusEnum implements IntArrayValuable {
return ARRAYS;
}
+ /**
+ * 判断是否处于【上架】状态
+ *
+ * @param status 状态
+ * @return 是否处于【上架】状态
+ */
+ public static boolean isEnable(Integer status) {
+ return ENABLE.getStatus().equals(status);
+ }
+
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/property/ProductPropertyValueApiImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/property/ProductPropertyValueApiImpl.java
new file mode 100644
index 000000000..9aab9e560
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/property/ProductPropertyValueApiImpl.java
@@ -0,0 +1,31 @@
+package cn.iocoder.yudao.module.product.api.property;
+
+import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO;
+import cn.iocoder.yudao.module.product.convert.propertyvalue.ProductPropertyValueConvert;
+import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+import javax.annotation.Resource;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 商品属性值 API 实现类
+ *
+ * @author 芋道源码
+ */
+@Service
+@Validated
+public class ProductPropertyValueApiImpl implements ProductPropertyValueApi {
+
+ @Resource
+ private ProductPropertyValueService productPropertyValueService;
+
+ @Override
+ public List getPropertyValueDetailList(Collection ids) {
+ return ProductPropertyValueConvert.INSTANCE.convertList02(
+ productPropertyValueService.getPropertyValueDetailList(ids));
+ }
+
+}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyController.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyController.java
index 9a4c20c58..5efecd0c7 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyController.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyController.java
@@ -1,9 +1,14 @@
package cn.iocoder.yudao.module.product.controller.admin.property;
+import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.*;
+import cn.iocoder.yudao.module.product.convert.property.ProductPropertyConvert;
+import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO;
+import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO;
import cn.iocoder.yudao.module.product.service.property.ProductPropertyService;
+import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
@@ -13,12 +18,13 @@ import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
-
+import java.util.Collections;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
-@Api(tags = "管理后台 - 规格名称")
+@Api(tags = "管理后台 - 商品属性项")
@RestController
@RequestMapping("/product/property")
@Validated
@@ -26,16 +32,18 @@ public class ProductPropertyController {
@Resource
private ProductPropertyService productPropertyService;
+ @Resource
+ private ProductPropertyValueService productPropertyValueService;
@PostMapping("/create")
- @ApiOperation("创建规格名称")
+ @ApiOperation("创建属性项")
@PreAuthorize("@ss.hasPermission('product:property:create')")
public CommonResult createProperty(@Valid @RequestBody ProductPropertyCreateReqVO createReqVO) {
return success(productPropertyService.createProperty(createReqVO));
}
@PutMapping("/update")
- @ApiOperation("更新规格名称")
+ @ApiOperation("更新属性项")
@PreAuthorize("@ss.hasPermission('product:property:update')")
public CommonResult updateProperty(@Valid @RequestBody ProductPropertyUpdateReqVO updateReqVO) {
productPropertyService.updateProperty(updateReqVO);
@@ -43,7 +51,7 @@ public class ProductPropertyController {
}
@DeleteMapping("/delete")
- @ApiOperation("删除规格名称")
+ @ApiOperation("删除属性项")
@ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('product:property:delete')")
public CommonResult deleteProperty(@RequestParam("id") Long id) {
@@ -52,32 +60,40 @@ public class ProductPropertyController {
}
@GetMapping("/get")
- @ApiOperation("获得规格名称")
+ @ApiOperation("获得属性项")
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('product:property:query')")
public CommonResult getProperty(@RequestParam("id") Long id) {
- return success(productPropertyService.getProperty(id));
+ return success(ProductPropertyConvert.INSTANCE.convert(productPropertyService.getProperty(id)));
}
@GetMapping("/list")
- @ApiOperation("获得规格名称列表")
+ @ApiOperation("获得属性项列表")
@PreAuthorize("@ss.hasPermission('product:property:query')")
public CommonResult> getPropertyList(@Valid ProductPropertyListReqVO listReqVO) {
- return success(productPropertyService.getPropertyList(listReqVO));
+ return success(ProductPropertyConvert.INSTANCE.convertList(productPropertyService.getPropertyList(listReqVO)));
}
@GetMapping("/page")
- @ApiOperation("获得规格名称分页")
+ @ApiOperation("获得属性项分页")
@PreAuthorize("@ss.hasPermission('product:property:query')")
public CommonResult> getPropertyPage(@Valid ProductPropertyPageReqVO pageVO) {
- return success(productPropertyService.getPropertyPage(pageVO));
+ return success(ProductPropertyConvert.INSTANCE.convertPage(productPropertyService.getPropertyPage(pageVO)));
}
- @GetMapping("/listAndValue")
- @ApiOperation("获得规格名称列表")
+ @GetMapping("/get-value-list")
+ @ApiOperation("获得属性项列表")
@PreAuthorize("@ss.hasPermission('product:property:query')")
public CommonResult> getPropertyAndValueList(@Valid ProductPropertyListReqVO listReqVO) {
- return success(productPropertyService.getPropertyAndValueList(listReqVO));
+ // 查询属性项
+ List keys = productPropertyService.getPropertyList(listReqVO);
+ if (CollUtil.isEmpty(keys)) {
+ return success(Collections.emptyList());
+ }
+ // 查询属性值
+ List values = productPropertyValueService.getPropertyValueListByPropertyId(
+ convertSet(keys, ProductPropertyDO::getId));
+ return success(ProductPropertyConvert.INSTANCE.convertList(keys, values));
}
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyValueController.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyValueController.java
index e88c91415..fec327946 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyValueController.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyValueController.java
@@ -2,11 +2,11 @@ package cn.iocoder.yudao.module.product.controller.admin.property;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyPageReqVO;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueCreateReqVO;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValuePageReqVO;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueUpdateReqVO;
+import cn.iocoder.yudao.module.product.convert.propertyvalue.ProductPropertyValueConvert;
import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
@@ -20,7 +20,7 @@ import javax.validation.Valid;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
-@Api(tags = "管理后台 - 规格值名称")
+@Api(tags = "管理后台 - 商品属性值")
@RestController
@RequestMapping("/product/property/value")
@Validated
@@ -30,14 +30,14 @@ public class ProductPropertyValueController {
private ProductPropertyValueService productPropertyValueService;
@PostMapping("/create")
- @ApiOperation("创建规格名称")
+ @ApiOperation("创建属性值")
@PreAuthorize("@ss.hasPermission('product:property:create')")
public CommonResult createProperty(@Valid @RequestBody ProductPropertyValueCreateReqVO createReqVO) {
return success(productPropertyValueService.createPropertyValue(createReqVO));
}
@PutMapping("/update")
- @ApiOperation("更新规格名称")
+ @ApiOperation("更新属性值")
@PreAuthorize("@ss.hasPermission('product:property:update')")
public CommonResult updateProperty(@Valid @RequestBody ProductPropertyValueUpdateReqVO updateReqVO) {
productPropertyValueService.updatePropertyValue(updateReqVO);
@@ -45,7 +45,7 @@ public class ProductPropertyValueController {
}
@DeleteMapping("/delete")
- @ApiOperation("删除规格名称")
+ @ApiOperation("删除属性值")
@ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('product:property:delete')")
public CommonResult deleteProperty(@RequestParam("id") Long id) {
@@ -54,17 +54,17 @@ public class ProductPropertyValueController {
}
@GetMapping("/get")
- @ApiOperation("获得规格名称")
+ @ApiOperation("获得属性值")
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('product:property:query')")
public CommonResult getProperty(@RequestParam("id") Long id) {
- return success(productPropertyValueService.getPropertyValue(id));
+ return success(ProductPropertyValueConvert.INSTANCE.convert(productPropertyValueService.getPropertyValue(id)));
}
@GetMapping("/page")
- @ApiOperation("获得规格名称分页")
+ @ApiOperation("获得属性值分页")
@PreAuthorize("@ss.hasPermission('product:property:query')")
public CommonResult> getPropertyValuePage(@Valid ProductPropertyValuePageReqVO pageVO) {
- return success(productPropertyValueService.getPropertyValueListPage(pageVO));
+ return success(ProductPropertyValueConvert.INSTANCE.convertPage(productPropertyValueService.getPropertyValuePage(pageVO)));
}
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/ProductPropertyViewRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/ProductPropertyViewRespVO.java
deleted file mode 100644
index 9bdc70bd7..000000000
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/ProductPropertyViewRespVO.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package cn.iocoder.yudao.module.product.controller.admin.property.vo;
-
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-import lombok.ToString;
-
-import java.util.List;
-
-/**
- * @Description: ProductPropertyViewRespVO
- * @Author: franky
- * @CreateDate: 2022/7/5 21:29
- * @Version: 1.0.0
- */
-@ApiModel("管理后台 - 规格名称详情展示 Request VO")
-@Data
-@ToString(callSuper = true)
-public class ProductPropertyViewRespVO {
-
- @ApiModelProperty(value = "规格名称id", example = "1")
- public Long propertyId;
-
- @ApiModelProperty(value = "规格名称", example = "内存")
- public String name;
-
- @ApiModelProperty(value = "规格属性值集合", example = "[{\"v1\":11,\"v2\":\"64G\"},{\"v1\":10,\"v2\":\"32G\"}]")
- public List propertyValues;
-
- @Data
- @ApiModel(value = "规格属性值元组")
- public static class Tuple2 {
- private final long id;
- private final String name;
-
- public Tuple2(Long id, String name) {
- this.id = id;
- this.name = name;
- }
-
- }
-
-
-}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyAndValueRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyAndValueRespVO.java
index e7b3c352f..a739bc0f2 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyAndValueRespVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyAndValueRespVO.java
@@ -1,30 +1,36 @@
package cn.iocoder.yudao.module.product.controller.admin.property.vo.property;
-import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.ToString;
-import java.time.LocalDateTime;
import java.util.List;
-@ApiModel("管理后台 - 规格 + 规格值 Response VO")
+@ApiModel("管理后台 - 商品属性项 + 属性值 Response VO")
@Data
-@EqualsAndHashCode(callSuper = true)
-@ToString(callSuper = true)
-public class ProductPropertyAndValueRespVO extends ProductPropertyBaseVO {
+public class ProductPropertyAndValueRespVO {
- @ApiModelProperty(value = "规格的编号", required = true, example = "1024")
+ @ApiModelProperty(value = "属性项的编号", required = true, example = "1024")
private Long id;
- @ApiModelProperty(value = "创建时间", required = true)
- private LocalDateTime createTime;
+ @ApiModelProperty(value = "属性项的名称", required = true, example = "颜色")
+ private String name;
/**
- * 规格值的集合
+ * 属性值的集合
*/
- private List values;
+ private List values;
+
+ @ApiModel("管理后台 - 属性值的简单 Response VO")
+ @Data
+ public static class Value {
+
+ @ApiModelProperty(value = "属性值的编号", required = true, example = "2048")
+ private Long id;
+
+ @ApiModelProperty(value = "属性值的名称", required = true, example = "红色")
+ private String name;
+
+ }
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyBaseVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyBaseVO.java
index 25fc4c01a..fb089dce1 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyBaseVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyBaseVO.java
@@ -4,24 +4,19 @@ import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.NotNull;
/**
- * 规格名称 Base VO,提供给添加、修改、详细的子 VO 使用
+ * 商品属性项 Base VO,提供给添加、修改、详细的子 VO 使用
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
*/
@Data
public class ProductPropertyBaseVO {
- @ApiModelProperty(value = "规格名称", required = true, example = "颜色")
- @NotBlank(message = "规格名称不能为空")
+ @ApiModelProperty(value = "名称", required = true, example = "颜色")
+ @NotBlank(message = "名称不能为空")
private String name;
@ApiModelProperty(value = "备注", example = "颜色")
private String remark;
- @ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 CommonStatusEnum 枚举")
- @NotNull(message = "状态不能为空")
- private Integer status;
-
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyCreateReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyCreateReqVO.java
index 8dfd58a5d..2e68f21e3 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyCreateReqVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyCreateReqVO.java
@@ -5,7 +5,7 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
-@ApiModel("管理后台 - 规格名称创建 Request VO")
+@ApiModel("管理后台 - 属性项创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyListReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyListReqVO.java
index 314288ffb..1233480d1 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyListReqVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyListReqVO.java
@@ -5,15 +5,12 @@ import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.ToString;
-@ApiModel("管理后台 - 规格名称 List Request VO")
+@ApiModel("管理后台 - 属性项 List Request VO")
@Data
@ToString(callSuper = true)
public class ProductPropertyListReqVO {
- @ApiModelProperty(value = "规格名称", example = "颜色")
+ @ApiModelProperty(value = "名称", example = "颜色")
private String name;
- @ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 CommonStatusEnum 枚举")
- private Integer status;
-
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyPageReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyPageReqVO.java
index 05a67e874..60bd7db5b 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyPageReqVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyPageReqVO.java
@@ -12,13 +12,13 @@ import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
-@ApiModel("管理后台 - 规格名称分页 Request VO")
+@ApiModel("管理后台 - 属性项 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ProductPropertyPageReqVO extends PageParam {
- @ApiModelProperty(value = "规格名称", example = "颜色")
+ @ApiModelProperty(value = "名称", example = "颜色")
private String name;
@ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 CommonStatusEnum 枚举")
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyRespVO.java
index 75a9a5eea..299aa56e4 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyRespVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyRespVO.java
@@ -8,13 +8,13 @@ import lombok.ToString;
import java.time.LocalDateTime;
-@ApiModel("管理后台 - 规格 + 规格值 Response VO")
+@ApiModel("管理后台 - 属性项 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ProductPropertyRespVO extends ProductPropertyBaseVO {
- @ApiModelProperty(value = "规格的编号", required = true, example = "1024")
+ @ApiModelProperty(value = "编号", required = true, example = "1024")
private Long id;
@ApiModelProperty(value = "创建时间", required = true)
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyUpdateReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyUpdateReqVO.java
index f4630d874..4dfa48366 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyUpdateReqVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyUpdateReqVO.java
@@ -1,12 +1,14 @@
package cn.iocoder.yudao.module.product.controller.admin.property.vo.property;
-import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueCreateReqVO;
-import lombok.*;
-import io.swagger.annotations.*;
-import javax.validation.constraints.*;
-import java.util.List;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
-@ApiModel("管理后台 - 规格名称更新 Request VO")
+import javax.validation.constraints.NotNull;
+
+@ApiModel("管理后台 - 属性项更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueBaseVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueBaseVO.java
index 142a8e6e2..76b2f1a8b 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueBaseVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueBaseVO.java
@@ -7,24 +7,20 @@ import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
/**
-* 规格值 Base VO,提供给添加、修改、详细的子 VO 使用
+* 属性值 Base VO,提供给添加、修改、详细的子 VO 使用
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
*/
@Data
public class ProductPropertyValueBaseVO {
- @ApiModelProperty(value = "规格编号", required = true, example = "1024")
- @NotNull(message = "规格编号不能为空")
+ @ApiModelProperty(value = "属性项的编号", required = true, example = "1024")
+ @NotNull(message = "属性项的编号不能为空")
private Long propertyId;
- @ApiModelProperty(value = "规格值名字", required = true, example = "红色")
- @NotEmpty(message = "规格值名字不能为空")
+ @ApiModelProperty(value = "名称", required = true, example = "红色")
+ @NotEmpty(message = "名称名字不能为空")
private String name;
- @ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 CommonStatusEnum 枚举")
- @NotNull(message = "状态不能为空")
- private Integer status;
-
@ApiModelProperty(value = "备注", example = "颜色")
private String remark;
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueCreateReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueCreateReqVO.java
index f7237f9cd..8930f6ba3 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueCreateReqVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueCreateReqVO.java
@@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.product.controller.admin.property.vo.value;
import lombok.*;
import io.swagger.annotations.*;
-@ApiModel("管理后台 - 规格值创建 Request VO")
+@ApiModel("管理后台 - 商品属性值创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueDetailRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueDetailRespVO.java
new file mode 100644
index 000000000..55bae16df
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueDetailRespVO.java
@@ -0,0 +1,23 @@
+package cn.iocoder.yudao.module.product.controller.admin.property.vo.value;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+@ApiModel("管理后台 - 商品属性值的明细 Response VO")
+@Data
+public class ProductPropertyValueDetailRespVO {
+
+ @ApiModelProperty(value = "属性的编号", required = true, example = "1")
+ private Long propertyId;
+
+ @ApiModelProperty(value = "属性的名称", required = true, example = "颜色")
+ private String propertyName;
+
+ @ApiModelProperty(value = "属性值的编号", required = true, example = "1024")
+ private Long valueId;
+
+ @ApiModelProperty(value = "属性值的名称", required = true, example = "红色")
+ private String valueName;
+
+}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValuePageReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValuePageReqVO.java
index ae77d822b..3f5ffee3d 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValuePageReqVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValuePageReqVO.java
@@ -6,23 +6,17 @@ import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
-import org.springframework.format.annotation.DateTimeFormat;
-import javax.validation.constraints.NotEmpty;
-import java.util.Date;
-
-import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
-
-@ApiModel("管理后台 - 规格名称值分页 Request VO")
+@ApiModel("管理后台 - 商品属性值分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ProductPropertyValuePageReqVO extends PageParam {
- @ApiModelProperty(value = "规格id", example = "1024")
+ @ApiModelProperty(value = "属性项的编号", example = "1024")
private String propertyId;
- @ApiModelProperty(value = "规格值", example = "红色")
+ @ApiModelProperty(value = "名称", example = "红色")
private String name;
@ApiModelProperty(value = "状态", required = true, example = "1", notes = "参见 CommonStatusEnum 枚举")
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueRespVO.java
index 501afd752..fb5ecead9 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueRespVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueRespVO.java
@@ -8,13 +8,13 @@ import lombok.ToString;
import java.time.LocalDateTime;
-@ApiModel("管理后台 - 规格值 Response VO")
+@ApiModel("管理后台 - 商品属性值 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ProductPropertyValueRespVO extends ProductPropertyValueBaseVO {
- @ApiModelProperty(value = "主键", required = true, example = "10")
+ @ApiModelProperty(value = "编号", required = true, example = "10")
private Long id;
@ApiModelProperty(value = "创建时间")
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueUpdateReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueUpdateReqVO.java
index 2437600a8..f13d434b3 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueUpdateReqVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/value/ProductPropertyValueUpdateReqVO.java
@@ -4,7 +4,7 @@ import lombok.*;
import io.swagger.annotations.*;
import javax.validation.constraints.*;
-@ApiModel("管理后台 - 规格值更新 Request VO")
+@ApiModel("管理后台 - 商品属性值更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuBaseVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuBaseVO.java
index 45cb447b8..1bb08ff32 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuBaseVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuBaseVO.java
@@ -4,7 +4,9 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
import lombok.Data;
+import lombok.NoArgsConstructor;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
@@ -55,8 +57,10 @@ public class ProductSkuBaseVO {
@ApiModelProperty(value = "商品体积", example = "1024", notes = "单位:m^3 平米")
private Double volume;
- @ApiModel("规格值")
+ @ApiModel("商品属性")
@Data
+ @AllArgsConstructor
+ @NoArgsConstructor
public static class Property {
@ApiModelProperty(value = "属性编号", required = true, example = "1")
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuCreateOrUpdateReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuCreateOrUpdateReqVO.java
index 6d5ce024d..ab83eeeac 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuCreateOrUpdateReqVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuCreateOrUpdateReqVO.java
@@ -1,7 +1,6 @@
package cn.iocoder.yudao.module.product.controller.admin.sku.vo;
import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@@ -14,11 +13,8 @@ import java.util.List;
@ToString(callSuper = true)
public class ProductSkuCreateOrUpdateReqVO extends ProductSkuBaseVO {
- @ApiModelProperty(value = "商品 SKU 编号", example = "1")
- private Long id;
-
/**
- * 规格值数组
+ * 属性数组
*/
private List properties;
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuRespVO.java
index 1ac29724b..85f5903cc 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuRespVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuRespVO.java
@@ -22,7 +22,7 @@ public class ProductSkuRespVO extends ProductSkuBaseVO {
private LocalDateTime createTime;
/**
- * 规格值数组
+ * 属性数组
*/
private List properties;
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.http b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.http
new file mode 100644
index 000000000..4ab7b4f71
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.http
@@ -0,0 +1,4 @@
+### 获得商品 SPU 明细
+GET {{baseUrl}}/product/spu/get-detail?id=4
+Authorization: Bearer {{token}}
+tenant-id: {{adminTenentId}}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.java
index 155fd0265..f19fde594 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.java
@@ -3,8 +3,13 @@ package cn.iocoder.yudao.module.product.controller.admin.spu;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*;
+import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert;
import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert;
+import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
+import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService;
+import cn.iocoder.yudao.module.product.service.property.bo.ProductPropertyValueDetailRespBO;
+import cn.iocoder.yudao.module.product.service.sku.ProductSkuService;
import cn.iocoder.yudao.module.product.service.spu.ProductSpuService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
@@ -15,10 +20,11 @@ import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
-import java.util.Collection;
import java.util.List;
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS;
@Api(tags = "管理后台 - 商品 SPU")
@RestController
@@ -27,20 +33,24 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
public class ProductSpuController {
@Resource
- private ProductSpuService spuService;
+ private ProductSpuService productSpuService;
+ @Resource
+ private ProductSkuService productSkuService;
+ @Resource
+ private ProductPropertyValueService productPropertyValueService;
@PostMapping("/create")
@ApiOperation("创建商品 SPU")
@PreAuthorize("@ss.hasPermission('product:spu:create')")
public CommonResult createProductSpu(@Valid @RequestBody ProductSpuCreateReqVO createReqVO) {
- return success(spuService.createSpu(createReqVO));
+ return success(productSpuService.createSpu(createReqVO));
}
@PutMapping("/update")
@ApiOperation("更新商品 SPU")
@PreAuthorize("@ss.hasPermission('product:spu:update')")
public CommonResult updateSpu(@Valid @RequestBody ProductSpuUpdateReqVO updateReqVO) {
- spuService.updateSpu(updateReqVO);
+ productSpuService.updateSpu(updateReqVO);
return success(true);
}
@@ -49,42 +59,35 @@ public class ProductSpuController {
@ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('product:spu:delete')")
public CommonResult deleteSpu(@RequestParam("id") Long id) {
- spuService.deleteSpu(id);
+ productSpuService.deleteSpu(id);
return success(true);
}
- // TODO 芋艿:修改接口
- @GetMapping("/get/detail")
- @ApiOperation("获得商品 SPU")
+ @GetMapping("/get-detail")
+ @ApiOperation("获得商品 SPU 明细")
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('product:spu:query')")
public CommonResult getSpuDetail(@RequestParam("id") Long id) {
- return success(spuService.getSpuDetail(id));
- }
+ // 获得商品 SPU
+ ProductSpuDO spu = productSpuService.getSpu(id);
+ if (spu == null) {
+ throw exception(SPU_NOT_EXISTS);
+ }
- @GetMapping("/get")
- @ApiOperation("获得商品 SPU")
- @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
- @PreAuthorize("@ss.hasPermission('product:spu:query')")
- public CommonResult getSpu(@RequestParam("id") Long id) {
- return success(spuService.getSpu(id));
- }
-
-
- @GetMapping("/list")
- @ApiOperation("获得商品 SPU 列表")
- @ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class)
- @PreAuthorize("@ss.hasPermission('product:spu:query')")
- public CommonResult> getSpuList(@RequestParam("ids") Collection ids) {
- List list = spuService.getSpuList(ids);
- return success(ProductSpuConvert.INSTANCE.convertList(list));
+ // 查询商品 SKU
+ List skus = productSkuService.getSkuListBySpuIdAndStatus(spu.getId(), null);
+ // 查询商品属性
+ List propertyValues = productPropertyValueService
+ .getPropertyValueDetailList(ProductSkuConvert.INSTANCE.convertPropertyValueIds(skus));
+ // 拼接
+ return success(ProductSpuConvert.INSTANCE.convert03(spu, skus, propertyValues));
}
@GetMapping("/get-simple-list")
@ApiOperation("获得商品 SPU 精简列表")
@PreAuthorize("@ss.hasPermission('product:spu:query')")
public CommonResult> getSpuSimpleList() {
- List list = spuService.getSpuList();
+ List list = productSpuService.getSpuList();
return success(ProductSpuConvert.INSTANCE.convertList02(list));
}
@@ -92,7 +95,7 @@ public class ProductSpuController {
@ApiOperation("获得商品 SPU 分页")
@PreAuthorize("@ss.hasPermission('product:spu:query')")
public CommonResult> getSpuPage(@Valid ProductSpuPageReqVO pageVO) {
- return success(spuService.getSpuPage(pageVO));
+ return success(ProductSpuConvert.INSTANCE.convertPage(productSpuService.getSpuPage(pageVO)));
}
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuBaseVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuBaseVO.java
index 54f0986dd..5f9f8a24c 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuBaseVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuBaseVO.java
@@ -64,28 +64,13 @@ public class ProductSpuBaseVO {
@NotNull(message = "是否展示库存不能为空")
private Boolean showStock;
- @ApiModelProperty(value = "库存", required = true, example = "true")
- private Integer totalStock;
-
@ApiModelProperty(value = "市场价", example = "1024")
private Integer marketPrice;
- @ApiModelProperty(value = " 最小价格,单位使用:分", required = true, example = "1024")
- private Integer minPrice;
-
- @ApiModelProperty(value = "最大价格,单位使用:分", required = true, example = "1024")
- private Integer maxPrice;
-
// ========== 统计相关字段 =========
- @ApiModelProperty(value = "商品销量", example = "1024")
- private Integer salesCount;
-
@ApiModelProperty(value = "虚拟销量", required = true, example = "1024")
@NotNull(message = "虚拟销量不能为空")
private Integer virtualSalesCount;
- @ApiModelProperty(value = "点击量", example = "1024")
- private Integer clickCount;
-
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuDetailRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuDetailRespVO.java
index de41d1416..65cdd22a2 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuDetailRespVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuDetailRespVO.java
@@ -1,27 +1,21 @@
package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
-import cn.iocoder.yudao.module.product.controller.admin.property.vo.ProductPropertyViewRespVO;
+import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueDetailRespVO;
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuBaseVO;
import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
-import java.time.LocalDateTime;
import java.util.List;
@ApiModel(value = "管理后台 - 商品 SPU 详细 Response VO", description = "包括关联的 SKU 等信息")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
-public class ProductSpuDetailRespVO extends ProductSpuBaseVO {
+public class ProductSpuDetailRespVO extends ProductSpuRespVO {
- @ApiModelProperty(value = "主键", required = true, example = "1")
- private Long id;
-
- @ApiModelProperty(value = "创建时间")
- private LocalDateTime createTime;
+ // ========== SKU 相关字段 =========
/**
* SKU 数组
@@ -35,31 +29,10 @@ public class ProductSpuDetailRespVO extends ProductSpuBaseVO {
public static class Sku extends ProductSkuBaseVO {
/**
- * 规格的数组
+ * 属性数组
*/
- private List properties;
+ private List properties;
}
- @ApiModel(value = "管理后台 - 商品规格的详细 Response VO")
- @Data
- @EqualsAndHashCode(callSuper = true)
- @ToString(callSuper = true)
- public static class Property extends ProductSkuBaseVO.Property {
-
- @ApiModelProperty(value = "规格的名字", required = true, example = "颜色")
- private String propertyName;
-
- @ApiModelProperty(value = "规格值的名字", required = true, example = "蓝色")
- private String valueName;
-
- }
-
- @ApiModelProperty(value = "分类 id 数组,一直递归到一级父节点", example = "4")
- private Long categoryId;
-
- // TODO @芋艿:在瞅瞅~
- @ApiModelProperty(value = "规格属性修改和详情展示组合", example = "[{\"propertyId\":2,\"name\":\"内存\",\"propertyValues\":[{\"v1\":11,\"v2\":\"64G\"},{\"v1\":10,\"v2\":\"32G\"}]},{\"propertyId\":3,\"name\":\"尺寸\",\"propertyValues\":[{\"v1\":16,\"v2\":\"6.1\"},{\"v1\":15,\"v2\":\"5.7\"}]}]")
- private List productPropertyViews;
-
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuPageReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuPageReqVO.java
index 8d1bbee5f..3d74dc80c 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuPageReqVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuPageReqVO.java
@@ -19,7 +19,7 @@ public class ProductSpuPageReqVO extends PageParam {
@ApiModelProperty(value = "商品编码", example = "yudaoyuanma")
private String code;
- @ApiModelProperty(value = "分类id", example = "1")
+ @ApiModelProperty(value = "分类编号", example = "1")
private Long categoryId;
@ApiModelProperty(value = "商品品牌编号", example = "1")
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuRespVO.java
index a8dca328b..66b86e0a5 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuRespVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuRespVO.java
@@ -7,7 +7,6 @@ import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.time.LocalDateTime;
-import java.util.List;
@ApiModel("管理后台 - 商品 SPU Response VO")
@Data
@@ -21,4 +20,22 @@ public class ProductSpuRespVO extends ProductSpuBaseVO {
@ApiModelProperty(value = "创建时间")
private LocalDateTime createTime;
+ // ========== SKU 相关字段 =========
+
+ @ApiModelProperty(value = "库存", required = true, example = "true")
+ private Integer totalStock;
+
+ @ApiModelProperty(value = " 最小价格,单位使用:分", required = true, example = "1024")
+ private Integer minPrice;
+
+ @ApiModelProperty(value = "最大价格,单位使用:分", required = true, example = "1024")
+ private Integer maxPrice;
+
+ @ApiModelProperty(value = "商品销量", example = "1024")
+ private Integer salesCount;
+
+ // ========== 统计相关字段 =========
+
+ @ApiModelProperty(value = "点击量", example = "1024")
+ private Integer clickCount;
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/package-info.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/package-info.java
new file mode 100644
index 000000000..379e85180
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * 占位符,无时间作用,避免 package 缩进
+ */
+package cn.iocoder.yudao.module.product.controller.app.property;
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/vo/property/package-info.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/vo/property/package-info.java
new file mode 100644
index 000000000..6538bea3c
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/vo/property/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * 占位符,无时间作用,避免 package 缩进
+ */
+package cn.iocoder.yudao.module.product.controller.app.property.vo.property;
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/vo/value/AppProductPropertyValueDetailRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/vo/value/AppProductPropertyValueDetailRespVO.java
new file mode 100644
index 000000000..516dd077f
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/vo/value/AppProductPropertyValueDetailRespVO.java
@@ -0,0 +1,23 @@
+package cn.iocoder.yudao.module.product.controller.app.property.vo.value;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+@ApiModel("用户 App - 商品属性值的明细 Response VO")
+@Data
+public class AppProductPropertyValueDetailRespVO {
+
+ @ApiModelProperty(value = "属性的编号", required = true, example = "1")
+ private Long propertyId;
+
+ @ApiModelProperty(value = "属性的名称", required = true, example = "颜色")
+ private String propertyName;
+
+ @ApiModelProperty(value = "属性值的编号", required = true, example = "1024")
+ private Long valueId;
+
+ @ApiModelProperty(value = "属性值的名称", required = true, example = "红色")
+ private String valueName;
+
+}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.http b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.http
new file mode 100644
index 000000000..04df7bfec
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.http
@@ -0,0 +1,8 @@
+### 获得订单交易的分页 TODO
+GET {{appApi}}/product/spu/page?pageNo=1&pageSize=10
+Authorization: Bearer {{appToken}}
+tenant-id: {{appTenentId}}
+
+### 获得商品 SPU 明细
+GET {{appApi}}/product/spu/get-detail?id=4
+tenant-id: {{appTenentId}}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.java
index 7e0f912b4..9116f29cf 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.java
@@ -1,13 +1,22 @@
package cn.iocoder.yudao.module.product.controller.app.spu;
-import cn.hutool.core.bean.BeanUtil;
+import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageReqVO;
-import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageRespVO;
-import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuRespVO;
+import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO;
+import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuDetailRespVO;
+import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageItemRespVO;
+import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert;
+import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert;
+import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
+import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
+import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;
+import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService;
+import cn.iocoder.yudao.module.product.service.property.bo.ProductPropertyValueDetailRespBO;
+import cn.iocoder.yudao.module.product.service.sku.ProductSkuService;
import cn.iocoder.yudao.module.product.service.spu.ProductSpuService;
import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
@@ -17,28 +26,54 @@ import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.validation.Valid;
+import java.util.List;
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_ENABLE;
+import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS;
-@Api(tags = "用户 APP - 商品spu")
+@Api(tags = "用户 APP - 商品 SPU")
@RestController
@RequestMapping("/product/spu")
@Validated
public class AppProductSpuController {
@Resource
- private ProductSpuService spuService;
+ private ProductSpuService productSpuService;
+ @Resource
+ private ProductSkuService productSkuService;
+ @Resource
+ private ProductPropertyValueService productPropertyValueService;
@GetMapping("/page")
- @ApiOperation("获得商品spu分页")
- public CommonResult> getSpuPage(@Valid AppSpuPageReqVO pageVO) {
- return success(spuService.getSpuPage(pageVO));
+ @ApiOperation("获得商品 SPU 分页")
+ public CommonResult> getSpuPage(@Valid AppProductSpuPageReqVO pageVO) {
+ PageResult pageResult = productSpuService.getSpuPage(pageVO, ProductSpuStatusEnum.ENABLE.getStatus());
+ return success(ProductSpuConvert.INSTANCE.convertPage02(pageResult));
}
- @GetMapping("/")
- @ApiOperation("获取商品 - 通过商品id")
- public CommonResult getSpu(@RequestParam("spuId") Long spuId) {
- AppSpuRespVO appSpuRespVO = BeanUtil.toBean(spuService.getSpu(spuId), AppSpuRespVO.class);
- return success(appSpuRespVO);
+ @GetMapping("/get-detail")
+ @ApiOperation("获得商品 SPU 明细")
+ @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
+ public CommonResult getSpuDetail(@RequestParam("id") Long id) {
+ // 获得商品 SPU
+ ProductSpuDO spu = productSpuService.getSpu(id);
+ if (spu == null) {
+ throw exception(SPU_NOT_EXISTS);
+ }
+ if (!ProductSpuStatusEnum.isEnable(spu.getStatus())) {
+ throw exception(SPU_NOT_ENABLE);
+ }
+
+ // 查询商品 SKU
+ List skus = productSkuService.getSkuListBySpuIdAndStatus(spu.getId(),
+ CommonStatusEnum.ENABLE.getStatus());
+ // 查询商品属性
+ List propertyValues = productPropertyValueService
+ .getPropertyValueDetailList(ProductSkuConvert.INSTANCE.convertPropertyValueIds(skus));
+ // 拼接
+ return success(ProductSpuConvert.INSTANCE.convert(spu, skus, propertyValues));
}
+
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuDetailRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuDetailRespVO.java
new file mode 100644
index 000000000..699ca1caa
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuDetailRespVO.java
@@ -0,0 +1,92 @@
+package cn.iocoder.yudao.module.product.controller.app.spu.vo;
+
+import cn.iocoder.yudao.module.product.controller.app.property.vo.value.AppProductPropertyValueDetailRespVO;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.List;
+
+@ApiModel("用户 App - 商品 SPU 明细 Response VO")
+@Data
+public class AppProductSpuDetailRespVO {
+
+ @ApiModelProperty(value = "商品 SPU 编号", required = true, example = "1")
+ private Long id;
+
+ // ========== 基本信息 =========
+
+ @ApiModelProperty(value = "商品名称", required = true, example = "芋道")
+ private String name;
+
+ @ApiModelProperty(value = "促销语", example = "好吃!")
+ private String sellPoint;
+
+ @ApiModelProperty(value = "商品详情", required = true, example = "我是商品描述")
+ private String description;
+
+ @ApiModelProperty(value = "商品分类编号", required = true, example = "1")
+ private Long categoryId;
+
+ @ApiModelProperty(value = "商品图片的数组", required = true)
+ private List picUrls;
+
+ @ApiModelProperty(value = "商品视频", required = true)
+ private String videoUrl;
+
+ // ========== SKU 相关字段 =========
+
+ @ApiModelProperty(value = "规格类型", required = true, example = "1", notes = "参见 ProductSpuSpecTypeEnum 枚举类")
+ private Integer specType;
+
+ @ApiModelProperty(value = "是否展示库存", required = true, example = "true")
+ private Boolean showStock;
+
+ @ApiModelProperty(value = " 最小价格,单位使用:分", required = true, example = "1024")
+ private Integer minPrice;
+
+ @ApiModelProperty(value = "最大价格,单位使用:分", required = true, example = "1024")
+ private Integer maxPrice;
+
+ /**
+ * SKU 数组
+ */
+ private List skus;
+
+ // ========== 统计相关字段 =========
+
+ @ApiModelProperty(value = "商品销量", required = true, example = "1024")
+ private Integer salesCount;
+
+ @ApiModel("用户 App - 商品 SPU 明细的 SKU 信息")
+ @Data
+ public static class Sku {
+
+ @ApiModelProperty(value = "商品 SKU 编号", example = "1")
+ private Long id;
+
+ /**
+ * 商品属性数组
+ */
+ private List properties;
+
+ @ApiModelProperty(value = "销售价格,单位:分", required = true, example = "1024", notes = "单位:分")
+ private Integer price;
+
+ @ApiModelProperty(value = "市场价", example = "1024", notes = "单位:分")
+ private Integer marketPrice;
+
+ @ApiModelProperty(value = "图片地址", required = true, example = "https://www.iocoder.cn/xx.png")
+ private String picUrl;
+
+ @ApiModelProperty(value = "库存", required = true, example = "1")
+ private Integer stock;
+
+ @ApiModelProperty(value = "商品重量", example = "1", notes = "单位:kg 千克")
+ private Double weight;
+
+ @ApiModelProperty(value = "商品体积", example = "1024", notes = "单位:m^3 平米")
+ private Double volume;
+ }
+
+}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuPageItemRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuPageItemRespVO.java
new file mode 100644
index 000000000..60fc9235e
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuPageItemRespVO.java
@@ -0,0 +1,40 @@
+package cn.iocoder.yudao.module.product.controller.app.spu.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+import java.util.List;
+
+@ApiModel("用户 App - 商品 SPU 分页项 Response VO")
+@Data
+public class AppProductSpuPageItemRespVO {
+
+ @ApiModelProperty(value = "商品 SPU 编号", required = true, example = "1")
+ private Long id;
+
+ @ApiModelProperty(value = "商品名称", required = true, example = "芋道")
+ @NotEmpty(message = "商品名称不能为空")
+ private String name;
+
+ @ApiModelProperty(value = "分类编号", required = true)
+ @NotNull(message = "分类编号不能为空")
+ private Long categoryId;
+
+ @ApiModelProperty(value = "商品图片的数组", required = true)
+ private List picUrls;
+
+ @ApiModelProperty(value = " 最小价格,单位使用:分", required = true, example = "1024")
+ private Integer minPrice;
+
+ @ApiModelProperty(value = "最大价格,单位使用:分", required = true, example = "1024")
+ private Integer maxPrice;
+
+ // ========== 统计相关字段 =========
+
+ @ApiModelProperty(value = "商品销量", example = "1024")
+ private Integer salesCount;
+
+}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuPageReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuPageReqVO.java
new file mode 100644
index 000000000..f19a7c21a
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuPageReqVO.java
@@ -0,0 +1,44 @@
+package cn.iocoder.yudao.module.product.controller.app.spu.vo;
+
+import cn.hutool.core.util.StrUtil;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+import javax.validation.constraints.AssertTrue;
+
+@ApiModel("用户 App - 商品 SPU 分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class AppProductSpuPageReqVO extends PageParam {
+
+ public static final String SORT_FIELD_PRICE = "price";
+ public static final String SORT_FIELD_SALES_COUNT = "salesCount";
+
+ @ApiModelProperty(value = "分类编号", example = "1")
+ private Long categoryId;
+
+ @ApiModelProperty(value = "关键字", example = "好看")
+ private String keyword;
+
+ @ApiModelProperty(value = "排序字段", example = "price", notes = "参见 AppSpuPageReqVO.SORT_FIELD_XXX 常量")
+ private String sortField;
+
+ @ApiModelProperty(value = "排序方式", example = "true", notes = "true - 升序;false - 降序")
+ private Boolean sortAsc;
+
+ @AssertTrue(message = "排序字段不合法")
+ @JsonIgnore
+ public boolean isSortFieldValid() {
+ if (StrUtil.isEmpty(sortField)) {
+ return true;
+ }
+ return StrUtil.equalsAny(sortField, SORT_FIELD_PRICE, SORT_FIELD_SALES_COUNT);
+ }
+
+}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppSpuPageReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppSpuPageReqVO.java
deleted file mode 100644
index 38ed4975e..000000000
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppSpuPageReqVO.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package cn.iocoder.yudao.module.product.controller.app.spu.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;
-
-@ApiModel("App - 商品spu分页 Request VO")
-@Data
-@EqualsAndHashCode(callSuper = true)
-@ToString(callSuper = true)
-public class AppSpuPageReqVO extends PageParam {
-
- @ApiModelProperty(value = "分类id")
- private Long categoryId;
-}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppSpuPageRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppSpuPageRespVO.java
deleted file mode 100644
index c0a0f0eb8..000000000
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppSpuPageRespVO.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package cn.iocoder.yudao.module.product.controller.app.spu.vo;
-
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-
-import javax.validation.constraints.NotNull;
-import java.util.List;
-
-@ApiModel("App - 商品spu分页 Request VO")
-@Data
-public class AppSpuPageRespVO {
-
- @ApiModelProperty(value = "主键", required = true, example = "1")
- private Long id;
-
- @ApiModelProperty(value = "商品名称")
- private String name;
-
- @ApiModelProperty(value = "卖点", required = true)
- @NotNull(message = "卖点不能为空")
- private String sellPoint;
-
- @ApiModelProperty(value = "描述", required = true)
- @NotNull(message = "描述不能为空")
- private String description;
-
- @ApiModelProperty(value = "分类id", required = true)
- @NotNull(message = "分类id不能为空")
- private Long categoryId;
-
- @ApiModelProperty(value = "商品主图地址,* 数组,以逗号分隔,最多上传15张", required = true)
- @NotNull(message = "商品主图地址,* 数组,以逗号分隔,最多上传15张不能为空")
- private List picUrls;
-
- @ApiModelProperty(value = "排序字段", required = true)
- @NotNull(message = "排序字段不能为空")
- private Integer sort;
-
- @ApiModelProperty(value = "点赞初始人数")
- private Integer likeCount;
-
- @ApiModelProperty(value = "价格 单位使用:分")
- private Integer price;
-
- @ApiModelProperty(value = "库存数量")
- private Integer quantity;
-
- @ApiModelProperty(value = "上下架状态: 0 上架(开启) 1 下架(禁用)")
- private Integer status;
-
-}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppSpuRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppSpuRespVO.java
deleted file mode 100644
index b45987370..000000000
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppSpuRespVO.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package cn.iocoder.yudao.module.product.controller.app.spu.vo;
-
-import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuRespVO;
-import io.swagger.annotations.ApiModel;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-
-/**
- *
- *
- *
- *
- * @author LuoWenFeng
- */
-@ApiModel("App - 商品spu Response VO")
-@Data
-@EqualsAndHashCode(callSuper = true)
-public class AppSpuRespVO extends ProductSpuRespVO {
-
-
-}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/property/ProductPropertyConvert.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/property/ProductPropertyConvert.java
index 91f811ad6..211bcc293 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/property/ProductPropertyConvert.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/property/ProductPropertyConvert.java
@@ -1,20 +1,21 @@
package cn.iocoder.yudao.module.product.convert.property;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyAndValueRespVO;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyCreateReqVO;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyRespVO;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyUpdateReqVO;
-import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO;
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO;
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import java.util.List;
+import java.util.Map;
/**
- * 规格名称 Convert
+ * 属性项 Convert
*
* @author 芋道源码
*/
@@ -27,12 +28,21 @@ public interface ProductPropertyConvert {
ProductPropertyDO convert(ProductPropertyUpdateReqVO bean);
- ProductPropertyAndValueRespVO convert(ProductPropertyRespVO bean);
-
ProductPropertyRespVO convert(ProductPropertyDO bean);
List convertList(List list);
PageResult convertPage(PageResult page);
+ default List convertList(List keys, List values) {
+ Map> valueMap = CollectionUtils.convertMultiMap(values, ProductPropertyValueDO::getPropertyId);
+ return CollectionUtils.convertList(keys, key -> {
+ ProductPropertyAndValueRespVO respVO = convert02(key);
+ respVO.setValues(convertList02(valueMap.get(key.getId())));
+ return respVO;
+ });
+ }
+ ProductPropertyAndValueRespVO convert02(ProductPropertyDO bean);
+ List convertList02(List list);
+
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/propertyvalue/ProductPropertyValueConvert.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/propertyvalue/ProductPropertyValueConvert.java
index 331ad623f..d6167c174 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/propertyvalue/ProductPropertyValueConvert.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/propertyvalue/ProductPropertyValueConvert.java
@@ -1,18 +1,25 @@
package cn.iocoder.yudao.module.product.convert.propertyvalue;
-import java.util.*;
-
import cn.iocoder.yudao.framework.common.pojo.PageResult;
-
+import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
+import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
+import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueCreateReqVO;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueUpdateReqVO;
+import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO;
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO;
+import cn.iocoder.yudao.module.product.service.property.bo.ProductPropertyValueDetailRespBO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
+import java.util.List;
+import java.util.Map;
+
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
+
/**
- * 规格值 Convert
+ * 属性值 Convert
*
* @author 芋道源码
*/
@@ -31,6 +38,18 @@ public interface ProductPropertyValueConvert {
PageResult convertPage(PageResult page);
- List convertList03(List list);
+ default List convertList(List values, List keys) {
+ Map keyMap = convertMap(keys, ProductPropertyDO::getId);
+ return CollectionUtils.convertList(values, value -> {
+ ProductPropertyValueDetailRespBO valueDetail = new ProductPropertyValueDetailRespBO()
+ .setValueId(value.getId()).setValueName(value.getName());
+ // 设置属性项
+ MapUtils.findAndThen(keyMap, value.getPropertyId(),
+ key -> valueDetail.setPropertyId(key.getId()).setPropertyName(key.getName()));
+ return valueDetail;
+ });
+ }
+
+ List convertList02(List list);
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/sku/ProductSkuConvert.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/sku/ProductSkuConvert.java
index b29d612be..f397dfc48 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/sku/ProductSkuConvert.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/sku/ProductSkuConvert.java
@@ -1,5 +1,7 @@
package cn.iocoder.yudao.module.product.convert.sku;
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO;
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO;
@@ -10,9 +12,8 @@ import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
+import java.util.stream.Collectors;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
@@ -32,12 +33,16 @@ public interface ProductSkuConvert {
List convertList(List list);
- List convertSkuDOList(List list);
+ List convertList06(List list);
+
+ default List convertList06(List list, Long spuId, String spuName) {
+ List result = convertList06(list);
+ result.forEach(item -> item.setSpuId(spuId).setSpuName(spuName));
+ return result;
+ }
ProductSkuRespDTO convert02(ProductSkuDO bean);
- List convertList02(List list);
-
List convertList03(List list);
List convertList04(List list);
@@ -66,4 +71,23 @@ public interface ProductSkuConvert {
return spuIdAndStockMap;
}
+ default Collection convertPropertyValueIds(List list) {
+ if (CollUtil.isEmpty(list)) {
+ return new HashSet<>();
+ }
+ return list.stream().filter(item -> item.getProperties() != null)
+ .flatMap(p -> p.getProperties().stream()) // 遍历多个 Property 属性
+ .map(ProductSkuDO.Property::getValueId) // 将每个 Property 转换成对应的 propertyId,最后形成集合
+ .collect(Collectors.toSet());
+ }
+
+ default String buildPropertyKey(ProductSkuDO bean) {
+ if (CollUtil.isEmpty(bean.getProperties())) {
+ return StrUtil.EMPTY;
+ }
+ List properties = new ArrayList<>(bean.getProperties());
+ properties.sort(Comparator.comparing(ProductSkuDO.Property::getValueId));
+ return properties.stream().map(m -> String.valueOf(m.getValueId())).collect(Collectors.joining());
+ }
+
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java
index 98b7d8837..fcf6d6436 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java
@@ -1,18 +1,29 @@
package cn.iocoder.yudao.module.product.convert.spu;
+import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
+import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueDetailRespVO;
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*;
-import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageReqVO;
-import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageRespVO;
+import cn.iocoder.yudao.module.product.controller.app.property.vo.value.AppProductPropertyValueDetailRespVO;
+import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuDetailRespVO;
+import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO;
+import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageItemRespVO;
+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.service.property.bo.ProductPropertyValueDetailRespBO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
+import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
+
+import static cn.hutool.core.util.ObjectUtil.defaultIfNull;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
/**
- * 商品spu Convert
+ * 商品 SPU Convert
*
* @author 芋道源码
*/
@@ -25,18 +36,73 @@ public interface ProductSpuConvert {
ProductSpuDO convert(ProductSpuUpdateReqVO bean);
- ProductSpuRespVO convert(ProductSpuDO bean);
-
- List convertList(List list);
+ List convertList(List list);
PageResult convertPage(PageResult page);
- ProductSpuPageReqVO convert(AppSpuPageReqVO bean);
-
- AppSpuPageRespVO convertAppResp(ProductSpuDO list);
+ ProductSpuPageReqVO convert(AppProductSpuPageReqVO bean);
List convertList2(List list);
List convertList02(List list);
+ default AppProductSpuDetailRespVO convert(ProductSpuDO spu, List skus,
+ List propertyValues) {
+ AppProductSpuDetailRespVO spuVO = convert02(spu)
+ .setSalesCount(spu.getSalesCount() + defaultIfNull(spu.getVirtualSalesCount(), 0));
+ spuVO.setSkus(convertList03(skus));
+ // 处理商品属性
+ Map propertyValueMap = convertMap(propertyValues, ProductPropertyValueDetailRespBO::getValueId);
+ for (int i = 0; i < skus.size(); i++) {
+ List properties = skus.get(i).getProperties();
+ if (CollUtil.isEmpty(properties)) {
+ continue;
+ }
+ AppProductSpuDetailRespVO.Sku sku = spuVO.getSkus().get(i);
+ sku.setProperties(new ArrayList<>(properties.size()));
+ // 遍历每个 properties,设置到 AppSpuDetailRespVO.Sku 中
+ properties.forEach(property -> {
+ ProductPropertyValueDetailRespBO propertyValue = propertyValueMap.get(property.getValueId());
+ if (propertyValue == null) {
+ return;
+ }
+ sku.getProperties().add(convert03(propertyValue));
+ });
+ }
+ return spuVO;
+ }
+ AppProductSpuDetailRespVO convert02(ProductSpuDO spu);
+ List convertList03(List skus);
+ AppProductPropertyValueDetailRespVO convert03(ProductPropertyValueDetailRespBO propertyValue);
+
+ PageResult convertPage02(PageResult page);
+
+ default ProductSpuDetailRespVO convert03(ProductSpuDO spu, List skus,
+ List propertyValues) {
+ ProductSpuDetailRespVO spuVO = convert03(spu);
+ spuVO.setSkus(convertList04(skus));
+ // 处理商品属性
+ Map propertyValueMap = convertMap(propertyValues, ProductPropertyValueDetailRespBO::getValueId);
+ for (int i = 0; i < skus.size(); i++) {
+ List properties = skus.get(i).getProperties();
+ if (CollUtil.isEmpty(properties)) {
+ continue;
+ }
+ ProductSpuDetailRespVO.Sku sku = spuVO.getSkus().get(i);
+ sku.setProperties(new ArrayList<>(properties.size()));
+ // 遍历每个 properties,设置到 AppSpuDetailRespVO.Sku 中
+ properties.forEach(property -> {
+ ProductPropertyValueDetailRespBO propertyValue = propertyValueMap.get(property.getValueId());
+ if (propertyValue == null) {
+ return;
+ }
+ sku.getProperties().add(convert04(propertyValue));
+ });
+ }
+ return spuVO;
+ }
+ ProductSpuDetailRespVO convert03(ProductSpuDO spu);
+ List convertList04(List skus);
+ ProductPropertyValueDetailRespVO convert04(ProductPropertyValueDetailRespBO propertyValue);
+
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyDO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyDO.java
index b3831491e..2976674c1 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyDO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyDO.java
@@ -1,6 +1,5 @@
package cn.iocoder.yudao.module.product.dal.dataobject.property;
-import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
@@ -8,7 +7,7 @@ import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
/**
- * 规格名称 DO
+ * 商品属性项 DO
*
* @author 芋道源码
*/
@@ -28,20 +27,12 @@ public class ProductPropertyDO extends BaseDO {
@TableId
private Long id;
/**
- * 规格名称
+ * 名称
*/
private String name;
- /**
- * 状态
- *
- * 枚举 {@link CommonStatusEnum}
- */
- private Integer status;
/**
* 备注
*/
private String remark;
- // TODO 芋艿:rule;规格属性 (发布商品时,和 SKU 关联);规格参数(搜索商品时,与 Category 关联搜索)
-
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyValueDO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyValueDO.java
index b75f0d592..d73fe06b2 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyValueDO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyValueDO.java
@@ -1,6 +1,5 @@
package cn.iocoder.yudao.module.product.dal.dataobject.property;
-import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
@@ -9,7 +8,7 @@ import lombok.*;
/**
- * 规格值 DO
+ * 商品属性值 DO
*
* @author 芋道源码
*/
@@ -29,21 +28,15 @@ public class ProductPropertyValueDO extends BaseDO {
@TableId
private Long id;
/**
- * 规格键编号
+ * 属性项的编号
*
* 关联 {@link ProductPropertyDO#getId()}
*/
private Long propertyId;
/**
- * 规格值名字
+ * 名称
*/
private String name;
- /**
- * 状态
- *
- * 枚举 {@link CommonStatusEnum}
- */
- private Integer status;
/**
* 备注
*
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/sku/ProductSkuDO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/sku/ProductSkuDO.java
index f953534ed..3836f20e5 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/sku/ProductSkuDO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/sku/ProductSkuDO.java
@@ -35,10 +35,6 @@ public class ProductSkuDO extends BaseDO {
*/
@TableId
private Long id;
- /**
- * 商品 SKU 名字
- */
- private String name;
/**
* SPU 编号
*
@@ -46,7 +42,13 @@ public class ProductSkuDO extends BaseDO {
*/
private Long spuId;
/**
- * 规格值数组,JSON 格式
+ * SPU 名字
+ *
+ * 冗余 {@link ProductSkuDO#getSpuName()}
+ */
+ private String spuName;
+ /**
+ * 属性数组,JSON 格式
*/
@TableField(typeHandler = PropertyTypeHandler.class)
private List properties;
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyMapper.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyMapper.java
index 890df3477..26f8d5239 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyMapper.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyMapper.java
@@ -3,31 +3,30 @@ package cn.iocoder.yudao.module.product.dal.mysql.property;
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.property.vo.property.ProductPropertyListReqVO;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyPageReqVO;
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
-/**
- * 规格名称 Mapper
- *
- * @author 芋道源码
- */
@Mapper
public interface ProductPropertyMapper extends BaseMapperX {
default PageResult selectPage(ProductPropertyPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX()
.likeIfPresent(ProductPropertyDO::getName, reqVO.getName())
- .eqIfPresent(ProductPropertyDO::getStatus, reqVO.getStatus())
.betweenIfPresent(ProductPropertyDO::getCreateTime, reqVO.getCreateTime())
.orderByDesc(ProductPropertyDO::getId));
}
default ProductPropertyDO selectByName(String name) {
- return selectOne(new LambdaQueryWrapperX()
- .eqIfPresent(ProductPropertyDO::getName, name));
+ return selectOne(ProductPropertyDO::getName, name);
+ }
+
+ default List selectList(ProductPropertyListReqVO listReqVO) {
+ return selectList(new LambdaQueryWrapperX()
+ .eqIfPresent(ProductPropertyDO::getName, listReqVO.getName()));
}
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyValueMapper.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyValueMapper.java
index ca9bafab2..402df51e7 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyValueMapper.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/property/ProductPropertyValueMapper.java
@@ -7,17 +7,13 @@ import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.Produc
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO;
import org.apache.ibatis.annotations.Mapper;
+import java.util.Collection;
import java.util.List;
-/**
- * 规格值 Mapper
- *
- * @author 芋道源码
- */
@Mapper
public interface ProductPropertyValueMapper extends BaseMapperX {
- default List selectListByPropertyId(List propertyIds) {
+ default List selectListByPropertyId(Collection propertyIds) {
return selectList(new LambdaQueryWrapperX()
.inIfPresent(ProductPropertyValueDO::getPropertyId, propertyIds));
}
@@ -28,17 +24,20 @@ public interface ProductPropertyValueMapper extends BaseMapperX().eq(ProductPropertyValueDO::getPropertyId, propertyId)
- .eq(ProductPropertyValueDO::getDeleted, false));
+ default void deleteByPropertyId(Long propertyId) {
+ delete(new LambdaQueryWrapperX()
+ .eq(ProductPropertyValueDO::getPropertyId, propertyId));
}
default PageResult selectPage(ProductPropertyValuePageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX()
.eqIfPresent(ProductPropertyValueDO::getPropertyId, reqVO.getPropertyId())
.likeIfPresent(ProductPropertyValueDO::getName, reqVO.getName())
- .eqIfPresent(ProductPropertyValueDO::getStatus, reqVO.getStatus())
.orderByDesc(ProductPropertyValueDO::getId));
}
+ default Integer selectCountByPropertyId(Long propertyId) {
+ return selectCount(ProductPropertyValueDO::getPropertyId, propertyId).intValue();
+ }
+
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/sku/ProductSkuMapper.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/sku/ProductSkuMapper.java
index 3e5a9ce8f..56bc54499 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/sku/ProductSkuMapper.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/sku/ProductSkuMapper.java
@@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.apache.ibatis.annotations.Mapper;
+import java.util.Collection;
import java.util.List;
/**
@@ -22,6 +23,17 @@ public interface ProductSkuMapper extends BaseMapperX {
return selectList(ProductSkuDO::getSpuId, spuId);
}
+ default List selectListBySpuIdAndStatus(Long spuId,
+ Integer status) {
+ return selectList(new LambdaQueryWrapperX()
+ .eq(ProductSkuDO::getSpuId, spuId)
+ .eqIfPresent(ProductSkuDO::getStatus, status));
+ }
+
+ default List selectListBySpuId(Collection spuIds) {
+ return selectList(ProductSkuDO::getSpuId, spuIds);
+ }
+
default void deleteBySpuId(Long spuId) {
delete(new LambdaQueryWrapperX().eq(ProductSkuDO::getSpuId, spuId));
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/spu/ProductSpuMapper.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/spu/ProductSpuMapper.java
index a271b5051..57a3125d8 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/spu/ProductSpuMapper.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/spu/ProductSpuMapper.java
@@ -4,10 +4,12 @@ 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.spu.vo.ProductSpuPageReqVO;
+import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO;
import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.apache.ibatis.annotations.Mapper;
+import java.util.Objects;
import java.util.Set;
/**
@@ -44,6 +46,19 @@ public interface ProductSpuMapper extends BaseMapperX {
.orderByDesc(ProductSpuDO::getSort));
}
+ default PageResult selectPage(AppProductSpuPageReqVO pageReqVO, Integer status) {
+ LambdaQueryWrapperX query = new LambdaQueryWrapperX()
+ .eqIfPresent(ProductSpuDO::getCategoryId, pageReqVO.getCategoryId())
+ .eqIfPresent(ProductSpuDO::getStatus, status);
+ // 排序逻辑
+ if (Objects.equals(pageReqVO.getSortField(), AppProductSpuPageReqVO.SORT_FIELD_PRICE)) {
+ query.orderBy(true, pageReqVO.getSortAsc(), ProductSpuDO::getMaxPrice);
+ } else if (Objects.equals(pageReqVO.getSortField(), AppProductSpuPageReqVO.SORT_FIELD_SALES_COUNT)) {
+ query.orderBy(true, pageReqVO.getSortAsc(), ProductSpuDO::getSalesCount);
+ }
+ return selectPage(pageReqVO, query);
+ }
+
/**
* 更新商品 SPU 库存
*
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/package-info.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/package-info.java
index 117f35931..01967857e 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/package-info.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/package-info.java
@@ -2,7 +2,7 @@
* trade 模块,主要实现交易相关功能
* 例如:订单、退款、购物车等功能。
*
- * 1. Controller URL:以 /trade/ 开头,避免和其它 Module 冲突
- * 2. DataObject 表名:以 trade_ 开头,方便在数据库中区分
+ * 1. Controller URL:以 /product/ 开头,避免和其它 Module 冲突
+ * 2. DataObject 表名:以 product_ 开头,方便在数据库中区分
*/
package cn.iocoder.yudao.module.product;
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryService.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryService.java
index 118e8118b..32a4c030d 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryService.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryService.java
@@ -6,7 +6,6 @@ import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCateg
import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO;
import javax.validation.Valid;
-import java.util.Collection;
import java.util.List;
/**
@@ -47,12 +46,19 @@ public interface ProductCategoryService {
ProductCategoryDO getCategory(Long id);
/**
- * 获得商品分类列表
+ * 校验商品分类
*
- * @param ids 编号
- * @return 商品分类列表
+ * @param id 分类编号
*/
- List getEnableCategoryList(Collection ids);
+ void validateCategory(Long id);
+
+ /**
+ * 获得商品分类的层级
+ *
+ * @param id 编号
+ * @return 商品分类的层级
+ */
+ Integer getCategoryLevel(Long id);
/**
* 获得商品分类列表
@@ -62,14 +68,6 @@ public interface ProductCategoryService {
*/
List getEnableCategoryList(ProductCategoryListReqVO listReqVO);
- /**
- * 验证选择的商品分类的级别是否合法
- * 例如说,商品发布的时候,必须在第 3 级别
- *
- * @param id 分类编号
- */
- void validateCategoryLevel(Long id);
-
/**
* 获得开启状态的商品分类列表
*
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImpl.java
index ffe55e9bf..f0d10b8b8 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImpl.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImpl.java
@@ -11,7 +11,6 @@ import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
-import java.util.Collection;
import java.util.List;
import java.util.Objects;
@@ -90,31 +89,40 @@ public class ProductCategoryServiceImpl implements ProductCategoryService {
}
}
- @Override
- public void validateCategoryLevel(Long id) {
- // TODO @芋艿:在看看,杂能优化下
- Long parentId = id;
- int i = 2;
- for (; i >= 0; --i) {
- ProductCategoryDO category = productCategoryMapper.selectById(parentId);
- parentId = category.getParentId();
- if(Objects.equals(parentId, ProductCategoryDO.PARENT_ID_NULL)){
- break;
- }
- }
- if (!Objects.equals(parentId, ProductCategoryDO.PARENT_ID_NULL) || i != 0) {
- throw exception(CATEGORY_LEVEL_ERROR);
- }
- }
-
@Override
public ProductCategoryDO getCategory(Long id) {
return productCategoryMapper.selectById(id);
}
@Override
- public List getEnableCategoryList(Collection ids) {
- return productCategoryMapper.selectBatchIds(ids);
+ public void validateCategory(Long id) {
+ ProductCategoryDO category = productCategoryMapper.selectById(id);
+ if (category == null) {
+ throw exception(CATEGORY_NOT_EXISTS);
+ }
+ if (Objects.equals(category.getStatus(), CommonStatusEnum.ENABLE.getStatus())) {
+ throw exception(CATEGORY_DISABLED, category.getName());
+ }
+ }
+
+ @Override
+ public Integer getCategoryLevel(Long id) {
+ if (Objects.equals(id, ProductCategoryDO.PARENT_ID_NULL)) {
+ return 0;
+ }
+ int level = 1;
+ for (int i = 0; i < 100; i++) {
+ ProductCategoryDO category = productCategoryMapper.selectById(id);
+ // 如果没有父节点,break 结束
+ if (category == null
+ || Objects.equals(category.getParentId(), ProductCategoryDO.PARENT_ID_NULL)) {
+ break;
+ }
+ // 继续递归父节点
+ level++;
+ id = category.getParentId();
+ }
+ return level;
}
@Override
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyService.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyService.java
index 8780c7865..564bc82a9 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyService.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyService.java
@@ -1,7 +1,6 @@
package cn.iocoder.yudao.module.product.service.property;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyRespVO;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.*;
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO;
@@ -10,14 +9,15 @@ import java.util.Collection;
import java.util.List;
/**
- * 规格名称 Service 接口
+ * 商品属性项 Service 接口
*
* @author 芋道源码
*/
public interface ProductPropertyService {
/**
- * 创建规格名称
+ * 创建属性项
+ * 注意,如果已经存在该属性项,直接返回它的编号即可
*
* @param createReqVO 创建信息
* @return 编号
@@ -25,56 +25,48 @@ public interface ProductPropertyService {
Long createProperty(@Valid ProductPropertyCreateReqVO createReqVO);
/**
- * 更新规格名称
+ * 更新属性项
*
* @param updateReqVO 更新信息
*/
void updateProperty(@Valid ProductPropertyUpdateReqVO updateReqVO);
/**
- * 删除规格名称
+ * 删除属性项
*
* @param id 编号
*/
void deleteProperty(Long id);
/**
- * 获得规格名称列表
+ * 获得属性项列表
* @param listReqVO 集合查询
- * @return 规格名称集合
+ * @return 属性项集合
*/
- List getPropertyList(ProductPropertyListReqVO listReqVO);
+ List getPropertyList(ProductPropertyListReqVO listReqVO);
/**
* 获取属性名称分页
*
* @param pageReqVO 分页条件
- * @return 规格名称分页
+ * @return 属性项分页
*/
- PageResult getPropertyPage(ProductPropertyPageReqVO pageReqVO);
+ PageResult getPropertyPage(ProductPropertyPageReqVO pageReqVO);
/**
- * 获得指定编号的规格名称
+ * 获得指定编号的属性项
*
* @param id 编号
- * @return 规格名称
+ * @return 属性项
*/
- ProductPropertyRespVO getProperty(Long id);
+ ProductPropertyDO getProperty(Long id);
/**
- * 根据规格属性编号的集合,获得对应的规格 + 规格值的集合
+ * 根据属性项的编号的集合,获得对应的属性项数组
*
- * @param ids 规格编号的集合
- * @return 对应的规格
+ * @param ids 属性项的编号的集合
+ * @return 属性项数组
*/
- List getPropertyList(Collection ids);
-
- /**
- * 获得规格名称 + 值的列表
- *
- * @param listReqVO 列表查询
- * @return 规格名称 + 值的列表
- */
- List getPropertyAndValueList(ProductPropertyListReqVO listReqVO);
+ List getPropertyList(Collection ids);
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyServiceImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyServiceImpl.java
index 74e370f9c..328c343d6 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyServiceImpl.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyServiceImpl.java
@@ -1,16 +1,15 @@
package cn.iocoder.yudao.module.product.service.property;
+import cn.hutool.core.util.ObjUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
-import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
-import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
-import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.*;
+import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyCreateReqVO;
+import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyListReqVO;
+import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyPageReqVO;
+import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyUpdateReqVO;
import cn.iocoder.yudao.module.product.convert.property.ProductPropertyConvert;
-import cn.iocoder.yudao.module.product.convert.propertyvalue.ProductPropertyValueConvert;
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO;
-import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO;
import cn.iocoder.yudao.module.product.dal.mysql.property.ProductPropertyMapper;
-import cn.iocoder.yudao.module.product.dal.mysql.property.ProductPropertyValueMapper;
+import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
@@ -18,15 +17,12 @@ import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.util.Collection;
import java.util.List;
-import java.util.Map;
-import java.util.Objects;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
-import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.PROPERTY_EXISTS;
-import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.PROPERTY_NOT_EXISTS;
+import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.*;
/**
- * 规格名称 Service 实现类
+ * 商品属性项 Service 实现类
*
* @author 芋道源码
*/
@@ -38,15 +34,18 @@ public class ProductPropertyServiceImpl implements ProductPropertyService {
private ProductPropertyMapper productPropertyMapper;
@Resource
- private ProductPropertyValueMapper productPropertyValueMapper;
+ @Lazy // 延迟加载,解决循环依赖问题
+ private ProductPropertyValueService productPropertyValueService;
@Override
@Transactional(rollbackFor = Exception.class)
public Long createProperty(ProductPropertyCreateReqVO createReqVO) {
- // 校验存在
- if (productPropertyMapper.selectByName(createReqVO.getName()) != null) {
- throw exception(PROPERTY_EXISTS);
+ // 如果已经添加过该属性项,直接返回
+ ProductPropertyDO dbProperty = productPropertyMapper.selectByName(createReqVO.getName());
+ if (dbProperty != null) {
+ return dbProperty.getId();
}
+
// 插入
ProductPropertyDO property = ProductPropertyConvert.INSTANCE.convert(createReqVO);
productPropertyMapper.insert(property);
@@ -57,12 +56,14 @@ public class ProductPropertyServiceImpl implements ProductPropertyService {
@Override
@Transactional(rollbackFor = Exception.class)
public void updateProperty(ProductPropertyUpdateReqVO updateReqVO) {
- // 校验存在
- this.validatePropertyExists(updateReqVO.getId());
+ validatePropertyExists(updateReqVO.getId());
+ // 校验名字重复
ProductPropertyDO productPropertyDO = productPropertyMapper.selectByName(updateReqVO.getName());
- if (productPropertyDO != null && !productPropertyDO.getId().equals(updateReqVO.getId())) {
+ if (productPropertyDO != null &&
+ ObjUtil.notEqual(productPropertyDO.getId(), updateReqVO.getId())) {
throw exception(PROPERTY_EXISTS);
}
+
// 更新
ProductPropertyDO updateObj = ProductPropertyConvert.INSTANCE.convert(updateReqVO);
productPropertyMapper.updateById(updateObj);
@@ -71,11 +72,16 @@ public class ProductPropertyServiceImpl implements ProductPropertyService {
@Override
public void deleteProperty(Long id) {
// 校验存在
- this.validatePropertyExists(id);
+ validatePropertyExists(id);
+ // 校验其下是否有规格值
+ if (productPropertyValueService.getPropertyValueCountByPropertyId(id) > 0) {
+ throw exception(PROPERTY_DELETE_FAIL_VALUE_EXISTS);
+ }
+
// 删除
productPropertyMapper.deleteById(id);
- //同步删除属性值
- productPropertyValueMapper.deletePropertyValueByPropertyId(id);
+ // 同步删除属性值
+ productPropertyValueService.deletePropertyValueByPropertyId(id);
}
private void validatePropertyExists(Long id) {
@@ -85,41 +91,23 @@ public class ProductPropertyServiceImpl implements ProductPropertyService {
}
@Override
- public List getPropertyList(ProductPropertyListReqVO listReqVO) {
- return ProductPropertyConvert.INSTANCE.convertList(productPropertyMapper.selectList(new LambdaQueryWrapperX()
- .likeIfPresent(ProductPropertyDO::getName, listReqVO.getName())
- .eqIfPresent(ProductPropertyDO::getStatus, listReqVO.getStatus())));
+ public List getPropertyList(ProductPropertyListReqVO listReqVO) {
+ return productPropertyMapper.selectList(listReqVO);
}
@Override
- public PageResult getPropertyPage(ProductPropertyPageReqVO pageReqVO) {
- //获取属性列表
- PageResult pageResult = productPropertyMapper.selectPage(pageReqVO);
- return ProductPropertyConvert.INSTANCE.convertPage(pageResult);
+ public PageResult getPropertyPage(ProductPropertyPageReqVO pageReqVO) {
+ return productPropertyMapper.selectPage(pageReqVO);
}
@Override
- public ProductPropertyRespVO getProperty(Long id) {
- ProductPropertyDO property = productPropertyMapper.selectById(id);
- return ProductPropertyConvert.INSTANCE.convert(property);
+ public ProductPropertyDO getProperty(Long id) {
+ return productPropertyMapper.selectById(id);
}
@Override
- public List getPropertyList(Collection ids) {
- return ProductPropertyConvert.INSTANCE.convertList(productPropertyMapper.selectBatchIds(ids));
+ public List getPropertyList(Collection ids) {
+ return productPropertyMapper.selectBatchIds(ids);
}
- @Override
- public List getPropertyAndValueList(ProductPropertyListReqVO listReqVO) {
- List propertyList = getPropertyList(listReqVO);
-
- // 查询属性值
- List valueDOList = productPropertyValueMapper.selectListByPropertyId(CollectionUtils.convertList(propertyList, ProductPropertyRespVO::getId));
- Map> valueDOMap = CollectionUtils.convertMultiMap(valueDOList, ProductPropertyValueDO::getPropertyId);
- return CollectionUtils.convertList(propertyList, m -> {
- ProductPropertyAndValueRespVO productPropertyAndValueRespVO = ProductPropertyConvert.INSTANCE.convert(m);
- productPropertyAndValueRespVO.setValues(ProductPropertyValueConvert.INSTANCE.convertList(valueDOMap.get(m.getId())));
- return productPropertyAndValueRespVO;
- });
- }
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyValueService.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyValueService.java
index 9dcbd72e7..553e2578d 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyValueService.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyValueService.java
@@ -3,22 +3,23 @@ package cn.iocoder.yudao.module.product.service.property;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueCreateReqVO;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValuePageReqVO;
-import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueUpdateReqVO;
+import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO;
+import cn.iocoder.yudao.module.product.service.property.bo.ProductPropertyValueDetailRespBO;
+import java.util.Collection;
import java.util.List;
/**
- *
- * 规格值 Service 接口
- *
+ * 商品属性值 Service 接口
*
* @author LuoWenFeng
*/
public interface ProductPropertyValueService {
/**
- * 创建规格值
+ * 创建属性值
+ * 注意,如果已经存在该属性值,直接返回它的编号即可
*
* @param createReqVO 创建信息
* @return 编号
@@ -26,40 +27,64 @@ public interface ProductPropertyValueService {
Long createPropertyValue(ProductPropertyValueCreateReqVO createReqVO);
/**
- * 更新规格值
+ * 更新属性值
*
* @param updateReqVO 更新信息
*/
void updatePropertyValue(ProductPropertyValueUpdateReqVO updateReqVO);
/**
- * 删除规格值
+ * 删除属性值
*
* @param id 编号
*/
void deletePropertyValue(Long id);
/**
- * 获得规格值
+ * 获得属性值
*
* @param id 编号
- * @return 规格名称
+ * @return 属性值
*/
- ProductPropertyValueRespVO getPropertyValue(Long id);
+ ProductPropertyValueDO getPropertyValue(Long id);
/**
- * 获得规格值
+ * 根据属性项编号数组,获得属性值列表
*
- * @param id 编号
- * @return 规格名称
+ * @param propertyIds 属性项目编号数组
+ * @return 属性值列表
*/
- List getPropertyValueListByPropertyId(List id);
+ List getPropertyValueListByPropertyId(Collection propertyIds);
/**
- * 获取规格值 分页
+ * 根据编号数组,获得属性值列表
+ *
+ * @param ids 编号数组
+ * @return 属性值明细列表
+ */
+ List getPropertyValueDetailList(Collection ids);
+
+ /**
+ * 根据属性项编号,活的属性值数量
+ *
+ * @param propertyId 属性项编号数
+ * @return 属性值数量
+ */
+ Integer getPropertyValueCountByPropertyId(Long propertyId);
+
+ /**
+ * 获取属性值的分页
*
* @param pageReqVO 查询条件
- * @return
+ * @return 属性值的分页
*/
- PageResult getPropertyValueListPage(ProductPropertyValuePageReqVO pageReqVO);
+ PageResult getPropertyValuePage(ProductPropertyValuePageReqVO pageReqVO);
+
+ /**
+ * 删除指定属性项编号下的属性值们
+ *
+ * @param propertyId 属性项的编号
+ */
+ void deletePropertyValueByPropertyId(Long propertyId);
+
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyValueServiceImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyValueServiceImpl.java
index 5addb37e8..e5bc6874b 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyValueServiceImpl.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyValueServiceImpl.java
@@ -1,26 +1,31 @@
package cn.iocoder.yudao.module.product.service.property;
+import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueCreateReqVO;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValuePageReqVO;
-import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueUpdateReqVO;
import cn.iocoder.yudao.module.product.convert.propertyvalue.ProductPropertyValueConvert;
+import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO;
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO;
import cn.iocoder.yudao.module.product.dal.mysql.property.ProductPropertyValueMapper;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import cn.iocoder.yudao.module.product.service.property.bo.ProductPropertyValueDetailRespBO;
+import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
+import java.util.Collection;
+import java.util.Collections;
import java.util.List;
-import java.util.Objects;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.PROPERTY_VALUE_EXISTS;
+import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.PROPERTY_VALUE_NOT_EXISTS;
/**
- * 规格值 Service 实现类
+ * 商品属性值 Service 实现类
*
* @author LuoWenFeng
*/
@@ -31,45 +36,92 @@ public class ProductPropertyValueServiceImpl implements ProductPropertyValueServ
@Resource
private ProductPropertyValueMapper productPropertyValueMapper;
+ @Resource
+ @Lazy // 延迟加载,避免循环依赖
+ private ProductPropertyService productPropertyService;
+
@Override
public Long createPropertyValue(ProductPropertyValueCreateReqVO createReqVO) {
- if (productPropertyValueMapper.selectByName(createReqVO.getPropertyId(), createReqVO.getName()) != null) {
- throw exception(PROPERTY_VALUE_EXISTS);
+ // 如果已经添加过该属性值,直接返回
+ ProductPropertyValueDO dbValue = productPropertyValueMapper.selectByName(
+ createReqVO.getPropertyId(), createReqVO.getName());
+ if (dbValue != null) {
+ return dbValue.getId();
}
- ProductPropertyValueDO convert = ProductPropertyValueConvert.INSTANCE.convert(createReqVO);
- productPropertyValueMapper.insert(convert);
- return convert.getId();
+
+ // 新增
+ ProductPropertyValueDO value = ProductPropertyValueConvert.INSTANCE.convert(createReqVO);
+ productPropertyValueMapper.insert(value);
+ return value.getId();
}
@Override
public void updatePropertyValue(ProductPropertyValueUpdateReqVO updateReqVO) {
- ProductPropertyValueDO productPropertyValueDO = productPropertyValueMapper.selectByName(updateReqVO.getPropertyId(), updateReqVO.getName());
+ validatePropertyValueExists(updateReqVO.getId());
+ // 校验名字唯一
+ ProductPropertyValueDO productPropertyValueDO = productPropertyValueMapper.selectByName
+ (updateReqVO.getPropertyId(), updateReqVO.getName());
if (productPropertyValueDO != null && !productPropertyValueDO.getId().equals(updateReqVO.getId())) {
throw exception(PROPERTY_VALUE_EXISTS);
}
- ProductPropertyValueDO convert = ProductPropertyValueConvert.INSTANCE.convert(updateReqVO);
- productPropertyValueMapper.updateById(convert);
+
+ // 更新
+ ProductPropertyValueDO updateObj = ProductPropertyValueConvert.INSTANCE.convert(updateReqVO);
+ productPropertyValueMapper.updateById(updateObj);
}
@Override
public void deletePropertyValue(Long id) {
+ validatePropertyValueExists(id);
productPropertyValueMapper.deleteById(id);
}
- @Override
- public ProductPropertyValueRespVO getPropertyValue(Long id) {
- ProductPropertyValueDO productPropertyValueDO = productPropertyValueMapper.selectOne(new LambdaQueryWrapper()
- .eq(ProductPropertyValueDO::getId, id));
- return ProductPropertyValueConvert.INSTANCE.convert(productPropertyValueDO);
+ private void validatePropertyValueExists(Long id) {
+ if (productPropertyValueMapper.selectById(id) == null) {
+ throw exception(PROPERTY_VALUE_NOT_EXISTS);
+ }
}
@Override
- public List getPropertyValueListByPropertyId(List id) {
- return ProductPropertyValueConvert.INSTANCE.convertList(productPropertyValueMapper.selectList("property_id", id));
+ public ProductPropertyValueDO getPropertyValue(Long id) {
+ return productPropertyValueMapper.selectById(id);
}
@Override
- public PageResult getPropertyValueListPage(ProductPropertyValuePageReqVO pageReqVO) {
- return ProductPropertyValueConvert.INSTANCE.convertPage(productPropertyValueMapper.selectPage(pageReqVO));
+ public List getPropertyValueListByPropertyId(Collection propertyIds) {
+ return productPropertyValueMapper.selectListByPropertyId(propertyIds);
}
+
+ @Override
+ public List getPropertyValueDetailList(Collection ids) {
+ // 获得属性值列表
+ if (CollUtil.isEmpty(ids)) {
+ return Collections.emptyList();
+ }
+ List values = productPropertyValueMapper.selectBatchIds(ids);
+ if (CollUtil.isEmpty(values)) {
+ return Collections.emptyList();
+ }
+ // 获得属性项列表
+ List keys = productPropertyService.getPropertyList(
+ convertSet(values, ProductPropertyValueDO::getPropertyId));
+ // 组装明细
+ return ProductPropertyValueConvert.INSTANCE.convertList(values, keys);
+ }
+
+ @Override
+ public Integer getPropertyValueCountByPropertyId(Long propertyId) {
+ return productPropertyValueMapper.selectCountByPropertyId(propertyId);
+ }
+
+ @Override
+ public PageResult getPropertyValuePage(ProductPropertyValuePageReqVO pageReqVO) {
+ return productPropertyValueMapper.selectPage(pageReqVO);
+ }
+
+ @Override
+ public void deletePropertyValueByPropertyId(Long propertyId) {
+ productPropertyValueMapper.deleteByPropertyId(propertyId);
+ }
+
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/bo/ProductPropertyValueDetailRespBO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/bo/ProductPropertyValueDetailRespBO.java
new file mode 100644
index 000000000..6776731f9
--- /dev/null
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/bo/ProductPropertyValueDetailRespBO.java
@@ -0,0 +1,33 @@
+package cn.iocoder.yudao.module.product.service.property.bo;
+
+import lombok.Data;
+
+/**
+ * 商品属性项的明细 Response BO
+ *
+ * @author 芋道源码
+ */
+@Data
+public class ProductPropertyValueDetailRespBO {
+
+ /**
+ * 属性的编号
+ */
+ private Long propertyId;
+
+ /**
+ * 属性的名称
+ */
+ private String propertyName;
+
+ /**
+ * 属性值的编号
+ */
+ private Long valueId;
+
+ /**
+ * 属性值的名称
+ */
+ private String valueName;
+
+}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java
index 1036d8348..621e12d9f 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java
@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.product.service.sku;
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO;
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO;
import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
+import org.springframework.lang.Nullable;
import java.util.Collection;
import java.util.List;
@@ -49,23 +50,25 @@ public interface ProductSkuService {
*
* @param list sku组合的集合
*/
- void validateSkus(List list, Integer specType);
+ void validateSkuList(List list, Integer specType);
/**
* 批量创建 SKU
*
* @param spuId 商品 SPU 编号
+ * @param spuName 商品 SPU 名称
* @param list SKU 对象集合
*/
- void createSkus(Long spuId, List list);
+ void createSkuList(Long spuId, String spuName, List list);
/**
* 根据 SPU 编号,批量更新它的 SKU 信息
*
* @param spuId SPU 编码
+ * @param spuName 商品 SPU 名称
* @param skus SKU 的集合
*/
- void updateSkus(Long spuId, List skus);
+ void updateSkuList(Long spuId, String spuName, List skus);
/**
* 更新 SKU 库存(增量)
@@ -77,20 +80,30 @@ public interface ProductSkuService {
void updateSkuStock(ProductSkuUpdateStockReqDTO updateStockReqDTO);
/**
- * 获得商品 sku 集合
+ * 获得商品 SKU 集合
*
* @param spuId spu 编号
* @return 商品sku 集合
*/
- List getSkusBySpuId(Long spuId);
+ List getSkuListBySpuId(Long spuId);
/**
- * 获得 spu 对应的 sku 集合
+ * 基于 SPU 编号和状态,获得商品 SKU 集合
+ *
+ * @param spuId SPU 编号
+ * @param status 状态
+ * @return 商品 SKU 集合
+ */
+ List getSkuListBySpuIdAndStatus(Long spuId,
+ @Nullable Integer status);
+
+ /**
+ * 获得 spu 对应的 SKU 集合
*
* @param spuIds spu 编码集合
* @return 商品 sku 集合
*/
- List getSkusBySpuIds(List spuIds);
+ List getSkuListBySpuId(List spuIds);
/**
* 通过 spuId 删除 sku 信息
@@ -104,7 +117,6 @@ public interface ProductSkuService {
*
* @return SKU 数组
*/
- List getSkusByAlarmStock();
-
+ List getSkuListByAlarmStock();
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java
index 2791ae5d3..1ab2523cc 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java
@@ -1,13 +1,13 @@
package cn.iocoder.yudao.module.product.service.sku;
+import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
-import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO;
-import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyRespVO;
-import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO;
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuBaseVO;
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO;
import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert;
+import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO;
+import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO;
import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
import cn.iocoder.yudao.module.product.dal.mysql.sku.ProductSkuMapper;
import cn.iocoder.yudao.module.product.enums.ErrorCodeConstants;
@@ -25,6 +25,7 @@ import java.util.*;
import java.util.stream.Collectors;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.*;
@@ -78,22 +79,24 @@ public class ProductSkuServiceImpl implements ProductSkuService {
}
@Override
- public void validateSkus(List skus, Integer specType) {
+ public void validateSkuList(List skus, Integer specType) {
// 非多规格,不需要校验
if (ObjectUtil.notEqual(specType, ProductSpuSpecTypeEnum.DISABLE.getType())) {
return;
}
- // 1、校验规格属性存在
- Set propertyIds = skus.stream().filter(p -> p.getProperties() != null).flatMap(p -> p.getProperties().stream()) // 遍历多个 Property 属性
- .map(ProductSkuBaseVO.Property::getPropertyId).collect(Collectors.toSet()); // 将每个 Property 转换成对应的 propertyId,最后形成集合
- List propertyList = productPropertyService.getPropertyList(propertyIds);
+ // 1、校验属性项存在
+ Set propertyIds = skus.stream().filter(p -> p.getProperties() != null)
+ .flatMap(p -> p.getProperties().stream()) // 遍历多个 Property 属性
+ .map(ProductSkuBaseVO.Property::getPropertyId) // 将每个 Property 转换成对应的 propertyId,最后形成集合
+ .collect(Collectors.toSet());
+ List propertyList = productPropertyService.getPropertyList(propertyIds);
if (propertyList.size() != propertyIds.size()) {
throw exception(PROPERTY_NOT_EXISTS);
}
- // 2. 校验,一个 SKU 下,没有重复的规格。校验方式是,遍历每个 SKU ,看看是否有重复的规格 propertyId
- Map propertyValueMap = CollectionUtils.convertMap(productPropertyValueService.getPropertyValueListByPropertyId(new ArrayList<>(propertyIds)), ProductPropertyValueRespVO::getId);
+ // 2. 校验,一个 SKU 下,没有重复的属性。校验方式是,遍历每个 SKU ,看看是否有重复的属性 propertyId
+ Map propertyValueMap = convertMap(productPropertyValueService.getPropertyValueListByPropertyId(propertyIds), ProductPropertyValueDO::getId);
skus.forEach(sku -> {
Set skuPropertyIds = convertSet(sku.getProperties(), propertyItem -> propertyValueMap.get(propertyItem.getValueId()).getPropertyId());
if (skuPropertyIds.size() != sku.getProperties().size()) {
@@ -101,7 +104,7 @@ public class ProductSkuServiceImpl implements ProductSkuService {
}
});
- // 3. 再校验,每个 Sku 的规格值的数量,是一致的。
+ // 3. 再校验,每个 Sku 的属性值的数量,是一致的。
int attrValueIdsSize = skus.get(0).getProperties().size();
for (int i = 1; i < skus.size(); i++) {
if (attrValueIdsSize != skus.get(i).getProperties().size()) {
@@ -119,21 +122,23 @@ public class ProductSkuServiceImpl implements ProductSkuService {
}
@Override
- public void createSkus(Long spuId, List skuCreateReqList) {
- // 批量插入 SKU
- List skuDOList = ProductSkuConvert.INSTANCE.convertSkuDOList(skuCreateReqList);
- skuDOList.forEach(v -> v.setSpuId(spuId));
- productSkuMapper.insertBatch(skuDOList);
+ public void createSkuList(Long spuId, String spuName, List skuCreateReqList) {
+ productSkuMapper.insertBatch(ProductSkuConvert.INSTANCE.convertList06(skuCreateReqList, spuId, spuName));
}
@Override
- public List getSkusBySpuId(Long spuId) {
- return productSkuMapper.selectList(ProductSkuDO::getSpuId, spuId);
+ public List getSkuListBySpuId(Long spuId) {
+ return productSkuMapper.selectListBySpuId(spuId);
}
@Override
- public List getSkusBySpuIds(List spuIds) {
- return productSkuMapper.selectList(ProductSkuDO::getSpuId, spuIds);
+ public List getSkuListBySpuIdAndStatus(Long spuId, Integer status) {
+ return productSkuMapper.selectListBySpuIdAndStatus(spuId, status);
+ }
+
+ @Override
+ public List getSkuListBySpuId(List spuIds) {
+ return productSkuMapper.selectListBySpuId(spuIds);
}
@Override
@@ -142,59 +147,44 @@ public class ProductSkuServiceImpl implements ProductSkuService {
}
@Override
- public List getSkusByAlarmStock() {
+ public List getSkuListByAlarmStock() {
return productSkuMapper.selectListByAlarmStock();
}
@Override
- @Transactional
- public void updateSkus(Long spuId, List skus) {
- // 查询 SPU 下已经存在的 SKU 的集合
- List existsSkus = productSkuMapper.selectListBySpuId(spuId);
- // 构建规格与 SKU 的映射关系;
- // TODO @luowenfeng: 可以下 existsSkuMap2; 会简洁一点; 另外, 可以考虑抽一个小方法, 用于 Properties 生成一个串; 这样 177 也可以复用了
- Map existsSkuMap = existsSkus.stream()
- .map(v -> {
- String collect = v.getProperties() == null? "null": v.getProperties()
- .stream()
- .map(m -> String.valueOf(m.getValueId()))
- .collect(Collectors.joining());
- return String.join("-", collect, String.valueOf(v.getId()));
- })
- .collect(Collectors.toMap(v -> v.split("-")[0], v -> Long.valueOf(v.split("-")[1])));
+ @Transactional(rollbackFor = Exception.class)
+ public void updateSkuList(Long spuId, String spuName, List skus) {
+ // 构建属性与 SKU 的映射关系;
+ Map existsSkuMap = convertMap(productSkuMapper.selectListBySpuId(spuId),
+ ProductSkuConvert.INSTANCE::buildPropertyKey, ProductSkuDO::getId);
// 拆分三个集合,新插入的、需要更新的、需要删除的
List insertSkus = new ArrayList<>();
List updateSkus = new ArrayList<>();
- List deleteSkus = new ArrayList<>();
-
- List allUpdateSkus = ProductSkuConvert.INSTANCE.convertSkuDOList(skus);
- allUpdateSkus.forEach(p -> {
- String propertiesKey = p.getProperties() == null? "null": p.getProperties().stream().map(m -> String.valueOf(m.getValueId())).collect(Collectors.joining());
+ List allUpdateSkus = ProductSkuConvert.INSTANCE.convertList06(skus, null, spuName);
+ allUpdateSkus.forEach(sku -> {
+ String propertiesKey = ProductSkuConvert.INSTANCE.buildPropertyKey(sku);
// 1、找得到的,进行更新
- if (existsSkuMap.containsKey(propertiesKey)) {
- updateSkus.add(p);
- existsSkuMap.remove(propertiesKey);
+ Long existsSkuId = existsSkuMap.remove(propertiesKey);
+ if (existsSkuId != null) {
+ sku.setId(existsSkuId);
+ updateSkus.add(sku);
return;
}
// 2、找不到,进行插入
- p.setSpuId(spuId);
- insertSkus.add(p);
+ sku.setSpuId(spuId);
+ insertSkus.add(sku);
});
- // 3、多余的,删除
- if(!existsSkuMap.isEmpty()){
- deleteSkus = new ArrayList<>(existsSkuMap.values());
- }
- // 4、执行修改 Sku
- if (!insertSkus.isEmpty()) {
+ // 执行最终的批量操作
+ if (CollUtil.isNotEmpty(insertSkus)) {
productSkuMapper.insertBatch(insertSkus);
}
- if (!updateSkus.isEmpty()) {
- updateSkus.forEach(p -> productSkuMapper.updateById(p));
+ if (CollUtil.isNotEmpty(updateSkus)) {
+ updateSkus.forEach(sku -> productSkuMapper.updateById(sku));
}
- if (!deleteSkus.isEmpty()) {
- productSkuMapper.deleteBatchIds(deleteSkus);
+ if (CollUtil.isNotEmpty(existsSkuMap)) {
+ productSkuMapper.deleteBatchIds(existsSkuMap.values());
}
}
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuService.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuService.java
index 151edbf86..0ae7359eb 100755
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuService.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuService.java
@@ -2,8 +2,7 @@ package cn.iocoder.yudao.module.product.service.spu;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*;
-import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageReqVO;
-import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageRespVO;
+import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO;
import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
import javax.validation.Valid;
@@ -42,21 +41,13 @@ public interface ProductSpuService {
*/
void deleteSpu(Long id);
- /**
- * 获得商品 SPU 详情
- *
- * @param id 编号
- * @return 商品 SPU
- */
- ProductSpuDetailRespVO getSpuDetail(Long id);
-
/**
* 获得商品 SPU
*
* @param id 编号
* @return 商品 SPU
*/
- ProductSpuRespVO getSpu(Long id);
+ ProductSpuDO getSpu(Long id);
/**
* 获得商品 SPU 列表
@@ -89,15 +80,16 @@ public interface ProductSpuService {
* @param pageReqVO 分页查询
* @return 商品spu分页
*/
- PageResult getSpuPage(ProductSpuPageReqVO pageReqVO);
+ PageResult getSpuPage(ProductSpuPageReqVO pageReqVO);
/**
* 获得商品 SPU 分页
*
* @param pageReqVO 分页查询
- * @return 商品spu分页
+ * @param status 状态
+ * @return 商品 SPU 分页
*/
- PageResult