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 06ca657eb..e328d2512 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 @@ -28,4 +28,5 @@ public interface ErrorCodeConstants { // ========== 商品sku 1008006000 ========== ErrorCode SKU_NOT_EXISTS = new ErrorCode(1008006000, "商品sku不存在"); + ErrorCode SKU_PROPERTIES_DUPLICATED = new ErrorCode(1008006001, "商品sku的属性组合存在重复"); } 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 c3c84d3cc..7f8d00f71 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 @@ -45,7 +45,9 @@ public class ProductSkuBaseVO { @Data public static class Property { + @NotNull(message = "规格属性名id不能为空") private Integer propertyId; + @NotNull(message = "规格属性值id不能为空") private Integer valueId; } 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 0aac851c3..232ce3178 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 @@ -37,6 +37,8 @@ public interface ProductSkuConvert { List convertList(List list); + List convertSkuDOList(List list); + 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/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 ec2622af5..1e6d13c3a 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 @@ -76,4 +76,10 @@ public interface ProductPropertyService { ProductPropertyRespVO getPropertyResp(Long id); + /** + * 根据数据名id集合查询属性名以及属性值的集合 + * @param propertyIds 属性名id集合 + * @return + */ + List selectByIds(List propertyIds); } 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 b940b6799..f6fadaae0 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,5 +1,6 @@ package cn.iocoder.yudao.module.product.service.property; +import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.product.controller.admin.property.vo.*; import cn.iocoder.yudao.module.product.controller.admin.property.vo.ProductPropertyCreateReqVO; @@ -113,13 +114,13 @@ public class ProductPropertyServiceImpl implements ProductPropertyService { //获取属性列表 PageResult pageResult = productPropertyMapper.selectPage(pageReqVO); PageResult propertyRespVOPageResult = ProductPropertyConvert.INSTANCE.convertPage(pageResult); - List propertyIds = propertyRespVOPageResult.getList().stream().map(x -> x.getId()).collect(Collectors.toList()); + List propertyIds = propertyRespVOPageResult.getList().stream().map(ProductPropertyRespVO::getId).collect(Collectors.toList()); //获取属性值列表 List productPropertyValueDOList = productPropertyValueService.getPropertyValueListByPropertyId(propertyIds); List propertyValueRespVOList = ProductPropertyValueConvert.INSTANCE.convertList(productPropertyValueDOList); //组装一对多 - propertyRespVOPageResult.getList().stream().forEach(x->{ + propertyRespVOPageResult.getList().forEach(x->{ Long propertyId = x.getId(); List valueDOList = propertyValueRespVOList.stream().filter(v -> v.getPropertyId().equals(propertyId)).collect(Collectors.toList()); x.setPropertyValueList(valueDOList); @@ -140,4 +141,8 @@ public class ProductPropertyServiceImpl implements ProductPropertyService { return propertyRespVO; } + @Override + public List selectByIds(List propertyIds) { + return ProductPropertyConvert.INSTANCE.convertList(productPropertyMapper.selectBatchIds(propertyIds)); + } } 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 ea0c4651a..df10d777e 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 @@ -72,4 +72,11 @@ public interface ProductSkuService { * @param skuCreateReqList sku组合的集合 */ void validatedSkuReq(List skuCreateReqList); + + /** + * 批量保存sku + * @param skuDOList sku对象集合 + * @return + */ + void batchSave(List skuDOList); } 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 c0b90db45..eed0ee91f 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,21 +1,25 @@ package cn.iocoder.yudao.module.product.service.sku; +import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.product.controller.admin.property.vo.ProductPropertyRespVO; +import cn.iocoder.yudao.module.product.controller.admin.propertyvalue.vo.ProductPropertyValueRespVO; +import cn.iocoder.yudao.module.product.controller.admin.sku.vo.*; +import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert; +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; +import cn.iocoder.yudao.module.product.service.property.ProductPropertyService; import org.springframework.stereotype.Service; -import javax.annotation.Resource; import org.springframework.validation.annotation.Validated; +import javax.annotation.Resource; import java.util.*; import java.util.stream.Collectors; -import cn.iocoder.yudao.module.product.controller.admin.sku.vo.*; -import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; -import cn.iocoder.yudao.framework.common.pojo.PageResult; - -import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert; -import cn.iocoder.yudao.module.product.dal.mysql.sku.ProductSkuMapper; - import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.*; +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.PROPERTY_NOT_EXISTS; +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS; /** * 商品sku Service 实现类 @@ -27,13 +31,16 @@ import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.*; public class ProductSkuServiceImpl implements ProductSkuService { @Resource - private ProductSkuMapper ProductSkuMapper; + private ProductSkuMapper productSkuMapper; + + @Resource + private ProductPropertyService productPropertyService; @Override public Long createSku(ProductSkuCreateReqVO createReqVO) { // 插入 ProductSkuDO sku = ProductSkuConvert.INSTANCE.convert(createReqVO); - ProductSkuMapper.insert(sku); + productSkuMapper.insert(sku); // 返回 return sku.getId(); } @@ -44,7 +51,7 @@ public class ProductSkuServiceImpl implements ProductSkuService { this.validateSkuExists(updateReqVO.getId()); // 更新 ProductSkuDO updateObj = ProductSkuConvert.INSTANCE.convert(updateReqVO); - ProductSkuMapper.updateById(updateObj); + productSkuMapper.updateById(updateObj); } @Override @@ -52,40 +59,67 @@ public class ProductSkuServiceImpl implements ProductSkuService { // 校验存在 this.validateSkuExists(id); // 删除 - ProductSkuMapper.deleteById(id); + productSkuMapper.deleteById(id); } private void validateSkuExists(Long id) { - if (ProductSkuMapper.selectById(id) == null) { + if (productSkuMapper.selectById(id) == null) { throw exception(SKU_NOT_EXISTS); } } @Override public ProductSkuDO getSku(Long id) { - return ProductSkuMapper.selectById(id); + return productSkuMapper.selectById(id); } @Override public List getSkuList(Collection ids) { - return ProductSkuMapper.selectBatchIds(ids); + return productSkuMapper.selectBatchIds(ids); } @Override public PageResult getSkuPage(ProductSkuPageReqVO pageReqVO) { - return ProductSkuMapper.selectPage(pageReqVO); + return productSkuMapper.selectPage(pageReqVO); } @Override public List getSkuList(ProductSkuExportReqVO exportReqVO) { - return ProductSkuMapper.selectList(exportReqVO); + return productSkuMapper.selectList(exportReqVO); } @Override public void validatedSkuReq(List skuCreateReqList) { + List skuPropertyList = skuCreateReqList.stream().flatMap(p -> p.getProperties().stream()).collect(Collectors.toList()); // 校验规格属性以及规格值是否存在 - List propertyIds = skuCreateReqList.stream().flatMap(p -> p.getProperties().stream()).map(ProductSkuBaseVO.Property::getPropertyId).collect(Collectors.toList()); - + List propertyIds = skuPropertyList.stream().map(ProductSkuBaseVO.Property::getPropertyId).collect(Collectors.toList()); + List propertyAndValueList = productPropertyService.selectByIds(propertyIds); + if (propertyAndValueList.isEmpty()) + throw ServiceExceptionUtil.exception(PROPERTY_NOT_EXISTS); + Map propertyMap = propertyAndValueList.stream().collect(Collectors.toMap(ProductPropertyRespVO::getId, p -> p)); + skuPropertyList.forEach(p -> { + ProductPropertyRespVO productPropertyRespVO = propertyMap.get(p.getPropertyId()); + // 如果对应的属性名不存在或属性名下的属性值集合为空,给出提示 + if (null == productPropertyRespVO || productPropertyRespVO.getPropertyValueList().isEmpty()) + throw ServiceExceptionUtil.exception(PROPERTY_NOT_EXISTS); + // 判断改属性名对应的属性值是否存在,不存在,给出提示 + if (!productPropertyRespVO.getPropertyValueList().stream().map(ProductPropertyValueRespVO::getId).collect(Collectors.toSet()).contains(p.getValueId())) { + throw ServiceExceptionUtil.exception(ErrorCodeConstants.PROPERTY_VALUE_NOT_EXISTS); + } + }); // 校验是否有重复的sku组合 + List> skuProperties = skuCreateReqList.stream().map(ProductSkuBaseVO::getProperties).collect(Collectors.toList()); + Set skuPropertiesConvertSet = new HashSet<>(); + skuProperties.forEach(p -> { + // 组合属性值id为 1~2~3.... 形式的字符串,通过set的特性判断是否有重复的组合 + if (!skuPropertiesConvertSet.add(p.stream().map(pr -> String.valueOf(pr.getValueId())).sorted().collect(Collectors.joining("~")))) { + throw ServiceExceptionUtil.exception(ErrorCodeConstants.SKU_PROPERTIES_DUPLICATED); + } + }); + } + + @Override + public void batchSave(List skuDOList) { + productSkuMapper.insertBatch(skuDOList); } } 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 5ebbabb33..d0eb5879a 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 @@ -1,6 +1,8 @@ package cn.iocoder.yudao.module.product.service.spu; import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateReqVO; +import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert; +import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; import cn.iocoder.yudao.module.product.service.category.CategoryService; import cn.iocoder.yudao.module.product.service.sku.ProductSkuService; import org.springframework.stereotype.Service; @@ -11,6 +13,8 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import java.util.*; +import java.util.stream.Collectors; + import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*; import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; import cn.iocoder.yudao.framework.common.pojo.PageResult; @@ -47,12 +51,16 @@ public class ProductSpuServiceImpl implements ProductSpuService { // 校验SKU List skuCreateReqList = createReqVO.getProductSkuCreateReqVOS(); productSkuService.validatedSkuReq(skuCreateReqList); - // 插入 + // 插入SPU ProductSpuDO spu = ProductSpuConvert.INSTANCE.convert(createReqVO); + ProductSpuMapper.insert(spu); + // sku关联SPU属性 skuCreateReqList.forEach(p -> { p.setSpuId(spu.getId()); }); - ProductSpuMapper.insert(spu); + List skuDOList = ProductSkuConvert.INSTANCE.convertSkuDOList(skuCreateReqList); + // 批量插入sku + productSkuService.batchSave(skuDOList); // 返回 return spu.getId(); } diff --git a/yudao-ui-admin/src/views/mall/product/spu/index.vue b/yudao-ui-admin/src/views/mall/product/spu/index.vue index 4fba24ac4..0596ebb03 100644 --- a/yudao-ui-admin/src/views/mall/product/spu/index.vue +++ b/yudao-ui-admin/src/views/mall/product/spu/index.vue @@ -20,14 +20,14 @@ - - - + + + + type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"/> 搜索 @@ -39,28 +39,31 @@ 新增 + v-hasPermi="['product:spu:create']">新增 + - 导出 + 导出 + - - - - - - - - - - - + + + + + + + + + + +