Commit abbfbd5f25a633cd5dcb30c368860712c8589370
1 parent
1e0f197c
code review:商品 spu、sku 的逻辑
Showing
9 changed files
with
54 additions
and
38 deletions
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/ProductSkuController.java
| ... | ... | @@ -25,7 +25,7 @@ import java.util.List; |
| 25 | 25 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 26 | 26 | import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; |
| 27 | 27 | |
| 28 | -@Api(tags = "管理后台-商品 sku") | |
| 28 | +@Api(tags = "管理后台 - 商品 sku") | |
| 29 | 29 | @RestController |
| 30 | 30 | @RequestMapping("/product/sku") |
| 31 | 31 | @Validated | ... | ... |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/sku/vo/ProductSkuExcelVO.java
| 1 | 1 | package cn.iocoder.yudao.module.product.controller.admin.sku.vo; |
| 2 | 2 | |
| 3 | -import lombok.*; | |
| 4 | -import java.util.*; | |
| 5 | -import io.swagger.annotations.*; | |
| 6 | - | |
| 7 | 3 | import com.alibaba.excel.annotation.ExcelProperty; |
| 4 | +import lombok.Data; | |
| 5 | + | |
| 6 | +import java.util.Date; | |
| 7 | +import java.util.List; | |
| 8 | 8 | |
| 9 | 9 | /** |
| 10 | 10 | * 商品sku Excel VO |
| ... | ... | @@ -20,6 +20,7 @@ public class ProductSkuExcelVO { |
| 20 | 20 | @ExcelProperty("spu编号") |
| 21 | 21 | private Long spuId; |
| 22 | 22 | |
| 23 | + // TODO @franky:这个单元格,可能会有点展示的问题 | |
| 23 | 24 | @ExcelProperty("规格值数组-json格式, [{propertId: , valueId: }, {propertId: , valueId: }]") |
| 24 | 25 | private List<Property> properties; |
| 25 | 26 | ... | ... |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/SpuRespVO.java
| 1 | 1 | package cn.iocoder.yudao.module.product.controller.admin.spu.vo; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuRespVO; |
| 4 | -import lombok.*; | |
| 5 | -import java.util.*; | |
| 6 | -import io.swagger.annotations.*; | |
| 4 | +import io.swagger.annotations.ApiModel; | |
| 5 | +import io.swagger.annotations.ApiModelProperty; | |
| 6 | +import lombok.Data; | |
| 7 | +import lombok.EqualsAndHashCode; | |
| 8 | +import lombok.ToString; | |
| 9 | + | |
| 10 | +import java.util.Date; | |
| 11 | +import java.util.List; | |
| 7 | 12 | |
| 8 | 13 | @ApiModel("管理后台 - 商品spu Response VO") |
| 9 | 14 | @Data |
| ... | ... | @@ -11,12 +16,17 @@ import io.swagger.annotations.*; |
| 11 | 16 | @ToString(callSuper = true) |
| 12 | 17 | public class SpuRespVO extends ProductSpuBaseVO { |
| 13 | 18 | |
| 19 | + // TODO @franky:注解要完整 | |
| 20 | + | |
| 14 | 21 | @ApiModelProperty(value = "主键", required = true) |
| 15 | 22 | private Long id; |
| 16 | 23 | |
| 17 | 24 | @ApiModelProperty(value = "创建时间") |
| 18 | 25 | private Date createTime; |
| 19 | 26 | |
| 27 | + /** | |
| 28 | + * SKU 数组 | |
| 29 | + */ | |
| 20 | 30 | List<ProductSkuRespVO> skus; |
| 21 | 31 | |
| 22 | 32 | } | ... | ... |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/sku/ProductSkuDO.java
| ... | ... | @@ -6,8 +6,6 @@ import com.baomidou.mybatisplus.annotation.TableId; |
| 6 | 6 | import com.baomidou.mybatisplus.annotation.TableName; |
| 7 | 7 | import lombok.*; |
| 8 | 8 | |
| 9 | -import java.util.List; | |
| 10 | - | |
| 11 | 9 | /** |
| 12 | 10 | * 商品sku DO |
| 13 | 11 | * |
| ... | ... | @@ -35,6 +33,7 @@ public class ProductSkuDO extends BaseDO { |
| 35 | 33 | /** |
| 36 | 34 | * 规格值数组-json格式, [{propertId: , valueId: }, {propertId: , valueId: }] |
| 37 | 35 | */ |
| 36 | + // TODO franky:可以定义一个内部的 Property 类,然后 List<Property> | |
| 38 | 37 | private String properties; |
| 39 | 38 | /** |
| 40 | 39 | * 销售价格,单位:分 | ... | ... |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/propertyvalue/ProductPropertyValueMapper.java
| 1 | 1 | package cn.iocoder.yudao.module.product.dal.mysql.propertyvalue; |
| 2 | 2 | |
| 3 | -import java.util.*; | |
| 4 | - | |
| 5 | -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | |
| 6 | 3 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| 4 | +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | |
| 7 | 5 | import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO; |
| 8 | 6 | import org.apache.ibatis.annotations.Mapper; |
| 9 | 7 | |
| 8 | +import java.util.List; | |
| 9 | + | |
| 10 | 10 | /** |
| 11 | 11 | * 规格值 Mapper |
| 12 | 12 | * |
| ... | ... | @@ -15,12 +15,15 @@ import org.apache.ibatis.annotations.Mapper; |
| 15 | 15 | @Mapper |
| 16 | 16 | public interface ProductPropertyValueMapper extends BaseMapperX<ProductPropertyValueDO> { |
| 17 | 17 | |
| 18 | + // TODO @franky:方法名,selectListByXXX。mapper 的操作都是 crud | |
| 18 | 19 | default List<ProductPropertyValueDO> getPropertyValueListByPropertyId(List<Long> propertyIds){ |
| 20 | + // TODO @franky:调用父类的 selectList | |
| 19 | 21 | return selectList(new LambdaQueryWrapperX<ProductPropertyValueDO>() |
| 20 | 22 | .inIfPresent(ProductPropertyValueDO::getPropertyId, propertyIds)); |
| 21 | 23 | } |
| 22 | 24 | |
| 23 | 25 | default void deletePropertyValueByPropertyId(Long propertyId){ |
| 26 | + // TODO @franky:delete(new ) 即可 | |
| 24 | 27 | LambdaQueryWrapperX<ProductPropertyValueDO> queryWrapperX = new LambdaQueryWrapperX<>(); |
| 25 | 28 | queryWrapperX.eq(ProductPropertyValueDO::getPropertyId, propertyId) |
| 26 | 29 | .eq(ProductPropertyValueDO::getDeleted, false); | ... | ... |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/sku/ProductSkuMapper.java
| 1 | 1 | package cn.iocoder.yudao.module.product.dal.mysql.sku; |
| 2 | 2 | |
| 3 | -import java.util.*; | |
| 4 | - | |
| 5 | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 6 | -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | |
| 7 | 4 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| 8 | -import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert; | |
| 5 | +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | |
| 6 | +import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuExportReqVO; | |
| 7 | +import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuPageReqVO; | |
| 9 | 8 | import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; |
| 10 | 9 | import org.apache.ibatis.annotations.Mapper; |
| 11 | -import cn.iocoder.yudao.module.product.controller.admin.sku.vo.*; | |
| 10 | + | |
| 11 | +import java.util.List; | |
| 12 | 12 | |
| 13 | 13 | /** |
| 14 | 14 | * 商品sku Mapper |
| ... | ... | @@ -46,13 +46,14 @@ public interface ProductSkuMapper extends BaseMapperX<ProductSkuDO> { |
| 46 | 46 | .orderByDesc(ProductSkuDO::getId)); |
| 47 | 47 | } |
| 48 | 48 | |
| 49 | + // TODO @franky:方法名 selectList; 可以直接调用 selectList | |
| 49 | 50 | default List<ProductSkuDO> selectBySpuIds(List<Long> spuIds) { |
| 50 | 51 | return selectList(new LambdaQueryWrapperX<ProductSkuDO>() |
| 51 | - .inIfPresent(ProductSkuDO::getSpuId, spuIds) | |
| 52 | - ); | |
| 52 | + .inIfPresent(ProductSkuDO::getSpuId, spuIds)); | |
| 53 | 53 | } |
| 54 | 54 | |
| 55 | 55 | default void deleteBySpuId(Long spuId) { |
| 56 | + // TODO @franky:直接 delete(new XXX) 即可,更简洁一些 | |
| 56 | 57 | LambdaQueryWrapperX<ProductSkuDO> lambdaQueryWrapperX = new LambdaQueryWrapperX<ProductSkuDO>() |
| 57 | 58 | .eqIfPresent(ProductSkuDO::getSpuId, spuId); |
| 58 | 59 | delete(lambdaQueryWrapperX); | ... | ... |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java
| ... | ... | @@ -80,13 +80,14 @@ public interface ProductSkuService { |
| 80 | 80 | void validateSkus(List<ProductSkuCreateReqVO> list); |
| 81 | 81 | |
| 82 | 82 | /** |
| 83 | - * 批量保存sku | |
| 83 | + * 批量保存 sku | |
| 84 | + * | |
| 84 | 85 | * @param list sku对象集合 |
| 85 | 86 | */ |
| 86 | 87 | void createSkus(List<ProductSkuDO> list); |
| 87 | 88 | |
| 88 | 89 | /** |
| 89 | - * 获得商品sku 集合 | |
| 90 | + * 获得商品 sku 集合 | |
| 90 | 91 | * |
| 91 | 92 | * @param spuId spu 编号 |
| 92 | 93 | * @return 商品sku 集合 |
| ... | ... | @@ -94,6 +95,7 @@ public interface ProductSkuService { |
| 94 | 95 | List<ProductSkuDO> getSkusBySpuId(Long spuId); |
| 95 | 96 | |
| 96 | 97 | /** |
| 98 | + * 获得 spu 对应的 sku 集合 | |
| 97 | 99 | * |
| 98 | 100 | * @param spuIds spu 编码集合 |
| 99 | 101 | * @return 商品 sku 集合 |
| ... | ... | @@ -102,12 +104,14 @@ public interface ProductSkuService { |
| 102 | 104 | |
| 103 | 105 | /** |
| 104 | 106 | * 通过 spuId 删除 sku 信息 |
| 107 | + * | |
| 105 | 108 | * @param spuId spu 编码 |
| 106 | 109 | */ |
| 107 | 110 | void deleteSkuBySpuId(Long spuId); |
| 108 | 111 | |
| 109 | 112 | /** |
| 110 | 113 | * 根据 spuId 更新 spu 下的 sku 信息 |
| 114 | + * | |
| 111 | 115 | * @param spuId spu 编码 |
| 112 | 116 | * @param skus sku 的集合 |
| 113 | 117 | */ | ... | ... |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java
| ... | ... | @@ -148,6 +148,7 @@ public class ProductSkuServiceImpl implements ProductSkuService { |
| 148 | 148 | List<ProductSkuDO> allUpdateSkus = ProductSkuConvert.INSTANCE.convertSkuDOList(skus); |
| 149 | 149 | // 查询 spu 下已经存在的 sku 的集合 |
| 150 | 150 | List<ProductSkuDO> existsSkus = productSkuMapper.selectBySpuIds(Collections.singletonList(spuId)); |
| 151 | + // TODO @franky:使用 CollUtils 即可 | |
| 151 | 152 | Map<Long, ProductSkuDO> existsSkuMap = existsSkus.stream().collect(Collectors.toMap(ProductSkuDO::getId, p -> p)); |
| 152 | 153 | |
| 153 | 154 | // 拆分三个集合, 新插入的, 需要更新的,需要删除的 |
| ... | ... | @@ -155,6 +156,7 @@ public class ProductSkuServiceImpl implements ProductSkuService { |
| 155 | 156 | List<ProductSkuDO> updateSkus = new ArrayList<>(); |
| 156 | 157 | List<ProductSkuDO> deleteSkus = new ArrayList<>(); |
| 157 | 158 | |
| 159 | + // TODO @芋艿:是不是基于规格匹配会比较好。 | |
| 158 | 160 | allUpdateSkus.forEach(p -> { |
| 159 | 161 | if (null != p.getId()) { |
| 160 | 162 | if (existsSkuMap.get(p.getId()) != null) { | ... | ... |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java
| 1 | 1 | package cn.iocoder.yudao.module.product.service.spu; |
| 2 | 2 | |
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 3 | 4 | import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateReqVO; |
| 4 | 5 | import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuRespVO; |
| 6 | +import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*; | |
| 5 | 7 | import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert; |
| 8 | +import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert; | |
| 6 | 9 | import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; |
| 10 | +import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; | |
| 11 | +import cn.iocoder.yudao.module.product.dal.mysql.spu.ProductSpuMapper; | |
| 7 | 12 | import cn.iocoder.yudao.module.product.service.category.CategoryService; |
| 8 | 13 | import cn.iocoder.yudao.module.product.service.sku.ProductSkuService; |
| 9 | 14 | import org.springframework.stereotype.Service; |
| 10 | - | |
| 11 | -import javax.annotation.Resource; | |
| 12 | -import javax.validation.Valid; | |
| 13 | - | |
| 14 | 15 | import org.springframework.transaction.annotation.Transactional; |
| 15 | 16 | import org.springframework.validation.annotation.Validated; |
| 16 | 17 | |
| 17 | -import java.util.*; | |
| 18 | +import javax.annotation.Resource; | |
| 19 | +import java.util.Collection; | |
| 20 | +import java.util.List; | |
| 21 | +import java.util.Map; | |
| 18 | 22 | import java.util.stream.Collectors; |
| 19 | 23 | |
| 20 | -import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*; | |
| 21 | -import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; | |
| 22 | -import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 23 | - | |
| 24 | -import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert; | |
| 25 | -import cn.iocoder.yudao.module.product.dal.mysql.spu.ProductSpuMapper; | |
| 26 | - | |
| 27 | 24 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 28 | -import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.*; | |
| 25 | +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS; | |
| 29 | 26 | |
| 30 | 27 | /** |
| 31 | 28 | * 商品spu Service 实现类 |
| ... | ... | @@ -123,11 +120,10 @@ public class ProductSpuServiceImpl implements ProductSpuService { |
| 123 | 120 | // 查询 sku 的信息 |
| 124 | 121 | List<Long> spuIds = spuVOs.getList().stream().map(SpuRespVO::getId).collect(Collectors.toList()); |
| 125 | 122 | List<ProductSkuRespVO> skus = ProductSkuConvert.INSTANCE.convertList(productSkuService.getSkusBySpuIds(spuIds)); |
| 123 | + // TODO @franky:使用 CollUtil 里的方法替代哈 | |
| 126 | 124 | Map<Long, List<ProductSkuRespVO>> skuMap = skus.stream().collect(Collectors.groupingBy(ProductSkuRespVO::getSpuId)); |
| 127 | 125 | // 将 spu 和 sku 进行组装 |
| 128 | - spuVOs.getList().forEach(p -> { | |
| 129 | - p.setSkus(skuMap.get(p.getId())); | |
| 130 | - }); | |
| 126 | + spuVOs.getList().forEach(p -> p.setSkus(skuMap.get(p.getId()))); | |
| 131 | 127 | return spuVOs; |
| 132 | 128 | } |
| 133 | 129 | ... | ... |