初始化提交

This commit is contained in:
YangJ
2024-03-20 09:42:17 +08:00
commit 72f30209cf
3705 changed files with 285827 additions and 0 deletions

View File

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-module-mall</artifactId>
<version>${revision}</version>
</parent>
<artifactId>yudao-module-product-api</artifactId>
<packaging>jar</packaging>
<name>${project.artifactId}</name>
<description>
product 模块 API暴露给其它模块调用
</description>
<dependencies>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-common</artifactId>
</dependency>
<!-- 参数校验 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,20 @@
package cn.iocoder.yudao.module.product.api.category;
import java.util.Collection;
/**
* 商品分类 API 接口
*
* @author owen
*/
public interface ProductCategoryApi {
/**
* 校验商品分类是否有效。如下情况,视为无效:
* 1. 商品分类编号不存在
* 2. 商品分类被禁用
*
* @param ids 商品分类编号数组
*/
void validateCategoryList(Collection<Long> ids);
}

View File

@ -0,0 +1,20 @@
package cn.iocoder.yudao.module.product.api.comment;
import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO;
/**
* 产品评论 API 接口
*
* @author HUIHUI
*/
public interface ProductCommentApi {
/**
* 创建评论
*
* @param createReqDTO 评论参数
* @return 返回评论创建后的 id
*/
Long createComment(ProductCommentCreateReqDTO createReqDTO);
}

View File

@ -0,0 +1,61 @@
package cn.iocoder.yudao.module.product.api.comment.dto;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* 评论创建请求 DTO
*
* @author HUIHUI
*/
@Data
public class ProductCommentCreateReqDTO {
/**
* 商品 SKU 编号
*/
@NotNull(message = "商品 SKU 编号不能为空")
private Long skuId;
/**
* 订单编号
*/
private Long orderId;
/**
* 交易订单项编号
*/
private Long orderItemId;
/**
* 描述星级 1-5 分
*/
@NotNull(message = "描述星级不能为空")
private Integer descriptionScores;
/**
* 服务星级 1-5 分
*/
@NotNull(message = "服务星级不能为空")
private Integer benefitScores;
/**
* 评论内容
*/
@NotNull(message = "评论内容不能为空")
private String content;
/**
* 评论图片地址数组,以逗号分隔最多上传 9 张
*/
private List<String> picUrls;
/**
* 是否匿名
*/
@NotNull(message = "是否匿名不能为空")
private Boolean anonymous;
/**
* 评价人
*/
@NotNull(message = "评价人不能为空")
private Long userId;
}

View File

@ -0,0 +1,4 @@
/**
* 占位
*/
package cn.iocoder.yudao.module.product.api;

View File

@ -0,0 +1,33 @@
package cn.iocoder.yudao.module.product.api.property.dto;
import lombok.Data;
/**
* 商品属性项的明细 Response DTO
*
* @author 芋道源码
*/
@Data
public class ProductPropertyValueDetailRespDTO {
/**
* 属性的编号
*/
private Long propertyId;
/**
* 属性的名称
*/
private String propertyName;
/**
* 属性值的编号
*/
private Long valueId;
/**
* 属性值的名称
*/
private String valueName;
}

View File

@ -0,0 +1,48 @@
package cn.iocoder.yudao.module.product.api.sku;
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO;
import java.util.Collection;
import java.util.List;
/**
* 商品 SKU API 接口
*
* @author LeeYan9
* @since 2022-08-26
*/
public interface ProductSkuApi {
/**
* 查询 SKU 信息
*
* @param id SKU 编号
* @return SKU 信息
*/
ProductSkuRespDTO getSku(Long id);
/**
* 批量查询 SKU 数组
*
* @param ids SKU 编号列表
* @return SKU 数组
*/
List<ProductSkuRespDTO> getSkuList(Collection<Long> ids);
/**
* 批量查询 SKU 数组
*
* @param spuIds SPU 编号列表
* @return SKU 数组
*/
List<ProductSkuRespDTO> getSkuListBySpuId(Collection<Long> spuIds);
/**
* 更新 SKU 库存(增加 or 减少)
*
* @param updateStockReqDTO 更新请求
*/
void updateSkuStock(ProductSkuUpdateStockReqDTO updateStockReqDTO);
}

View File

@ -0,0 +1,71 @@
package cn.iocoder.yudao.module.product.api.sku.dto;
import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO;
import lombok.Data;
import java.util.List;
/**
* 商品 SKU 信息 Response DTO
*
* @author LeeYan9
* @since 2022-08-26
*/
@Data
public class ProductSkuRespDTO {
/**
* 商品 SKU 编号,自增
*/
private Long id;
/**
* SPU 编号
*/
private Long spuId;
/**
* 属性数组
*/
private List<ProductPropertyValueDetailRespDTO> properties;
/**
* 销售价格,单位:分
*/
private Integer price;
/**
* 市场价,单位:分
*/
private Integer marketPrice;
/**
* 成本价,单位:分
*/
private Integer costPrice;
/**
* SKU 的条形码
*/
private String barCode;
/**
* 图片地址
*/
private String picUrl;
/**
* 库存
*/
private Integer stock;
/**
* 商品重量单位kg 千克
*/
private Double weight;
/**
* 商品体积单位m^3 平米
*/
private Double volume;
/**
* 一级分销的佣金,单位:分
*/
private Integer firstBrokeragePrice;
/**
* 二级分销的佣金,单位:分
*/
private Integer secondBrokeragePrice;
}

View File

@ -0,0 +1,47 @@
package cn.iocoder.yudao.module.product.api.sku.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* 商品 SKU 更新库存 Request DTO
*
* @author LeeYan9
* @since 2022-08-26
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ProductSkuUpdateStockReqDTO {
/**
* 商品 SKU
*/
@NotNull(message = "商品 SKU 不能为空")
private List<Item> items;
@Data
public static class Item {
/**
* 商品 SKU 编号
*/
@NotNull(message = "商品 SKU 编号不能为空")
private Long id;
/**
* 库存变化数量
*
* 正数:增加库存
* 负数:扣减库存
*/
@NotNull(message = "库存变化数量不能为空")
private Integer incrCount;
}
}

View File

@ -0,0 +1,43 @@
package cn.iocoder.yudao.module.product.api.spu;
import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
import java.util.Collection;
import java.util.List;
/**
* 商品 SPU API 接口
*
* @author LeeYan9
* @since 2022-08-26
*/
public interface ProductSpuApi {
/**
* 批量查询 SPU 数组
*
* @param ids SPU 编号列表
* @return SPU 数组
*/
List<ProductSpuRespDTO> getSpuList(Collection<Long> ids);
/**
* 批量查询 SPU 数组,并且校验是否 SPU 是否有效。
*
* 如下情况,视为无效:
* 1. 商品编号不存在
* 2. 商品被禁用
*
* @param ids SPU 编号列表
* @return SPU 数组
*/
List<ProductSpuRespDTO> validateSpuList(Collection<Long> ids);
/**
* 获得 SPU
*
* @return SPU
*/
ProductSpuRespDTO getSpu(Long id);
}

View File

@ -0,0 +1,102 @@
package cn.iocoder.yudao.module.product.api.spu.dto;
import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;
import lombok.Data;
// TODO @LeeYan9: ProductSpuRespDTO
/**
* 商品 SPU 信息 Response DTO
*
* @author LeeYan9
* @since 2022-08-26
*/
@Data
public class ProductSpuRespDTO {
/**
* 商品 SPU 编号,自增
*/
private Long id;
// ========== 基本信息 =========
/**
* 商品名称
*/
private String name;
/**
* 单位
*
* 对应 product_unit 数据字典
*/
private Integer unit;
/**
* 商品分类编号
*/
private Long categoryId;
/**
* 商品封面图
*/
private String picUrl;
/**
* 商品状态
* <p>
* 枚举 {@link ProductSpuStatusEnum}
*/
private Integer status;
// ========== SKU 相关字段 =========
/**
* 规格类型
*
* false - 单规格
* true - 多规格
*/
private Boolean specType;
/**
* 商品价格,单位使用:分
*/
private Integer price;
/**
* 市场价,单位使用:分
*/
private Integer marketPrice;
/**
* 成本价,单位使用:分
*/
private Integer costPrice;
/**
* 库存
*/
private Integer stock;
// ========== 物流相关字段 =========
/**
* 物流配置模板编号
*
* 对应 TradeDeliveryExpressTemplateDO 的 id 编号
*/
private Long deliveryTemplateId;
// ========== 营销相关字段 =========
/**
* 赠送积分
*/
private Integer giveIntegral;
// ========== 分销相关字段 =========
/**
* 分销类型
*
* false - 默认
* true - 自行设置
*/
private Boolean subCommissionType;
}

View File

@ -0,0 +1,12 @@
package cn.iocoder.yudao.module.product.enums;
/**
* product 字典类型的枚举类
*
* @author HUIHUI
*/
public interface DictTypeConstants {
String PRODUCT_SPU_STATUS = "product_spu_status"; // 商品 SPU 状态
}

View File

@ -0,0 +1,56 @@
package cn.iocoder.yudao.module.product.enums;
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
/**
* Product 错误码枚举类
*
* product 系统,使用 1-008-000-000 段
*/
public interface ErrorCodeConstants {
// ========== 商品分类相关 1-008-001-000 ============
ErrorCode CATEGORY_NOT_EXISTS = new ErrorCode(1_008_001_000, "商品分类不存在");
ErrorCode CATEGORY_PARENT_NOT_EXISTS = new ErrorCode(1_008_001_001, "父分类不存在");
ErrorCode CATEGORY_PARENT_NOT_FIRST_LEVEL = new ErrorCode(1_008_001_002, "父分类不能是二级分类");
ErrorCode CATEGORY_EXISTS_CHILDREN = new ErrorCode(1_008_001_003, "存在子分类,无法删除");
ErrorCode CATEGORY_DISABLED = new ErrorCode(1_008_001_004, "商品分类({})已禁用,无法使用");
ErrorCode CATEGORY_HAVE_BIND_SPU = new ErrorCode(1_008_001_005, "类别下存在商品,无法删除");
// ========== 商品品牌相关编号 1-008-002-000 ==========
ErrorCode BRAND_NOT_EXISTS = new ErrorCode(1_008_002_000, "品牌不存在");
ErrorCode BRAND_DISABLED = new ErrorCode(1_008_002_001, "品牌已禁用");
ErrorCode BRAND_NAME_EXISTS = new ErrorCode(1_008_002_002, "品牌名称已存在");
// ========== 商品属性项 1-008-003-000 ==========
ErrorCode PROPERTY_NOT_EXISTS = new ErrorCode(1_008_003_000, "属性项不存在");
ErrorCode PROPERTY_EXISTS = new ErrorCode(1_008_003_001, "属性项的名称已存在");
ErrorCode PROPERTY_DELETE_FAIL_VALUE_EXISTS = new ErrorCode(1_008_003_002, "属性项下存在属性值,无法删除");
// ========== 商品属性值 1-008-004-000 ==========
ErrorCode PROPERTY_VALUE_NOT_EXISTS = new ErrorCode(1_008_004_000, "属性值不存在");
ErrorCode PROPERTY_VALUE_EXISTS = new ErrorCode(1_008_004_001, "属性值的名称已存在");
// ========== 商品 SPU 1-008-005-000 ==========
ErrorCode SPU_NOT_EXISTS = new ErrorCode(1_008_005_000, "商品 SPU 不存在");
ErrorCode SPU_SAVE_FAIL_CATEGORY_LEVEL_ERROR = new ErrorCode(1_008_005_001, "商品分类不正确,原因:必须使用第二级的商品分类及以下");
ErrorCode SPU_SAVE_FAIL_COUPON_TEMPLATE_NOT_EXISTS = new ErrorCode(1_008_005_002, "商品 SPU 保存失败,原因:优惠卷不存在");
ErrorCode SPU_NOT_ENABLE = new ErrorCode(1_008_005_003, "商品 SPU【{}】不处于上架状态");
ErrorCode SPU_NOT_RECYCLE = new ErrorCode(1_008_005_004, "商品 SPU 不处于回收站状态");
// ========== 商品 SKU 1-008-006-000 ==========
ErrorCode SKU_NOT_EXISTS = new ErrorCode(1_008_006_000, "商品 SKU 不存在");
ErrorCode SKU_PROPERTIES_DUPLICATED = new ErrorCode(1_008_006_001, "商品 SKU 的属性组合存在重复");
ErrorCode SPU_ATTR_NUMBERS_MUST_BE_EQUALS = new ErrorCode(1_008_006_002, "一个 SPU 下的每个 SKU其属性项必须一致");
ErrorCode SPU_SKU_NOT_DUPLICATE = new ErrorCode(1_008_006_003, "一个 SPU 下的每个 SKU必须不重复");
ErrorCode SKU_STOCK_NOT_ENOUGH = new ErrorCode(1_008_006_004, "商品 SKU 库存不足");
// ========== 商品 评价 1-008-007-000 ==========
ErrorCode COMMENT_NOT_EXISTS = new ErrorCode(1_008_007_000, "商品评价不存在");
ErrorCode COMMENT_ORDER_EXISTS = new ErrorCode(1_008_007_001, "订单的商品评价已存在");
// ========== 商品 收藏 1-008-008-000 ==========
ErrorCode FAVORITE_EXISTS = new ErrorCode(1_008_008_000, "该商品已经被收藏");
ErrorCode FAVORITE_NOT_EXISTS = new ErrorCode(1_008_008_001, "商品收藏不存在");
}

View File

@ -0,0 +1,15 @@
package cn.iocoder.yudao.module.product.enums;
/**
* Product 常量
*
* @author HUIHUI
*/
public interface ProductConstants {
/**
* 警戒库存 TODO 警戒库存暂时为 10后期需要使用常量或者数据库配置替换
*/
int ALERT_STOCK = 10;
}

View File

@ -0,0 +1,38 @@
package cn.iocoder.yudao.module.product.enums.comment;
import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
/**
* 商品评论的审批状态枚举
*
* @author 芋道源码
*/
@Getter
@AllArgsConstructor
public enum ProductCommentAuditStatusEnum implements IntArrayValuable {
NONE(1, "待审核"),
APPROVE(2, "审批通过"),
REJECT(2, "审批不通过"),;
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ProductCommentAuditStatusEnum::getStatus).toArray();
/**
* 审批状态
*/
private final Integer status;
/**
* 状态名
*/
private final String name;
@Override
public int[] array() {
return ARRAYS;
}
}

View File

@ -0,0 +1,41 @@
package cn.iocoder.yudao.module.product.enums.comment;
import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
/**
* 商品评论的星级枚举
*
* @author wangzhs
*/
@Getter
@AllArgsConstructor
public enum ProductCommentScoresEnum implements IntArrayValuable {
ONE(1, "1星"),
TWO(2, "2星"),
THREE(3, "3星"),
FOUR(4, "4星"),
FIVE(5, "5星");
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ProductCommentScoresEnum::getScores).toArray();
/**
* 星级
*/
private final Integer scores;
/**
* 星级名
*/
private final String name;
@Override
public int[] array() {
return ARRAYS;
}
}

View File

@ -0,0 +1,48 @@
package cn.iocoder.yudao.module.product.enums.spu;
import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
/**
* 商品 SPU 状态
*
* @author 芋道源码
*/
@Getter
@AllArgsConstructor
public enum ProductSpuStatusEnum implements IntArrayValuable {
RECYCLE(-1, "回收站"),
DISABLE(0, "下架"),
ENABLE(1, "上架");
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ProductSpuStatusEnum::getStatus).toArray();
/**
* 状态
*/
private final Integer status;
/**
* 状态名
*/
private final String name;
@Override
public int[] array() {
return ARRAYS;
}
/**
* 判断是否处于【上架】状态
*
* @param status 状态
* @return 是否处于【上架】状态
*/
public static boolean isEnable(Integer status) {
return ENABLE.getStatus().equals(status);
}
}