From 70816371e51ae57c3b85ee236c28b437dfd65c81 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Tue, 2 May 2023 02:33:14 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E6=AD=A5=E5=AE=8C=E6=88=90=E5=95=86?= =?UTF-8?q?=E5=93=81CRUD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/sku/vo/ProductSkuBaseVO.java | 10 +++ .../admin/spu/ProductSpuController.java | 2 +- .../admin/spu/vo/ProductSpuBaseVO.java | 61 ++++------------- .../admin/spu/vo/ProductSpuPageReqVO.java | 24 ------- .../admin/spu/vo/ProductSpuPageRespVO.java | 31 +++++++++ .../admin/spu/vo/ProductSpuRespVO.java | 18 ----- .../convert/sku/ProductSkuConvert.java | 3 +- .../convert/spu/ProductSpuConvert.java | 2 +- .../dal/dataobject/spu/ProductSpuDO.java | 6 +- .../dal/mysql/spu/ProductSpuMapper.java | 13 ---- .../category/ProductCategoryServiceImpl.java | 2 +- .../service/sku/ProductSkuService.java | 6 +- .../service/sku/ProductSkuServiceImpl.java | 30 ++++++--- .../service/spu/ProductSpuServiceImpl.java | 65 +++++++++++-------- .../service/sku/ProductSkuServiceTest.java | 2 +- .../spu/ProductSpuServiceImplTest.java | 42 +++--------- 16 files changed, 133 insertions(+), 184 deletions(-) create mode 100644 yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuPageRespVO.java 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 e9c9bb48c4..dde623b500 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 @@ -50,4 +50,14 @@ public class ProductSkuBaseVO { @Schema(description = "商品体积", example = "1024") // 单位:m^3 平米 private Double volume; + /** + * 一级分销的佣金,单位:分 + */ + @Schema(description = "一级分销的佣金", example = "1024") + private Integer subCommissionFirstPrice; + /** + * 二级分销的佣金,单位:分 + */ + @Schema(description = "二级分销的佣金", example = "1024") + private Integer subCommissionSecondPrice; } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.java index 85fa93f8ea..f2ce90c1d9 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/ProductSpuController.java @@ -94,7 +94,7 @@ public class ProductSpuController { @GetMapping("/page") @Operation(summary = "获得商品 SPU 分页") @PreAuthorize("@ss.hasPermission('product:spu:query')") - public CommonResult> getSpuPage(@Valid ProductSpuPageReqVO pageVO) { + public CommonResult> getSpuPage(@Valid ProductSpuPageReqVO pageVO) { return success(ProductSpuConvert.INSTANCE.convertPage(productSpuService.getSpuPage(pageVO))); } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuBaseVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuBaseVO.java index e7a30484d0..251b4be47d 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuBaseVO.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuBaseVO.java @@ -38,16 +38,11 @@ public class ProductSpuBaseVO { @NotEmpty(message = "商品详情不能为空") private String description; - @Schema(description = "商品条码(一维码)", required = true, example = "芋道") - @NotEmpty(message = "商品条码(一维码)不能为空") - private String barCode; - @Schema(description = "商品分类编号", required = true, example = "芋道") - @NotEmpty(message = "商品分类编号不能为空") + @NotNull(message = "商品分类编号不能为空") private Long categoryId; @Schema(description = "商品品牌编号", required = true, example = "芋道") - @NotEmpty(message = "商品品牌编号不能为空") private Long brandId; @Schema(description = "商品封面图", required = true, example = "芋道") @@ -55,99 +50,71 @@ public class ProductSpuBaseVO { private String picUrl; @Schema(description = "商品轮播图", required = true) - @NotEmpty(message = "商品轮播图不能为空") private List sliderPicUrls; @Schema(description = "商品视频") private String videoUrl; @Schema(description = "单位", required = true, example = "1") - @NotEmpty(message = "商品单位不能为空") + @NotNull(message = "商品单位不能为空") private Integer unit; @Schema(description = "排序字段", required = true, example = "1") - @NotEmpty(message = "商品排序字段不能为空") + @NotNull(message = "商品排序字段不能为空") private Integer sort; - @Schema(description = "商品状态", required = true, example = "1") - @NotEmpty(message = "商品状态不能为空") - private Integer status; - // ========== SKU 相关字段 ========= @Schema(description = "规格类型", required = true, example = "true") - @NotEmpty(message = "商品规格类型不能为空") + @NotNull(message = "商品规格类型不能为空") private Boolean specType; - @Schema(description = "商品价格", required = true, example = "1212") - @NotEmpty(message = "商品价格不能为空") - private Integer price; - - @Schema(description = "市场价", required = true, example = "3") - @NotEmpty(message = "商品市场价不能为空") - private Integer marketPrice; - - @Schema(description = "成本价", required = true, example = "12") - @NotEmpty(message = "商品成本价不能为空") - private Integer costPrice; - - @Schema(description = "库存", required = true, example = "111") - @NotEmpty(message = "商品库存不能为空") - private Integer stock; - // ========== 物流相关字段 ========= @Schema(description = "物流配置模板编号", required = true, example = "111") - @NotEmpty(message = "物流配置模板编号不能为空") + @NotNull(message = "物流配置模板编号不能为空") private Long deliveryTemplateId; // ========== 营销相关字段 ========= @Schema(description = "是否热卖推荐", required = true, example = "true") - @NotEmpty(message = "商品推荐不能为空") + @NotNull(message = "商品推荐不能为空") private Boolean recommendHot; @Schema(description = "是否优惠推荐", required = true, example = "true") - @NotEmpty(message = "商品推荐不能为空") + @NotNull(message = "商品推荐不能为空") private Boolean recommendBenefit; @Schema(description = "是否精品推荐", required = true, example = "true") - @NotEmpty(message = "商品推荐不能为空") + @NotNull(message = "商品推荐不能为空") private Boolean recommendBest; @Schema(description = "是否新品推荐", required = true, example = "true") - @NotEmpty(message = "商品推荐不能为空") + @NotNull(message = "商品推荐不能为空") private Boolean recommendNew; @Schema(description = "是否优品推荐", required = true, example = "true") - @NotEmpty(message = "商品推荐不能为空") + @NotNull(message = "商品推荐不能为空") private Boolean recommendGood; @Schema(description = "赠送积分", required = true, example = "111") - @NotEmpty(message = "商品赠送积分不能为空") + @NotNull(message = "商品赠送积分不能为空") private Integer giveIntegral; - @Schema(description = "赠送的优惠劵编号的数组") + @Schema(description = "赠送的优惠劵编号的数组") // TODO 这块前端还未实现 private List giveCouponTemplateIds; @Schema(description = "分销类型") + @NotNull(message = "商品分销类型不能为空") private Boolean subCommissionType; - @Schema(description = "活动展示顺序") + @Schema(description = "活动展示顺序") // TODO 这块前端还未实现 private List activityOrders; // ========== 统计相关字段 ========= - @Schema(description = "商品销量", required = true, example = "芋道") - @NotEmpty(message = "商品销量不能为空") - private Integer salesCount; - @Schema(description = "虚拟销量", required = true, example = "芋道") - @NotEmpty(message = "商品虚拟销量不能为空") private Integer virtualSalesCount; - @Schema(description = "浏览量", required = true, example = "芋道") - @NotEmpty(message = "商品浏览量不能为空") - private Integer browseCount; } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuPageReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuPageReqVO.java index 0bfefb8d4d..91cd54ab26 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuPageReqVO.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuPageReqVO.java @@ -15,31 +15,7 @@ public class ProductSpuPageReqVO extends PageParam { @Schema(description = "商品名称", example = "yutou") private String name; - @Schema(description = "商品编码", example = "yudaoyuanma") - private String code; - @Schema(description = "分类编号", example = "1") private Long categoryId; - @Schema(description = "商品品牌编号", example = "1") - private Long brandId; - - @Schema(description = "上下架状态", example = "1") - private Integer status; - - @Schema(description = "销量最小值", example = "1") - private Integer salesCountMin; - - @Schema(description = "销量最大值", example = "1024") - private Integer salesCountMax; - - @Schema(description = "市场价最小值", example = "1") - private Integer marketPriceMin; - - @Schema(description = "市场价最大值", example = "1024") - private Integer marketPriceMax; - - @Schema(description = "是否库存告警", example = "true") - private Boolean alarmStock; - } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuPageRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuPageRespVO.java new file mode 100644 index 0000000000..0517cd41c6 --- /dev/null +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuPageRespVO.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.product.controller.admin.spu.vo; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - 商品 SPU 分页 response VO") +@Data +public class ProductSpuPageRespVO { + @Schema(description = "spuId", example = "1") + private Long id; + @Schema(description = "商品封面图", example = "1") + private String picUrl; + @Schema(description = "商品名称", example = "1") + private String name; + @Schema(description = "商品价格", example = "1") + private Integer price; + @Schema(description = "商品销量", example = "1") + private Integer salesCount; + @Schema(description = "商品排序", example = "1") + private Integer stock; + @Schema(description = "商品封面图", example = "1") + private Integer sort; + @Schema(description = "商品创建时间", example = "1") + private LocalDateTime createTime; + @Schema(description = "商品状态", example = "1") + private Integer status; +} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuRespVO.java index 5f088b74b8..d550cb0c21 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuRespVO.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuRespVO.java @@ -19,22 +19,4 @@ public class ProductSpuRespVO extends ProductSpuBaseVO { @Schema(description = "创建时间") private LocalDateTime createTime; - // ========== SKU 相关字段 ========= - - @Schema(description = "库存", required = true, example = "true") - private Integer totalStock; - - @Schema(description = " 最小价格,单位使用:分", required = true, example = "1024") - private Integer minPrice; - - @Schema(description = "最大价格,单位使用:分", required = true, example = "1024") - private Integer maxPrice; - - @Schema(description = "商品销量", example = "1024") - private Integer salesCount; - - // ========== 统计相关字段 ========= - - @Schema(description = "点击量", example = "1024") - private Integer clickCount; } 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 9b7714bb96..8336242b41 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 @@ -35,9 +35,8 @@ public interface ProductSkuConvert { List convertList06(List list); - default List convertList06(List list, Long spuId, String spuName) { + default List convertList06(List list, Long spuId) { List result = convertList06(list); - // result.forEach(item -> item.setSpuId(spuId).setSpuName(spuName)); TODO ProductSkuDO中已经没有name相关属性 result.forEach(item -> item.setSpuId(spuId)); return result; } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java index fcf6d64368..4ceddab4d3 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java @@ -38,7 +38,7 @@ public interface ProductSpuConvert { List convertList(List list); - PageResult convertPage(PageResult page); + PageResult convertPage(PageResult page); ProductSpuPageReqVO convert(AppProductSpuPageReqVO bean); diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/spu/ProductSpuDO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/spu/ProductSpuDO.java index 1260c71702..e2ed9f2a1f 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/spu/ProductSpuDO.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/spu/ProductSpuDO.java @@ -116,19 +116,19 @@ public class ProductSpuDO extends TenantBaseDO { /** * 商品价格,单位使用:分 * - * 基于其对应的 {@link ProductSkuDO#getPrice()} 最小值 + * 基于其对应的 {@link ProductSkuDO#getPrice()} sku单价最低的商品的 */ private Integer price; /** * 市场价,单位使用:分 * - * 基于其对应的 {@link ProductSkuDO#getMarketPrice()} 最大值 TODO 芋艿:待确定最大还是最小 + * 基于其对应的 {@link ProductSkuDO#getMarketPrice()} sku单价最低的商品的 */ private Integer marketPrice; /** * 成本价,单位使用:分 * - * 基于其对应的 {@link ProductSkuDO#getCostPrice()} 最大值 TODO 芋艿:待确定最大还是最小 + * 基于其对应的 {@link ProductSkuDO#getCostPrice()} sku单价最低的商品的 */ private Integer costPrice; /** diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/spu/ProductSpuMapper.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/spu/ProductSpuMapper.java index 256bc43f19..6ac1e86110 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/spu/ProductSpuMapper.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/spu/ProductSpuMapper.java @@ -24,11 +24,6 @@ public interface ProductSpuMapper extends BaseMapperX { return selectPage(reqVO, new LambdaQueryWrapperX() .likeIfPresent(ProductSpuDO::getName, reqVO.getName()) .eqIfPresent(ProductSpuDO::getCategoryId, reqVO.getCategoryId()) - .eqIfPresent(ProductSpuDO::getStatus, reqVO.getStatus()) - .leIfPresent(ProductSpuDO::getSalesCount, reqVO.getSalesCountMax()) - .geIfPresent(ProductSpuDO::getSalesCount, reqVO.getSalesCountMin()) - .leIfPresent(ProductSpuDO::getMarketPrice, reqVO.getMarketPriceMax()) - .geIfPresent(ProductSpuDO::getMarketPrice, reqVO.getMarketPriceMin()) .orderByDesc(ProductSpuDO::getSort)); } @@ -36,13 +31,7 @@ public interface ProductSpuMapper extends BaseMapperX { return selectPage(reqVO, new LambdaQueryWrapperX() .likeIfPresent(ProductSpuDO::getName, reqVO.getName()) .eqIfPresent(ProductSpuDO::getCategoryId, reqVO.getCategoryId()) - .eqIfPresent(ProductSpuDO::getStatus, reqVO.getStatus()) - .leIfPresent(ProductSpuDO::getSalesCount, reqVO.getSalesCountMax()) - .geIfPresent(ProductSpuDO::getSalesCount, reqVO.getSalesCountMin()) - .leIfPresent(ProductSpuDO::getMarketPrice, reqVO.getMarketPriceMax()) - .geIfPresent(ProductSpuDO::getMarketPrice, reqVO.getMarketPriceMin()) .inIfPresent(ProductSpuDO::getId, alarmStockSpuIds) // 库存告警 - .eqIfPresent(ProductSpuDO::getStatus, reqVO.getStatus()) .orderByDesc(ProductSpuDO::getSort)); } @@ -52,8 +41,6 @@ public interface ProductSpuMapper extends BaseMapperX { .eqIfPresent(ProductSpuDO::getStatus, status); // 排序逻辑 if (Objects.equals(pageReqVO.getSortField(), AppProductSpuPageReqVO.SORT_FIELD_PRICE)) { - // TODO ProductSpuDO 已经没有maxPrice 属性 - //query.orderBy(true, pageReqVO.getSortAsc(), ProductSpuDO::getMaxPrice); } else if (Objects.equals(pageReqVO.getSortField(), AppProductSpuPageReqVO.SORT_FIELD_SALES_COUNT)) { query.orderBy(true, pageReqVO.getSortAsc(), ProductSpuDO::getSalesCount); } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImpl.java index 21dfb9dee8..02bde434dd 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImpl.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImpl.java @@ -100,7 +100,7 @@ public class ProductCategoryServiceImpl implements ProductCategoryService { if (category == null) { throw exception(CATEGORY_NOT_EXISTS); } - if (Objects.equals(category.getStatus(), CommonStatusEnum.ENABLE.getStatus())) { + if (Objects.equals(category.getStatus(), CommonStatusEnum.DISABLE.getStatus())) { throw exception(CATEGORY_DISABLED, category.getName()); } } 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 8db4911ab2..923603487f 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 @@ -56,19 +56,17 @@ public interface ProductSkuService { * 批量创建 SKU * * @param spuId 商品 SPU 编号 - * @param spuName 商品 SPU 名称 * @param list SKU 对象集合 */ - void createSkuList(Long spuId, String spuName, List list); + void createSkuList(Long spuId, List list); /** * 根据 SPU 编号,批量更新它的 SKU 信息 * * @param spuId SPU 编码 - * @param spuName 商品 SPU 名称 * @param skus SKU 的集合 */ - void updateSkuList(Long spuId, String spuName, List skus); + void updateSkuList(Long spuId, List skus); /** * 更新 SKU 库存(增量) diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java index a314318fc4..62e59f2c90 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 @@ -84,10 +84,17 @@ public class ProductSkuServiceImpl implements ProductSkuService { return; } + // 0、校验skus是否为空 + if (CollUtil.isEmpty(skus)){ + throw exception(SKU_NOT_EXISTS); + } + // 1、校验属性项存在 Set propertyIds = skus.stream().filter(p -> p.getProperties() != null) - .flatMap(p -> p.getProperties().stream()) // 遍历多个 Property 属性 - .map(ProductSkuCreateOrUpdateReqVO.Property::getPropertyId) // 将每个 Property 转换成对应的 propertyId,最后形成集合 + // 遍历多个 Property 属性 + .flatMap(p -> p.getProperties().stream()) + // 将每个 Property 转换成对应的 propertyId,最后形成集合 + .map(ProductSkuCreateOrUpdateReqVO.Property::getPropertyId) .collect(Collectors.toSet()); List propertyList = productPropertyService.getPropertyList(propertyIds); if (propertyList.size() != propertyIds.size()) { @@ -107,22 +114,24 @@ public class ProductSkuServiceImpl implements ProductSkuService { int attrValueIdsSize = skus.get(0).getProperties().size(); for (int i = 1; i < skus.size(); i++) { if (attrValueIdsSize != skus.get(i).getProperties().size()) { - throw exception(ErrorCodeConstants.SPU_ATTR_NUMBERS_MUST_BE_EQUALS); + throw exception(SPU_ATTR_NUMBERS_MUST_BE_EQUALS); } } // 4. 最后校验,每个 Sku 之间不是重复的 - Set> skuAttrValues = new HashSet<>(); // 每个元素,都是一个 Sku 的 attrValueId 集合。这样,通过最外层的 Set ,判断是否有重复的. + // 每个元素,都是一个 Sku 的 attrValueId 集合。这样,通过最外层的 Set ,判断是否有重复的. + Set> skuAttrValues = new HashSet<>(); for (ProductSkuCreateOrUpdateReqVO sku : skus) { - if (!skuAttrValues.add(convertSet(sku.getProperties(), ProductSkuCreateOrUpdateReqVO.Property::getValueId))) { // 添加失败,说明重复 - throw exception(ErrorCodeConstants.SPU_SKU_NOT_DUPLICATE); + // 添加失败,说明重复 + if (!skuAttrValues.add(convertSet(sku.getProperties(), ProductSkuCreateOrUpdateReqVO.Property::getValueId))) { + throw exception(SPU_SKU_NOT_DUPLICATE); } } } @Override - public void createSkuList(Long spuId, String spuName, List skuCreateReqList) { - productSkuMapper.insertBatch(ProductSkuConvert.INSTANCE.convertList06(skuCreateReqList, spuId, spuName)); + public void createSkuList(Long spuId, List skuCreateReqList) { + productSkuMapper.insertBatch(ProductSkuConvert.INSTANCE.convertList06(skuCreateReqList, spuId)); } @Override @@ -152,7 +161,7 @@ public class ProductSkuServiceImpl implements ProductSkuService { @Override @Transactional(rollbackFor = Exception.class) - public void updateSkuList(Long spuId, String spuName, List skus) { + public void updateSkuList(Long spuId, List skus) { // 构建属性与 SKU 的映射关系; Map existsSkuMap = convertMap(productSkuMapper.selectListBySpuId(spuId), ProductSkuConvert.INSTANCE::buildPropertyKey, ProductSkuDO::getId); @@ -160,13 +169,14 @@ public class ProductSkuServiceImpl implements ProductSkuService { // 拆分三个集合,新插入的、需要更新的、需要删除的 List insertSkus = new ArrayList<>(); List updateSkus = new ArrayList<>(); - List allUpdateSkus = ProductSkuConvert.INSTANCE.convertList06(skus, null, spuName); + List allUpdateSkus = ProductSkuConvert.INSTANCE.convertList06(skus, null); allUpdateSkus.forEach(sku -> { String propertiesKey = ProductSkuConvert.INSTANCE.buildPropertyKey(sku); // 1、找得到的,进行更新 Long existsSkuId = existsSkuMap.remove(propertiesKey); if (existsSkuId != null) { sku.setId(existsSkuId); + // TODO 那spuId岂不是为null了 updateSkus.add(sku); return; } 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 352c8b3412..45bc233893 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 @@ -12,6 +12,7 @@ import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert; import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; import cn.iocoder.yudao.module.product.dal.mysql.spu.ProductSpuMapper; +import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum; import cn.iocoder.yudao.module.product.service.brand.ProductBrandService; import cn.iocoder.yudao.module.product.service.category.ProductCategoryService; import cn.iocoder.yudao.module.product.service.sku.ProductSkuService; @@ -21,10 +22,7 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; @@ -54,20 +52,21 @@ public class ProductSpuServiceImpl implements ProductSpuService { @Override @Transactional(rollbackFor = Exception.class) public Long createSpu(ProductSpuCreateReqVO createReqVO) { - // 校验分类 - validateCategory(createReqVO.getCategoryId()); - // 校验品牌 - brandService.validateProductBrand(createReqVO.getBrandId()); - // 校验SKU - List skuSaveReqList = createReqVO.getSkus(); - productSkuService.validateSkuList(skuSaveReqList, createReqVO.getSpecType()); + // 校验分类 TODO 暂不清楚为什么只能选择第三层的结点 + //validateCategory(createReqVO.getCategoryId()); + // 校验品牌 TODO 暂不校验 + //brandService.validateProductBrand(createReqVO.getBrandId()); - // 插入 SPU + List skuSaveReqList = createReqVO.getSkus(); + // 校验SKU + productSkuService.validateSkuList(skuSaveReqList, createReqVO.getSpecType()); ProductSpuDO spu = ProductSpuConvert.INSTANCE.convert(createReqVO); + // 初始化SPU中SKU相关属性 initSpuFromSkus(spu, skuSaveReqList); + // 插入 SPU productSpuMapper.insert(spu); // 插入 SKU - productSkuService.createSkuList(spu.getId(), spu.getName(), skuSaveReqList); + productSkuService.createSkuList(spu.getId(), skuSaveReqList); // 返回 return spu.getId(); } @@ -90,7 +89,7 @@ public class ProductSpuServiceImpl implements ProductSpuService { initSpuFromSkus(updateObj, skuSaveReqList); productSpuMapper.updateById(updateObj); // 批量更新 SKU - productSkuService.updateSkuList(updateObj.getId(), updateObj.getName(), updateReqVO.getSkus()); + productSkuService.updateSkuList(updateObj.getId(), updateReqVO.getSkus()); } /** @@ -101,11 +100,25 @@ public class ProductSpuServiceImpl implements ProductSpuService { * @param skus 商品 SKU 数组 */ private void initSpuFromSkus(ProductSpuDO spu, List skus) { - spu.setMarketPrice(getMaxValue(skus, ProductSkuCreateOrUpdateReqVO::getMarketPrice)); - // TODO ProductSpuDO中已没有相关属性 - //spu.setMaxPrice(getMaxValue(skus, ProductSkuCreateOrUpdateReqVO::getPrice)); - //spu.setMinPrice(getMinValue(skus, ProductSkuCreateOrUpdateReqVO::getPrice)); - //spu.setTotalStock(getSumValue(skus, ProductSkuCreateOrUpdateReqVO::getStock, Integer::sum)); + // 断言,避免告警 + assert skus.size() > 0; + // 获取sku单价最低的商品 + ProductSkuCreateOrUpdateReqVO vo = skus.stream().min(Comparator.comparing(ProductSkuCreateOrUpdateReqVO::getPrice)).get(); + // sku单价最低的商品的价格 + spu.setPrice(vo.getPrice()); + // sku单价最低的商品的市场价格 + spu.setMarketPrice(vo.getMarketPrice()); + // sku单价最低的商品的成本价格 + spu.setCostPrice(vo.getCostPrice()); + // sku单价最低的商品的条形码 + spu.setBarCode(vo.getBarCode()); + // 默认状态为上架 + spu.setStatus(ProductSpuStatusEnum.ENABLE.getStatus()); + // TODO 默认商品销量和浏览量为零 + spu.setSalesCount(0); + spu.setBrowseCount(0); + // skus库存总数 + spu.setStock(getSumValue(skus, ProductSkuCreateOrUpdateReqVO::getStock, Integer::sum)); } /** @@ -155,14 +168,14 @@ public class ProductSpuServiceImpl implements ProductSpuService { @Override public PageResult getSpuPage(ProductSpuPageReqVO pageReqVO) { - // 库存告警的 SPU 编号的集合 + // 库存告警的 SPU 编号的集合 TODO 一个接口一个接口来 Set alarmStockSpuIds = null; - if (Boolean.TRUE.equals(pageReqVO.getAlarmStock())) { - alarmStockSpuIds = CollectionUtils.convertSet(productSkuService.getSkuListByAlarmStock(), ProductSkuDO::getSpuId); - if (CollUtil.isEmpty(alarmStockSpuIds)) { - return PageResult.empty(); - } - } + //if (Boolean.TRUE.equals(pageReqVO.getAlarmStock())) { + // alarmStockSpuIds = CollectionUtils.convertSet(productSkuService.getSkuListByAlarmStock(), ProductSkuDO::getSpuId); + // if (CollUtil.isEmpty(alarmStockSpuIds)) { + // return PageResult.empty(); + // } + //} // 分页查询 return productSpuMapper.selectPage(pageReqVO, alarmStockSpuIds); } diff --git a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceTest.java b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceTest.java index a6651c8b29..59305e22da 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceTest.java +++ b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceTest.java @@ -75,7 +75,7 @@ public class ProductSkuServiceTest extends BaseDbUnitTest { ); // 调用 - productSkuService.updateSkuList(spuId, spuName, skus); + productSkuService.updateSkuList(spuId, skus); // 断言 List dbSkus = productSkuMapper.selectListBySpuId(spuId); assertEquals(dbSkus.size(), 2); diff --git a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java index 8048e93448..d6e1bdb4e1 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java +++ b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java @@ -9,10 +9,7 @@ import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.collection.SetUtils; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO; -import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuCreateReqVO; -import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuPageReqVO; -import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuRespVO; -import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuUpdateReqVO; +import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*; import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO; import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert; import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; @@ -37,6 +34,7 @@ import java.util.*; import java.util.stream.Collectors; import java.util.stream.Stream; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.getSumValue; import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; @@ -83,21 +81,9 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest { // 准备参数 ProductSpuCreateReqVO createReqVO = randomPojo(ProductSpuCreateReqVO.class, o -> { o.setSpecType(true); - o.setStatus(ProductSpuStatusEnum.ENABLE.getStatus()); }); - - // 校验SKU - List skuCreateReqList = createReqVO.getSkus(); - Long spu = productSpuService.createSpu(createReqVO); ProductSpuDO productSpuDO = productSpuMapper.selectById(spu); - - createReqVO.setMarketPrice(CollectionUtils.getMaxValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getMarketPrice)); - // TODO ProductSpuCreateReqVO中已没有相关属性 -// createReqVO.setMaxPrice(CollectionUtils.getMaxValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getPrice)); -// createReqVO.setMinPrice(CollectionUtils.getMinValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getPrice)); -// createReqVO.setTotalStock(CollectionUtils.getSumValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getStock, Integer::sum)); - assertPojoEquals(createReqVO, productSpuDO); } @@ -111,18 +97,9 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest { ProductSpuUpdateReqVO reqVO = randomPojo(ProductSpuUpdateReqVO.class, o -> { o.setId(createReqVO.getId()); // 设置更新的 ID o.setSpecType(true); - o.setStatus(ProductSpuStatusEnum.DISABLE.getStatus()); }); // 调用 productSpuService.updateSpu(reqVO); - - List skuCreateReqList = reqVO.getSkus(); - reqVO.setMarketPrice(CollectionUtils.getMaxValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getMarketPrice)); - // TODO ProductSpuUpdateReqVO中已没有相关属性 -// reqVO.setMaxPrice(CollectionUtils.getMaxValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getPrice)); -// reqVO.setMinPrice(CollectionUtils.getMinValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getPrice)); -// reqVO.setTotalStock(CollectionUtils.getSumValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getStock, Integer::sum)); - // 校验是否更新正确 ProductSpuDO spu = productSpuMapper.selectById(reqVO.getId()); // 获取最新的 assertPojoEquals(reqVO, spu); @@ -132,7 +109,6 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest { public void testValidateSpuExists_exception() { ProductSpuUpdateReqVO reqVO = randomPojo(ProductSpuUpdateReqVO.class, o -> { o.setSpecType(true); - o.setStatus(ProductSpuStatusEnum.DISABLE.getStatus()); }); // 调用 Assertions.assertThrows(ServiceException.class, () -> productSpuService.updateSpu(reqVO)); @@ -175,7 +151,7 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest { void getSpuPage_alarmStock_empty() { // 调用 ProductSpuPageReqVO productSpuPageReqVO = new ProductSpuPageReqVO(); - productSpuPageReqVO.setAlarmStock(true); + //productSpuPageReqVO.setAlarmStock(true); PageResult spuPage = productSpuService.getSpuPage(productSpuPageReqVO); @@ -225,10 +201,10 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest { // 调用 ProductSpuPageReqVO productSpuPageReqVO = new ProductSpuPageReqVO(); - productSpuPageReqVO.setAlarmStock(true); + //productSpuPageReqVO.setAlarmStock(true); PageResult spuPage = productSpuService.getSpuPage(productSpuPageReqVO); - PageResult result = ProductSpuConvert.INSTANCE.convertPage(productSpuMapper.selectPage(productSpuPageReqVO, alarmStockSpuIds)); + PageResult result = ProductSpuConvert.INSTANCE.convertPage(productSpuMapper.selectPage(productSpuPageReqVO, alarmStockSpuIds)); Assertions.assertIterableEquals(result.getList(), spuPage.getList()); assertEquals(spuPage.getTotal(), result.getTotal()); } @@ -273,14 +249,14 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest { // 调用 ProductSpuPageReqVO productSpuPageReqVO = new ProductSpuPageReqVO(); - productSpuPageReqVO.setAlarmStock(false); - productSpuPageReqVO.setBrandId(brandId); - productSpuPageReqVO.setStatus(ProductSpuStatusEnum.ENABLE.getStatus()); + //productSpuPageReqVO.setAlarmStock(false); + //productSpuPageReqVO.setBrandId(brandId); + //productSpuPageReqVO.setStatus(ProductSpuStatusEnum.ENABLE.getStatus()); productSpuPageReqVO.setCategoryId(categoryId); PageResult spuPage = productSpuService.getSpuPage(productSpuPageReqVO); - PageResult result = ProductSpuConvert.INSTANCE.convertPage(productSpuMapper.selectPage(productSpuPageReqVO, (Set) null)); + PageResult result = ProductSpuConvert.INSTANCE.convertPage(productSpuMapper.selectPage(productSpuPageReqVO, (Set) null)); assertEquals(result, spuPage); }