REVIEW 商品管理的逻辑

This commit is contained in:
YunaiV 2023-05-05 23:01:23 +08:00
parent 7345d80b53
commit cd86620b74
23 changed files with 62 additions and 82 deletions

View File

@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.product.enums.spu;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
// TODO @puhui999中英文之间要有空格 商品 spu Tab 标签枚举这个类可以改成 ProductSpuPageTabEnum 会更好一点哈分页 Tab 的意思
/** /**
* 商品spu标签枚举类型 * 商品spu标签枚举类型
* *
@ -11,11 +12,13 @@ import lombok.Getter;
@Getter @Getter
@AllArgsConstructor @AllArgsConstructor
public enum ProductSpuTabTypeEnum { public enum ProductSpuTabTypeEnum {
FOR_SALE(0,"出售中商品"), FOR_SALE(0,"出售中商品"),
IN_WAREHOUSE(1,"仓库中商品"), IN_WAREHOUSE(1,"仓库中商品"),
SOLD_OUT(2,"已售空商品"), SOLD_OUT(2,"已售空商品"),
ALERT_STOCK(3,"警戒库存"), ALERT_STOCK(3,"警戒库存"),
RECYCLE_BIN(4,"商品回收站"); RECYCLE_BIN(4,"商品回收站");
/** /**
* 状态 * 状态
*/ */
@ -24,4 +27,5 @@ public enum ProductSpuTabTypeEnum {
* 状态名 * 状态名
*/ */
private final String name; private final String name;
} }

View File

@ -6,6 +6,7 @@ import lombok.Getter;
import java.util.Arrays; import java.util.Arrays;
// TODO @puhui999是不是放到数据字典里
/** /**
* 产品单位枚举 * 产品单位枚举
* *
@ -14,6 +15,7 @@ import java.util.Arrays;
@Getter @Getter
@AllArgsConstructor @AllArgsConstructor
public enum ProductUnitEnum implements IntArrayValuable { public enum ProductUnitEnum implements IntArrayValuable {
PIECE(1, ""), PIECE(1, ""),
DOZEN(2, ""), DOZEN(2, ""),
BOX(3, ""), BOX(3, ""),

View File

@ -35,6 +35,7 @@
<groupId>cn.iocoder.boot</groupId> <groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-biz-operatelog</artifactId> <artifactId>yudao-spring-boot-starter-biz-operatelog</artifactId>
</dependency> </dependency>
<!-- TODO 芋艿:是不是可以去掉这个依赖呀? -->
<dependency> <dependency>
<groupId>cn.iocoder.boot</groupId> <groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-biz-tenant</artifactId> <artifactId>yudao-spring-boot-starter-biz-tenant</artifactId>

View File

@ -12,7 +12,6 @@ import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueServ
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import oracle.jdbc.proxy.annotation.Post;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
@ -85,7 +84,8 @@ public class ProductPropertyController {
@PostMapping("/get-value-list") @PostMapping("/get-value-list")
@Operation(summary = "获得属性项列表") @Operation(summary = "获得属性项列表")
@PreAuthorize("@ss.hasPermission('product:property:query')") @PreAuthorize("@ss.hasPermission('product:property:query')")
public CommonResult<List<ProductPropertyAndValueRespVO>> getPropertyAndValueList(@Valid @RequestBody ProductPropertyListReqVO listReqVO) { public CommonResult<List<ProductPropertyAndValueRespVO>> getPropertyAndValueList(
@Valid @RequestBody ProductPropertyListReqVO listReqVO) {
// 查询属性项 // 查询属性项
List<ProductPropertyDO> keys = productPropertyService.getPropertyList(listReqVO); List<ProductPropertyDO> keys = productPropertyService.getPropertyList(listReqVO);
if (CollUtil.isEmpty(keys)) { if (CollUtil.isEmpty(keys)) {

View File

@ -4,7 +4,6 @@ import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
import lombok.ToString; import lombok.ToString;
import javax.validation.constraints.NotEmpty;
import java.util.List; import java.util.List;
@Schema(description = "管理后台 - 属性项 List Request VO") @Schema(description = "管理后台 - 属性项 List Request VO")
@ -15,6 +14,8 @@ public class ProductPropertyListReqVO {
@Schema(description = "属性名称", example = "颜色") @Schema(description = "属性名称", example = "颜色")
private String name; private String name;
@Schema(description = "属性ids", example = "1,2") // TODO @puhui999这个查询条件的作用是啥呀
@Schema(description = "属性编号的数组", example = "1,2")
private List<Long> propertyIds; private List<Long> propertyIds;
} }

View File

@ -1,11 +1,7 @@
package cn.iocoder.yudao.module.product.controller.admin.sku.vo; package cn.iocoder.yudao.module.product.controller.admin.sku.vo;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
@ -50,6 +46,7 @@ public class ProductSkuBaseVO {
@Schema(description = "商品体积", example = "1024") // 单位m^3 平米 @Schema(description = "商品体积", example = "1024") // 单位m^3 平米
private Double volume; private Double volume;
// TODO @pitui999注释可以去掉VO 使用 @Schema 作为注释
/** /**
* 一级分销的佣金单位 * 一级分销的佣金单位
*/ */

View File

@ -11,6 +11,7 @@ import java.util.List;
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true) @ToString(callSuper = true)
public class ProductSkuCreateOrUpdateReqVO extends ProductSkuBaseVO { public class ProductSkuCreateOrUpdateReqVO extends ProductSkuBaseVO {
@Schema(description = "商品属性") @Schema(description = "商品属性")
@Data @Data
@AllArgsConstructor @AllArgsConstructor

View File

@ -4,12 +4,8 @@ import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*; import lombok.*;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import java.time.LocalDateTime;
import java.util.List; import java.util.List;
/**
* @author HUIHUI
*/
@Schema(description = "管理后台 - 商品 SKU Response VO") @Schema(description = "管理后台 - 商品 SKU Response VO")
@Data @Data
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@ -29,13 +25,17 @@ public class ProductSkuRespVO extends ProductSkuBaseVO {
@NotNull(message = "属性编号不能为空") @NotNull(message = "属性编号不能为空")
private Long propertyId; private Long propertyId;
// TODO @puhui999:propertyName 是不是也返回下
@Schema(description = "属性值编号", required = true, example = "1024") @Schema(description = "属性值编号", required = true, example = "1024")
@NotNull(message = "属性值编号不能为空") @NotNull(message = "属性值编号不能为空")
private Long valueId; private Long valueId;
@Schema(description = "属性值", example = "1024") @Schema(description = "属性值", example = "1024")
private String valueName; private String valueName;
} }
/** /**
* 属性数组 * 属性数组
*/ */

View File

@ -3,12 +3,9 @@ package cn.iocoder.yudao.module.product.controller.admin.spu;
import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult; 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.*;
import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert;
import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert; 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.dataobject.spu.ProductSpuDO;
import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService; import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService;
import cn.iocoder.yudao.module.product.service.property.bo.ProductPropertyValueDetailRespBO;
import cn.iocoder.yudao.module.product.service.sku.ProductSkuService; import cn.iocoder.yudao.module.product.service.sku.ProductSkuService;
import cn.iocoder.yudao.module.product.service.spu.ProductSpuService; import cn.iocoder.yudao.module.product.service.spu.ProductSpuService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
@ -23,9 +20,7 @@ import javax.validation.Valid;
import java.util.List; import java.util.List;
import java.util.Map; 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.CommonResult.success;
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS;
@Tag(name = "管理后台 - 商品 SPU") @Tag(name = "管理后台 - 商品 SPU")
@RestController @RestController
@ -94,6 +89,8 @@ public class ProductSpuController {
public CommonResult<PageResult<ProductSpuPageRespVO>> getSpuPage(@Valid ProductSpuPageReqVO pageVO) { public CommonResult<PageResult<ProductSpuPageRespVO>> getSpuPage(@Valid ProductSpuPageReqVO pageVO) {
return success(ProductSpuConvert.INSTANCE.convertPage(productSpuService.getSpuPage(pageVO))); return success(ProductSpuConvert.INSTANCE.convertPage(productSpuService.getSpuPage(pageVO)));
} }
// TODO @tuihui999get-count另外url 使用 - 拆分
@GetMapping("/tabsCount") @GetMapping("/tabsCount")
@Operation(summary = "获得商品 SPU tabsCount") @Operation(summary = "获得商品 SPU tabsCount")
@PreAuthorize("@ss.hasPermission('product:spu:query')") @PreAuthorize("@ss.hasPermission('product:spu:query')")

View File

@ -1,13 +1,5 @@
package cn.iocoder.yudao.module.product.controller.admin.spu.vo; package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import cn.iocoder.yudao.module.product.dal.dataobject.brand.ProductBrandDO;
import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO;
import cn.iocoder.yudao.module.product.dal.dataobject.delivery.DeliveryTemplateDO;
import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
@ -116,5 +108,4 @@ public class ProductSpuBaseVO {
@Schema(description = "虚拟销量", required = true, example = "芋道") @Schema(description = "虚拟销量", required = true, example = "芋道")
private Integer virtualSalesCount; private Integer virtualSalesCount;
} }

View File

@ -1,14 +1,11 @@
package cn.iocoder.yudao.module.product.controller.admin.spu.vo; package cn.iocoder.yudao.module.product.controller.admin.spu.vo;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueDetailRespVO;
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuBaseVO;
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuRespVO; import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuRespVO;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.ToString; import lombok.ToString;
import javax.validation.constraints.NotNull;
import java.util.List; import java.util.List;
@Schema(description = "管理后台 - 商品 SPU 详细 Response VO") // 包括关联的 SKU 等信息 @Schema(description = "管理后台 - 商品 SPU 详细 Response VO") // 包括关联的 SKU 等信息
@ -19,6 +16,7 @@ public class ProductSpuDetailRespVO extends ProductSpuBaseVO {
@Schema(description = "商品编号", example = "1") @Schema(description = "商品编号", example = "1")
private Long id; private Long id;
// ========== SKU 相关字段 ========= // ========== SKU 相关字段 =========
@Schema(description = "SKU 数组", example = "1") @Schema(description = "SKU 数组", example = "1")

View File

@ -20,6 +20,7 @@ public class ProductSpuPageReqVO extends PageParam {
@Schema(description = "商品名称", example = "yutou") @Schema(description = "商品名称", example = "yutou")
private String name; private String name;
// TODO @puhui999加下 @InEnum 校验
@Schema(description = "前端请求的tab类型", example = "1") @Schema(description = "前端请求的tab类型", example = "1")
private Integer tabType; private Integer tabType;

View File

@ -1,15 +1,15 @@
package cn.iocoder.yudao.module.product.controller.admin.spu.vo; 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 io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
import java.time.LocalDateTime; import java.time.LocalDateTime;
// TODO @puhui999可以直接继承 ProductSpuRespVO 一般情况下多返回一些字段问题不大的另外是不是使用 ProductSpuRespVO 替代
@Schema(description = "管理后台 - 商品 SPU 分页 response VO") @Schema(description = "管理后台 - 商品 SPU 分页 response VO")
@Data @Data
public class ProductSpuPageRespVO { public class ProductSpuPageRespVO {
@Schema(description = "spuId", example = "1") @Schema(description = "spuId", example = "1")
private Long id; private Long id;
@Schema(description = "商品封面图", example = "1") @Schema(description = "商品封面图", example = "1")
@ -28,4 +28,5 @@ public class ProductSpuPageRespVO {
private LocalDateTime createTime; private LocalDateTime createTime;
@Schema(description = "商品状态", example = "1") @Schema(description = "商品状态", example = "1")
private Integer status; private Integer status;
} }

View File

@ -47,7 +47,7 @@ public interface ProductSpuConvert {
List<ProductSpuSimpleRespVO> convertList02(List<ProductSpuDO> list); List<ProductSpuSimpleRespVO> convertList02(List<ProductSpuDO> list);
// TODO @puhui999是不是可以删除啦
default ProductSpuDetailRespVO convert03(ProductSpuDO spu, List<ProductSkuDO> skus, default ProductSpuDetailRespVO convert03(ProductSpuDO spu, List<ProductSkuDO> skus,
List<ProductPropertyValueDetailRespBO> propertyValues) { List<ProductPropertyValueDetailRespBO> propertyValues) {
ProductSpuDetailRespVO spuVO = convert03(spu); ProductSpuDetailRespVO spuVO = convert03(spu);

View File

@ -1,6 +1,5 @@
package cn.iocoder.yudao.module.product.dal.dataobject.property; package cn.iocoder.yudao.module.product.dal.dataobject.property;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO; import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
@ -20,7 +19,7 @@ import lombok.*;
@Builder @Builder
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
public class ProductPropertyDO extends TenantBaseDO { public class ProductPropertyDO extends TenantBaseDO { // TODO @puhui999这里是不是用 BaseDO 就可以了
/** /**
* 主键 * 主键

View File

@ -1,6 +1,5 @@
package cn.iocoder.yudao.module.product.dal.dataobject.property; package cn.iocoder.yudao.module.product.dal.dataobject.property;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO; import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
@ -21,7 +20,7 @@ import lombok.*;
@Builder @Builder
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
public class ProductPropertyValueDO extends TenantBaseDO { public class ProductPropertyValueDO extends TenantBaseDO { // TODO @puhui999这里是不是用 BaseDO 就可以了
/** /**
* 主键 * 主键

View File

@ -1,7 +1,6 @@
package cn.iocoder.yudao.module.product.dal.dataobject.sku; package cn.iocoder.yudao.module.product.dal.dataobject.sku;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO; import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO; import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO;
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO; import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO;
@ -28,7 +27,7 @@ import java.util.List;
@Builder @Builder
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
public class ProductSkuDO extends TenantBaseDO { public class ProductSkuDO extends TenantBaseDO { // TODO @puhui999这里是不是用 BaseDO 就可以了
/** /**
* 商品 SKU 编号自增 * 商品 SKU 编号自增
@ -116,7 +115,7 @@ public class ProductSkuDO extends TenantBaseDO {
// * 冗余 {@link ProductPropertyDO#getName()} // * 冗余 {@link ProductPropertyDO#getName()}
// * // *
// * 注意每次属性名字发生变化时需要更新该冗余 // * 注意每次属性名字发生变化时需要更新该冗余
// */ TODO 与已有代码逻辑存在冲突 // */ TODO @puhui999与已有代码逻辑存在冲突芋艿冲突点是啥呀
//private String propertyName; //private String propertyName;
/** /**
@ -131,7 +130,7 @@ public class ProductSkuDO extends TenantBaseDO {
// * 冗余 {@link ProductPropertyValueDO#getName()} // * 冗余 {@link ProductPropertyValueDO#getName()}
// * // *
// * 注意每次属性值名字发生变化时需要更新该冗余 // * 注意每次属性值名字发生变化时需要更新该冗余
// */ TODO 与已有代码逻辑存在冲突 // */ TODO @puhui999与已有代码逻辑存在冲突芋艿冲突点是啥呀
//private String valueName; //private String valueName;
} }

View File

@ -1,11 +1,9 @@
package cn.iocoder.yudao.module.product.dal.mysql.spu; package cn.iocoder.yudao.module.product.dal.mysql.spu;
import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; 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.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils;
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuPageReqVO; 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.controller.app.spu.vo.AppProductSpuPageReqVO;
import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
@ -14,24 +12,14 @@ import cn.iocoder.yudao.module.product.enums.spu.ProductSpuTabTypeEnum;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.Set; import java.util.Set;
/**
* 商品spu Mapper
*
* @author 芋道源码
*/
@Mapper @Mapper
public interface ProductSpuMapper extends BaseMapperX<ProductSpuDO> { public interface ProductSpuMapper extends BaseMapperX<ProductSpuDO> {
//default PageResult<ProductSpuDO> selectPage(ProductSpuPageReqVO reqVO) {
// return selectPage(reqVO, new LambdaQueryWrapperX<ProductSpuDO>()
// .likeIfPresent(ProductSpuDO::getName, reqVO.getName())
// .orderByDesc(ProductSpuDO::getSort));
//}
default PageResult<ProductSpuDO> selectPage(ProductSpuPageReqVO reqVO) { default PageResult<ProductSpuDO> selectPage(ProductSpuPageReqVO reqVO) {
// TODO @puhui999多个 tab if else 去补条件可阅读性会好点哈
return selectPage(reqVO, new LambdaQueryWrapperX<ProductSpuDO>() return selectPage(reqVO, new LambdaQueryWrapperX<ProductSpuDO>()
// 商品名称 // 商品名称
.likeIfPresent(ProductSpuDO::getName, reqVO.getName()) .likeIfPresent(ProductSpuDO::getName, reqVO.getName())
@ -42,7 +30,7 @@ public interface ProductSpuMapper extends BaseMapperX<ProductSpuDO> {
.eq(ProductSpuTabTypeEnum.IN_WAREHOUSE.getType().equals(reqVO.getTabType()),ProductSpuDO::getStatus,ProductSpuStatusEnum.DISABLE.getStatus()) .eq(ProductSpuTabTypeEnum.IN_WAREHOUSE.getType().equals(reqVO.getTabType()),ProductSpuDO::getStatus,ProductSpuStatusEnum.DISABLE.getStatus())
// 已售空商品 // 已售空商品
.eq(ProductSpuTabTypeEnum.SOLD_OUT.getType().equals(reqVO.getTabType()),ProductSpuDO::getStock,0) .eq(ProductSpuTabTypeEnum.SOLD_OUT.getType().equals(reqVO.getTabType()),ProductSpuDO::getStock,0)
// TODO 警戒库存暂时为 10后期需要使用常量或者数据库配置替换 // TODO @phuui999警戒库存暂时为 10后期需要使用常量或者数据库配置替换
.le(ProductSpuTabTypeEnum.ALERT_STOCK.getType().equals(reqVO.getTabType()),ProductSpuDO::getStock,10) .le(ProductSpuTabTypeEnum.ALERT_STOCK.getType().equals(reqVO.getTabType()),ProductSpuDO::getStock,10)
// 回收站 // 回收站
.eq(ProductSpuTabTypeEnum.RECYCLE_BIN.getType().equals(reqVO.getTabType()),ProductSpuDO::getStatus,ProductSpuStatusEnum.RECYCLE.getStatus()) .eq(ProductSpuTabTypeEnum.RECYCLE_BIN.getType().equals(reqVO.getTabType()),ProductSpuDO::getStatus,ProductSpuStatusEnum.RECYCLE.getStatus())

View File

@ -40,6 +40,7 @@ public interface ProductPropertyService {
/** /**
* 获得属性项列表 * 获得属性项列表
*
* @param listReqVO 集合查询 * @param listReqVO 集合查询
* @return 属性项集合 * @return 属性项集合
*/ */

View File

@ -87,7 +87,9 @@ public interface ProductSkuService {
/** /**
* 基于 SPU 编号和状态获得商品 SKU 集合 * 基于 SPU 编号和状态获得商品 SKU 集合
* TODO SKU中已经不存在status属性 *
* TODO @puhui999SKU中已经不存在status属性芋艿那就去掉 status
*
* @param spuId SPU 编号 * @param spuId SPU 编号
* @param status 状态 * @param status 状态
* @return 商品 SKU 集合 * @return 商品 SKU 集合

View File

@ -1,12 +1,9 @@
package cn.iocoder.yudao.module.product.service.spu; package cn.iocoder.yudao.module.product.service.spu;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; 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.sku.vo.ProductSkuCreateOrUpdateReqVO; 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.controller.admin.sku.vo.ProductSkuRespVO;
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*; import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*;
@ -23,7 +20,6 @@ import cn.iocoder.yudao.module.product.service.category.ProductCategoryService;
import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService; import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService;
import cn.iocoder.yudao.module.product.service.property.bo.ProductPropertyValueDetailRespBO; import cn.iocoder.yudao.module.product.service.property.bo.ProductPropertyValueDetailRespBO;
import cn.iocoder.yudao.module.product.service.sku.ProductSkuService; import cn.iocoder.yudao.module.product.service.sku.ProductSkuService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@ -34,7 +30,7 @@ import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.getSumValue;
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS; import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS;
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_SAVE_FAIL_CATEGORY_LEVEL_ERROR; import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_SAVE_FAIL_CATEGORY_LEVEL_ERROR;
@ -63,9 +59,9 @@ public class ProductSpuServiceImpl implements ProductSpuService {
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public Long createSpu(ProductSpuCreateReqVO createReqVO) { public Long createSpu(ProductSpuCreateReqVO createReqVO) {
// 校验分类 TODO 暂不清楚为什么只能选择第三层的结点 // 校验分类 TODO puhui999暂不清楚为什么只能选择第三层的结点芋艿改成二级分类因为商品只能放在叶子节点级别
//validateCategory(createReqVO.getCategoryId()); //validateCategory(createReqVO.getCategoryId());
// 校验品牌 TODO 暂不校验前端没有做品牌选择 // 校验品牌 TODO puhui999暂不校验前端没有做品牌选择芋艿可以加下哈
//brandService.validateProductBrand(createReqVO.getBrandId()); //brandService.validateProductBrand(createReqVO.getBrandId());
List<ProductSkuCreateOrUpdateReqVO> skuSaveReqList = createReqVO.getSkus(); List<ProductSkuCreateOrUpdateReqVO> skuSaveReqList = createReqVO.getSkus();
@ -74,6 +70,7 @@ public class ProductSpuServiceImpl implements ProductSpuService {
ProductSpuDO spu = ProductSpuConvert.INSTANCE.convert(createReqVO); ProductSpuDO spu = ProductSpuConvert.INSTANCE.convert(createReqVO);
// 初始化 SPU SKU 相关属性 // 初始化 SPU SKU 相关属性
initSpuFromSkus(spu, skuSaveReqList); initSpuFromSkus(spu, skuSaveReqList);
// 插入 SPU // 插入 SPU
productSpuMapper.insert(spu); productSpuMapper.insert(spu);
// 插入 SKU // 插入 SKU
@ -193,6 +190,7 @@ public class ProductSpuServiceImpl implements ProductSpuService {
stockIncrCounts.forEach((id, incCount) -> productSpuMapper.updateStock(id, incCount)); stockIncrCounts.forEach((id, incCount) -> productSpuMapper.updateStock(id, incCount));
} }
// TODO @puhui999Service 尽量不做一些跟 VO 相关的拼接逻辑目的是让 Service 更加简洁一点哈
@Override @Override
public ProductSpuDetailRespVO getSpuDetail(Long id) { public ProductSpuDetailRespVO getSpuDetail(Long id) {
// 获得商品 SPU // 获得商品 SPU
@ -204,12 +202,17 @@ public class ProductSpuServiceImpl implements ProductSpuService {
// 查询商品 SKU // 查询商品 SKU
List<ProductSkuDO> skus = productSkuService.getSkuListBySpuId(spu.getId()); List<ProductSkuDO> skus = productSkuService.getSkuListBySpuId(spu.getId());
if (CollUtil.isNotEmpty(skus)){ if (CollUtil.isNotEmpty(skus)){
// TODO @puhui999skuVOs 更简洁一点然后大小写要注释哈RespVOs因为 VO 是缩写s 是复数
List<ProductSkuRespVO> skuRespVoS = ProductSkuConvert.INSTANCE.convertList(skus); List<ProductSkuRespVO> skuRespVoS = ProductSkuConvert.INSTANCE.convertList(skus);
// 非多规格不需要处理 // 非多规格不需要处理
// TODO @puhui999统一模型即使是单规格也查询下问题不大的
if (ObjectUtil.equal(productSpuDetailRespVO.getSpecType(), true)) { if (ObjectUtil.equal(productSpuDetailRespVO.getSpecType(), true)) {
// 获取所有的属性值 id // 获取所有的属性值 id
Set<Long> valueIds = skus.stream().flatMap(p -> p.getProperties().stream()).map(ProductSkuDO.Property::getValueId).collect(Collectors.toSet()); Set<Long> valueIds = skus.stream().flatMap(p -> p.getProperties().stream())
.map(ProductSkuDO.Property::getValueId)
.collect(Collectors.toSet());
List<ProductPropertyValueDetailRespBO> valueDetailList = productPropertyValueService.getPropertyValueDetailList(valueIds); List<ProductPropertyValueDetailRespBO> valueDetailList = productPropertyValueService.getPropertyValueDetailList(valueIds);
// TODO @puhui999拼接的逻辑最好查询好后丢到 convert 里面统一处理这样 Service or Controller 也可以更简洁原则上Controller 去组合Service 写逻辑Convert 转换
Map<Long, String> stringMap = valueDetailList.stream().collect(Collectors.toMap(ProductPropertyValueDetailRespBO::getValueId, ProductPropertyValueDetailRespBO::getValueName)); Map<Long, String> stringMap = valueDetailList.stream().collect(Collectors.toMap(ProductPropertyValueDetailRespBO::getValueId, ProductPropertyValueDetailRespBO::getValueName));
// 设置属性值名称 // 设置属性值名称
skuRespVoS.stream().flatMap(p -> p.getProperties().stream()).forEach(item ->item.setValueName(stringMap.get(item.getValueId()))); skuRespVoS.stream().flatMap(p -> p.getProperties().stream()).forEach(item ->item.setValueName(stringMap.get(item.getValueId())));
@ -232,6 +235,7 @@ public class ProductSpuServiceImpl implements ProductSpuService {
@Override @Override
public Map<Integer, Long> getTabsCount() { public Map<Integer, Long> getTabsCount() {
// TODO @puhui999map =counts尽量避免出现 map 这种命名无命名含义哈
Map<Integer, Long> map = new HashMap<>(); Map<Integer, Long> map = new HashMap<>();
// 查询销售中的商品数量 // 查询销售中的商品数量
map.put(ProductSpuTabTypeEnum.FOR_SALE.getType(), productSpuMapper.selectCount(ProductSpuDO::getStatus, ProductSpuStatusEnum.ENABLE.getStatus())); map.put(ProductSpuTabTypeEnum.FOR_SALE.getType(), productSpuMapper.selectCount(ProductSpuDO::getStatus, ProductSpuStatusEnum.ENABLE.getStatus()));
@ -240,6 +244,8 @@ public class ProductSpuServiceImpl implements ProductSpuService {
// 查询售空的商品数量 // 查询售空的商品数量
map.put(ProductSpuTabTypeEnum.SOLD_OUT.getType(),productSpuMapper.selectCount(ProductSpuDO::getStock, 0)); map.put(ProductSpuTabTypeEnum.SOLD_OUT.getType(),productSpuMapper.selectCount(ProductSpuDO::getStock, 0));
// 查询触发警戒库存的商品数量 TODO 警戒库存暂时为 10后期需要使用常量或者数据库配置替换 // 查询触发警戒库存的商品数量 TODO 警戒库存暂时为 10后期需要使用常量或者数据库配置替换
// TODO @puhui999要有空格, productSpuMapper
// TODO @puhui999Service 不要有 Mapper 的逻辑想想咋抽象一下哈
map.put(ProductSpuTabTypeEnum.ALERT_STOCK.getType(),productSpuMapper.selectCount(new LambdaQueryWrapperX<ProductSpuDO>().le(ProductSpuDO::getStock, 10))); map.put(ProductSpuTabTypeEnum.ALERT_STOCK.getType(),productSpuMapper.selectCount(new LambdaQueryWrapperX<ProductSpuDO>().le(ProductSpuDO::getStock, 10)));
// 查询回收站中的商品数量 // 查询回收站中的商品数量
map.put(ProductSpuTabTypeEnum.RECYCLE_BIN.getType(),productSpuMapper.selectCount(ProductSpuDO::getStatus, ProductSpuStatusEnum.RECYCLE.getStatus())); map.put(ProductSpuTabTypeEnum.RECYCLE_BIN.getType(),productSpuMapper.selectCount(ProductSpuDO::getStatus, ProductSpuStatusEnum.RECYCLE.getStatus()));

View File

@ -5,11 +5,11 @@ import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.RandomUtil; import cn.hutool.core.util.RandomUtil;
import cn.iocoder.yudao.framework.common.exception.ServiceException; import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
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.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.*; import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuPageReqVO;
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuPageRespVO;
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuUpdateReqVO;
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO; 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.convert.spu.ProductSpuConvert;
import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
@ -34,7 +34,6 @@ import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; 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.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.AssertUtils.assertPojoEquals;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
@ -79,13 +78,10 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
@Test @Test
public void testCreateSpu_success() { public void testCreateSpu_success() {
// 准备参数 // 准备参数
ProductSpuCreateReqVO createReqVO = randomPojo(ProductSpuCreateReqVO.class, o -> { ProductSpuCreateReqVO createReqVO = randomPojo(ProductSpuCreateReqVO.class);
o.setSpecType(true);
});
Long spu = productSpuService.createSpu(createReqVO); Long spu = productSpuService.createSpu(createReqVO);
ProductSpuDO productSpuDO = productSpuMapper.selectById(spu); ProductSpuDO productSpuDO = productSpuMapper.selectById(spu);
assertPojoEquals(createReqVO, productSpuDO); assertPojoEquals(createReqVO, productSpuDO);
} }
@Test @Test
@ -96,7 +92,6 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
// 准备参数 // 准备参数
ProductSpuUpdateReqVO reqVO = randomPojo(ProductSpuUpdateReqVO.class, o -> { ProductSpuUpdateReqVO reqVO = randomPojo(ProductSpuUpdateReqVO.class, o -> {
o.setId(createReqVO.getId()); // 设置更新的 ID o.setId(createReqVO.getId()); // 设置更新的 ID
o.setSpecType(true);
}); });
// 调用 // 调用
productSpuService.updateSpu(reqVO); productSpuService.updateSpu(reqVO);
@ -107,9 +102,7 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
@Test @Test
public void testValidateSpuExists_exception() { public void testValidateSpuExists_exception() {
ProductSpuUpdateReqVO reqVO = randomPojo(ProductSpuUpdateReqVO.class, o -> { ProductSpuUpdateReqVO reqVO = randomPojo(ProductSpuUpdateReqVO.class);
o.setSpecType(true);
});
// 调用 // 调用
Assertions.assertThrows(ServiceException.class, () -> productSpuService.updateSpu(reqVO)); Assertions.assertThrows(ServiceException.class, () -> productSpuService.updateSpu(reqVO));
} }
@ -174,7 +167,6 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
//o.setMinPrice(1); // TODO ProductSpuDO中已没有相关属性 //o.setMinPrice(1); // TODO ProductSpuDO中已没有相关属性
//o.setMaxPrice(50); //o.setMaxPrice(50);
o.setMarketPrice(25); o.setMarketPrice(25);
o.setSpecType(false);
o.setBrandId(brandId); o.setBrandId(brandId);
o.setCategoryId(categoryId); o.setCategoryId(categoryId);
//o.setClickCount(100); //o.setClickCount(100);
@ -222,8 +214,8 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest {
//o.setMinPrice(1); // TODO ProductSpuDO中已没有相关属性 //o.setMinPrice(1); // TODO ProductSpuDO中已没有相关属性
//o.setMaxPrice(1); //o.setMaxPrice(1);
o.setMarketPrice(1); o.setMarketPrice(1);
o.setSpecType(false);
o.setBrandId(brandId); o.setBrandId(brandId);
o.setSpecType(false);
o.setCategoryId(categoryId); o.setCategoryId(categoryId);
//o.setClickCount(1); // TODO ProductSpuDO中已没有相关属性 //o.setClickCount(1); // TODO ProductSpuDO中已没有相关属性
//o.setCode(generateNo()); //o.setCode(generateNo());