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 454314e78..af97bb9c3 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 @@ -10,30 +10,29 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode; public interface ErrorCodeConstants { // ========== 商品分类相关 1008001000 ============ - ErrorCode PRODUCT_CATEGORY_NOT_EXISTS = new ErrorCode(1008001000, "商品分类不存在"); - ErrorCode PRODUCT_CATEGORY_PARENT_NOT_EXISTS = new ErrorCode(1008001001, "父分类不存在"); - ErrorCode PRODUCT_CATEGORY_PARENT_NOT_FIRST_LEVEL = new ErrorCode(1008001002, "父分类不能是二级分类"); - ErrorCode PRODUCT_CATEGORY_EXISTS_CHILDREN = new ErrorCode(1008001003, "存在子分类,无法删除"); - ErrorCode PRODUCT_CATEGORY_DISABLED = new ErrorCode(1008001004, "商品分类({})已禁用,无法使用"); - ErrorCode PRODUCT_CATEGORY_LEVEL = new ErrorCode(1008001005, "商品需挂在三级分类下"); + ErrorCode CATEGORY_NOT_EXISTS = new ErrorCode(1008001000, "商品分类不存在"); + ErrorCode CATEGORY_PARENT_NOT_EXISTS = new ErrorCode(1008001001, "父分类不存在"); + 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 PRODUCT_BRAND_NOT_EXISTS = new ErrorCode(1008002000, "品牌不存在"); + // ========== 商品品牌相关编号 1008002000 ========== + ErrorCode BRAND_NOT_EXISTS = new ErrorCode(1008002000, "品牌不存在"); - // ========== 规格名称 1008003000 ========== + // ========== 商品规格名称 1008003000 ========== ErrorCode PROPERTY_NOT_EXISTS = new ErrorCode(1008003000, "规格名称不存在"); // ========== 规格值 1008004000 ========== ErrorCode PROPERTY_VALUE_NOT_EXISTS = new ErrorCode(1008004000, "规格值不存在"); - // ========== 商品spu 1008005000 ========== - ErrorCode SPU_NOT_EXISTS = new ErrorCode(1008005000, "商品spu不存在"); + // ========== 商品 SPU 1008005000 ========== + ErrorCode SPU_NOT_EXISTS = new ErrorCode(1008005000, "商品 SPU 不存在"); - // ========== 商品sku 1008006000 ========== - ErrorCode SKU_NOT_EXISTS = new ErrorCode(1008006000, "商品sku不存在"); - ErrorCode SKU_PROPERTIES_DUPLICATED = new ErrorCode(1008006001, "商品sku的属性组合存在重复"); + // ========== 商品 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_SKU_NOT_DUPLICATE = new ErrorCode(1008006003, "一个 SPU 下的每个 SKU,必须不重复"); - ErrorCode PRODUCT_SPU_ATTR_NUMBERS_MUST_BE_EQUALS = new ErrorCode(1008006002, "一个 Spu 下的每个 SKU ,其规格数必须一致"); - - ErrorCode PRODUCT_SPU_SKU_NOT_DUPLICATE = new ErrorCode(1008006003, "一个 SPU 下的每个 SKU ,必须不重复"); } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/ProductBrandController.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/ProductBrandController.java index c159883be..0558d9866 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/ProductBrandController.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/ProductBrandController.java @@ -2,15 +2,9 @@ package cn.iocoder.yudao.module.product.controller.admin.brand; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; -import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.yudao.module.product.controller.admin.brand.vo.*; -import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryListReqVO; -import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryRespVO; import cn.iocoder.yudao.module.product.convert.brand.ProductBrandConvert; -import cn.iocoder.yudao.module.product.convert.category.ProductCategoryConvert; import cn.iocoder.yudao.module.product.dal.dataobject.brand.ProductBrandDO; -import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO; import cn.iocoder.yudao.module.product.service.brand.ProductBrandService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; @@ -20,14 +14,11 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; -import javax.servlet.http.HttpServletResponse; import javax.validation.Valid; -import java.io.IOException; import java.util.Comparator; import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; @Api(tags = "管理后台 - 商品品牌") @RestController @@ -88,5 +79,4 @@ public class ProductBrandController { return success(ProductBrandConvert.INSTANCE.convertList(list)); } - } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/ProductCategoryController.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/ProductCategoryController.java index 4467d392a..2a93a5a26 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/ProductCategoryController.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/ProductCategoryController.java @@ -35,14 +35,14 @@ public class ProductCategoryController { @ApiOperation("创建商品分类") @PreAuthorize("@ss.hasPermission('product:category:create')") public CommonResult createProductCategory(@Valid @RequestBody ProductCategoryCreateReqVO createReqVO) { - return success(categoryService.createProductCategory(createReqVO)); + return success(categoryService.createCategory(createReqVO)); } @PutMapping("/update") @ApiOperation("更新商品分类") @PreAuthorize("@ss.hasPermission('product:category:update')") public CommonResult updateProductCategory(@Valid @RequestBody ProductCategoryUpdateReqVO updateReqVO) { - categoryService.updateProductCategory(updateReqVO); + categoryService.updateCategory(updateReqVO); return success(true); } @@ -51,7 +51,7 @@ public class ProductCategoryController { @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class) @PreAuthorize("@ss.hasPermission('product:category:delete')") public CommonResult deleteProductCategory(@RequestParam("id") Long id) { - categoryService.deleteProductCategory(id); + categoryService.deleteCategory(id); return success(true); } @@ -60,7 +60,7 @@ public class ProductCategoryController { @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class) @PreAuthorize("@ss.hasPermission('product:category:query')") public CommonResult getProductCategory(@RequestParam("id") Long id) { - ProductCategoryDO category = categoryService.getProductCategory(id); + ProductCategoryDO category = categoryService.getCategory(id); return success(ProductCategoryConvert.INSTANCE.convert(category)); } @@ -68,7 +68,7 @@ public class ProductCategoryController { @ApiOperation("获得商品分类列表") @PreAuthorize("@ss.hasPermission('product:category:query')") public CommonResult> getProductCategoryList(@Valid ProductCategoryListReqVO treeListReqVO) { - List list = categoryService.getEnableProductCategoryList(treeListReqVO); + List list = categoryService.getEnableCategoryList(treeListReqVO); list.sort(Comparator.comparing(ProductCategoryDO::getSort)); return success(ProductCategoryConvert.INSTANCE.convertList(list)); } 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 f1d31acab..6ed0ec1d1 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 @@ -62,7 +62,7 @@ public class ProductPropertyController { @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) { + public CommonResult getProperty(@RequestParam("id") Long id) { return success(productPropertyService.getPropertyResp(id)); } @@ -70,7 +70,7 @@ public class ProductPropertyController { @ApiOperation("获得规格名称列表") @ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class) @PreAuthorize("@ss.hasPermission('product:property:query')") - public CommonResult> getPropertyList(@RequestParam("ids") Collection ids) { + public CommonResult> getPropertyList(@RequestParam("ids") Collection ids) { List list = productPropertyService.getPropertyList(ids); return success(ProductPropertyConvert.INSTANCE.convertList(list)); } @@ -78,7 +78,7 @@ public class ProductPropertyController { @GetMapping("/page") @ApiOperation("获得规格名称分页") @PreAuthorize("@ss.hasPermission('product:property:query')") - public CommonResult> getPropertyPage(@Valid ProductPropertyPageReqVO pageVO) { + public CommonResult> getPropertyPage(@Valid ProductPropertyPageReqVO pageVO) { return success(productPropertyService.getPropertyListPage(pageVO)); } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/ProductPropertyAndValueRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/ProductPropertyAndValueRespVO.java new file mode 100644 index 000000000..7a73ca35f --- /dev/null +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/ProductPropertyAndValueRespVO.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.product.controller.admin.property.vo; + +import cn.iocoder.yudao.module.product.controller.admin.propertyvalue.vo.ProductPropertyValueRespVO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import java.util.Date; +import java.util.List; + +@ApiModel("管理后台 - 规格 + 规格值 Response VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ProductPropertyAndValueRespVO extends ProductPropertyBaseVO { + + @ApiModelProperty(value = "规格的编号", required = true, example = "1024") + private Long id; + + @ApiModelProperty(value = "创建时间", required = true) + private Date createTime; + + /** + * 规格值的集合 + */ + private List values; + +} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/ProductPropertyBaseVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/ProductPropertyBaseVO.java index 4d38763f9..e3deb8838 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/ProductPropertyBaseVO.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/ProductPropertyBaseVO.java @@ -1,10 +1,9 @@ package cn.iocoder.yudao.module.product.controller.admin.property.vo; -import lombok.*; -import java.util.*; -import io.swagger.annotations.*; -import javax.validation.constraints.*; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +// TODO @芋艿:完整的 review 下规格 /** * 规格名称 Base VO,提供给添加、修改、详细的子 VO 使用 * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/ProductPropertyRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/ProductPropertyRespVO.java deleted file mode 100644 index 978f26308..000000000 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/ProductPropertyRespVO.java +++ /dev/null @@ -1,23 +0,0 @@ -package cn.iocoder.yudao.module.product.controller.admin.property.vo; - -import cn.iocoder.yudao.module.product.controller.admin.propertyvalue.vo.ProductPropertyValueRespVO; -import lombok.*; -import java.util.*; -import io.swagger.annotations.*; - -@ApiModel("管理后台 - 规格名称 Response VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class ProductPropertyRespVO extends ProductPropertyBaseVO { - - @ApiModelProperty(value = "主键", required = true) - private Long id; - - @ApiModelProperty(value = "创建时间") - private Date createTime; - - @ApiModelProperty(value = "属性值") - private List propertyValueList; - -} 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 c9d059578..adc450011 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 @@ -6,14 +6,13 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; -import javax.validation.constraints.NotEmpty; - @ApiModel("管理后台 - 商品 SKU 创建/更新 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) public class ProductSkuCreateOrUpdateReqVO extends ProductSkuBaseVO { + // TODO @Luowenfeng:可以不用哈,如果基于规格匹配 @ApiModelProperty(value = "商品 id 更新时须有", example = "1") private Long id; 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 31dba3eff..4fa59012d 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 @@ -36,14 +36,14 @@ public class ProductSpuController { @ApiOperation("创建商品 SPU") @PreAuthorize("@ss.hasPermission('product:spu:create')") public CommonResult createProductSpu(@Valid @RequestBody ProductSpuCreateReqVO createReqVO) { - return success(spuService.createProductSpu(createReqVO)); + return success(spuService.createSpu(createReqVO)); } @PutMapping("/update") @ApiOperation("更新商品 SPU") @PreAuthorize("@ss.hasPermission('product:spu:update')") public CommonResult updateSpu(@Valid @RequestBody ProductSpuUpdateReqVO updateReqVO) { - spuService.updateProductSpu(updateReqVO); + spuService.updateSpu(updateReqVO); return success(true); } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/SpuRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/SpuRespVO.java index 0121aec47..7cdf6f975 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/SpuRespVO.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/SpuRespVO.java @@ -35,6 +35,8 @@ public class SpuRespVO extends ProductSpuBaseVO { @ApiModelProperty(value = "分类id数组,一直递归到一级父节点", example = "[1,2,4]") private LinkedList categoryIds; + // TODO @芋艿:再琢磨下 这个 VO 类,其实变成 SpuRespVO 内嵌的 VO 类会更好一点;然后把 SpuRespVO 改成 SpuDetailSpuVO + @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/app/category/AppCategoryController.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/category/AppCategoryController.java index 1b5664b85..fec882c48 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/category/AppCategoryController.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/category/AppCategoryController.java @@ -30,7 +30,7 @@ public class AppCategoryController { @GetMapping("/list") @ApiOperation("获得商品分类列表") public CommonResult> getProductCategoryList() { - List list = categoryService.getEnableProductCategoryList(); + List list = categoryService.getEnableCategoryList(); list.sort(Comparator.comparing(ProductCategoryDO::getSort)); return success(ProductCategoryConvert.INSTANCE.convertList03(list)); } 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 c44cdc841..022580f30 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 @@ -23,11 +23,11 @@ public interface ProductPropertyConvert { ProductPropertyDO convert(ProductPropertyUpdateReqVO bean); - ProductPropertyRespVO convert(ProductPropertyDO bean); + ProductPropertyAndValueRespVO convert(ProductPropertyDO bean); - List convertList(List list); + List convertList(List list); - PageResult convertPage(PageResult page); + PageResult convertPage(PageResult page); List convertList02(List list); diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/brand/ProductBrandMapper.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/brand/ProductBrandMapper.java index 38558564c..55e4e6927 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/brand/ProductBrandMapper.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/brand/ProductBrandMapper.java @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.product.dal.mysql.brand; 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.brand.vo.ProductBrandBaseVO; import cn.iocoder.yudao.module.product.controller.admin.brand.vo.ProductBrandListReqVO; import cn.iocoder.yudao.module.product.controller.admin.brand.vo.ProductBrandPageReqVO; import cn.iocoder.yudao.module.product.dal.dataobject.brand.ProductBrandDO; @@ -27,4 +26,5 @@ public interface ProductBrandMapper extends BaseMapperX { return selectList(new LambdaQueryWrapperX() .likeIfPresent(ProductBrandDO::getName, reqVO.getName())); } + } 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 7651e0c8c..0e3c8653c 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 @@ -7,7 +7,6 @@ import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuPageReq import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; import org.apache.ibatis.annotations.Mapper; -import java.util.Collections; import java.util.List; /** @@ -34,13 +33,12 @@ public interface ProductSkuMapper extends BaseMapperX { // TODO @franky:方法名 selectList; 可以直接调用 selectList - default List selectBySpuIds(List spuIds) { - return selectList(new LambdaQueryWrapperX() - .inIfPresent(ProductSkuDO::getSpuId, spuIds)); + default List selectListBySpuIds(List spuIds) { + return selectList(ProductSkuDO::getSpuId, spuIds); } - default List selectBySpuId(Long spuIds) { - return selectBySpuIds(Collections.singletonList(spuIds)); + default List selectListBySpuId(Long spuId) { + return selectList(ProductSkuDO::getSpuId, spuId); } default void deleteBySpuId(Long spuId) { diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandService.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandService.java index 4c9060055..54d4df601 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandService.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandService.java @@ -55,10 +55,11 @@ public interface ProductBrandService { /** * 获得品牌列表 - * @param listVo 请求参数 + * + * @param listReqVO 请求参数 * @return 品牌列表 */ - List getBrandList(ProductBrandListReqVO listVo); + List getBrandList(ProductBrandListReqVO listReqVO); /** * 验证选择的商品分类是否合法 diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandServiceImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandServiceImpl.java index be67260ff..28a02da38 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandServiceImpl.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandServiceImpl.java @@ -1,11 +1,13 @@ package cn.iocoder.yudao.module.product.service.brand; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.product.controller.admin.brand.vo.*; +import cn.iocoder.yudao.module.product.controller.admin.brand.vo.ProductBrandCreateReqVO; +import cn.iocoder.yudao.module.product.controller.admin.brand.vo.ProductBrandListReqVO; +import cn.iocoder.yudao.module.product.controller.admin.brand.vo.ProductBrandPageReqVO; +import cn.iocoder.yudao.module.product.controller.admin.brand.vo.ProductBrandUpdateReqVO; import cn.iocoder.yudao.module.product.convert.brand.ProductBrandConvert; import cn.iocoder.yudao.module.product.dal.dataobject.brand.ProductBrandDO; import cn.iocoder.yudao.module.product.dal.mysql.brand.ProductBrandMapper; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; @@ -14,8 +16,7 @@ import java.util.Collection; import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.PRODUCT_BRAND_NOT_EXISTS; -import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.PRODUCT_CATEGORY_LEVEL; +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.BRAND_NOT_EXISTS; /** * 品牌 Service 实现类 @@ -57,7 +58,7 @@ public class ProductBrandServiceImpl implements ProductBrandService { private void validateBrandExists(Long id) { if (brandMapper.selectById(id) == null) { - throw exception(PRODUCT_BRAND_NOT_EXISTS); + throw exception(BRAND_NOT_EXISTS); } } @@ -72,14 +73,14 @@ public class ProductBrandServiceImpl implements ProductBrandService { } @Override - public List getBrandList(ProductBrandListReqVO listVo) { - return brandMapper.selectList(listVo); + public List getBrandList(ProductBrandListReqVO listReqVO) { + return brandMapper.selectList(listReqVO); } @Override public void validateProductBrand(Long id) { if(getBrand(id) == null){ - throw exception(PRODUCT_BRAND_NOT_EXISTS); + throw exception(BRAND_NOT_EXISTS); } } 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 264f81c27..118e8118b 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 @@ -22,21 +22,21 @@ public interface ProductCategoryService { * @param createReqVO 创建信息 * @return 编号 */ - Long createProductCategory(@Valid ProductCategoryCreateReqVO createReqVO); + Long createCategory(@Valid ProductCategoryCreateReqVO createReqVO); /** * 更新商品分类 * * @param updateReqVO 更新信息 */ - void updateProductCategory(@Valid ProductCategoryUpdateReqVO updateReqVO); + void updateCategory(@Valid ProductCategoryUpdateReqVO updateReqVO); /** * 删除商品分类 * * @param id 编号 */ - void deleteProductCategory(Long id); + void deleteCategory(Long id); /** * 获得商品分类 @@ -44,7 +44,7 @@ public interface ProductCategoryService { * @param id 编号 * @return 商品分类 */ - ProductCategoryDO getProductCategory(Long id); + ProductCategoryDO getCategory(Long id); /** * 获得商品分类列表 @@ -52,7 +52,7 @@ public interface ProductCategoryService { * @param ids 编号 * @return 商品分类列表 */ - List getEnableProductCategoryList(Collection ids); + List getEnableCategoryList(Collection ids); /** * 获得商品分类列表 @@ -60,20 +60,21 @@ public interface ProductCategoryService { * @param listReqVO 查询条件 * @return 商品分类列表 */ - List getEnableProductCategoryList(ProductCategoryListReqVO listReqVO); + List getEnableCategoryList(ProductCategoryListReqVO listReqVO); /** - * 验证选择的商品分类是否合法 + * 验证选择的商品分类的级别是否合法 + * 例如说,商品发布的时候,必须在第 3 级别 * * @param id 分类编号 */ - void validateProductCategory(Long id); + void validateCategoryLevel(Long id); /** * 获得开启状态的商品分类列表 * * @return 商品分类列表 */ - List getEnableProductCategoryList(); + List getEnableCategoryList(); } 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 7f1da8553..b4664fd4d 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 @@ -32,7 +32,7 @@ public class ProductCategoryServiceImpl implements ProductCategoryService { private ProductCategoryMapper productCategoryMapper; @Override - public Long createProductCategory(ProductCategoryCreateReqVO createReqVO) { + public Long createCategory(ProductCategoryCreateReqVO createReqVO) { // 校验父分类存在 validateParentProductCategory(createReqVO.getParentId()); @@ -44,7 +44,7 @@ public class ProductCategoryServiceImpl implements ProductCategoryService { } @Override - public void updateProductCategory(ProductCategoryUpdateReqVO updateReqVO) { + public void updateCategory(ProductCategoryUpdateReqVO updateReqVO) { // 校验分类是否存在 validateProductCategoryExists(updateReqVO.getId()); // 校验父分类存在 @@ -56,12 +56,12 @@ public class ProductCategoryServiceImpl implements ProductCategoryService { } @Override - public void deleteProductCategory(Long id) { + public void deleteCategory(Long id) { // 校验分类是否存在 validateProductCategoryExists(id); // 校验是否还有子分类 if (productCategoryMapper.selectCountByParentId(id) > 0) { - throw exception(PRODUCT_CATEGORY_EXISTS_CHILDREN); + throw exception(CATEGORY_EXISTS_CHILDREN); } // 删除 @@ -76,61 +76,69 @@ public class ProductCategoryServiceImpl implements ProductCategoryService { // 父分类不存在 ProductCategoryDO category = productCategoryMapper.selectById(id); if (category == null) { - throw exception(PRODUCT_CATEGORY_PARENT_NOT_EXISTS); + throw exception(CATEGORY_PARENT_NOT_EXISTS); } // 父分类不能是二级分类 if (Objects.equals(id, ProductCategoryDO.PARENT_ID_NULL)) { - throw exception(PRODUCT_CATEGORY_PARENT_NOT_FIRST_LEVEL); + throw exception(CATEGORY_PARENT_NOT_FIRST_LEVEL); } } private void validateProductCategoryExists(Long id) { ProductCategoryDO category = productCategoryMapper.selectById(id); if (category == null) { - throw exception(PRODUCT_CATEGORY_NOT_EXISTS); + throw exception(CATEGORY_NOT_EXISTS); } } @Override - public void validateProductCategory(Long id) { - Integer level = categoryLevel(id, 1); + public void validateCategoryLevel(Long id) { + Integer level = getProductCategoryLevel(id, 1); if(level < 3){ - throw exception(PRODUCT_CATEGORY_LEVEL); + throw exception(CATEGORY_LEVEL_ERROR); } } - // 校验分类级别 - private Integer categoryLevel(Long id, int level){ + // TODO @Luowenfeng:建议使用 for 循环,避免递归 + /** + * 获得商品分类的级别 + * + * @param id 商品分类的编号 + * @return 级别 + */ + private Integer getProductCategoryLevel(Long id, int level){ ProductCategoryDO category = productCategoryMapper.selectById(id); if (category == null) { - throw exception(PRODUCT_CATEGORY_NOT_EXISTS); + throw exception(CATEGORY_NOT_EXISTS); } + // TODO Luowenfeng:去掉是否开启,它不影响级别哈 if (ObjectUtil.notEqual(category.getStatus(), CommonStatusEnum.ENABLE.getStatus())) { - throw exception(PRODUCT_CATEGORY_DISABLED); + throw exception(CATEGORY_DISABLED); } - if(category.getParentId() == 0) { + // TODO Luowenfeng:不使用 0 直接比较哈,使用枚举 + if (category.getParentId() == 0) { return level; } - return categoryLevel(category.getParentId(), ++level); + return getProductCategoryLevel(category.getParentId(), ++level); } @Override - public ProductCategoryDO getProductCategory(Long id) { + public ProductCategoryDO getCategory(Long id) { return productCategoryMapper.selectById(id); } @Override - public List getEnableProductCategoryList(Collection ids) { + public List getEnableCategoryList(Collection ids) { return productCategoryMapper.selectBatchIds(ids); } @Override - public List getEnableProductCategoryList(ProductCategoryListReqVO listReqVO) { + public List getEnableCategoryList(ProductCategoryListReqVO listReqVO) { return productCategoryMapper.selectList(listReqVO); } @Override - public List getEnableProductCategoryList() { + public List getEnableCategoryList() { return productCategoryMapper.selectListByStatus(CommonStatusEnum.ENABLE.getStatus()); } 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 a663a49ce..90d1d15bd 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,10 +1,12 @@ package cn.iocoder.yudao.module.product.service.property; -import java.util.*; -import javax.validation.*; +import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.product.controller.admin.property.vo.*; import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO; -import cn.iocoder.yudao.framework.common.pojo.PageResult; + +import javax.validation.Valid; +import java.util.Collection; +import java.util.List; /** * 规格名称 Service 接口 @@ -72,14 +74,16 @@ public interface ProductPropertyService { * @param pageReqVO * @return */ - PageResult getPropertyListPage(ProductPropertyPageReqVO pageReqVO); + PageResult getPropertyListPage(ProductPropertyPageReqVO pageReqVO); - ProductPropertyRespVO getPropertyResp(Long id); + ProductPropertyAndValueRespVO getPropertyResp(Long id); /** - * 根据数据名id集合查询属性名以及属性值的集合 - * @param propertyIds 属性名id集合 - * @return + * 根据规格属性编号的集合,获得对应的规格 + 规格值的集合 + * + * @param ids 规格编号的集合 + * @return 对应的规格 + 规格值的集合 */ - List selectByIds(List propertyIds); + List getPropertyAndValueList(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 f650e90d9..5744e6ec3 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 @@ -108,11 +108,11 @@ public class ProductPropertyServiceImpl implements ProductPropertyService { } @Override - public PageResult getPropertyListPage(ProductPropertyPageReqVO pageReqVO) { + public PageResult getPropertyListPage(ProductPropertyPageReqVO pageReqVO) { //获取属性列表 PageResult pageResult = productPropertyMapper.selectPage(pageReqVO); - PageResult propertyRespVOPageResult = ProductPropertyConvert.INSTANCE.convertPage(pageResult); - List propertyIds = propertyRespVOPageResult.getList().stream().map(ProductPropertyRespVO::getId).collect(Collectors.toList()); + PageResult propertyRespVOPageResult = ProductPropertyConvert.INSTANCE.convertPage(pageResult); + List propertyIds = propertyRespVOPageResult.getList().stream().map(ProductPropertyAndValueRespVO::getId).collect(Collectors.toList()); //获取属性值列表 List productPropertyValueDOList = productPropertyValueMapper.getPropertyValueListByPropertyId(propertyIds); @@ -121,7 +121,7 @@ public class ProductPropertyServiceImpl implements ProductPropertyService { propertyRespVOPageResult.getList().forEach(x->{ Long propertyId = x.getId(); List valueDOList = propertyValueRespVOList.stream().filter(v -> v.getPropertyId().equals(propertyId)).collect(Collectors.toList()); - x.setPropertyValueList(valueDOList); + x.setValues(valueDOList); }); return propertyRespVOPageResult; } @@ -131,25 +131,25 @@ public class ProductPropertyServiceImpl implements ProductPropertyService { } @Override - public ProductPropertyRespVO getPropertyResp(Long id) { + public ProductPropertyAndValueRespVO getPropertyResp(Long id) { //查询规格 ProductPropertyDO property = getProperty(id); - ProductPropertyRespVO propertyRespVO = ProductPropertyConvert.INSTANCE.convert(property); + ProductPropertyAndValueRespVO propertyRespVO = ProductPropertyConvert.INSTANCE.convert(property); //查询属性值 List valueDOList = productPropertyValueMapper.getPropertyValueListByPropertyId(Arrays.asList(id)); List propertyValueRespVOS = ProductPropertyValueConvert.INSTANCE.convertList(valueDOList); //组装 - propertyRespVO.setPropertyValueList(propertyValueRespVOS); + propertyRespVO.setValues(propertyValueRespVOS); return propertyRespVO; } @Override - public List selectByIds(List propertyIds) { - List productPropertyRespVO = ProductPropertyConvert.INSTANCE.convertList(productPropertyMapper.selectBatchIds(propertyIds)); + public List getPropertyAndValueList(Collection ids) { + List productPropertyRespVO = ProductPropertyConvert.INSTANCE.convertList(productPropertyMapper.selectBatchIds(ids)); //查询属性值 - List valueDOList = productPropertyValueMapper.getPropertyValueListByPropertyId(propertyIds); + List valueDOList = productPropertyValueMapper.selectBatchIds(ids); Map> propertyValuesMap = valueDOList.stream().collect(Collectors.groupingBy(ProductPropertyValueDO::getPropertyId)); - productPropertyRespVO.forEach(p -> p.setPropertyValueList(ProductPropertyValueConvert.INSTANCE.convertList(propertyValuesMap.get(p.getId())))); + productPropertyRespVO.forEach(p -> p.setValues(ProductPropertyValueConvert.INSTANCE.convertList(propertyValuesMap.get(p.getId())))); return productPropertyRespVO; } } 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 59e8a04d7..7629bd5a3 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 @@ -11,14 +11,14 @@ import java.util.Collection; import java.util.List; /** - * 商品sku Service 接口 + * 商品 SKU Service 接口 * * @author 芋道源码 */ public interface ProductSkuService { /** - * 创建商品sku + * 创建商品 SKU * * @param createReqVO 创建信息 * @return 编号 @@ -68,14 +68,15 @@ public interface ProductSkuService { * * @param list sku组合的集合 */ - void validateProductSkus(List list, Integer specType); + void validateSkus(List list, Integer specType); /** * 批量创建 SKU * + * @param spuId 商品 SPU 编号 * @param list SKU 对象集合 */ - void createProductSkus(List list, Long spuId); + void createSkus(Long spuId, List list); /** * 根据 SPU 编号,批量更新它的 SKU 信息 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 60191d1b0..1e30a597a 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,9 +1,10 @@ package cn.iocoder.yudao.module.product.service.sku; import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.ObjectUtil; 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.ProductPropertyRespVO; +import cn.iocoder.yudao.module.product.controller.admin.property.vo.ProductPropertyAndValueRespVO; import cn.iocoder.yudao.module.product.controller.admin.propertyvalue.vo.ProductPropertyValueRespVO; import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuBaseVO; import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO; @@ -24,11 +25,10 @@ import java.util.*; import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.PROPERTY_NOT_EXISTS; -import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS; +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.*; /** - * 商品sku Service 实现类 + * 商品 SKU Service 实现类 * * @author 芋道源码 */ @@ -90,48 +90,51 @@ public class ProductSkuServiceImpl implements ProductSkuService { } @Override - public void validateProductSkus(List list, Integer specType) { - // 多规格才需校验 - if (specType.equals(ProductSpuSpecTypeEnum.DISABLE.getType())) { - List skuPropertyList = list.stream().flatMap(p -> Optional.of(p.getProperties()).orElse(new ArrayList<>()).stream()).collect(Collectors.toList()); - // 1、校验规格属性存在 - List propertyIds = CollectionUtils.convertList(skuPropertyList, ProductSkuBaseVO.Property::getPropertyId); - List propertyAndValueList = productPropertyService.selectByIds(propertyIds); - if (propertyAndValueList.size() == propertyIds.size()) { - throw exception(PROPERTY_NOT_EXISTS); - } - // 2. 校验,一个 Sku 下,没有重复的规格。校验方式是,遍历每个 Sku ,看看是否有重复的规格 attrId - List collect = propertyAndValueList.stream() - .flatMap(v -> Optional.of(v.getPropertyValueList()) - .orElse(new ArrayList<>()).stream()).collect(Collectors.toList()); - Map propertyValueRespVOMap = CollectionUtils.convertMap(collect, ProductPropertyValueRespVO::getId); - list.forEach(v -> { - Set keys = v.getProperties().stream().map(k -> propertyValueRespVOMap.get(k.getValueId()).getPropertyId()).collect(Collectors.toSet()); - if (keys.size() != v.getProperties().size()) { - throw exception(ErrorCodeConstants.SKU_PROPERTIES_DUPLICATED); - } - }); + public void validateSkus(List skus, Integer specType) { + // 非多规格,不需要校验 + if (ObjectUtil.notEqual(specType, ProductSpuSpecTypeEnum.DISABLE.getType())) { + return; + } - // 3. 再校验,每个 Sku 的规格值的数量,是一致的。 - int attrValueIdsSize = list.get(0).getProperties().size(); - for (int i = 1; i < list.size(); i++) { - if (attrValueIdsSize != list.get(i).getProperties().size()) { - throw exception(ErrorCodeConstants.PRODUCT_SPU_ATTR_NUMBERS_MUST_BE_EQUALS); - } - } + // 1、校验规格属性存在 + // TODO @Luowenfeng:stream 的写法;不用改哈,就是说下可以酱紫写; + 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 propertyAndValueList = productPropertyService.getPropertyAndValueList(propertyIds); + if (propertyAndValueList.size() == propertyIds.size()) { + throw exception(PROPERTY_NOT_EXISTS); + } - // 4. 最后校验,每个 Sku 之间不是重复的 - Set> skuAttrValues = new HashSet<>(); // 每个元素,都是一个 Sku 的 attrValueId 集合。这样,通过最外层的 Set ,判断是否有重复的. - for (ProductSkuCreateOrUpdateReqVO sku : list) { - if (!skuAttrValues.add(sku.getProperties().stream().map(ProductSkuBaseVO.Property::getValueId).collect(Collectors.toSet()))) { // 添加失败,说明重复 - throw exception(ErrorCodeConstants.PRODUCT_SPU_SKU_NOT_DUPLICATE); - } + // 2. 校验,一个 SKU 下,没有重复的规格。校验方式是,遍历每个 SKU ,看看是否有重复的规格 propertyId + Map propertyValueMap = propertyAndValueList.stream().filter(p -> p.getValues() != null).flatMap(p -> p.getValues().stream()) + .collect(Collectors.toMap(ProductPropertyValueRespVO::getId, value -> value)); // KEY:规格属性值的编号 + skus.forEach(sku -> { + Set skuPropertyIds = CollectionUtils.convertSet(sku.getProperties(), propertyItem -> propertyValueMap.get(propertyItem.getValueId()).getPropertyId()); + if (skuPropertyIds.size() != sku.getProperties().size()) { + throw exception(SKU_PROPERTIES_DUPLICATED); + } + }); + + // 3. 再校验,每个 Sku 的规格值的数量,是一致的。 + int attrValueIdsSize = skus.get(0).getProperties().size(); + for (int i = 1; i < skus.size(); i++) { + if (attrValueIdsSize != skus.get(i).getProperties().size()) { + throw exception(ErrorCodeConstants.SPU_ATTR_NUMBERS_MUST_BE_EQUALS); + } + } + + // 4. 最后校验,每个 Sku 之间不是重复的 + Set> skuAttrValues = new HashSet<>(); // 每个元素,都是一个 Sku 的 attrValueId 集合。这样,通过最外层的 Set ,判断是否有重复的. + for (ProductSkuCreateOrUpdateReqVO sku : skus) { + // TODO @Luowenfeng:可以使用 CollectionUtils.convertSet(),简化下面的 stream 操作 + if (!skuAttrValues.add(sku.getProperties().stream().map(ProductSkuBaseVO.Property::getValueId).collect(Collectors.toSet()))) { // 添加失败,说明重复 + throw exception(ErrorCodeConstants.SPU_SKU_NOT_DUPLICATE); } } } @Override - public void createProductSkus(List skuCreateReqList, Long spuId) { + public void createSkus(Long spuId, List skuCreateReqList) { // 批量插入 SKU List skuDOList = ProductSkuConvert.INSTANCE.convertSkuDOList(skuCreateReqList); skuDOList.forEach(v -> v.setSpuId(spuId)); @@ -140,13 +143,12 @@ public class ProductSkuServiceImpl implements ProductSkuService { @Override public List getSkusBySpuId(Long spuId) { - List productSkuDOS = productSkuMapper.selectBySpuIds(Collections.singletonList(spuId)); - return productSkuDOS; + return productSkuMapper.selectListBySpuIds(Collections.singletonList(spuId)); } @Override public List getSkusBySpuIds(List spuIds) { - return productSkuMapper.selectBySpuIds(spuIds); + return productSkuMapper.selectListBySpuIds(spuIds); } @Override @@ -157,16 +159,16 @@ public class ProductSkuServiceImpl implements ProductSkuService { @Override @Transactional public void updateProductSkus(Long spuId, List skus) { - // 查询 spu 下已经存在的 sku 的集合 - List existsSkus = productSkuMapper.selectBySpuId(spuId); + // 查询 SPU 下已经存在的 SKU 的集合 + List existsSkus = productSkuMapper.selectListBySpuId(spuId); Map existsSkuMap = CollectionUtils.convertMap(existsSkus, ProductSkuDO::getId); // 拆分三个集合,新插入的、需要更新的、需要删除的 List insertSkus = new ArrayList<>(); - List updateSkus = new ArrayList<>(); + List updateSkus = new ArrayList<>(); // TODO Luowenfeng:使用 Long 即可 List deleteSkus = new ArrayList<>(); - // TODO @芋艿:是不是基于规格匹配会比较好。 + // TODO @Luowenfeng:是不是基于规格匹配会比较好。可以参考下 onemall 的 ProductSpuServiceImpl 的 updateProductSpu 逻辑 List allUpdateSkus = ProductSkuConvert.INSTANCE.convertSkuDOList(skus); allUpdateSkus.forEach(p -> { if (p.getId() != null) { 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 37883b677..8907c6207 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 @@ -26,14 +26,14 @@ public interface ProductSpuService { * @param createReqVO 创建信息 * @return 编号 */ - Long createProductSpu(@Valid ProductSpuCreateReqVO createReqVO); + Long createSpu(@Valid ProductSpuCreateReqVO createReqVO); /** * 更新商品 SPU * * @param updateReqVO 更新信息 */ - void updateProductSpu(@Valid ProductSpuUpdateReqVO updateReqVO); + void updateSpu(@Valid ProductSpuUpdateReqVO updateReqVO); /** * 删除商品spu diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java index f583f8685..664d619c4 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java @@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.product.service.spu; 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.ProductPropertyRespVO; +import cn.iocoder.yudao.module.product.controller.admin.property.vo.ProductPropertyAndValueRespVO; import cn.iocoder.yudao.module.product.controller.admin.property.vo.ProductPropertyViewRespVO; import cn.iocoder.yudao.module.product.controller.admin.propertyvalue.vo.ProductPropertyValueRespVO; import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuBaseVO; @@ -16,7 +16,6 @@ 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.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.dal.mysql.spu.ProductSpuMapper; import cn.iocoder.yudao.module.product.enums.spu.ProductSpuSpecTypeEnum; @@ -30,7 +29,6 @@ import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; import java.util.*; -import java.util.function.Function; import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; @@ -62,14 +60,14 @@ public class ProductSpuServiceImpl implements ProductSpuService { @Override @Transactional - public Long createProductSpu(ProductSpuCreateReqVO createReqVO) { + public Long createSpu(ProductSpuCreateReqVO createReqVO) { // 校验分类 - categoryService.validateProductCategory(createReqVO.getCategoryId()); + categoryService.validateCategoryLevel(createReqVO.getCategoryId()); // 校验品牌 brandService.validateProductBrand(createReqVO.getBrandId()); // 校验SKU List skuCreateReqList = createReqVO.getSkus(); - productSkuService.validateProductSkus(skuCreateReqList, createReqVO.getSpecType()); + productSkuService.validateSkus(skuCreateReqList, createReqVO.getSpecType()); // 插入 SPU ProductSpuDO spu = ProductSpuConvert.INSTANCE.convert(createReqVO); spu.setMarketPrice(CollectionUtils.getMaxValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getMarketPrice)); @@ -78,24 +76,25 @@ public class ProductSpuServiceImpl implements ProductSpuService { spu.setTotalStock(CollectionUtils.getSumValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getStock, Integer::sum)); ProductSpuMapper.insert(spu); // 插入 SKU - productSkuService.createProductSkus(skuCreateReqList, spu.getId()); + productSkuService.createSkus(spu.getId(), skuCreateReqList); // 返回 return spu.getId(); } @Override @Transactional - public void updateProductSpu(ProductSpuUpdateReqVO updateReqVO) { + public void updateSpu(ProductSpuUpdateReqVO updateReqVO) { // 校验 SPU 是否存在 validateSpuExists(updateReqVO.getId()); // 校验分类 - categoryService.validateProductCategory(updateReqVO.getCategoryId()); + categoryService.validateCategoryLevel(updateReqVO.getCategoryId()); // 校验品牌 brandService.validateProductBrand(updateReqVO.getBrandId()); // 校验SKU List skuCreateReqList = updateReqVO.getSkus(); // 多规格才需校验 - productSkuService.validateProductSkus(skuCreateReqList, updateReqVO.getSpecType()); + productSkuService.validateSkus(skuCreateReqList, updateReqVO.getSpecType()); + // 更新 SPU ProductSpuDO updateObj = ProductSpuConvert.INSTANCE.convert(updateReqVO); updateObj.setMarketPrice(CollectionUtils.getMaxValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getMarketPrice)); @@ -103,7 +102,7 @@ public class ProductSpuServiceImpl implements ProductSpuService { updateObj.setMinPrice(CollectionUtils.getMinValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getPrice)); updateObj.setTotalStock(CollectionUtils.getSumValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getStock, Integer::sum)); ProductSpuMapper.updateById(updateObj); - // 更新 SKU + // 批量更新 SKU productSkuService.updateProductSkus(updateObj.getId(), updateReqVO.getSkus()); } @@ -111,7 +110,7 @@ public class ProductSpuServiceImpl implements ProductSpuService { @Transactional public void deleteSpu(Long id) { // 校验存在 - this.validateSpuExists(id); + validateSpuExists(id); // 删除 SPU ProductSpuMapper.deleteById(id); // 删除关联的 SKU @@ -125,6 +124,7 @@ public class ProductSpuServiceImpl implements ProductSpuService { } @Override + // TODO @芋艿:需要再 review 下 public SpuRespVO getSpu(Long id) { ProductSpuDO spu = ProductSpuMapper.selectById(id); SpuRespVO spuVO = ProductSpuConvert.INSTANCE.convert(spu); @@ -138,7 +138,7 @@ public class ProductSpuServiceImpl implements ProductSpuService { properties.addAll(productSkuRespVO.getProperties()); } Map> propertyMaps = properties.stream().collect(Collectors.groupingBy(ProductSkuBaseVO.Property::getPropertyId)); - List propertyAndValueList = productPropertyService.selectByIds(new ArrayList<>(propertyMaps.keySet())); + List propertyAndValueList = productPropertyService.getPropertyAndValueList(new ArrayList<>(propertyMaps.keySet())); // 装载组装过后的属性 List productPropertyViews = new ArrayList<>(); propertyAndValueList.forEach(p -> { @@ -146,7 +146,7 @@ public class ProductSpuServiceImpl implements ProductSpuService { productPropertyViewRespVO.setPropertyId(p.getId()); productPropertyViewRespVO.setName(p.getName()); List propertyValues = new ArrayList<>(); - Map propertyValueMaps = p.getPropertyValueList().stream().collect(Collectors.toMap(ProductPropertyValueRespVO::getId, pv -> pv)); + Map propertyValueMaps = p.getValues().stream().collect(Collectors.toMap(ProductPropertyValueRespVO::getId, pv -> pv)); propertyMaps.get(p.getId()).forEach(pv -> { ProductPropertyViewRespVO.Tuple2 tuple2 = new ProductPropertyViewRespVO.Tuple2(pv.getValueId(), propertyValueMaps.get(pv.getValueId()).getName()); propertyValues.add(tuple2); @@ -162,7 +162,7 @@ public class ProductSpuServiceImpl implements ProductSpuService { Long parentId = spuVO.getCategoryId(); categoryArray.addFirst(parentId); while (parentId != 0) { - parentId = categoryService.getProductCategory(parentId).getParentId(); + parentId = categoryService.getCategory(parentId).getParentId(); if (parentId > 0) { categoryArray.addFirst(parentId); } diff --git a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandServiceImplTest.java b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandServiceImplTest.java index 68ca66922..179778d0b 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandServiceImplTest.java +++ b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/brand/ProductBrandServiceImplTest.java @@ -20,7 +20,7 @@ import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEq import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; -import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.PRODUCT_BRAND_NOT_EXISTS; +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.BRAND_NOT_EXISTS; import static org.junit.jupiter.api.Assertions.*; /** @@ -74,7 +74,7 @@ public class ProductBrandServiceImplTest extends BaseDbUnitTest { ProductBrandUpdateReqVO reqVO = randomPojo(ProductBrandUpdateReqVO.class); // 调用, 并断言异常 - assertServiceException(() -> brandService.updateBrand(reqVO), PRODUCT_BRAND_NOT_EXISTS); + assertServiceException(() -> brandService.updateBrand(reqVO), BRAND_NOT_EXISTS); } @Test @@ -97,7 +97,7 @@ public class ProductBrandServiceImplTest extends BaseDbUnitTest { Long id = randomLongId(); // 调用, 并断言异常 - assertServiceException(() -> brandService.deleteBrand(id), PRODUCT_BRAND_NOT_EXISTS); + assertServiceException(() -> brandService.deleteBrand(id), BRAND_NOT_EXISTS); } @Test diff --git a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImplTest.java b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImplTest.java index 7fc3e2a22..a56c1aa1a 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImplTest.java +++ b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImplTest.java @@ -17,7 +17,7 @@ import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEq import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; -import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.PRODUCT_CATEGORY_NOT_EXISTS; +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.CATEGORY_NOT_EXISTS; import static org.junit.jupiter.api.Assertions.*; /** @@ -43,7 +43,7 @@ public class ProductCategoryServiceImplTest extends BaseDbUnitTest { productCategoryMapper.insert(parentProductCategory); // 调用 - Long categoryId = productCategoryService.createProductCategory(reqVO); + Long categoryId = productCategoryService.createCategory(reqVO); // 断言 assertNotNull(categoryId); // 校验记录的属性是否正确 @@ -65,7 +65,7 @@ public class ProductCategoryServiceImplTest extends BaseDbUnitTest { productCategoryMapper.insert(parentProductCategory); // 调用 - productCategoryService.updateProductCategory(reqVO); + productCategoryService.updateCategory(reqVO); // 校验是否更新正确 ProductCategoryDO category = productCategoryMapper.selectById(reqVO.getId()); // 获取最新的 assertPojoEquals(reqVO, category); @@ -77,7 +77,7 @@ public class ProductCategoryServiceImplTest extends BaseDbUnitTest { ProductCategoryUpdateReqVO reqVO = randomPojo(ProductCategoryUpdateReqVO.class); // 调用, 并断言异常 - assertServiceException(() -> productCategoryService.updateProductCategory(reqVO), PRODUCT_CATEGORY_NOT_EXISTS); + assertServiceException(() -> productCategoryService.updateCategory(reqVO), CATEGORY_NOT_EXISTS); } @Test @@ -89,7 +89,7 @@ public class ProductCategoryServiceImplTest extends BaseDbUnitTest { Long id = dbCategory.getId(); // 调用 - productCategoryService.deleteProductCategory(id); + productCategoryService.deleteCategory(id); // 校验数据不存在了 assertNull(productCategoryMapper.selectById(id)); } @@ -100,7 +100,7 @@ public class ProductCategoryServiceImplTest extends BaseDbUnitTest { Long id = randomLongId(); // 调用, 并断言异常 - assertServiceException(() -> productCategoryService.deleteProductCategory(id), PRODUCT_CATEGORY_NOT_EXISTS); + assertServiceException(() -> productCategoryService.deleteCategory(id), CATEGORY_NOT_EXISTS); } @Test @@ -117,7 +117,7 @@ public class ProductCategoryServiceImplTest extends BaseDbUnitTest { reqVO.setName("特曼"); // 调用 - List list = productCategoryService.getEnableProductCategoryList(reqVO); + List list = productCategoryService.getEnableCategoryList(reqVO); // 断言 assertEquals(1, list.size()); assertPojoEquals(dbCategory, list.get(0)); diff --git a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java index e2b3a3d98..57b7fdfeb 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java +++ b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java @@ -41,7 +41,7 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest { ProductSpuCreateReqVO reqVO = randomPojo(ProductSpuCreateReqVO.class); // 调用 - Long spuId = spuService.createProductSpu(reqVO); + Long spuId = spuService.createSpu(reqVO); // 断言 assertNotNull(spuId); // 校验记录的属性是否正确 @@ -60,7 +60,7 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest { }); // 调用 - spuService.updateProductSpu(reqVO); + spuService.updateSpu(reqVO); // 校验是否更新正确 ProductSpuDO spu = ProductSpuMapper.selectById(reqVO.getId()); // 获取最新的 assertPojoEquals(reqVO, spu); @@ -72,7 +72,7 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest { ProductSpuUpdateReqVO reqVO = randomPojo(ProductSpuUpdateReqVO.class); // 调用, 并断言异常 - assertServiceException(() -> spuService.updateProductSpu(reqVO), SPU_NOT_EXISTS); + assertServiceException(() -> spuService.updateSpu(reqVO), SPU_NOT_EXISTS); } @Test