Commit 652428a723f44f2823deecdbbc80e08704742ad8
1 parent
b7c44789
product:完善 App 商品详情接口
Showing
18 changed files
with
300 additions
and
70 deletions
yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/ErrorCodeConstants.java
| ... | ... | @@ -33,6 +33,7 @@ public interface ErrorCodeConstants { |
| 33 | 33 | // ========== 商品 SPU 1008005000 ========== |
| 34 | 34 | ErrorCode SPU_NOT_EXISTS = new ErrorCode(1008005000, "商品 SPU 不存在"); |
| 35 | 35 | ErrorCode SPU_SAVE_FAIL_CATEGORY_LEVEL_ERROR = new ErrorCode(1008005001, "商品分类不正确,原因:必须使用第三级的商品分类下"); |
| 36 | + ErrorCode SPU_NOT_ENABLE = new ErrorCode(1008005002, "商品 SPU 不处于上架状态"); | |
| 36 | 37 | |
| 37 | 38 | // ========== 商品 SKU 1008006000 ========== |
| 38 | 39 | ErrorCode SKU_NOT_EXISTS = new ErrorCode(1008006000, "商品 SKU 不存在"); | ... | ... |
yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/spu/ProductSpuStatusEnum.java
| ... | ... | @@ -35,4 +35,14 @@ public enum ProductSpuStatusEnum implements IntArrayValuable { |
| 35 | 35 | return ARRAYS; |
| 36 | 36 | } |
| 37 | 37 | |
| 38 | + /** | |
| 39 | + * 判断是否处于【上架】状态 | |
| 40 | + * | |
| 41 | + * @param status 状态 | |
| 42 | + * @return 是否处于【上架】状态 | |
| 43 | + */ | |
| 44 | + public static boolean isEnable(Integer status) { | |
| 45 | + return ENABLE.getStatus().equals(status); | |
| 46 | + } | |
| 47 | + | |
| 38 | 48 | } | ... | ... |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.java
| ... | ... | @@ -66,7 +66,7 @@ public class ProductSpuController { |
| 66 | 66 | @ApiOperation("获得商品 SPU") |
| 67 | 67 | @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class) |
| 68 | 68 | @PreAuthorize("@ss.hasPermission('product:spu:query')") |
| 69 | - public CommonResult<ProductSpuRespVO> getSpu(@RequestParam("id") Long id) { | |
| 69 | + public CommonResult<ProductSpuDO> getSpu(@RequestParam("id") Long id) { | |
| 70 | 70 | return success(spuService.getSpu(id)); |
| 71 | 71 | } |
| 72 | 72 | |
| ... | ... | @@ -75,7 +75,7 @@ public class ProductSpuController { |
| 75 | 75 | @ApiOperation("获得商品 SPU 列表") |
| 76 | 76 | @ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class) |
| 77 | 77 | @PreAuthorize("@ss.hasPermission('product:spu:query')") |
| 78 | - public CommonResult<List<ProductSpuRespVO>> getSpuList(@RequestParam("ids") Collection<Long> ids) { | |
| 78 | + public CommonResult<List<ProductSpuDO>> getSpuList(@RequestParam("ids") Collection<Long> ids) { | |
| 79 | 79 | List<ProductSpuDO> list = spuService.getSpuList(ids); |
| 80 | 80 | return success(ProductSpuConvert.INSTANCE.convertList(list)); |
| 81 | 81 | } | ... | ... |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/package-info.java
0 → 100644
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/vo/property/package-info.java
0 → 100644
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/property/vo/value/AppProductPropertyValueDetailRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.product.controller.app.property.vo.value; | |
| 2 | + | |
| 3 | +import io.swagger.annotations.ApiModel; | |
| 4 | +import io.swagger.annotations.ApiModelProperty; | |
| 5 | +import lombok.Data; | |
| 6 | + | |
| 7 | +@ApiModel("用户 App - 商品属性值的明细 Response VO") | |
| 8 | +@Data | |
| 9 | +public class AppProductPropertyValueDetailRespVO { | |
| 10 | + | |
| 11 | + @ApiModelProperty(value = "属性的编号", required = true, example = "1") | |
| 12 | + private Long propertyId; | |
| 13 | + | |
| 14 | + @ApiModelProperty(value = "属性的名称", required = true, example = "颜色") | |
| 15 | + private String propertyName; | |
| 16 | + | |
| 17 | + @ApiModelProperty(value = "属性值的编号", required = true, example = "1024") | |
| 18 | + private Long valueId; | |
| 19 | + | |
| 20 | + @ApiModelProperty(value = "属性值的名称", required = true, example = "红色") | |
| 21 | + private String valueName; | |
| 22 | + | |
| 23 | +} | ... | ... |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.http
0 → 100644
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.java
| 1 | 1 | package cn.iocoder.yudao.module.product.controller.app.spu; |
| 2 | 2 | |
| 3 | -import cn.hutool.core.bean.BeanUtil; | |
| 3 | +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | |
| 4 | 4 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 5 | 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 6 | +import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuDetailRespVO; | |
| 6 | 7 | import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageReqVO; |
| 7 | 8 | import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageRespVO; |
| 8 | -import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuRespVO; | |
| 9 | +import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert; | |
| 10 | +import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert; | |
| 11 | +import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; | |
| 12 | +import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; | |
| 13 | +import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum; | |
| 14 | +import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService; | |
| 15 | +import cn.iocoder.yudao.module.product.service.property.bo.ProductPropertyValueDetailRespBO; | |
| 16 | +import cn.iocoder.yudao.module.product.service.sku.ProductSkuService; | |
| 9 | 17 | import cn.iocoder.yudao.module.product.service.spu.ProductSpuService; |
| 10 | 18 | import io.swagger.annotations.Api; |
| 19 | +import io.swagger.annotations.ApiImplicitParam; | |
| 11 | 20 | import io.swagger.annotations.ApiOperation; |
| 12 | 21 | import org.springframework.validation.annotation.Validated; |
| 13 | 22 | import org.springframework.web.bind.annotation.GetMapping; |
| ... | ... | @@ -17,28 +26,53 @@ import org.springframework.web.bind.annotation.RestController; |
| 17 | 26 | |
| 18 | 27 | import javax.annotation.Resource; |
| 19 | 28 | import javax.validation.Valid; |
| 29 | +import java.util.List; | |
| 20 | 30 | |
| 31 | +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | |
| 21 | 32 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 33 | +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_ENABLE; | |
| 34 | +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS; | |
| 22 | 35 | |
| 23 | -@Api(tags = "用户 APP - 商品spu") | |
| 36 | +@Api(tags = "用户 APP - 商品 SPU") | |
| 24 | 37 | @RestController |
| 25 | 38 | @RequestMapping("/product/spu") |
| 26 | 39 | @Validated |
| 27 | 40 | public class AppProductSpuController { |
| 28 | 41 | |
| 29 | 42 | @Resource |
| 30 | - private ProductSpuService spuService; | |
| 43 | + private ProductSpuService productSpuService; | |
| 44 | + @Resource | |
| 45 | + private ProductSkuService productSkuService; | |
| 46 | + @Resource | |
| 47 | + private ProductPropertyValueService productPropertyValueService; | |
| 31 | 48 | |
| 32 | 49 | @GetMapping("/page") |
| 33 | 50 | @ApiOperation("获得商品spu分页") |
| 34 | 51 | public CommonResult<PageResult<AppSpuPageRespVO>> getSpuPage(@Valid AppSpuPageReqVO pageVO) { |
| 35 | - return success(spuService.getSpuPage(pageVO)); | |
| 52 | + return success(productSpuService.getSpuPage(pageVO)); | |
| 36 | 53 | } |
| 37 | 54 | |
| 38 | - @GetMapping("/") | |
| 39 | - @ApiOperation("获取商品 - 通过商品id") | |
| 40 | - public CommonResult<AppSpuRespVO> getSpu(@RequestParam("spuId") Long spuId) { | |
| 41 | - AppSpuRespVO appSpuRespVO = BeanUtil.toBean(spuService.getSpu(spuId), AppSpuRespVO.class); | |
| 42 | - return success(appSpuRespVO); | |
| 55 | + @GetMapping("/get-detail") | |
| 56 | + @ApiOperation("获得商品 SPU 明细") | |
| 57 | + @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class) | |
| 58 | + public CommonResult<AppSpuDetailRespVO> getSpuDetail(@RequestParam("id") Long id) { | |
| 59 | + // 获得商品 SPU | |
| 60 | + ProductSpuDO spu = productSpuService.getSpu(id); | |
| 61 | + if (spu == null) { | |
| 62 | + throw exception(SPU_NOT_EXISTS); | |
| 63 | + } | |
| 64 | + if (!ProductSpuStatusEnum.isEnable(spu.getStatus())) { | |
| 65 | + throw exception(SPU_NOT_ENABLE); | |
| 66 | + } | |
| 67 | + | |
| 68 | + // 查询商品 SKU | |
| 69 | + List<ProductSkuDO> skus = productSkuService.getSkuListBySpuIdAndStatus(spu.getId(), | |
| 70 | + CommonStatusEnum.ENABLE.getStatus()); | |
| 71 | + // 查询商品属性 | |
| 72 | + List<ProductPropertyValueDetailRespBO> propertyValues = productPropertyValueService | |
| 73 | + .getPropertyValueDetailList(ProductSkuConvert.INSTANCE.convertPropertyValueIds(skus)); | |
| 74 | + // 拼接 | |
| 75 | + return success(ProductSpuConvert.INSTANCE.convert(spu, skus, propertyValues)); | |
| 43 | 76 | } |
| 77 | + | |
| 44 | 78 | } | ... | ... |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppSpuDetailRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.product.controller.app.spu.vo; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.module.product.controller.app.property.vo.value.AppProductPropertyValueDetailRespVO; | |
| 4 | +import io.swagger.annotations.ApiModel; | |
| 5 | +import io.swagger.annotations.ApiModelProperty; | |
| 6 | +import lombok.Data; | |
| 7 | + | |
| 8 | +import java.util.List; | |
| 9 | + | |
| 10 | +@ApiModel("用户 App - 商品 SPU 明细 Response VO") | |
| 11 | +@Data | |
| 12 | +public class AppSpuDetailRespVO { | |
| 13 | + | |
| 14 | + @ApiModelProperty(value = "商品 SPU 编号", required = true, example = "1") | |
| 15 | + private Long id; | |
| 16 | + | |
| 17 | + // ========== 基本信息 ========= | |
| 18 | + | |
| 19 | + @ApiModelProperty(value = "商品名称", required = true, example = "芋道") | |
| 20 | + private String name; | |
| 21 | + | |
| 22 | + @ApiModelProperty(value = "促销语", example = "好吃!") | |
| 23 | + private String sellPoint; | |
| 24 | + | |
| 25 | + @ApiModelProperty(value = "商品详情", required = true, example = "我是商品描述") | |
| 26 | + private String description; | |
| 27 | + | |
| 28 | + @ApiModelProperty(value = "商品分类编号", required = true, example = "1") | |
| 29 | + private Long categoryId; | |
| 30 | + | |
| 31 | + @ApiModelProperty(value = "商品图片的数组", required = true) | |
| 32 | + private List<String> picUrls; | |
| 33 | + | |
| 34 | + @ApiModelProperty(value = "商品视频", required = true) | |
| 35 | + private String videoUrl; | |
| 36 | + | |
| 37 | + // ========== SKU 相关字段 ========= | |
| 38 | + | |
| 39 | + @ApiModelProperty(value = "规格类型", required = true, example = "1", notes = "参见 ProductSpuSpecTypeEnum 枚举类") | |
| 40 | + private Integer specType; | |
| 41 | + | |
| 42 | + @ApiModelProperty(value = "是否展示库存", required = true, example = "true") | |
| 43 | + private Boolean showStock; | |
| 44 | + | |
| 45 | + @ApiModelProperty(value = " 最小价格,单位使用:分", required = true, example = "1024") | |
| 46 | + private Integer minPrice; | |
| 47 | + | |
| 48 | + @ApiModelProperty(value = "最大价格,单位使用:分", required = true, example = "1024") | |
| 49 | + private Integer maxPrice; | |
| 50 | + | |
| 51 | + /** | |
| 52 | + * SKU 数组 | |
| 53 | + */ | |
| 54 | + private List<Sku> skus; | |
| 55 | + | |
| 56 | + // ========== 统计相关字段 ========= | |
| 57 | + | |
| 58 | + @ApiModelProperty(value = "商品销量", required = true, example = "1024") | |
| 59 | + private Integer salesCount; | |
| 60 | + | |
| 61 | + @ApiModel("用户 App - 商品 SPU 明细的 SKU 信息") | |
| 62 | + @Data | |
| 63 | + public static class Sku { | |
| 64 | + | |
| 65 | + @ApiModelProperty(value = "商品 SKU 编号", example = "1") | |
| 66 | + private Long id; | |
| 67 | + | |
| 68 | + /** | |
| 69 | + * 商品属性数组 | |
| 70 | + */ | |
| 71 | + private List<AppProductPropertyValueDetailRespVO> properties; | |
| 72 | + | |
| 73 | + @ApiModelProperty(value = "销售价格,单位:分", required = true, example = "1024", notes = "单位:分") | |
| 74 | + private Integer price; | |
| 75 | + | |
| 76 | + @ApiModelProperty(value = "市场价", example = "1024", notes = "单位:分") | |
| 77 | + private Integer marketPrice; | |
| 78 | + | |
| 79 | + @ApiModelProperty(value = "图片地址", required = true, example = "https://www.iocoder.cn/xx.png") | |
| 80 | + private String picUrl; | |
| 81 | + | |
| 82 | + @ApiModelProperty(value = "库存", required = true, example = "1") | |
| 83 | + private Integer stock; | |
| 84 | + | |
| 85 | + @ApiModelProperty(value = "商品重量", example = "1", notes = "单位:kg 千克") | |
| 86 | + private Double weight; | |
| 87 | + | |
| 88 | + @ApiModelProperty(value = "商品体积", example = "1024", notes = "单位:m^3 平米") | |
| 89 | + private Double volume; | |
| 90 | + } | |
| 91 | + | |
| 92 | +} | ... | ... |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppSpuRespVO.java deleted
| 1 | -package cn.iocoder.yudao.module.product.controller.app.spu.vo; | |
| 2 | - | |
| 3 | -import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuRespVO; | |
| 4 | -import io.swagger.annotations.ApiModel; | |
| 5 | -import lombok.Data; | |
| 6 | -import lombok.EqualsAndHashCode; | |
| 7 | - | |
| 8 | -/** | |
| 9 | - * <p> | |
| 10 | - * | |
| 11 | - * </p> | |
| 12 | - * | |
| 13 | - * @author LuoWenFeng | |
| 14 | - */ | |
| 15 | -@ApiModel("App - 商品spu Response VO") | |
| 16 | -@Data | |
| 17 | -@EqualsAndHashCode(callSuper = true) | |
| 18 | -public class AppSpuRespVO extends ProductSpuRespVO { | |
| 19 | - | |
| 20 | - | |
| 21 | -} |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/sku/ProductSkuConvert.java
| 1 | 1 | package cn.iocoder.yudao.module.product.convert.sku; |
| 2 | 2 | |
| 3 | +import cn.hutool.core.collection.CollUtil; | |
| 3 | 4 | import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; |
| 4 | 5 | import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO; |
| 5 | 6 | import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO; |
| ... | ... | @@ -10,9 +11,8 @@ import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; |
| 10 | 11 | import org.mapstruct.Mapper; |
| 11 | 12 | import org.mapstruct.factory.Mappers; |
| 12 | 13 | |
| 13 | -import java.util.HashMap; | |
| 14 | -import java.util.List; | |
| 15 | -import java.util.Map; | |
| 14 | +import java.util.*; | |
| 15 | +import java.util.stream.Collectors; | |
| 16 | 16 | |
| 17 | 17 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; |
| 18 | 18 | |
| ... | ... | @@ -72,4 +72,14 @@ public interface ProductSkuConvert { |
| 72 | 72 | return spuIdAndStockMap; |
| 73 | 73 | } |
| 74 | 74 | |
| 75 | + default Collection<Long> convertPropertyValueIds(List<ProductSkuDO> list) { | |
| 76 | + if (CollUtil.isEmpty(list)) { | |
| 77 | + return new HashSet<>(); | |
| 78 | + } | |
| 79 | + return list.stream().filter(item -> item.getProperties() != null) | |
| 80 | + .flatMap(p -> p.getProperties().stream()) // 遍历多个 Property 属性 | |
| 81 | + .map(ProductSkuDO.Property::getValueId) // 将每个 Property 转换成对应的 propertyId,最后形成集合 | |
| 82 | + .collect(Collectors.toSet()); | |
| 83 | + } | |
| 84 | + | |
| 75 | 85 | } | ... | ... |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java
| 1 | 1 | package cn.iocoder.yudao.module.product.convert.spu; |
| 2 | 2 | |
| 3 | +import cn.hutool.core.collection.CollUtil; | |
| 3 | 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | 5 | import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; |
| 5 | 6 | import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*; |
| 7 | +import cn.iocoder.yudao.module.product.controller.app.property.vo.value.AppProductPropertyValueDetailRespVO; | |
| 8 | +import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuDetailRespVO; | |
| 6 | 9 | import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageReqVO; |
| 7 | 10 | import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageRespVO; |
| 11 | +import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; | |
| 8 | 12 | import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; |
| 13 | +import cn.iocoder.yudao.module.product.service.property.bo.ProductPropertyValueDetailRespBO; | |
| 9 | 14 | import org.mapstruct.Mapper; |
| 10 | 15 | import org.mapstruct.factory.Mappers; |
| 11 | 16 | |
| 17 | +import java.util.ArrayList; | |
| 12 | 18 | import java.util.List; |
| 19 | +import java.util.Map; | |
| 20 | + | |
| 21 | +import static cn.hutool.core.util.ObjectUtil.defaultIfNull; | |
| 22 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; | |
| 13 | 23 | |
| 14 | 24 | /** |
| 15 | 25 | * 商品spu Convert |
| ... | ... | @@ -25,18 +35,46 @@ public interface ProductSpuConvert { |
| 25 | 35 | |
| 26 | 36 | ProductSpuDO convert(ProductSpuUpdateReqVO bean); |
| 27 | 37 | |
| 28 | - ProductSpuRespVO convert(ProductSpuDO bean); | |
| 29 | - | |
| 30 | - List<ProductSpuRespVO> convertList(List<ProductSpuDO> list); | |
| 38 | + List<ProductSpuDO> convertList(List<ProductSpuDO> list); | |
| 31 | 39 | |
| 32 | 40 | PageResult<ProductSpuRespVO> convertPage(PageResult<ProductSpuDO> page); |
| 33 | 41 | |
| 34 | 42 | ProductSpuPageReqVO convert(AppSpuPageReqVO bean); |
| 35 | 43 | |
| 44 | + // TODO 芋艿:修改下 | |
| 36 | 45 | AppSpuPageRespVO convertAppResp(ProductSpuDO list); |
| 37 | 46 | |
| 38 | 47 | List<ProductSpuRespDTO> convertList2(List<ProductSpuDO> list); |
| 39 | 48 | |
| 40 | 49 | List<ProductSpuSimpleRespVO> convertList02(List<ProductSpuDO> list); |
| 41 | 50 | |
| 51 | + default AppSpuDetailRespVO convert(ProductSpuDO spu, List<ProductSkuDO> skus, | |
| 52 | + List<ProductPropertyValueDetailRespBO> propertyValues) { | |
| 53 | + AppSpuDetailRespVO spuVO = convert02(spu) | |
| 54 | + .setSalesCount(spu.getSalesCount() + defaultIfNull(spu.getVirtualSalesCount(), 0)); | |
| 55 | + spuVO.setSkus(convertList03(skus)); | |
| 56 | + // 处理商品属性 | |
| 57 | + Map<Long, ProductPropertyValueDetailRespBO> propertyValueMap = convertMap(propertyValues, ProductPropertyValueDetailRespBO::getValueId); | |
| 58 | + for (int i = 0; i < skus.size(); i++) { | |
| 59 | + List<ProductSkuDO.Property> properties = skus.get(i).getProperties(); | |
| 60 | + if (CollUtil.isEmpty(properties)) { | |
| 61 | + continue; | |
| 62 | + } | |
| 63 | + AppSpuDetailRespVO.Sku sku = spuVO.getSkus().get(i); | |
| 64 | + sku.setProperties(new ArrayList<>(properties.size())); | |
| 65 | + // 遍历每个 properties,设置到 AppSpuDetailRespVO.Sku 中 | |
| 66 | + properties.forEach(property -> { | |
| 67 | + ProductPropertyValueDetailRespBO propertyValue = propertyValueMap.get(property.getValueId()); | |
| 68 | + if (propertyValue == null) { | |
| 69 | + return; | |
| 70 | + } | |
| 71 | + sku.getProperties().add(convert03(propertyValue)); | |
| 72 | + }); | |
| 73 | + } | |
| 74 | + return spuVO; | |
| 75 | + } | |
| 76 | + AppSpuDetailRespVO convert02(ProductSpuDO spu); | |
| 77 | + List<AppSpuDetailRespVO.Sku> convertList03(List<ProductSkuDO> skus); | |
| 78 | + AppProductPropertyValueDetailRespVO convert03(ProductPropertyValueDetailRespBO propertyValue); | |
| 79 | + | |
| 42 | 80 | } | ... | ... |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/sku/ProductSkuMapper.java
| ... | ... | @@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| 8 | 8 | import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; |
| 9 | 9 | import org.apache.ibatis.annotations.Mapper; |
| 10 | 10 | |
| 11 | +import java.util.Collection; | |
| 11 | 12 | import java.util.List; |
| 12 | 13 | |
| 13 | 14 | /** |
| ... | ... | @@ -22,6 +23,17 @@ public interface ProductSkuMapper extends BaseMapperX<ProductSkuDO> { |
| 22 | 23 | return selectList(ProductSkuDO::getSpuId, spuId); |
| 23 | 24 | } |
| 24 | 25 | |
| 26 | + default List<ProductSkuDO> selectListBySpuIdAndStatus(Long spuId, | |
| 27 | + Integer status) { | |
| 28 | + return selectList(new LambdaQueryWrapperX<ProductSkuDO>() | |
| 29 | + .eq(ProductSkuDO::getSpuId, spuId) | |
| 30 | + .eqIfPresent(ProductSkuDO::getStatus, status)); | |
| 31 | + } | |
| 32 | + | |
| 33 | + default List<ProductSkuDO> selectListBySpuId(Collection<Long> spuIds) { | |
| 34 | + return selectList(ProductSkuDO::getSpuId, spuIds); | |
| 35 | + } | |
| 36 | + | |
| 25 | 37 | default void deleteBySpuId(Long spuId) { |
| 26 | 38 | delete(new LambdaQueryWrapperX<ProductSkuDO>().eq(ProductSkuDO::getSpuId, spuId)); |
| 27 | 39 | } | ... | ... |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java
| ... | ... | @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.product.service.sku; |
| 3 | 3 | import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO; |
| 4 | 4 | import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO; |
| 5 | 5 | import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; |
| 6 | +import org.springframework.lang.Nullable; | |
| 6 | 7 | |
| 7 | 8 | import java.util.Collection; |
| 8 | 9 | import java.util.List; |
| ... | ... | @@ -49,25 +50,25 @@ public interface ProductSkuService { |
| 49 | 50 | * |
| 50 | 51 | * @param list sku组合的集合 |
| 51 | 52 | */ |
| 52 | - void validateSkus(List<ProductSkuCreateOrUpdateReqVO> list, Integer specType); | |
| 53 | + void validateSkuList(List<ProductSkuCreateOrUpdateReqVO> list, Integer specType); | |
| 53 | 54 | |
| 54 | 55 | /** |
| 55 | 56 | * 批量创建 SKU |
| 56 | 57 | * |
| 57 | 58 | * @param spuId 商品 SPU 编号 |
| 58 | - * @para spuName 商品 SPU 名称 | |
| 59 | + * @param spuName 商品 SPU 名称 | |
| 59 | 60 | * @param list SKU 对象集合 |
| 60 | 61 | */ |
| 61 | - void createSkus(Long spuId, String spuName, List<ProductSkuCreateOrUpdateReqVO> list); | |
| 62 | + void createSkuList(Long spuId, String spuName, List<ProductSkuCreateOrUpdateReqVO> list); | |
| 62 | 63 | |
| 63 | 64 | /** |
| 64 | 65 | * 根据 SPU 编号,批量更新它的 SKU 信息 |
| 65 | 66 | * |
| 66 | 67 | * @param spuId SPU 编码 |
| 67 | - * @para spuName 商品 SPU 名称 | |
| 68 | + * @param spuName 商品 SPU 名称 | |
| 68 | 69 | * @param skus SKU 的集合 |
| 69 | 70 | */ |
| 70 | - void updateSkus(Long spuId, String spuName, List<ProductSkuCreateOrUpdateReqVO> skus); | |
| 71 | + void updateSkuList(Long spuId, String spuName, List<ProductSkuCreateOrUpdateReqVO> skus); | |
| 71 | 72 | |
| 72 | 73 | /** |
| 73 | 74 | * 更新 SKU 库存(增量) |
| ... | ... | @@ -79,20 +80,30 @@ public interface ProductSkuService { |
| 79 | 80 | void updateSkuStock(ProductSkuUpdateStockReqDTO updateStockReqDTO); |
| 80 | 81 | |
| 81 | 82 | /** |
| 82 | - * 获得商品 sku 集合 | |
| 83 | + * 获得商品 SKU 集合 | |
| 83 | 84 | * |
| 84 | 85 | * @param spuId spu 编号 |
| 85 | 86 | * @return 商品sku 集合 |
| 86 | 87 | */ |
| 87 | - List<ProductSkuDO> getSkusBySpuId(Long spuId); | |
| 88 | + List<ProductSkuDO> getSkuListBySpuId(Long spuId); | |
| 88 | 89 | |
| 89 | 90 | /** |
| 90 | - * 获得 spu 对应的 sku 集合 | |
| 91 | + * 基于 SPU 编号和状态,获得商品 SKU 集合 | |
| 92 | + * | |
| 93 | + * @param spuId SPU 编号 | |
| 94 | + * @param status 状态 | |
| 95 | + * @return 商品 SKU 集合 | |
| 96 | + */ | |
| 97 | + List<ProductSkuDO> getSkuListBySpuIdAndStatus(Long spuId, | |
| 98 | + @Nullable Integer status); | |
| 99 | + | |
| 100 | + /** | |
| 101 | + * 获得 spu 对应的 SKU 集合 | |
| 91 | 102 | * |
| 92 | 103 | * @param spuIds spu 编码集合 |
| 93 | 104 | * @return 商品 sku 集合 |
| 94 | 105 | */ |
| 95 | - List<ProductSkuDO> getSkusBySpuIds(List<Long> spuIds); | |
| 106 | + List<ProductSkuDO> getSkuListBySpuId(List<Long> spuIds); | |
| 96 | 107 | |
| 97 | 108 | /** |
| 98 | 109 | * 通过 spuId 删除 sku 信息 |
| ... | ... | @@ -106,7 +117,6 @@ public interface ProductSkuService { |
| 106 | 117 | * |
| 107 | 118 | * @return SKU 数组 |
| 108 | 119 | */ |
| 109 | - List<ProductSkuDO> getSkusByAlarmStock(); | |
| 110 | - | |
| 120 | + List<ProductSkuDO> getSkuListByAlarmStock(); | |
| 111 | 121 | |
| 112 | 122 | } | ... | ... |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java
| ... | ... | @@ -78,7 +78,7 @@ public class ProductSkuServiceImpl implements ProductSkuService { |
| 78 | 78 | } |
| 79 | 79 | |
| 80 | 80 | @Override |
| 81 | - public void validateSkus(List<ProductSkuCreateOrUpdateReqVO> skus, Integer specType) { | |
| 81 | + public void validateSkuList(List<ProductSkuCreateOrUpdateReqVO> skus, Integer specType) { | |
| 82 | 82 | // 非多规格,不需要校验 |
| 83 | 83 | if (ObjectUtil.notEqual(specType, ProductSpuSpecTypeEnum.DISABLE.getType())) { |
| 84 | 84 | return; |
| ... | ... | @@ -121,7 +121,7 @@ public class ProductSkuServiceImpl implements ProductSkuService { |
| 121 | 121 | } |
| 122 | 122 | |
| 123 | 123 | @Override |
| 124 | - public void createSkus(Long spuId, String spuName, List<ProductSkuCreateOrUpdateReqVO> skuCreateReqList) { | |
| 124 | + public void createSkuList(Long spuId, String spuName, List<ProductSkuCreateOrUpdateReqVO> skuCreateReqList) { | |
| 125 | 125 | // 批量插入 SKU |
| 126 | 126 | List<ProductSkuDO> skuDOList = ProductSkuConvert.INSTANCE.convertList06(skuCreateReqList, spuName); |
| 127 | 127 | skuDOList.forEach(v -> v.setSpuId(spuId)); |
| ... | ... | @@ -129,13 +129,18 @@ public class ProductSkuServiceImpl implements ProductSkuService { |
| 129 | 129 | } |
| 130 | 130 | |
| 131 | 131 | @Override |
| 132 | - public List<ProductSkuDO> getSkusBySpuId(Long spuId) { | |
| 133 | - return productSkuMapper.selectList(ProductSkuDO::getSpuId, spuId); | |
| 132 | + public List<ProductSkuDO> getSkuListBySpuId(Long spuId) { | |
| 133 | + return productSkuMapper.selectListBySpuId(spuId); | |
| 134 | 134 | } |
| 135 | 135 | |
| 136 | 136 | @Override |
| 137 | - public List<ProductSkuDO> getSkusBySpuIds(List<Long> spuIds) { | |
| 138 | - return productSkuMapper.selectList(ProductSkuDO::getSpuId, spuIds); | |
| 137 | + public List<ProductSkuDO> getSkuListBySpuIdAndStatus(Long spuId, Integer status) { | |
| 138 | + return productSkuMapper.selectListBySpuIdAndStatus(spuId, status); | |
| 139 | + } | |
| 140 | + | |
| 141 | + @Override | |
| 142 | + public List<ProductSkuDO> getSkuListBySpuId(List<Long> spuIds) { | |
| 143 | + return productSkuMapper.selectListBySpuId(spuIds); | |
| 139 | 144 | } |
| 140 | 145 | |
| 141 | 146 | @Override |
| ... | ... | @@ -144,13 +149,13 @@ public class ProductSkuServiceImpl implements ProductSkuService { |
| 144 | 149 | } |
| 145 | 150 | |
| 146 | 151 | @Override |
| 147 | - public List<ProductSkuDO> getSkusByAlarmStock() { | |
| 152 | + public List<ProductSkuDO> getSkuListByAlarmStock() { | |
| 148 | 153 | return productSkuMapper.selectListByAlarmStock(); |
| 149 | 154 | } |
| 150 | 155 | |
| 151 | 156 | @Override |
| 152 | 157 | @Transactional |
| 153 | - public void updateSkus(Long spuId, String spuName, List<ProductSkuCreateOrUpdateReqVO> skus) { | |
| 158 | + public void updateSkuList(Long spuId, String spuName, List<ProductSkuCreateOrUpdateReqVO> skus) { | |
| 154 | 159 | // 查询 SPU 下已经存在的 SKU 的集合 |
| 155 | 160 | List<ProductSkuDO> existsSkus = productSkuMapper.selectListBySpuId(spuId); |
| 156 | 161 | // 构建属性与 SKU 的映射关系; | ... | ... |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuService.java
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java
| ... | ... | @@ -72,7 +72,7 @@ public class ProductSpuServiceImpl implements ProductSpuService { |
| 72 | 72 | brandService.validateProductBrand(createReqVO.getBrandId()); |
| 73 | 73 | // 校验SKU |
| 74 | 74 | List<ProductSkuCreateOrUpdateReqVO> skuCreateReqList = createReqVO.getSkus(); |
| 75 | - productSkuService.validateSkus(skuCreateReqList, createReqVO.getSpecType()); | |
| 75 | + productSkuService.validateSkuList(skuCreateReqList, createReqVO.getSpecType()); | |
| 76 | 76 | // 插入 SPU |
| 77 | 77 | ProductSpuDO spu = ProductSpuConvert.INSTANCE.convert(createReqVO); |
| 78 | 78 | spu.setMarketPrice(CollectionUtils.getMaxValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getMarketPrice)); |
| ... | ... | @@ -81,7 +81,7 @@ public class ProductSpuServiceImpl implements ProductSpuService { |
| 81 | 81 | spu.setTotalStock(CollectionUtils.getSumValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getStock, Integer::sum)); |
| 82 | 82 | productSpuMapper.insert(spu); |
| 83 | 83 | // 插入 SKU |
| 84 | - productSkuService.createSkus(spu.getId(), spu.getName(), skuCreateReqList); | |
| 84 | + productSkuService.createSkuList(spu.getId(), spu.getName(), skuCreateReqList); | |
| 85 | 85 | // 返回 |
| 86 | 86 | return spu.getId(); |
| 87 | 87 | } |
| ... | ... | @@ -97,7 +97,7 @@ public class ProductSpuServiceImpl implements ProductSpuService { |
| 97 | 97 | brandService.validateProductBrand(updateReqVO.getBrandId()); |
| 98 | 98 | // 校验SKU |
| 99 | 99 | List<ProductSkuCreateOrUpdateReqVO> skuCreateReqList = updateReqVO.getSkus(); |
| 100 | - productSkuService.validateSkus(skuCreateReqList, updateReqVO.getSpecType()); | |
| 100 | + productSkuService.validateSkuList(skuCreateReqList, updateReqVO.getSpecType()); | |
| 101 | 101 | |
| 102 | 102 | // 更新 SPU |
| 103 | 103 | ProductSpuDO updateObj = ProductSpuConvert.INSTANCE.convert(updateReqVO); |
| ... | ... | @@ -107,7 +107,7 @@ public class ProductSpuServiceImpl implements ProductSpuService { |
| 107 | 107 | updateObj.setTotalStock(CollectionUtils.getSumValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getStock, Integer::sum)); |
| 108 | 108 | productSpuMapper.updateById(updateObj); |
| 109 | 109 | // 批量更新 SKU |
| 110 | - productSkuService.updateSkus(updateObj.getId(), updateObj.getName(), updateReqVO.getSkus()); | |
| 110 | + productSkuService.updateSkuList(updateObj.getId(), updateObj.getName(), updateReqVO.getSkus()); | |
| 111 | 111 | } |
| 112 | 112 | |
| 113 | 113 | /** |
| ... | ... | @@ -146,7 +146,7 @@ public class ProductSpuServiceImpl implements ProductSpuService { |
| 146 | 146 | ProductSpuDO spu = productSpuMapper.selectById(id); |
| 147 | 147 | ProductSpuDetailRespVO respVO = BeanUtil.copyProperties(spu, ProductSpuDetailRespVO.class); |
| 148 | 148 | if (null != spu) { |
| 149 | - List<ProductSpuDetailRespVO.Sku> skuReqs = ProductSkuConvert.INSTANCE.convertList03(productSkuService.getSkusBySpuId(id)); | |
| 149 | + List<ProductSpuDetailRespVO.Sku> skuReqs = ProductSkuConvert.INSTANCE.convertList03(productSkuService.getSkuListBySpuId(id)); | |
| 150 | 150 | respVO.setSkus(skuReqs); |
| 151 | 151 | // 组合 sku 属性 |
| 152 | 152 | if (spu.getSpecType().equals(ProductSpuSpecTypeEnum.DISABLE.getType())) { |
| ... | ... | @@ -181,8 +181,8 @@ public class ProductSpuServiceImpl implements ProductSpuService { |
| 181 | 181 | } |
| 182 | 182 | |
| 183 | 183 | @Override |
| 184 | - public ProductSpuRespVO getSpu(Long id) { | |
| 185 | - return ProductSpuConvert.INSTANCE.convert(productSpuMapper.selectById(id)); | |
| 184 | + public ProductSpuDO getSpu(Long id) { | |
| 185 | + return productSpuMapper.selectById(id); | |
| 186 | 186 | } |
| 187 | 187 | |
| 188 | 188 | @Override |
| ... | ... | @@ -200,7 +200,7 @@ public class ProductSpuServiceImpl implements ProductSpuService { |
| 200 | 200 | // 库存告警的 SPU 编号的集合 |
| 201 | 201 | Set<Long> alarmStockSpuIds = null; |
| 202 | 202 | if (Boolean.TRUE.equals(pageReqVO.getAlarmStock())) { |
| 203 | - alarmStockSpuIds = CollectionUtils.convertSet(productSkuService.getSkusByAlarmStock(), ProductSkuDO::getSpuId); | |
| 203 | + alarmStockSpuIds = CollectionUtils.convertSet(productSkuService.getSkuListByAlarmStock(), ProductSkuDO::getSpuId); | |
| 204 | 204 | if (CollUtil.isEmpty(alarmStockSpuIds)) { |
| 205 | 205 | return PageResult.empty(); |
| 206 | 206 | } | ... | ... |
yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java
| ... | ... | @@ -186,7 +186,7 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest { |
| 186 | 186 | |
| 187 | 187 | }); |
| 188 | 188 | |
| 189 | - Mockito.when(productSkuService.getSkusBySpuId(createReqVO.getId())).thenReturn(productSkuDOS); | |
| 189 | + Mockito.when(productSkuService.getSkuListBySpuId(createReqVO.getId())).thenReturn(productSkuDOS); | |
| 190 | 190 | // Mockito.when(productPropertyValueService.getPropertyValueListByPropertyId(new ArrayList<>(collect.keySet()))).thenReturn(productPropertyValueRespVO); |
| 191 | 191 | // Mockito.when(productPropertyService.getPropertyVOList(new ArrayList<>(collect.keySet()))).thenReturn(productPropertyRespVOS); |
| 192 | 192 | // |
| ... | ... | @@ -202,7 +202,7 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest { |
| 202 | 202 | ProductSpuDO createReqVO = randomPojo(ProductSpuDO.class); |
| 203 | 203 | productSpuMapper.insert(createReqVO); |
| 204 | 204 | |
| 205 | - ProductSpuRespVO spu = productSpuService.getSpu(createReqVO.getId()); | |
| 205 | + ProductSpuDO spu = productSpuService.getSpu(createReqVO.getId()); | |
| 206 | 206 | assertPojoEquals(createReqVO, spu); |
| 207 | 207 | } |
| 208 | 208 | |
| ... | ... | @@ -267,7 +267,7 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest { |
| 267 | 267 | o.setSpuId(createReqVO.getId()); |
| 268 | 268 | })); |
| 269 | 269 | |
| 270 | - Mockito.when(productSkuService.getSkusByAlarmStock()).thenReturn(productSpuDOS); | |
| 270 | + Mockito.when(productSkuService.getSkuListByAlarmStock()).thenReturn(productSpuDOS); | |
| 271 | 271 | |
| 272 | 272 | // 调用 |
| 273 | 273 | ProductSpuPageReqVO productSpuPageReqVO = new ProductSpuPageReqVO(); | ... | ... |