Commit 8d2bcc57aabc55b9f4c9ca6152b3317d2a520e32

Authored by puhui999
1 parent e8621401

fix: 完善商品管理

Showing 14 changed files with 197 additions and 25 deletions
yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/ErrorCodeConstants.java
@@ -15,6 +15,7 @@ public interface ErrorCodeConstants { @@ -15,6 +15,7 @@ public interface ErrorCodeConstants {
15 ErrorCode CATEGORY_PARENT_NOT_FIRST_LEVEL = new ErrorCode(1008001002, "父分类不能是二级分类"); 15 ErrorCode CATEGORY_PARENT_NOT_FIRST_LEVEL = new ErrorCode(1008001002, "父分类不能是二级分类");
16 ErrorCode CATEGORY_EXISTS_CHILDREN = new ErrorCode(1008001003, "存在子分类,无法删除"); 16 ErrorCode CATEGORY_EXISTS_CHILDREN = new ErrorCode(1008001003, "存在子分类,无法删除");
17 ErrorCode CATEGORY_DISABLED = new ErrorCode(1008001004, "商品分类({})已禁用,无法使用"); 17 ErrorCode CATEGORY_DISABLED = new ErrorCode(1008001004, "商品分类({})已禁用,无法使用");
  18 + ErrorCode CATEGORY_HAVE_BIND_SPU = new ErrorCode(1008001005, "类别下存在商品,无法删除");
18 19
19 // ========== 商品品牌相关编号 1008002000 ========== 20 // ========== 商品品牌相关编号 1008002000 ==========
20 ErrorCode BRAND_NOT_EXISTS = new ErrorCode(1008002000, "品牌不存在"); 21 ErrorCode BRAND_NOT_EXISTS = new ErrorCode(1008002000, "品牌不存在");
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/brand/ProductBrandController.java
@@ -65,7 +65,7 @@ public class ProductBrandController { @@ -65,7 +65,7 @@ public class ProductBrandController {
65 65
66 @GetMapping("/list-all-simple") 66 @GetMapping("/list-all-simple")
67 @Operation(summary = "获取品牌精简信息列表", description = "主要用于前端的下拉选项") 67 @Operation(summary = "获取品牌精简信息列表", description = "主要用于前端的下拉选项")
68 - public CommonResult<List<ProductBrandSimpleRespVO>> getSimpleUserList() { 68 + public CommonResult<List<ProductBrandSimpleRespVO>> getSimpleBrandList() {
69 // 获取品牌列表,只要开启状态的 69 // 获取品牌列表,只要开启状态的
70 List<ProductBrandDO> list = brandService.getBrandListByStatus(CommonStatusEnum.ENABLE.getStatus()); 70 List<ProductBrandDO> list = brandService.getBrandListByStatus(CommonStatusEnum.ENABLE.getStatus());
71 // 排序后,返回给前端 71 // 排序后,返回给前端
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/vo/property/ProductPropertyListReqVO.java
@@ -14,8 +14,4 @@ public class ProductPropertyListReqVO { @@ -14,8 +14,4 @@ public class ProductPropertyListReqVO {
14 @Schema(description = "属性名称", example = "颜色") 14 @Schema(description = "属性名称", example = "颜色")
15 private String name; 15 private String name;
16 16
17 - // TODO @puhui999:这个查询条件的作用是啥呀?  
18 - @Schema(description = "属性编号的数组", example = "1,2")  
19 - private List<Long> propertyIds;  
20 -  
21 } 17 }
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/sku/ProductSkuConvert.java
@@ -7,7 +7,6 @@ import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO; @@ -7,7 +7,6 @@ import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO;
7 import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO; 7 import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO;
8 import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuOptionRespVO; 8 import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuOptionRespVO;
9 import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuRespVO; 9 import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuRespVO;
10 -import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuDetailRespVO;  
11 import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; 10 import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
12 import org.mapstruct.Mapper; 11 import org.mapstruct.Mapper;
13 import org.mapstruct.factory.Mappers; 12 import org.mapstruct.factory.Mappers;
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/sku/ProductSkuMapper.java
1 package cn.iocoder.yudao.module.product.dal.mysql.sku; 1 package cn.iocoder.yudao.module.product.dal.mysql.sku;
2 2
3 import cn.hutool.core.lang.Assert; 3 import cn.hutool.core.lang.Assert;
  4 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  5 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; 6 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
5 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; 7 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
6 import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; 8 import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
  9 +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
7 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 10 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
8 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; 11 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
9 import org.apache.ibatis.annotations.Mapper; 12 import org.apache.ibatis.annotations.Mapper;
@@ -70,4 +73,22 @@ public interface ProductSkuMapper extends BaseMapperX&lt;ProductSkuDO&gt; { @@ -70,4 +73,22 @@ public interface ProductSkuMapper extends BaseMapperX&lt;ProductSkuDO&gt; {
70 return selectList(new QueryWrapper<ProductSkuDO>().apply("stock <= warn_stock")); 73 return selectList(new QueryWrapper<ProductSkuDO>().apply("stock <= warn_stock"));
71 } 74 }
72 75
  76 + /**
  77 + * 更新 sku 属性值时使用的分页查询
  78 + *
  79 + * @param pageParam 页面参数
  80 + * @return {@link PageResult}<{@link ProductSkuDO}>
  81 + */
  82 + default PageResult<ProductSkuDO> selectPage(PageParam pageParam) {
  83 + return selectPage(pageParam, new LambdaQueryWrapper<ProductSkuDO>().isNotNull(ProductSkuDO::getProperties));
  84 + }
  85 +
  86 + /**
  87 + * 查询 sku properties 不等于 null 的数量
  88 + *
  89 + * @return {@link Long}
  90 + */
  91 + default Long selectCountByPropertyNotNull() {
  92 + return selectCount(new LambdaQueryWrapper<ProductSkuDO>().isNotNull(ProductSkuDO::getProperties));
  93 + }
73 } 94 }
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImpl.java
@@ -7,7 +7,8 @@ import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCateg @@ -7,7 +7,8 @@ import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCateg
7 import cn.iocoder.yudao.module.product.convert.category.ProductCategoryConvert; 7 import cn.iocoder.yudao.module.product.convert.category.ProductCategoryConvert;
8 import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO; 8 import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO;
9 import cn.iocoder.yudao.module.product.dal.mysql.category.ProductCategoryMapper; 9 import cn.iocoder.yudao.module.product.dal.mysql.category.ProductCategoryMapper;
10 -import cn.iocoder.yudao.module.product.enums.ProductConstants; 10 +import cn.iocoder.yudao.module.product.service.spu.ProductSpuService;
  11 +import org.springframework.context.annotation.Lazy;
11 import org.springframework.stereotype.Service; 12 import org.springframework.stereotype.Service;
12 import org.springframework.validation.annotation.Validated; 13 import org.springframework.validation.annotation.Validated;
13 14
@@ -30,6 +31,9 @@ public class ProductCategoryServiceImpl implements ProductCategoryService { @@ -30,6 +31,9 @@ public class ProductCategoryServiceImpl implements ProductCategoryService {
30 31
31 @Resource 32 @Resource
32 private ProductCategoryMapper productCategoryMapper; 33 private ProductCategoryMapper productCategoryMapper;
  34 + @Resource
  35 + @Lazy // 循环依赖,避免报错
  36 + private ProductSpuService productSpuService;
33 37
34 @Override 38 @Override
35 public Long createCategory(ProductCategoryCreateReqVO createReqVO) { 39 public Long createCategory(ProductCategoryCreateReqVO createReqVO) {
@@ -63,7 +67,8 @@ public class ProductCategoryServiceImpl implements ProductCategoryService { @@ -63,7 +67,8 @@ public class ProductCategoryServiceImpl implements ProductCategoryService {
63 if (productCategoryMapper.selectCountByParentId(id) > 0) { 67 if (productCategoryMapper.selectCountByParentId(id) > 0) {
64 throw exception(CATEGORY_EXISTS_CHILDREN); 68 throw exception(CATEGORY_EXISTS_CHILDREN);
65 } 69 }
66 - // TODO 芋艿 补充只有不存在商品才可以删除 70 + // 校验分类是否绑定了 SPU
  71 + validateProductCategoryIsHaveBindSpu(id);
67 // 删除 72 // 删除
68 productCategoryMapper.deleteById(id); 73 productCategoryMapper.deleteById(id);
69 } 74 }
@@ -91,6 +96,13 @@ public class ProductCategoryServiceImpl implements ProductCategoryService { @@ -91,6 +96,13 @@ public class ProductCategoryServiceImpl implements ProductCategoryService {
91 } 96 }
92 } 97 }
93 98
  99 + private void validateProductCategoryIsHaveBindSpu(Long id) {
  100 + Long count = productSpuService.getSpuCountByCategoryId(id);
  101 + if (0 != count) {
  102 + throw exception(CATEGORY_HAVE_BIND_SPU);
  103 + }
  104 + }
  105 +
94 @Override 106 @Override
95 public ProductCategoryDO getCategory(Long id) { 107 public ProductCategoryDO getCategory(Long id) {
96 return productCategoryMapper.selectById(id); 108 return productCategoryMapper.selectById(id);
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyServiceImpl.java
@@ -10,6 +10,7 @@ import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.Pro @@ -10,6 +10,7 @@ import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.Pro
10 import cn.iocoder.yudao.module.product.convert.property.ProductPropertyConvert; 10 import cn.iocoder.yudao.module.product.convert.property.ProductPropertyConvert;
11 import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO; 11 import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO;
12 import cn.iocoder.yudao.module.product.dal.mysql.property.ProductPropertyMapper; 12 import cn.iocoder.yudao.module.product.dal.mysql.property.ProductPropertyMapper;
  13 +import cn.iocoder.yudao.module.product.service.sku.ProductSkuService;
13 import org.springframework.context.annotation.Lazy; 14 import org.springframework.context.annotation.Lazy;
14 import org.springframework.stereotype.Service; 15 import org.springframework.stereotype.Service;
15 import org.springframework.transaction.annotation.Transactional; 16 import org.springframework.transaction.annotation.Transactional;
@@ -38,6 +39,9 @@ public class ProductPropertyServiceImpl implements ProductPropertyService { @@ -38,6 +39,9 @@ public class ProductPropertyServiceImpl implements ProductPropertyService {
38 @Lazy // 延迟加载,解决循环依赖问题 39 @Lazy // 延迟加载,解决循环依赖问题
39 private ProductPropertyValueService productPropertyValueService; 40 private ProductPropertyValueService productPropertyValueService;
40 41
  42 + @Resource
  43 + private ProductSkuService productSkuService;
  44 +
41 @Override 45 @Override
42 @Transactional(rollbackFor = Exception.class) 46 @Transactional(rollbackFor = Exception.class)
43 public Long createProperty(ProductPropertyCreateReqVO createReqVO) { 47 public Long createProperty(ProductPropertyCreateReqVO createReqVO) {
@@ -68,7 +72,8 @@ public class ProductPropertyServiceImpl implements ProductPropertyService { @@ -68,7 +72,8 @@ public class ProductPropertyServiceImpl implements ProductPropertyService {
68 // 更新 72 // 更新
69 ProductPropertyDO updateObj = ProductPropertyConvert.INSTANCE.convert(updateReqVO); 73 ProductPropertyDO updateObj = ProductPropertyConvert.INSTANCE.convert(updateReqVO);
70 productPropertyMapper.updateById(updateObj); 74 productPropertyMapper.updateById(updateObj);
71 - // TODO 芋艿:更新时,需要看看 sku 表 75 + // TODO 芋艿:更新时,需要看看 sku 表 fix
  76 + productSkuService.updateSkuProperty(updateObj);
72 } 77 }
73 78
74 @Override 79 @Override
@@ -94,10 +99,6 @@ public class ProductPropertyServiceImpl implements ProductPropertyService { @@ -94,10 +99,6 @@ public class ProductPropertyServiceImpl implements ProductPropertyService {
94 99
95 @Override 100 @Override
96 public List<ProductPropertyDO> getPropertyList(ProductPropertyListReqVO listReqVO) { 101 public List<ProductPropertyDO> getPropertyList(ProductPropertyListReqVO listReqVO) {
97 - // 增加使用属性 id 查询  
98 - if (CollUtil.isNotEmpty(listReqVO.getPropertyIds())){  
99 - return productPropertyMapper.selectBatchIds(listReqVO.getPropertyIds());  
100 - }  
101 return productPropertyMapper.selectList(listReqVO); 102 return productPropertyMapper.selectList(listReqVO);
102 } 103 }
103 104
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyValueServiceImpl.java
@@ -10,6 +10,7 @@ import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO @@ -10,6 +10,7 @@ import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO
10 import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO; 10 import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO;
11 import cn.iocoder.yudao.module.product.dal.mysql.property.ProductPropertyValueMapper; 11 import cn.iocoder.yudao.module.product.dal.mysql.property.ProductPropertyValueMapper;
12 import cn.iocoder.yudao.module.product.service.property.bo.ProductPropertyValueDetailRespBO; 12 import cn.iocoder.yudao.module.product.service.property.bo.ProductPropertyValueDetailRespBO;
  13 +import cn.iocoder.yudao.module.product.service.sku.ProductSkuService;
13 import org.springframework.context.annotation.Lazy; 14 import org.springframework.context.annotation.Lazy;
14 import org.springframework.stereotype.Service; 15 import org.springframework.stereotype.Service;
15 import org.springframework.validation.annotation.Validated; 16 import org.springframework.validation.annotation.Validated;
@@ -40,6 +41,10 @@ public class ProductPropertyValueServiceImpl implements ProductPropertyValueServ @@ -40,6 +41,10 @@ public class ProductPropertyValueServiceImpl implements ProductPropertyValueServ
40 @Lazy // 延迟加载,避免循环依赖 41 @Lazy // 延迟加载,避免循环依赖
41 private ProductPropertyService productPropertyService; 42 private ProductPropertyService productPropertyService;
42 43
  44 + @Resource
  45 + @Lazy // 延迟加载,避免循环依赖
  46 + private ProductSkuService productSkuService;
  47 +
43 @Override 48 @Override
44 public Long createPropertyValue(ProductPropertyValueCreateReqVO createReqVO) { 49 public Long createPropertyValue(ProductPropertyValueCreateReqVO createReqVO) {
45 // 如果已经添加过该属性值,直接返回 50 // 如果已经添加过该属性值,直接返回
@@ -68,7 +73,8 @@ public class ProductPropertyValueServiceImpl implements ProductPropertyValueServ @@ -68,7 +73,8 @@ public class ProductPropertyValueServiceImpl implements ProductPropertyValueServ
68 // 更新 73 // 更新
69 ProductPropertyValueDO updateObj = ProductPropertyValueConvert.INSTANCE.convert(updateReqVO); 74 ProductPropertyValueDO updateObj = ProductPropertyValueConvert.INSTANCE.convert(updateReqVO);
70 productPropertyValueMapper.updateById(updateObj); 75 productPropertyValueMapper.updateById(updateObj);
71 - // TODO 芋艿:更新时,需要看看 sku 表 76 + // TODO 芋艿:更新时,需要看看 sku 表 fix
  77 + productSkuService.updateSkuPropertyValue(updateObj);
72 } 78 }
73 79
74 @Override 80 @Override
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java
@@ -2,6 +2,8 @@ package cn.iocoder.yudao.module.product.service.sku; @@ -2,6 +2,8 @@ package cn.iocoder.yudao.module.product.service.sku;
2 2
3 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO; 3 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO;
4 import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO; 4 import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO;
  5 +import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO;
  6 +import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO;
5 import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; 7 import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
6 import org.springframework.lang.Nullable; 8 import org.springframework.lang.Nullable;
7 9
@@ -115,4 +117,19 @@ public interface ProductSkuService { @@ -115,4 +117,19 @@ public interface ProductSkuService {
115 */ 117 */
116 List<ProductSkuDO> getSkuListByAlarmStock(); 118 List<ProductSkuDO> getSkuListByAlarmStock();
117 119
  120 + /**
  121 + * 更新 sku 属性
  122 + *
  123 + * @param updateObj 属性对象
  124 + * @return int 影响的行数
  125 + */
  126 + int updateSkuProperty(ProductPropertyDO updateObj);
  127 +
  128 + /**
  129 + * 更新 sku 属性值
  130 + *
  131 + * @param updateObj 属性值对象
  132 + * @return int 影响的行数
  133 + */
  134 + int updateSkuPropertyValue(ProductPropertyValueDO updateObj);
118 } 135 }
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java
@@ -2,6 +2,8 @@ package cn.iocoder.yudao.module.product.service.sku; @@ -2,6 +2,8 @@ package cn.iocoder.yudao.module.product.service.sku;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 import cn.hutool.core.util.ObjectUtil; 4 import cn.hutool.core.util.ObjectUtil;
  5 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  6 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO; 7 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO;
6 import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO; 8 import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO;
7 import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert; 9 import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert;
@@ -42,6 +44,7 @@ public class ProductSkuServiceImpl implements ProductSkuService { @@ -42,6 +44,7 @@ public class ProductSkuServiceImpl implements ProductSkuService {
42 @Lazy // 循环依赖,避免报错 44 @Lazy // 循环依赖,避免报错
43 private ProductSpuService productSpuService; 45 private ProductSpuService productSpuService;
44 @Resource 46 @Resource
  47 + @Lazy // 循环依赖,避免报错
45 private ProductPropertyService productPropertyService; 48 private ProductPropertyService productPropertyService;
46 @Resource 49 @Resource
47 private ProductPropertyValueService productPropertyValueService; 50 private ProductPropertyValueService productPropertyValueService;
@@ -158,6 +161,84 @@ public class ProductSkuServiceImpl implements ProductSkuService { @@ -158,6 +161,84 @@ public class ProductSkuServiceImpl implements ProductSkuService {
158 } 161 }
159 162
160 @Override 163 @Override
  164 + public int updateSkuProperty(ProductPropertyDO updateObj) {
  165 + // TODO 看了一下数据库有关于 json 字符串的处理,怕数据库出现兼容问题这里还是用数据库常规操作来实现
  166 + Long count = productSkuMapper.selectCountByPropertyNotNull();
  167 + int currentPage = 1;
  168 + List<ProductSkuDO> skuDOs = new ArrayList<>();
  169 + if (count == 0) {
  170 + return 0;
  171 + }
  172 + int pageSize = 100;
  173 + for (int i = 0; i <= count / 100; i++) {
  174 + PageParam pageParam = new PageParam().setPageNo(currentPage + i).setPageSize(pageSize);
  175 + // 分页查找出 sku 属性不为 null 的
  176 + PageResult<ProductSkuDO> skuPage = productSkuMapper.selectPage(pageParam);
  177 + List<ProductSkuDO> records = skuPage.getList();
  178 + if (CollUtil.isEmpty(records)) {
  179 + break;
  180 + }
  181 + records.stream()
  182 + .filter(sku -> sku.getProperties() != null)
  183 + .forEach(sku -> sku.getProperties().forEach(property -> {
  184 + if (property.getPropertyId().equals(updateObj.getId())) {
  185 + property.setPropertyName(updateObj.getName());
  186 + skuDOs.add(sku);
  187 + }
  188 + }));
  189 + }
  190 + if (CollUtil.isEmpty(skuDOs)) {
  191 + return 0;
  192 + }
  193 + // 每批处理的大小
  194 + int batchSize = 1000;
  195 + for (int i = 0; i < skuDOs.size(); i += batchSize) {
  196 + List<ProductSkuDO> batchSkuDOs = skuDOs.subList(i, Math.min(i + batchSize, skuDOs.size()));
  197 + productSkuMapper.updateBatch(batchSkuDOs, batchSize);
  198 + }
  199 + return skuDOs.size();
  200 + }
  201 +
  202 + @Override
  203 + public int updateSkuPropertyValue(ProductPropertyValueDO updateObj) {
  204 + // TODO 看了一下数据库有关于 json 字符串的处理,怕数据库出现兼容问题这里还是用数据库常规操作来实现
  205 + Long count = productSkuMapper.selectCountByPropertyNotNull();
  206 + int currentPage = 1;
  207 + List<ProductSkuDO> skuDOs = new ArrayList<>();
  208 + if (count == 0) {
  209 + return 0;
  210 + }
  211 + int pageSize = 100;
  212 + for (int i = 0; i <= count / 100; i++) {
  213 + PageParam pageParam = new PageParam().setPageNo(currentPage + i).setPageSize(pageSize);
  214 + // 分页查找出 sku 属性不为 null 的
  215 + PageResult<ProductSkuDO> skuPage = productSkuMapper.selectPage(pageParam);
  216 + List<ProductSkuDO> records = skuPage.getList();
  217 + if (CollUtil.isEmpty(records)) {
  218 + break;
  219 + }
  220 + records.stream()
  221 + .filter(sku -> sku.getProperties() != null)
  222 + .forEach(sku -> sku.getProperties().forEach(property -> {
  223 + if (property.getValueId().equals(updateObj.getId())) {
  224 + property.setValueName(updateObj.getName());
  225 + skuDOs.add(sku);
  226 + }
  227 + }));
  228 + }
  229 + if (CollUtil.isEmpty(skuDOs)) {
  230 + return 0;
  231 + }
  232 + // 每批处理的大小
  233 + int batchSize = 1000;
  234 + for (int i = 0; i < skuDOs.size(); i += batchSize) {
  235 + List<ProductSkuDO> batchSkuDOs = skuDOs.subList(i, Math.min(i + batchSize, skuDOs.size()));
  236 + productSkuMapper.updateBatch(batchSkuDOs, batchSize);
  237 + }
  238 + return skuDOs.size();
  239 + }
  240 +
  241 + @Override
161 @Transactional(rollbackFor = Exception.class) 242 @Transactional(rollbackFor = Exception.class)
162 public void updateSkuList(Long spuId, List<ProductSkuCreateOrUpdateReqVO> skus) { 243 public void updateSkuList(Long spuId, List<ProductSkuCreateOrUpdateReqVO> skus) {
163 // 构建属性与 SKU 的映射关系; 244 // 构建属性与 SKU 的映射关系;
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuService.java
@@ -126,4 +126,13 @@ public interface ProductSpuService { @@ -126,4 +126,13 @@ public interface ProductSpuService {
126 * @return {@link Map}<{@link Integer}, {@link Integer}> 126 * @return {@link Map}<{@link Integer}, {@link Integer}>
127 */ 127 */
128 Map<Integer, Long> getTabsCount(); 128 Map<Integer, Long> getTabsCount();
  129 +
  130 + /**
  131 + * 通过分类 id 查询 spu 个数
  132 + *
  133 + * @param id 分类 id
  134 + * @return spu
  135 + */
  136 + Long getSpuCountByCategoryId(Long id);
  137 +
129 } 138 }
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java
@@ -251,4 +251,9 @@ public class ProductSpuServiceImpl implements ProductSpuService { @@ -251,4 +251,9 @@ public class ProductSpuServiceImpl implements ProductSpuService {
251 return counts; 251 return counts;
252 } 252 }
253 253
  254 + @Override
  255 + public Long getSpuCountByCategoryId(Long id) {
  256 + return productSpuMapper.selectCount(ProductSpuDO::getCategoryId, id);
  257 + }
  258 +
254 } 259 }
yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceTest.java
@@ -49,13 +49,10 @@ public class ProductSkuServiceTest extends BaseDbUnitTest { @@ -49,13 +49,10 @@ public class ProductSkuServiceTest extends BaseDbUnitTest {
49 @MockBean 49 @MockBean
50 private ProductPropertyValueService productPropertyValueService; 50 private ProductPropertyValueService productPropertyValueService;
51 51
52 - // TODO @puhui999:是不是可以删除这 2 方法  
53 public Long generateId() { 52 public Long generateId() {
54 return RandomUtil.randomLong(100000, 999999); 53 return RandomUtil.randomLong(100000, 999999);
55 } 54 }
56 55
57 - public int generaInt(){return RandomUtil.randomInt(1,9999999);}  
58 -  
59 @Test 56 @Test
60 public void testUpdateSkuList() { 57 public void testUpdateSkuList() {
61 // mock 数据 58 // mock 数据
@@ -109,7 +106,14 @@ public class ProductSkuServiceTest extends BaseDbUnitTest { @@ -109,7 +106,14 @@ public class ProductSkuServiceTest extends BaseDbUnitTest {
109 ProductSkuUpdateStockReqDTO updateStockReqDTO = new ProductSkuUpdateStockReqDTO() 106 ProductSkuUpdateStockReqDTO updateStockReqDTO = new ProductSkuUpdateStockReqDTO()
110 .setItems(singletonList(new ProductSkuUpdateStockReqDTO.Item().setId(1L).setIncrCount(10))); 107 .setItems(singletonList(new ProductSkuUpdateStockReqDTO.Item().setId(1L).setIncrCount(10)));
111 // mock 数据 108 // mock 数据
112 - productSkuMapper.insert(randomPojo(ProductSkuDO.class, o -> o.setId(1L).setSpuId(10L).setStock(20))); 109 + productSkuMapper.insert(randomPojo(ProductSkuDO.class, o -> {
  110 + o.setId(1L).setSpuId(10L).setStock(20);
  111 + o.getProperties().forEach(p -> {
  112 + // 指定 id 范围 解决 Value too long
  113 + p.setPropertyId(generateId());
  114 + p.setValueId(generateId());
  115 + });
  116 + }));
113 117
114 // 调用 118 // 调用
115 productSkuService.updateSkuStock(updateStockReqDTO); 119 productSkuService.updateSkuStock(updateStockReqDTO);
@@ -129,7 +133,14 @@ public class ProductSkuServiceTest extends BaseDbUnitTest { @@ -129,7 +133,14 @@ public class ProductSkuServiceTest extends BaseDbUnitTest {
129 ProductSkuUpdateStockReqDTO updateStockReqDTO = new ProductSkuUpdateStockReqDTO() 133 ProductSkuUpdateStockReqDTO updateStockReqDTO = new ProductSkuUpdateStockReqDTO()
130 .setItems(singletonList(new ProductSkuUpdateStockReqDTO.Item().setId(1L).setIncrCount(-10))); 134 .setItems(singletonList(new ProductSkuUpdateStockReqDTO.Item().setId(1L).setIncrCount(-10)));
131 // mock 数据 135 // mock 数据
132 - productSkuMapper.insert(randomPojo(ProductSkuDO.class, o -> o.setId(1L).setSpuId(10L).setStock(20))); 136 + productSkuMapper.insert(randomPojo(ProductSkuDO.class, o -> {
  137 + o.setId(1L).setSpuId(10L).setStock(20);
  138 + o.getProperties().forEach(p -> {
  139 + // 指定 id 范围 解决 Value too long
  140 + p.setPropertyId(generateId());
  141 + p.setValueId(generateId());
  142 + });
  143 + }));
133 144
134 // 调用 145 // 调用
135 productSkuService.updateSkuStock(updateStockReqDTO); 146 productSkuService.updateSkuStock(updateStockReqDTO);
@@ -149,8 +160,14 @@ public class ProductSkuServiceTest extends BaseDbUnitTest { @@ -149,8 +160,14 @@ public class ProductSkuServiceTest extends BaseDbUnitTest {
149 ProductSkuUpdateStockReqDTO updateStockReqDTO = new ProductSkuUpdateStockReqDTO() 160 ProductSkuUpdateStockReqDTO updateStockReqDTO = new ProductSkuUpdateStockReqDTO()
150 .setItems(singletonList(new ProductSkuUpdateStockReqDTO.Item().setId(1L).setIncrCount(-30))); 161 .setItems(singletonList(new ProductSkuUpdateStockReqDTO.Item().setId(1L).setIncrCount(-30)));
151 // mock 数据 162 // mock 数据
152 - productSkuMapper.insert(randomPojo(ProductSkuDO.class, o -> o.setId(1L).setSpuId(10L).setStock(20)));  
153 - 163 + productSkuMapper.insert(randomPojo(ProductSkuDO.class, o -> {
  164 + o.setId(1L).setSpuId(10L).setStock(20);
  165 + o.getProperties().forEach(p -> {
  166 + // 指定 id 范围 解决 Value too long
  167 + p.setPropertyId(generateId());
  168 + p.setValueId(generateId());
  169 + });
  170 + }));
154 // 调用并断言 171 // 调用并断言
155 AssertUtils.assertServiceException(() -> productSkuService.updateSkuStock(updateStockReqDTO), 172 AssertUtils.assertServiceException(() -> productSkuService.updateSkuStock(updateStockReqDTO),
156 SKU_STOCK_NOT_ENOUGH); 173 SKU_STOCK_NOT_ENOUGH);
@@ -158,9 +175,16 @@ public class ProductSkuServiceTest extends BaseDbUnitTest { @@ -158,9 +175,16 @@ public class ProductSkuServiceTest extends BaseDbUnitTest {
158 175
159 @Test 176 @Test
160 public void testDeleteSku_success() { 177 public void testDeleteSku_success() {
  178 + ProductSkuDO dbSku = randomPojo(ProductSkuDO.class, o -> {
  179 + o.setId(generateId()).setSpuId(generateId());
  180 + o.getProperties().forEach(p -> {
  181 + // 指定 id 范围 解决 Value too long
  182 + p.setPropertyId(generateId());
  183 + p.setValueId(generateId());
  184 + });
  185 + });
161 // mock 数据 186 // mock 数据
162 - ProductSkuDO dbSku = randomPojo(ProductSkuDO.class);  
163 - productSkuMapper.insert(dbSku);// @Sql: 先插入出一条存在的数据 187 + productSkuMapper.insert(dbSku);
164 // 准备参数 188 // 准备参数
165 Long id = dbSku.getId(); 189 Long id = dbSku.getId();
166 190
yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java
@@ -455,7 +455,7 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest { @@ -455,7 +455,7 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
455 public void testUpdateSpuStock() { 455 public void testUpdateSpuStock() {
456 // 准备参数 456 // 准备参数
457 Map<Long, Integer> stockIncrCounts = MapUtil.builder(1L, 10).put(2L, -20).build(); 457 Map<Long, Integer> stockIncrCounts = MapUtil.builder(1L, 10).put(2L, -20).build();
458 - // mock 方法(数据) // TODO ProductSpuDO中已没有相关属性 458 + // mock 方法(数据)
459 productSpuMapper.insert(randomPojo(ProductSpuDO.class, o ->{ 459 productSpuMapper.insert(randomPojo(ProductSpuDO.class, o ->{
460 o.setCategoryId(generateId()); 460 o.setCategoryId(generateId());
461 o.setBrandId(generateId()); 461 o.setBrandId(generateId());
@@ -495,7 +495,7 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest { @@ -495,7 +495,7 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
495 495
496 // 调用 496 // 调用
497 productSpuService.updateSpuStock(stockIncrCounts); 497 productSpuService.updateSpuStock(stockIncrCounts);
498 - // 断言 // TODO ProductSpuDO中已没有相关属性 498 + // 断言
499 assertEquals(productSpuService.getSpu(1L).getStock(), 30); 499 assertEquals(productSpuService.getSpu(1L).getStock(), 30);
500 assertEquals(productSpuService.getSpu(2L).getStock(), 10); 500 assertEquals(productSpuService.getSpu(2L).getStock(), 10);
501 } 501 }