MALL:简化 SPU 的 VO 转化

This commit is contained in:
YunaiV 2024-01-12 22:48:58 +08:00
parent fe5c5e4223
commit f6c8159dac
32 changed files with 312 additions and 663 deletions

View File

@ -21,6 +21,14 @@ public class BeanUtils {
return BeanUtil.toBean(source, targetClass);
}
public static <T> T toBean(Object source, Class<T> targetClass, Consumer<T> peek) {
T target = toBean(source, targetClass);
if (target != null) {
peek.accept(target);
}
return target;
}
public static <S, T> List<T> toBean(List<S> source, Class<T> targetType) {
if (source == null) {
return null;
@ -28,6 +36,14 @@ public class BeanUtils {
return CollectionUtils.convertList(source, s -> toBean(s, targetType));
}
public static <S, T> List<T> toBean(List<S> source, Class<T> targetType, Consumer<T> peek) {
List<T> list = toBean(source, targetType);
if (list != null) {
list.forEach(peek);
}
return list;
}
public static <S, T> PageResult<T> toBean(PageResult<S> source, Class<T> targetType) {
return toBean(source, targetType, null);
}

View File

@ -1,14 +1,14 @@
package cn.iocoder.yudao.module.product.api.sku;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO;
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.sku.ProductSkuService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import jakarta.annotation.Resource;
import java.util.Collection;
import java.util.List;
@ -28,19 +28,19 @@ public class ProductSkuApiImpl implements ProductSkuApi {
@Override
public ProductSkuRespDTO getSku(Long id) {
ProductSkuDO sku = productSkuService.getSku(id);
return ProductSkuConvert.INSTANCE.convert02(sku);
return BeanUtils.toBean(sku, ProductSkuRespDTO.class);
}
@Override
public List<ProductSkuRespDTO> getSkuList(Collection<Long> ids) {
List<ProductSkuDO> skus = productSkuService.getSkuList(ids);
return ProductSkuConvert.INSTANCE.convertList04(skus);
return BeanUtils.toBean(skus, ProductSkuRespDTO.class);
}
@Override
public List<ProductSkuRespDTO> getSkuListBySpuId(Collection<Long> spuIds) {
List<ProductSkuDO> skus = productSkuService.getSkuListBySpuId(spuIds);
return ProductSkuConvert.INSTANCE.convertList04(skus);
return BeanUtils.toBean(skus, ProductSkuRespDTO.class);
}
@Override

View File

@ -1,15 +1,14 @@
package cn.iocoder.yudao.module.product.api.spu;
import cn.hutool.core.collection.CollectionUtil;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert;
import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
import cn.iocoder.yudao.module.product.service.spu.ProductSpuService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import jakarta.annotation.Resource;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
@ -27,17 +26,20 @@ public class ProductSpuApiImpl implements ProductSpuApi {
@Override
public List<ProductSpuRespDTO> getSpuList(Collection<Long> ids) {
return ProductSpuConvert.INSTANCE.convertList2(spuService.getSpuList(ids));
List<ProductSpuDO> spus = spuService.getSpuList(ids);
return BeanUtils.toBean(spus, ProductSpuRespDTO.class);
}
@Override
public List<ProductSpuRespDTO> validateSpuList(Collection<Long> ids) {
return ProductSpuConvert.INSTANCE.convertList2(spuService.validateSpuList(ids));
List<ProductSpuDO> spus = spuService.validateSpuList(ids);
return BeanUtils.toBean(spus, ProductSpuRespDTO.class);
}
@Override
public ProductSpuRespDTO getSpu(Long id) {
return ProductSpuConvert.INSTANCE.convert02(spuService.getSpu(id));
ProductSpuDO spu = spuService.getSpu(id);
return BeanUtils.toBean(spu, ProductSpuRespDTO.class);
}
}

View File

@ -1,12 +1,12 @@
package cn.iocoder.yudao.module.product.controller.admin.comment.vo;
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuBaseVO;
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSkuSaveReqVO;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import jakarta.validation.constraints.NotNull;
import java.time.LocalDateTime;
import java.util.List;
@ -58,6 +58,6 @@ public class ProductCommentRespVO extends ProductCommentBaseVO {
private String skuPicUrl;
@Schema(description = "商品 SKU 规格值数组")
private List<ProductSkuBaseVO.Property> skuProperties;
private List<ProductSkuSaveReqVO.Property> skuProperties;
}

View File

@ -1,22 +0,0 @@
package cn.iocoder.yudao.module.product.controller.admin.property.vo.value;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "管理后台 - 商品属性值的明细 Response VO")
@Data
public class ProductPropertyValueDetailRespVO {
@Schema(description = "属性的编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long propertyId;
@Schema(description = "属性的名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "颜色")
private String propertyName;
@Schema(description = "属性值的编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long valueId;
@Schema(description = "属性值的名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "红色")
private String valueName;
}

View File

@ -1,14 +0,0 @@
package cn.iocoder.yudao.module.product.controller.admin.sku;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Tag(name = "管理后台 - 商品 SKU")
@RestController
@RequestMapping("/product/sku")
@Validated
public class ProductSkuController {
}

View File

@ -1,16 +0,0 @@
package cn.iocoder.yudao.module.product.controller.admin.sku.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.util.List;
@Schema(description = "管理后台 - 商品 SKU 创建/更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ProductSkuCreateOrUpdateReqVO extends ProductSkuBaseVO {
}

View File

@ -1,18 +0,0 @@
package cn.iocoder.yudao.module.product.controller.admin.sku.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import jakarta.validation.constraints.NotNull;
import java.util.List;
@Schema(description = "管理后台 - 商品 SKU Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ProductSkuRespVO extends ProductSkuBaseVO {
@Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
}

View File

@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.product.controller.admin.spu;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*;
@ -14,23 +15,22 @@ import cn.iocoder.yudao.module.product.service.spu.ProductSpuService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import java.io.IOException;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE;
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS;
@Tag(name = "管理后台 - 商品 SPU")
@RestController
@ -46,14 +46,14 @@ public class ProductSpuController {
@PostMapping("/create")
@Operation(summary = "创建商品 SPU")
@PreAuthorize("@ss.hasPermission('product:spu:create')")
public CommonResult<Long> createProductSpu(@Valid @RequestBody ProductSpuCreateReqVO createReqVO) {
public CommonResult<Long> createProductSpu(@Valid @RequestBody ProductSpuSaveReqVO createReqVO) {
return success(productSpuService.createSpu(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新商品 SPU")
@PreAuthorize("@ss.hasPermission('product:spu:update')")
public CommonResult<Boolean> updateSpu(@Valid @RequestBody ProductSpuUpdateReqVO updateReqVO) {
public CommonResult<Boolean> updateSpu(@Valid @RequestBody ProductSpuSaveReqVO updateReqVO) {
productSpuService.updateSpu(updateReqVO);
return success(true);
}
@ -79,15 +79,15 @@ public class ProductSpuController {
@Operation(summary = "获得商品 SPU 明细")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('product:spu:query')")
public CommonResult<ProductSpuDetailRespVO> getSpuDetail(@RequestParam("id") Long id) {
public CommonResult<ProductSpuRespVO> getSpuDetail(@RequestParam("id") Long id) {
// 获得商品 SPU
ProductSpuDO spu = productSpuService.getSpu(id);
if (spu == null) {
throw exception(SPU_NOT_EXISTS);
return success(null);
}
// 查询商品 SKU
List<ProductSkuDO> skus = productSkuService.getSkuListBySpuId(spu.getId());
return success(ProductSpuConvert.INSTANCE.convertForSpuDetailRespVO(spu, skus));
return success(ProductSpuConvert.INSTANCE.convert(spu, skus));
}
@GetMapping("/list-all-simple")
@ -97,14 +97,14 @@ public class ProductSpuController {
List<ProductSpuDO> list = productSpuService.getSpuListByStatus(ProductSpuStatusEnum.ENABLE.getStatus());
// 降序排序后返回给前端
list.sort(Comparator.comparing(ProductSpuDO::getSort).reversed());
return success(ProductSpuConvert.INSTANCE.convertList02(list));
return success(BeanUtils.toBean(list, ProductSpuSimpleRespVO.class));
}
@GetMapping("/list")
@Operation(summary = "获得商品 SPU 详情列表")
@Parameter(name = "spuIds", description = "spu 编号列表", required = true, example = "[1,2,3]")
@PreAuthorize("@ss.hasPermission('product:spu:query')")
public CommonResult<List<ProductSpuDetailRespVO>> getSpuList(@RequestParam("spuIds") Collection<Long> spuIds) {
public CommonResult<List<ProductSpuRespVO>> getSpuList(@RequestParam("spuIds") Collection<Long> spuIds) {
return success(ProductSpuConvert.INSTANCE.convertForSpuDetailRespListVO(
productSpuService.getSpuList(spuIds), productSkuService.getSkuListBySpuId(spuIds)));
}
@ -113,7 +113,8 @@ public class ProductSpuController {
@Operation(summary = "获得商品 SPU 分页")
@PreAuthorize("@ss.hasPermission('product:spu:query')")
public CommonResult<PageResult<ProductSpuRespVO>> getSpuPage(@Valid ProductSpuPageReqVO pageVO) {
return success(ProductSpuConvert.INSTANCE.convertPage(productSpuService.getSpuPage(pageVO)));
PageResult<ProductSpuDO> pageResult = productSpuService.getSpuPage(pageVO);
return success(BeanUtils.toBean(pageResult, ProductSpuRespVO.class));
}
@GetMapping("/get-count")
@ -127,12 +128,13 @@ public class ProductSpuController {
@Operation(summary = "导出商品")
@PreAuthorize("@ss.hasPermission('product:spu:export')")
@OperateLog(type = EXPORT)
public void exportUserList(@Validated ProductSpuExportReqVO reqVO,
public void exportSpuList(@Validated ProductSpuPageReqVO reqVO,
HttpServletResponse response) throws IOException {
List<ProductSpuDO> spuList = productSpuService.getSpuList(reqVO);
reqVO.setPageSize(PAGE_SIZE_NONE);
List<ProductSpuDO> list = productSpuService.getSpuPage(reqVO).getList();
// 导出 Excel
List<ProductSpuExcelVO> datas = ProductSpuConvert.INSTANCE.convertList03(spuList);
ExcelUtils.write(response, "商品列表.xls", "数据", ProductSpuExcelVO.class, datas);
ExcelUtils.write(response, "商品列表.xls", "数据", ProductSpuRespVO.class,
BeanUtils.toBean(list, ProductSpuRespVO.class));
}
}

View File

@ -0,0 +1,51 @@
package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
@Schema(description = "管理后台 - 商品 SKU Response VO")
@Data
public class ProductSkuRespVO {
@Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "商品 SKU 名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉小短袖")
private String name;
@Schema(description = "销售价格,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1999")
private Integer price;
@Schema(description = "市场价", example = "2999")
private Integer marketPrice;
@Schema(description = "成本价", example = "19")
private Integer costPrice;
@Schema(description = "条形码", example = "15156165456")
private String barCode;
@Schema(description = "图片地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xx.png")
private String picUrl;
@Schema(description = "库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "200")
private Integer stock;
@Schema(description = "商品重量,单位kg 千克", example = "1.2")
private Double weight;
@Schema(description = "商品体积,单位m^3 平米", example = "2.5")
private Double volume;
@Schema(description = "一级分销的佣金,单位:分", example = "199")
private Integer firstBrokeragePrice;
@Schema(description = "二级分销的佣金,单位:分", example = "19")
private Integer secondBrokeragePrice;
@Schema(description = "属性数组")
private List<ProductSkuSaveReqVO.Property> properties;
}

View File

@ -1,20 +1,15 @@
package cn.iocoder.yudao.module.product.controller.admin.sku.vo;
package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.*;
import java.util.List;
/**
* 商品 SKU Base VO提供给添加修改详细的子 VO 使用
* 如果子 VO 存在差异的字段请不要添加到这里影响 Swagger 文档生成
*/
@Schema(description = "管理后台 - 商品 SKU 创建/更新 Request VO")
@Data
public class ProductSkuBaseVO {
public class ProductSkuSaveReqVO {
@Schema(description = "商品 SKU 名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉小短袖")
@NotEmpty(message = "商品 SKU 名字不能为空")
@ -41,9 +36,6 @@ public class ProductSkuBaseVO {
@NotNull(message = "库存不能为空")
private Integer stock;
@Schema(description = "预警预存", example = "10")
private Integer warnStock;
@Schema(description = "商品重量,单位kg 千克", example = "1.2")
private Double weight;

View File

@ -1,24 +0,0 @@
package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import jakarta.validation.Valid;
import java.util.List;
@Schema(description = "管理后台 - 商品 SPU 创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ProductSpuCreateReqVO extends ProductSpuBaseVO {
// ========== SKU 相关字段 =========
@Schema(description = "SKU 数组")
@Valid
private List<ProductSkuCreateOrUpdateReqVO> skus;
}

View File

@ -1,22 +0,0 @@
package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuRespVO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.util.List;
@Schema(description = "管理后台 - 商品 SPU 详细 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ProductSpuDetailRespVO extends ProductSpuRespVO {
// ========== SKU 相关字段 =========
@Schema(description = "SKU 数组")
private List<ProductSkuRespVO> skus;
}

View File

@ -1,90 +0,0 @@
package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
import cn.iocoder.yudao.module.product.enums.DictTypeConstants;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
import java.time.LocalDateTime;
/**
* 商品 Spu Excel 导出 VO TODO 暂定
*
* @author HUIHUI
*/
@Data
public class ProductSpuExcelVO {
@ExcelProperty("商品编号")
private Long id;
@ExcelProperty("商品名称")
private String name;
@ExcelProperty("关键字")
private String keyword;
@ExcelProperty("商品简介")
private String introduction;
@ExcelProperty("商品详情")
private String description;
@ExcelProperty("条形码")
private String barCode;
@ExcelProperty("商品分类编号")
private Long categoryId;
@ExcelProperty("商品品牌编号")
private Long brandId;
@ExcelProperty("商品封面图")
private String picUrl;
@ExcelProperty("排序字段")
private Integer sort;
@ExcelProperty(value = "商品状态", converter = DictConvert.class)
@DictFormat(DictTypeConstants.PRODUCT_SPU_STATUS)
private Integer status;
@ExcelProperty("规格类型")
private Boolean specType;
@ExcelProperty("商品价格")
private Integer price;
@ExcelProperty("市场价")
private Integer marketPrice;
@ExcelProperty("成本价")
private Integer costPrice;
@ExcelProperty("库存")
private Integer stock;
@ExcelProperty("物流配置模板编号")
private Long deliveryTemplateId;
@ExcelProperty("赠送积分")
private Integer giveIntegral;
@ExcelProperty("分销类型")
private Boolean subCommissionType;
@ExcelProperty("商品销量")
private Integer salesCount;
@ExcelProperty("虚拟销量")
private Integer virtualSalesCount;
@ExcelProperty("商品点击量")
private Integer browseCount;
@ExcelProperty("创建时间")
private LocalDateTime createTime;
}

View File

@ -1,32 +0,0 @@
package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 商品 SPU 导出 Request VO参数和 ProductSpuPageReqVO 是一致的")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ProductSpuExportReqVO {
@Schema(description = "商品名称", example = "清凉小短袖")
private String name;
@Schema(description = "前端请求的tab类型", example = "1")
private Integer tabType;
@Schema(description = "商品分类编号", example = "100")
private Long categoryId;
@Schema(description = "创建时间", example = "[2022-07-01 00:00:00,2022-07-01 23:59:59]")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
}

View File

@ -1,43 +1,126 @@
package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
import cn.iocoder.yudao.framework.excel.core.convert.MoneyConvert;
import cn.iocoder.yudao.module.product.enums.DictTypeConstants;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.time.LocalDateTime;
import java.util.List;
@Schema(description = "管理后台 - 商品 SPU Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ProductSpuRespVO extends ProductSpuBaseVO {
@ExcelIgnoreUnannotated
public class ProductSpuRespVO {
@Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "111")
@ExcelProperty("商品编号")
private Long id;
@Schema(description = "商品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉小短袖")
@ExcelProperty("商品名称")
private String name;
@Schema(description = "关键字", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉丝滑不出汗")
@ExcelProperty("关键字")
private String keyword;
@Schema(description = "商品简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉小短袖简介")
@ExcelProperty("商品简介")
private String introduction;
@Schema(description = "商品详情", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉小短袖详情")
@ExcelProperty("商品详情")
private String description;
@Schema(description = "商品分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@ExcelProperty("商品分类编号")
private Long categoryId;
@Schema(description = "商品品牌编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@ExcelProperty("商品品牌编号")
private Long brandId;
@Schema(description = "商品封面图", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xx.png")
@ExcelProperty("商品封面图")
private String picUrl;
@Schema(description = "商品轮播图", requiredMode = Schema.RequiredMode.REQUIRED, example = "[https://www.iocoder.cn/xx.png, https://www.iocoder.cn/xxx.png]")
private List<String> sliderPicUrls;
@Schema(description = "排序字段", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@ExcelProperty("排序字段")
private Integer sort;
@Schema(description = "商品状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@ExcelProperty(value = "商品状态", converter = DictConvert.class)
@DictFormat(DictTypeConstants.PRODUCT_SPU_STATUS)
private Integer status;
@Schema(description = "商品创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2023-05-24 00:00:00")
@ExcelProperty("创建时间")
private LocalDateTime createTime;
// ========== SKU 相关字段 =========
@Schema(description = "规格类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
@ExcelProperty("规格类型")
private Boolean specType;
@Schema(description = "商品价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "1999")
@ExcelProperty(value = "商品价格", converter = MoneyConvert.class)
private Integer price;
@Schema(description = "商品销量", requiredMode = Schema.RequiredMode.REQUIRED, example = "2000")
private Integer salesCount;
@Schema(description = "市场价,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "199")
@ExcelProperty(value = "市场价", converter = MoneyConvert.class)
private Integer marketPrice;
@Schema(description = "成本价,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "19")
@ExcelProperty(value = "成本价", converter = MoneyConvert.class)
private Integer costPrice;
@Schema(description = "商品库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "10000")
@ExcelProperty("库存")
private Integer stock;
@Schema(description = "商品创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2023-05-24 00:00:00")
private LocalDateTime createTime;
@Schema(description = "SKU 数组")
private List<ProductSkuRespVO> skus;
@Schema(description = "商品状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer status;
// ========== 物流相关字段 =========
@Schema(description = "配送方式数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private List<Integer> deliveryTypes;
@Schema(description = "物流配置模板编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "111")
@ExcelProperty("物流配置模板编号")
private Long deliveryTemplateId;
// ========== 营销相关字段 =========
@Schema(description = "赠送积分", requiredMode = Schema.RequiredMode.REQUIRED, example = "111")
@ExcelProperty("赠送积分")
private Integer giveIntegral;
@Schema(description = "分销类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
@ExcelProperty("分销类型")
private Boolean subCommissionType;
// ========== 统计相关字段 =========
@Schema(description = "商品销量", requiredMode = Schema.RequiredMode.REQUIRED, example = "2000")
@ExcelProperty("商品销量")
private Integer salesCount;
@Schema(description = "虚拟销量", example = "66")
@ExcelProperty("虚拟销量")
private Integer virtualSalesCount;
@Schema(description = "浏览量", requiredMode = Schema.RequiredMode.REQUIRED, example = "888")
@ExcelProperty("商品点击量")
private Integer browseCount;
}

View File

@ -1,20 +1,19 @@
package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.util.List;
/**
* 商品 SPU Base VO提供给添加修改详细的子 VO 使用
* 如果子 VO 存在差异的字段请不要添加到这里影响 Swagger 文档生成
*
* @author HUIHUI
*/
@Schema(description = "管理后台 - 商品 SPU 新增/更新 Request VO")
@Data
public class ProductSpuBaseVO {
public class ProductSpuSaveReqVO {
@Schema(description = "商品编号", example = "1")
private Long id;
@Schema(description = "商品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉小短袖")
@NotEmpty(message = "商品名称不能为空")
@ -44,7 +43,8 @@ public class ProductSpuBaseVO {
@NotEmpty(message = "商品封面图不能为空")
private String picUrl;
@Schema(description = "商品轮播图", requiredMode = Schema.RequiredMode.REQUIRED, example = "[https://www.iocoder.cn/xx.png, https://www.iocoder.cn/xxx.png]")
@Schema(description = "商品轮播图", requiredMode = Schema.RequiredMode.REQUIRED,
example = "[https://www.iocoder.cn/xx.png, https://www.iocoder.cn/xxx.png]")
private List<String> sliderPicUrls;
@Schema(description = "排序字段", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@ -64,7 +64,6 @@ public class ProductSpuBaseVO {
private List<Integer> deliveryTypes;
@Schema(description = "物流配置模板编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "111")
@NotNull(message = "物流配置模板编号不能为空")
private Long deliveryTemplateId;
// ========== 营销相关字段 =========
@ -82,4 +81,16 @@ public class ProductSpuBaseVO {
@Schema(description = "虚拟销量", example = "66")
private Integer virtualSalesCount;
@Schema(description = "商品销量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1999")
private Integer salesCount;
@Schema(description = "浏览量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1999")
private Integer browseCount;
// ========== SKU 相关字段 =========
@Schema(description = "SKU 数组")
@Valid
private List<ProductSkuSaveReqVO> skus;
}

View File

@ -1,41 +0,0 @@
package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO;
import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import java.util.List;
@Schema(description = "管理后台 - 商品 SPU 更新 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ProductSpuUpdateReqVO extends ProductSpuBaseVO {
@Schema(description = "商品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "商品编号不能为空")
private Long id;
@Schema(description = "商品销量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1999")
private Integer salesCount;
@Schema(description = "浏览量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1999")
private Integer browseCount;
@Schema(description = "商品状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@InEnum(ProductSpuStatusEnum.class)
private Integer status;
// ========== SKU 相关字段 =========
@Schema(description = "SKU 数组")
@Valid
private List<ProductSkuCreateOrUpdateReqVO> skus;
}

View File

@ -3,14 +3,14 @@ package cn.iocoder.yudao.module.product.controller.app.spu;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.member.api.level.MemberLevelApi;
import cn.iocoder.yudao.module.member.api.level.dto.MemberLevelRespDTO;
import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuDetailRespVO;
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO;
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageRespVO;
import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert;
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuRespVO;
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.enums.spu.ProductSpuStatusEnum;
@ -19,16 +19,15 @@ import cn.iocoder.yudao.module.product.service.sku.ProductSkuService;
import cn.iocoder.yudao.module.product.service.spu.ProductSpuService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import java.util.Collections;
import java.util.List;
import java.util.Set;
@ -57,39 +56,18 @@ public class AppProductSpuController {
@Resource
private MemberUserApi memberUserApi;
@GetMapping("/list")
@Operation(summary = "获得商品 SPU 列表")
@Parameters({
@Parameter(name = "recommendType", description = "推荐类型", required = true), // 参见 AppProductSpuPageReqVO.RECOMMEND_TYPE_XXX 常量
@Parameter(name = "count", description = "数量", required = true)
})
public CommonResult<List<AppProductSpuPageRespVO>> getSpuList(
@RequestParam("recommendType") String recommendType,
@RequestParam(value = "count", defaultValue = "10") Integer count) {
List<ProductSpuDO> list = productSpuService.getSpuList(recommendType, count);
if (CollUtil.isEmpty(list)) {
return success(Collections.emptyList());
}
// 拼接返回
List<AppProductSpuPageRespVO> voList = ProductSpuConvert.INSTANCE.convertListForGetSpuList(list);
// 处理 vip 价格
MemberLevelRespDTO memberLevel = getMemberLevel();
voList.forEach(vo -> vo.setVipPrice(calculateVipPrice(vo.getPrice(), memberLevel)));
return success(voList);
}
@GetMapping("/list-by-ids")
@Operation(summary = "获得商品 SPU 列表")
@Parameter(name = "ids", description = "编号列表", required = true)
public CommonResult<List<AppProductSpuPageRespVO>> getSpuList(@RequestParam("ids") Set<Long> ids) {
public CommonResult<List<AppProductSpuRespVO>> getSpuList(@RequestParam("ids") Set<Long> ids) {
List<ProductSpuDO> list = productSpuService.getSpuList(ids);
if (CollUtil.isEmpty(list)) {
return success(Collections.emptyList());
}
// 拼接返回
List<AppProductSpuPageRespVO> voList = ProductSpuConvert.INSTANCE.convertListForGetSpuList(list);
list.forEach(spu -> spu.setSalesCount(spu.getSalesCount() + spu.getVirtualSalesCount()));
List<AppProductSpuRespVO> voList = BeanUtils.toBean(list, AppProductSpuRespVO.class);
// 处理 vip 价格
MemberLevelRespDTO memberLevel = getMemberLevel();
voList.forEach(vo -> vo.setVipPrice(calculateVipPrice(vo.getPrice(), memberLevel)));
@ -98,14 +76,15 @@ public class AppProductSpuController {
@GetMapping("/page")
@Operation(summary = "获得商品 SPU 分页")
public CommonResult<PageResult<AppProductSpuPageRespVO>> getSpuPage(@Valid AppProductSpuPageReqVO pageVO) {
public CommonResult<PageResult<AppProductSpuRespVO>> getSpuPage(@Valid AppProductSpuPageReqVO pageVO) {
PageResult<ProductSpuDO> pageResult = productSpuService.getSpuPage(pageVO);
if (CollUtil.isEmpty(pageResult.getList())) {
return success(PageResult.empty(pageResult.getTotal()));
}
// 拼接返回
PageResult<AppProductSpuPageRespVO> voPageResult = ProductSpuConvert.INSTANCE.convertPageForGetSpuPage(pageResult);
pageResult.getList().forEach(spu -> spu.setSalesCount(spu.getSalesCount() + spu.getVirtualSalesCount()));
PageResult<AppProductSpuRespVO> voPageResult = BeanUtils.toBean(pageResult, AppProductSpuRespVO.class);
// 处理 vip 价格
MemberLevelRespDTO memberLevel = getMemberLevel();
voPageResult.getList().forEach(vo -> vo.setVipPrice(calculateVipPrice(vo.getPrice(), memberLevel)));
@ -124,6 +103,8 @@ public class AppProductSpuController {
if (!ProductSpuStatusEnum.isEnable(spu.getStatus())) {
throw exception(SPU_NOT_ENABLE);
}
// 获得商品 SKU
List<ProductSkuDO> skus = productSkuService.getSkuListBySpuId(spu.getId());
// 增加浏览量
productSpuService.updateBrowseCount(id, 1);
@ -131,12 +112,13 @@ public class AppProductSpuController {
productBrowseHistoryService.createBrowseHistory(getLoginUserId(), id);
// 拼接返回
List<ProductSkuDO> skus = productSkuService.getSkuListBySpuId(spu.getId());
AppProductSpuDetailRespVO detailVO = ProductSpuConvert.INSTANCE.convertForGetSpuDetail(spu, skus);
spu.setBrowseCount(spu.getBrowseCount() + spu.getVirtualSalesCount());
AppProductSpuDetailRespVO spuVO = BeanUtils.toBean(spu, AppProductSpuDetailRespVO.class)
.setSkus(BeanUtils.toBean(skus, AppProductSpuDetailRespVO.Sku.class));
// 处理 vip 价格
MemberLevelRespDTO memberLevel = getMemberLevel();
detailVO.setVipPrice(calculateVipPrice(detailVO.getPrice(), memberLevel));
return success(detailVO);
spuVO.setVipPrice(calculateVipPrice(spuVO.getPrice(), memberLevel));
return success(spuVO);
}
private MemberLevelRespDTO getMemberLevel() {

View File

@ -21,12 +21,6 @@ public class AppProductSpuPageReqVO extends PageParam {
public static final String SORT_FIELD_SALES_COUNT = "salesCount";
public static final String SORT_FIELD_CREATE_TIME = "createTime";
public static final String RECOMMEND_TYPE_HOT = "hot";
public static final String RECOMMEND_TYPE_BENEFIT = "benefit";
public static final String RECOMMEND_TYPE_BEST = "best";
public static final String RECOMMEND_TYPE_NEW = "new";
public static final String RECOMMEND_TYPE_GOOD = "good";
@Schema(description = "商品 SPU 编号数组", example = "1,3,5")
private List<Long> ids;
@ -45,9 +39,6 @@ public class AppProductSpuPageReqVO extends PageParam {
@Schema(description = "排序方式", example = "true")
private Boolean sortAsc;
@Schema(description = "推荐类型", example = "hot") // 参见 AppProductSpuPageReqVO.RECOMMEND_TYPE_XXX 常量
private String recommendType;
@AssertTrue(message = "排序字段不合法")
@JsonIgnore
public boolean isSortFieldValid() {

View File

@ -7,7 +7,7 @@ import java.util.List;
@Schema(description = "用户 App - 商品 SPU Response VO")
@Data
public class AppProductSpuPageRespVO {
public class AppProductSpuRespVO {
@Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long id;

View File

@ -2,10 +2,7 @@ package cn.iocoder.yudao.module.product.convert.sku;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO;
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO;
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuRespVO;
import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
@ -25,24 +22,6 @@ public interface ProductSkuConvert {
ProductSkuConvert INSTANCE = Mappers.getMapper(ProductSkuConvert.class);
ProductSkuDO convert(ProductSkuCreateOrUpdateReqVO bean);
ProductSkuRespVO convert(ProductSkuDO bean);
List<ProductSkuRespVO> convertList(List<ProductSkuDO> list);
List<ProductSkuDO> convertList06(List<ProductSkuCreateOrUpdateReqVO> list);
default List<ProductSkuDO> convertList06(List<ProductSkuCreateOrUpdateReqVO> list, Long spuId) {
List<ProductSkuDO> result = convertList06(list);
result.forEach(item -> item.setSpuId(spuId));
return result;
}
ProductSkuRespDTO convert02(ProductSkuDO bean);
List<ProductSkuRespDTO> convertList04(List<ProductSkuDO> list);
/**
* 获得 SPU 的库存变化 Map
*

View File

@ -1,25 +1,19 @@
package cn.iocoder.yudao.module.product.convert.spu;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*;
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuDetailRespVO;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSkuRespVO;
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.app.spu.vo.AppProductSpuPageReqVO;
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageRespVO;
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.dataobject.spu.ProductSpuDO;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Named;
import org.mapstruct.factory.Mappers;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import static cn.hutool.core.util.ObjectUtil.defaultIfNull;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMultiMap;
/**
@ -32,73 +26,17 @@ public interface ProductSpuConvert {
ProductSpuConvert INSTANCE = Mappers.getMapper(ProductSpuConvert.class);
ProductSpuDO convert(ProductSpuCreateReqVO bean);
ProductSpuDO convert(ProductSpuUpdateReqVO bean);
List<ProductSpuDO> convertList(List<ProductSpuDO> list);
PageResult<ProductSpuRespVO> convertPage(PageResult<ProductSpuDO> page);
ProductSpuPageReqVO convert(AppProductSpuPageReqVO bean);
List<ProductSpuRespDTO> convertList2(List<ProductSpuDO> list);
List<ProductSpuSimpleRespVO> convertList02(List<ProductSpuDO> list);
@Mapping(target = "price", expression = "java(spu.getPrice() / 100)")
@Mapping(target = "marketPrice", expression = "java(spu.getMarketPrice() / 100)")
@Mapping(target = "costPrice", expression = "java(spu.getCostPrice() / 100)")
ProductSpuExcelVO convert(ProductSpuDO spu);
default List<ProductSpuExcelVO> convertList03(List<ProductSpuDO> list) {
List<ProductSpuExcelVO> spuExcelVOs = new ArrayList<>();
list.forEach(spu -> {
ProductSpuExcelVO spuExcelVO = convert(spu);
spuExcelVOs.add(spuExcelVO);
});
return spuExcelVOs;
}
ProductSpuDetailRespVO convert03(ProductSpuDO spu);
ProductSpuRespDTO convert02(ProductSpuDO bean);
// ========== 用户 App 相关 ==========
PageResult<AppProductSpuPageRespVO> convertPageForGetSpuPage(PageResult<ProductSpuDO> page);
default List<AppProductSpuPageRespVO> convertListForGetSpuList(List<ProductSpuDO> list) {
// 处理虚拟销量
list.forEach(spu -> spu.setSalesCount(spu.getSalesCount() + spu.getVirtualSalesCount()));
// 处理 VO 字段
return convertListForGetSpuList0(list);
}
@Named("convertListForGetSpuList0")
List<AppProductSpuPageRespVO> convertListForGetSpuList0(List<ProductSpuDO> list);
default AppProductSpuDetailRespVO convertForGetSpuDetail(ProductSpuDO spu, List<ProductSkuDO> skus) {
// 处理 SPU
AppProductSpuDetailRespVO spuVO = convertForGetSpuDetail(spu)
.setSalesCount(spu.getSalesCount() + defaultIfNull(spu.getVirtualSalesCount(), 0));
// 处理 SKU
spuVO.setSkus(convertListForGetSpuDetail(skus));
default ProductSpuRespVO convert(ProductSpuDO spu, List<ProductSkuDO> skus) {
ProductSpuRespVO spuVO = BeanUtils.toBean(spu, ProductSpuRespVO.class);
spuVO.setSkus(BeanUtils.toBean(skus, ProductSkuRespVO.class));
return spuVO;
}
AppProductSpuDetailRespVO convertForGetSpuDetail(ProductSpuDO spu);
List<AppProductSpuDetailRespVO.Sku> convertListForGetSpuDetail(List<ProductSkuDO> skus);
default ProductSpuDetailRespVO convertForSpuDetailRespVO(ProductSpuDO spu, List<ProductSkuDO> skus) {
return convert03(spu).setSkus(ProductSkuConvert.INSTANCE.convertList(skus));
}
default List<ProductSpuDetailRespVO> convertForSpuDetailRespListVO(List<ProductSpuDO> spus, List<ProductSkuDO> skus) {
default List<ProductSpuRespVO> convertForSpuDetailRespListVO(List<ProductSpuDO> spus, List<ProductSkuDO> skus) {
Map<Long, List<ProductSkuDO>> skuMultiMap = convertMultiMap(skus, ProductSkuDO::getSpuId);
return CollectionUtils.convertList(spus, spu -> convert03(spu)
.setSkus(ProductSkuConvert.INSTANCE.convertList(skuMultiMap.get(spu.getId()))));
return CollectionUtils.convertList(spus, spu -> convert(spu, skuMultiMap.get(spu.getId())));
}
}

View File

@ -54,11 +54,6 @@ public class ProductSpuDO extends BaseDO {
* 商品详情
*/
private String description;
// TODO @芋艿是不是要删除
/**
* 商品条码一维码
*/
private String barCode;
/**
* 商品分类编号

View File

@ -4,7 +4,6 @@ import cn.hutool.core.lang.Assert;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.apache.ibatis.annotations.Mapper;
@ -56,8 +55,4 @@ public interface ProductSkuMapper extends BaseMapperX<ProductSkuDO> {
return update(null, updateWrapper);
}
default List<ProductSkuDO> selectListByAlarmStock() {
return selectList(new QueryWrapper<ProductSkuDO>().apply("stock <= warn_stock"));
}
}

View File

@ -1,12 +1,9 @@
package cn.iocoder.yudao.module.product.dal.mysql.spu;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuExportReqVO;
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuPageReqVO;
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO;
import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
@ -15,7 +12,6 @@ import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
import java.util.Objects;
import java.util.Set;
@ -81,21 +77,6 @@ public interface ProductSpuMapper extends BaseMapperX<ProductSpuDO> {
return selectPage(pageReqVO, query);
}
default List<ProductSpuDO> selectListByRecommendType(String recommendType, Integer count) {
QueryWrapperX<ProductSpuDO> query = new QueryWrapperX<>();
// 上架状态 且有库存
query.eq("status", ProductSpuStatusEnum.ENABLE.getStatus()).gt("stock", 0);
// 推荐类型的过滤条件
if (ObjUtil.equal(recommendType, AppProductSpuPageReqVO.RECOMMEND_TYPE_HOT)) {
query.eq("recommend_hot", true);
} else if (ObjUtil.equal(recommendType, AppProductSpuPageReqVO.RECOMMEND_TYPE_GOOD)) {
query.eq("recommend_good", true);
}
// 设置最大长度
query.limitN(count);
return selectList(query);
}
/**
* 更新商品 SPU 库存
*
@ -110,22 +91,6 @@ public interface ProductSpuMapper extends BaseMapperX<ProductSpuDO> {
update(null, updateWrapper);
}
/**
* 获得 Spu 列表
*
* @param reqVO 查询条件
* @return Spu 列表
*/
default List<ProductSpuDO> selectList(ProductSpuExportReqVO reqVO) {
Integer tabType = reqVO.getTabType();
LambdaQueryWrapperX<ProductSpuDO> queryWrapper = new LambdaQueryWrapperX<>();
queryWrapper.eqIfPresent(ProductSpuDO::getName, reqVO.getName());
queryWrapper.eqIfPresent(ProductSpuDO::getCategoryId, reqVO.getCategoryId());
queryWrapper.betweenIfPresent(ProductSpuDO::getCreateTime, reqVO.getCreateTime());
appendTabQuery(tabType, queryWrapper);
return selectList(queryWrapper);
}
/**
* 添加后台 Tab 选项的查询条件
*

View File

@ -1,7 +1,7 @@
package cn.iocoder.yudao.module.product.service.sku;
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO;
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO;
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSkuSaveReqVO;
import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
import java.util.Collection;
@ -29,13 +29,6 @@ public interface ProductSkuService {
*/
ProductSkuDO getSku(Long id);
/**
* 获得商品 SKU 列表
*
* @return 商品sku列表
*/
List<ProductSkuDO> getSkuList();
/**
* 获得商品 SKU 列表
*
@ -49,7 +42,7 @@ public interface ProductSkuService {
*
* @param list sku组合的集合
*/
void validateSkuList(List<ProductSkuCreateOrUpdateReqVO> list, Boolean specType);
void validateSkuList(List<ProductSkuSaveReqVO> list, Boolean specType);
/**
* 批量创建 SKU
@ -57,7 +50,7 @@ public interface ProductSkuService {
* @param spuId 商品 SPU 编号
* @param list SKU 对象集合
*/
void createSkuList(Long spuId, List<ProductSkuCreateOrUpdateReqVO> list);
void createSkuList(Long spuId, List<ProductSkuSaveReqVO> list);
/**
* 根据 SPU 编号批量更新它的 SKU 信息
@ -65,7 +58,7 @@ public interface ProductSkuService {
* @param spuId SPU 编码
* @param skus SKU 的集合
*/
void updateSkuList(Long spuId, List<ProductSkuCreateOrUpdateReqVO> skus);
void updateSkuList(Long spuId, List<ProductSkuSaveReqVO> skus);
/**
* 更新 SKU 库存增量
@ -99,13 +92,6 @@ public interface ProductSkuService {
*/
void deleteSkuBySpuId(Long spuId);
/**
* 获得库存预警的 SKU 数组
*
* @return SKU 数组
*/
List<ProductSkuDO> getSkuListByAlarmStock();
/**
* 更新 sku 属性
*

View File

@ -3,9 +3,9 @@ package cn.iocoder.yudao.module.product.service.sku;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO;
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuBaseVO;
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO;
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSkuSaveReqVO;
import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert;
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO;
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO;
@ -14,12 +14,12 @@ import cn.iocoder.yudao.module.product.dal.mysql.sku.ProductSkuMapper;
import cn.iocoder.yudao.module.product.service.property.ProductPropertyService;
import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService;
import cn.iocoder.yudao.module.product.service.spu.ProductSpuService;
import jakarta.annotation.Resource;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import jakarta.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;
@ -68,11 +68,6 @@ public class ProductSkuServiceImpl implements ProductSkuService {
return productSkuMapper.selectById(id);
}
@Override
public List<ProductSkuDO> getSkuList() {
return productSkuMapper.selectList();
}
@Override
public List<ProductSkuDO> getSkuList(Collection<Long> ids) {
if (CollUtil.isEmpty(ids)) {
@ -82,20 +77,18 @@ public class ProductSkuServiceImpl implements ProductSkuService {
}
@Override
public void validateSkuList(List<ProductSkuCreateOrUpdateReqVO> skus, Boolean specType) {
public void validateSkuList(List<ProductSkuSaveReqVO> skus, Boolean specType) {
// 0校验skus是否为空
if (CollUtil.isEmpty(skus)) {
throw exception(SKU_NOT_EXISTS);
}
// 单规格赋予单规格默认属性
if (ObjectUtil.equal(specType, false)) {
ProductSkuCreateOrUpdateReqVO skuVO = skus.get(0);
List<ProductSkuBaseVO.Property> properties = new ArrayList<>();
ProductSkuBaseVO.Property property = new ProductSkuBaseVO.Property();
property.setPropertyId(ProductPropertyDO.ID_DEFAULT);
property.setPropertyName(ProductPropertyDO.NAME_DEFAULT);
property.setValueId(ProductPropertyValueDO.ID_DEFAULT);
property.setValueName(ProductPropertyValueDO.NAME_DEFAULT);
ProductSkuSaveReqVO skuVO = skus.get(0);
List<ProductSkuSaveReqVO.Property> properties = new ArrayList<>();
ProductSkuSaveReqVO.Property property = new ProductSkuSaveReqVO.Property()
.setPropertyId(ProductPropertyDO.ID_DEFAULT).setPropertyName(ProductPropertyDO.NAME_DEFAULT)
.setValueId(ProductPropertyValueDO.ID_DEFAULT).setValueName(ProductPropertyValueDO.NAME_DEFAULT);
properties.add(property);
skuVO.setProperties(properties);
return; // 单规格不需要后续的校验
@ -106,7 +99,7 @@ public class ProductSkuServiceImpl implements ProductSkuService {
// 遍历多个 Property 属性
.flatMap(p -> p.getProperties().stream())
// 将每个 Property 转换成对应的 propertyId最后形成集合
.map(ProductSkuCreateOrUpdateReqVO.Property::getPropertyId)
.map(ProductSkuSaveReqVO.Property::getPropertyId)
.collect(Collectors.toSet());
List<ProductPropertyDO> propertyList = productPropertyService.getPropertyList(propertyIds);
if (propertyList.size() != propertyIds.size()) {
@ -133,17 +126,18 @@ public class ProductSkuServiceImpl implements ProductSkuService {
// 4. 最后校验每个 Sku 之间不是重复的
// 每个元素都是一个 Sku attrValueId 集合这样通过最外层的 Set 判断是否有重复的.
Set<Set<Long>> skuAttrValues = new HashSet<>();
for (ProductSkuCreateOrUpdateReqVO sku : skus) {
for (ProductSkuSaveReqVO sku : skus) {
// 添加失败说明重复
if (!skuAttrValues.add(convertSet(sku.getProperties(), ProductSkuCreateOrUpdateReqVO.Property::getValueId))) {
if (!skuAttrValues.add(convertSet(sku.getProperties(), ProductSkuSaveReqVO.Property::getValueId))) {
throw exception(SPU_SKU_NOT_DUPLICATE);
}
}
}
@Override
public void createSkuList(Long spuId, List<ProductSkuCreateOrUpdateReqVO> skuCreateReqList) {
productSkuMapper.insertBatch(ProductSkuConvert.INSTANCE.convertList06(skuCreateReqList, spuId));
public void createSkuList(Long spuId, List<ProductSkuSaveReqVO> skuCreateReqList) {
List<ProductSkuDO> skus = BeanUtils.toBean(skuCreateReqList, ProductSkuDO.class, sku -> sku.setSpuId(spuId));
productSkuMapper.insertBatch(skus);
}
@Override
@ -164,11 +158,6 @@ public class ProductSkuServiceImpl implements ProductSkuService {
productSkuMapper.deleteBySpuId(spuId);
}
@Override
public List<ProductSkuDO> getSkuListByAlarmStock() {
return productSkuMapper.selectListByAlarmStock();
}
@Override
public int updateSkuProperty(Long propertyId, String propertyName) {
// 获取所有的 sku
@ -220,7 +209,7 @@ public class ProductSkuServiceImpl implements ProductSkuService {
@Override
@Transactional(rollbackFor = Exception.class)
public void updateSkuList(Long spuId, List<ProductSkuCreateOrUpdateReqVO> skus) {
public void updateSkuList(Long spuId, List<ProductSkuSaveReqVO> skus) {
// 构建属性与 SKU 的映射关系;
Map<String, Long> existsSkuMap = convertMap(productSkuMapper.selectListBySpuId(spuId),
ProductSkuConvert.INSTANCE::buildPropertyKey, ProductSkuDO::getId);
@ -228,7 +217,7 @@ public class ProductSkuServiceImpl implements ProductSkuService {
// 拆分三个集合新插入的需要更新的需要删除的
List<ProductSkuDO> insertSkus = new ArrayList<>();
List<ProductSkuDO> updateSkus = new ArrayList<>();
List<ProductSkuDO> allUpdateSkus = ProductSkuConvert.INSTANCE.convertList06(skus, spuId);
List<ProductSkuDO> allUpdateSkus = BeanUtils.toBean(skus, ProductSkuDO.class, sku -> sku.setSpuId(spuId));
allUpdateSkus.forEach(sku -> {
String propertiesKey = ProductSkuConvert.INSTANCE.buildPropertyKey(sku);
// 1找得到的进行更新

View File

@ -1,10 +1,11 @@
package cn.iocoder.yudao.module.product.service.spu;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*;
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuPageReqVO;
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuSaveReqVO;
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuUpdateStatusReqVO;
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO;
import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
import jakarta.validation.Valid;
import org.springframework.scheduling.annotation.Async;
@ -12,8 +13,6 @@ import java.util.Collection;
import java.util.List;
import java.util.Map;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
/**
* 商品 SPU Service 接口
*
@ -27,14 +26,14 @@ public interface ProductSpuService {
* @param createReqVO 创建信息
* @return 编号
*/
Long createSpu(@Valid ProductSpuCreateReqVO createReqVO);
Long createSpu(@Valid ProductSpuSaveReqVO createReqVO);
/**
* 更新商品 SPU
*
* @param updateReqVO 更新信息
*/
void updateSpu(@Valid ProductSpuUpdateReqVO updateReqVO);
void updateSpu(@Valid ProductSpuSaveReqVO updateReqVO);
/**
* 删除商品 SPU
@ -59,16 +58,6 @@ public interface ProductSpuService {
*/
List<ProductSpuDO> getSpuList(Collection<Long> ids);
/**
* 获得商品 SPU 映射
*
* @param ids 编号数组
* @return 商品 SPU 映射
*/
default Map<Long, ProductSpuDO> getSpuMap(Collection<Long> ids) {
return convertMap(getSpuList(ids), ProductSpuDO::getId);
}
/**
* 获得指定状态的商品 SPU 列表
*
@ -77,14 +66,6 @@ public interface ProductSpuService {
*/
List<ProductSpuDO> getSpuListByStatus(Integer status);
/**
* 获得所有商品 SPU 列表
*
* @param reqVO 导出条件
* @return 商品 SPU 列表
*/
List<ProductSpuDO> getSpuList(ProductSpuExportReqVO reqVO);
/**
* 获得商品 SPU 分页提供给挂你兰后台使用
*
@ -101,15 +82,6 @@ public interface ProductSpuService {
*/
PageResult<ProductSpuDO> getSpuPage(AppProductSpuPageReqVO pageReqVO);
/**
* 获得商品 SPU 列表提供给用户 App 使用
*
* @param recommendType 推荐类型
* @param count 数量
* @return 商品 SPU 列表
*/
List<ProductSpuDO> getSpuList(String recommendType, Integer count);
/**
* 更新商品 SPU 库存增量
*

View File

@ -5,11 +5,13 @@ import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryListReqVO;
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO;
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*;
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSkuSaveReqVO;
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuPageReqVO;
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuSaveReqVO;
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuUpdateStatusReqVO;
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.category.ProductCategoryDO;
import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
import cn.iocoder.yudao.module.product.dal.mysql.spu.ProductSpuMapper;
@ -53,15 +55,15 @@ public class ProductSpuServiceImpl implements ProductSpuService {
@Override
@Transactional(rollbackFor = Exception.class)
public Long createSpu(ProductSpuCreateReqVO createReqVO) {
public Long createSpu(ProductSpuSaveReqVO createReqVO) {
// 校验分类品牌
validateCategory(createReqVO.getCategoryId());
brandService.validateProductBrand(createReqVO.getBrandId());
// 校验 SKU
List<ProductSkuCreateOrUpdateReqVO> skuSaveReqList = createReqVO.getSkus();
List<ProductSkuSaveReqVO> skuSaveReqList = createReqVO.getSkus();
productSkuService.validateSkuList(skuSaveReqList, createReqVO.getSpecType());
ProductSpuDO spu = ProductSpuConvert.INSTANCE.convert(createReqVO);
ProductSpuDO spu = BeanUtils.toBean(createReqVO, ProductSpuDO.class);
// 初始化 SPU SKU 相关属性
initSpuFromSkus(spu, skuSaveReqList);
// 插入 SPU
@ -74,18 +76,18 @@ public class ProductSpuServiceImpl implements ProductSpuService {
@Override
@Transactional(rollbackFor = Exception.class)
public void updateSpu(ProductSpuUpdateReqVO updateReqVO) {
public void updateSpu(ProductSpuSaveReqVO updateReqVO) {
// 校验 SPU 是否存在
validateSpuExists(updateReqVO.getId());
// 校验分类品牌
validateCategory(updateReqVO.getCategoryId());
brandService.validateProductBrand(updateReqVO.getBrandId());
// 校验SKU
List<ProductSkuCreateOrUpdateReqVO> skuSaveReqList = updateReqVO.getSkus();
List<ProductSkuSaveReqVO> skuSaveReqList = updateReqVO.getSkus();
productSkuService.validateSkuList(skuSaveReqList, updateReqVO.getSpecType());
// 更新 SPU
ProductSpuDO updateObj = ProductSpuConvert.INSTANCE.convert(updateReqVO);
ProductSpuDO updateObj = BeanUtils.toBean(updateReqVO, ProductSpuDO.class);
initSpuFromSkus(updateObj, skuSaveReqList);
productSpuMapper.updateById(updateObj);
// 批量更新 SKU
@ -99,26 +101,20 @@ public class ProductSpuServiceImpl implements ProductSpuService {
* @param spu 商品 SPU
* @param skus 商品 SKU 数组
*/
private void initSpuFromSkus(ProductSpuDO spu, List<ProductSkuCreateOrUpdateReqVO> skus) {
private void initSpuFromSkus(ProductSpuDO spu, List<ProductSkuSaveReqVO> skus) {
// sku 单价最低的商品的价格
spu.setPrice(getMinValue(skus, ProductSkuCreateOrUpdateReqVO::getPrice));
spu.setPrice(getMinValue(skus, ProductSkuSaveReqVO::getPrice));
// sku 单价最低的商品的市场价格
spu.setMarketPrice(getMinValue(skus, ProductSkuCreateOrUpdateReqVO::getMarketPrice));
spu.setMarketPrice(getMinValue(skus, ProductSkuSaveReqVO::getMarketPrice));
// sku 单价最低的商品的成本价格
spu.setCostPrice(getMinValue(skus, ProductSkuCreateOrUpdateReqVO::getCostPrice));
// sku 单价最低的商品的条形码 TODO 芋艿条形码字段是不是可以删除
spu.setBarCode("");
// spu.setBarCode(getMinValue(skus, ProductSkuCreateOrUpdateReqVO::getBarCode));
spu.setCostPrice(getMinValue(skus, ProductSkuSaveReqVO::getCostPrice));
// skus 库存总数
spu.setStock(getSumValue(skus, ProductSkuCreateOrUpdateReqVO::getStock, Integer::sum));
spu.setStock(getSumValue(skus, ProductSkuSaveReqVO::getStock, Integer::sum));
// 若是 spu 已有状态则不处理
if (spu.getStatus() == null) {
// 默认状态为上架
spu.setStatus(ProductSpuStatusEnum.ENABLE.getStatus());
// 默认商品销量
spu.setSalesCount(0);
// 默认商品浏览量
spu.setBrowseCount(0);
spu.setStatus(ProductSpuStatusEnum.ENABLE.getStatus()); // 默认状态为上架
spu.setSalesCount(0); // 默认商品销量
spu.setBrowseCount(0); // 默认商品浏览量
}
}
@ -203,11 +199,6 @@ public class ProductSpuServiceImpl implements ProductSpuService {
return productSpuMapper.selectList(ProductSpuDO::getStatus, status);
}
@Override
public List<ProductSpuDO> getSpuList(ProductSpuExportReqVO reqVO) {
return productSpuMapper.selectList(reqVO);
}
@Override
public PageResult<ProductSpuDO> getSpuPage(ProductSpuPageReqVO pageReqVO) {
return productSpuMapper.selectPage(pageReqVO);
@ -233,11 +224,6 @@ public class ProductSpuServiceImpl implements ProductSpuService {
return productSpuMapper.selectPage(pageReqVO, categoryIds);
}
@Override
public List<ProductSpuDO> getSpuList(String recommendType, Integer count) {
return productSpuMapper.selectListByRecommendType(recommendType, count);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void updateSpuStock(Map<Long, Integer> stockIncrCounts) {

View File

@ -4,7 +4,7 @@ import cn.hutool.core.util.RandomUtil;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.framework.test.core.util.AssertUtils;
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO;
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO;
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSkuSaveReqVO;
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.service.property.ProductPropertyService;
@ -74,13 +74,13 @@ public class ProductSkuServiceTest extends BaseDbUnitTest {
// 准备参数
Long spuId = 1L;
String spuName = "测试商品";
List<ProductSkuCreateOrUpdateReqVO> skus = Arrays.asList(
randomPojo(ProductSkuCreateOrUpdateReqVO.class, o -> { // 测试更新
o.setProperties(singletonList(new ProductSkuCreateOrUpdateReqVO.Property(
List<ProductSkuSaveReqVO> skus = Arrays.asList(
randomPojo(ProductSkuSaveReqVO.class, o -> { // 测试更新
o.setProperties(singletonList(new ProductSkuSaveReqVO.Property(
10L, "颜色", 20L, "红色")));
}),
randomPojo(ProductSkuCreateOrUpdateReqVO.class, o -> { // 测试新增
o.setProperties(singletonList(new ProductSkuCreateOrUpdateReqVO.Property(
randomPojo(ProductSkuSaveReqVO.class, o -> { // 测试新增
o.setProperties(singletonList(new ProductSkuSaveReqVO.Property(
10L, "颜色", 20L, "红色")));
})
);

View File

@ -6,12 +6,9 @@ import cn.hutool.core.util.RandomUtil;
import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
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.ProductSkuSaveReqVO;
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.convert.spu.ProductSpuConvert;
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuSaveReqVO;
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;
@ -21,13 +18,13 @@ import cn.iocoder.yudao.module.product.service.property.ProductPropertyService;
import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService;
import cn.iocoder.yudao.module.product.service.sku.ProductSkuServiceImpl;
import com.google.common.collect.Lists;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.Import;
import jakarta.annotation.Resource;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Date;
@ -87,20 +84,19 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
@Test
public void testCreateSpu_success() {
// 准备参数
ProductSkuCreateOrUpdateReqVO skuCreateOrUpdateReqVO = randomPojo(ProductSkuCreateOrUpdateReqVO.class,o->{
ProductSkuSaveReqVO skuCreateOrUpdateReqVO = randomPojo(ProductSkuSaveReqVO.class, o->{
// 限制范围为正整数
o.setCostPrice(generaInt());
o.setPrice(generaInt());
o.setMarketPrice(generaInt());
o.setStock(generaInt());
o.setWarnStock(10);
o.setFirstBrokeragePrice(generaInt());
o.setSecondBrokeragePrice(generaInt());
// 限制分数为两位数
o.setWeight(RandomUtil.randomDouble(10,2, RoundingMode.HALF_UP));
o.setVolume(RandomUtil.randomDouble(10,2, RoundingMode.HALF_UP));
});
ProductSpuCreateReqVO createReqVO = randomPojo(ProductSpuCreateReqVO.class,o->{
ProductSpuSaveReqVO createReqVO = randomPojo(ProductSpuSaveReqVO.class,o->{
o.setCategoryId(generateId());
o.setBrandId(generateId());
o.setSort(RandomUtil.randomInt(1,100)); // 限制排序范围
@ -134,13 +130,12 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
});
productSpuMapper.insert(createReqVO);
// 准备参数
ProductSkuCreateOrUpdateReqVO skuCreateOrUpdateReqVO = randomPojo(ProductSkuCreateOrUpdateReqVO.class,o->{
ProductSkuSaveReqVO skuCreateOrUpdateReqVO = randomPojo(ProductSkuSaveReqVO.class, o->{
// 限制范围为正整数
o.setCostPrice(generaInt());
o.setPrice(generaInt());
o.setMarketPrice(generaInt());
o.setStock(generaInt());
o.setWarnStock(10);
o.setFirstBrokeragePrice(generaInt());
o.setSecondBrokeragePrice(generaInt());
// 限制分数为两位数
@ -148,7 +143,7 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
o.setVolume(RandomUtil.randomDouble(10,2, RoundingMode.HALF_UP));
});
// 准备参数
ProductSpuUpdateReqVO reqVO = randomPojo(ProductSpuUpdateReqVO.class, o -> {
ProductSpuSaveReqVO reqVO = randomPojo(ProductSpuSaveReqVO.class, o -> {
o.setId(createReqVO.getId()); // 设置更新的 ID
o.setCategoryId(generateId());
o.setBrandId(generateId());
@ -158,7 +153,6 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
o.setGiveIntegral(generaInt()); // 限制范围为正整数
o.setSalesCount(generaInt()); // 限制范围为正整数
o.setBrowseCount(generaInt()); // 限制范围为正整数
o.setStatus(0);
o.setSkus(newArrayList(skuCreateOrUpdateReqVO,skuCreateOrUpdateReqVO,skuCreateOrUpdateReqVO));
});
when(categoryService.getCategoryLevel(eq(reqVO.getCategoryId()))).thenReturn(2);
@ -171,7 +165,7 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
@Test
public void testValidateSpuExists_exception() {
ProductSpuUpdateReqVO reqVO = randomPojo(ProductSpuUpdateReqVO.class);
ProductSpuSaveReqVO reqVO = randomPojo(ProductSpuSaveReqVO.class);
// 调用
Assertions.assertThrows(ServiceException.class, () -> productSpuService.updateSpu(reqVO));
}
@ -394,8 +388,7 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
PageResult<ProductSpuDO> spuPage = productSpuService.getSpuPage(productSpuPageReqVO);
PageResult<ProductSpuRespVO> result = ProductSpuConvert.INSTANCE.convertPage(productSpuMapper.selectPage(productSpuPageReqVO));
assertEquals(result.getTotal(), spuPage.getTotal());
assertEquals(1, spuPage.getTotal());
}
/**