Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
Y
yudao-cloud
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
hblj
yudao-cloud
Commits
e107b42f
提交
e107b42f
authored
7月 27, 2020
作者:
YunaiV
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
进行商品添加的迁移
上级
be4b34c8
隐藏空白字符变更
内嵌
并排
正在显示
45 个修改的文件
包含
449 行增加
和
941 行删除
+449
-941
ProductSpuController.http
...anagementweb/controller/product/ProductSpuController.http
+17
-1
ProductSpuController.java
...anagementweb/controller/product/ProductSpuController.java
+3
-0
ProductSpuCreateReqVO.java
...tweb/controller/product/vo/spu/ProductSpuCreateReqVO.java
+40
-10
ProductSpuPageReqVO.java
...entweb/controller/product/vo/spu/ProductSpuPageReqVO.java
+6
-16
ProductSpuConvert.java
...mall/managementweb/convert/product/ProductSpuConvert.java
+2
-2
ProductErrorCodeConstants.java
.../mall/productservice/enums/ProductErrorCodeConstants.java
+7
-7
ProductSpuRpc.java
...cn/iocoder/mall/productservice/rpc/spu/ProductSpuRpc.java
+2
-2
ProductSpuAndSkuCreateReqDTO.java
...ductservice/rpc/spu/dto/ProductSpuAndSkuCreateReqDTO.java
+41
-15
ProductSpuPageReqDTO.java
...mall/productservice/rpc/spu/dto/ProductSpuPageReqDTO.java
+8
-0
ProductSkuConvert.java
...er/mall/productservice/convert/sku/ProductSkuConvert.java
+33
-0
ProductSpuConvert.java
...er/mall/productservice/convert/spu/ProductSpuConvert.java
+7
-4
ProductAttrKeyDO.java
...ctservice/dal/mysql/dataobject/attr/ProductAttrKeyDO.java
+9
-5
ProductAttrValueDO.java
...service/dal/mysql/dataobject/attr/ProductAttrValueDO.java
+7
-5
ProductSkuDO.java
...productservice/dal/mysql/dataobject/spu/ProductSkuDO.java
+4
-3
ProductAttrKeyMapper.java
...ctservice/dal/mysql/mapper/attr/ProductAttrKeyMapper.java
+3
-4
ProductAttrValueMapper.java
...service/dal/mysql/mapper/attr/ProductAttrValueMapper.java
+3
-4
ProductSkuMapper.java
...productservice/dal/mysql/mapper/sku/ProductSkuMapper.java
+21
-0
ProductSpuMapper.java
...productservice/dal/mysql/mapper/spu/ProductSpuMapper.java
+2
-1
ProductSpuManager.java
...er/mall/productservice/manager/spu/ProductSpuManager.java
+54
-7
ProductSpuRpcImpl.java
...ocoder/mall/productservice/rpc/spu/ProductSpuRpcImpl.java
+2
-2
ProductAttrService.java
.../mall/productservice/service/attr/ProductAttrService.java
+64
-0
ProductAttrKeyValueBO.java
...productservice/service/attr/bo/ProductAttrKeyValueBO.java
+9
-9
ProductSkuService.java
...er/mall/productservice/service/sku/ProductSkuService.java
+74
-0
ProductSkuCreateOrUpdateBO.java
...uctservice/service/sku/bo/ProductSkuCreateOrUpdateBO.java
+6
-4
ProductSpuPageBO.java
.../mall/productservice/service/spu/bo/ProductSpuPageBO.java
+8
-0
ProductSkuMapper.xml
...ervice-app/src/main/resources/mapper/ProductSkuMapper.xml
+17
-0
ProductAttrAndValuePairBO.java
...all/product/biz/bo/product/ProductAttrAndValuePairBO.java
+0
-32
ProductAttrMapper.java
.../iocoder/mall/product/biz/dao/attr/ProductAttrMapper.java
+0
-11
ProductSkuAddOrUpdateDTO.java
...all/product/biz/dto/product/ProductSkuAddOrUpdateDTO.java
+0
-35
ProductSpuAddDTO.java
...ocoder/mall/product/biz/dto/product/ProductSpuAddDTO.java
+0
-62
ProductSkuAddOrUpdateDTO.java
...er/mall/product/biz/dto/sku/ProductSkuAddOrUpdateDTO.java
+0
-35
ProductSpuAddDTO.java
...cn/iocoder/mall/product/biz/dto/sku/ProductSpuAddDTO.java
+0
-63
ProductSpuUpdateDTO.java
...iocoder/mall/product/biz/dto/sku/ProductSpuUpdateDTO.java
+0
-69
ProductSpuMapper.xml
...roduct-biz/src/main/resources/mapper/ProductSpuMapper.xml
+0
-6
ProductSpuService.java
...n/java/cn/iocoder/mall/product/api/ProductSpuService.java
+0
-2
ProductSpuBO.java
...ain/java/cn/iocoder/mall/product/api/bo/ProductSpuBO.java
+0
-74
ProductSpuPageBO.java
...java/cn/iocoder/mall/product/api/bo/ProductSpuPageBO.java
+0
-25
ProductSpuAddDTO.java
...ava/cn/iocoder/mall/product/api/dto/ProductSpuAddDTO.java
+0
-62
ProductSpuPageDTO.java
...va/cn/iocoder/mall/product/api/dto/ProductSpuPageDTO.java
+0
-41
ProductSpuMapper.java
...in/java/cn/iocoder/mall/product/dao/ProductSpuMapper.java
+0
-21
ProductAttrServiceImpl.java
.../iocoder/mall/product/service/ProductAttrServiceImpl.java
+0
-33
ProductSpuServiceImpl.java
...n/iocoder/mall/product/service/ProductSpuServiceImpl.java
+0
-88
ProductSpuMapper.xml
...rvice-impl/src/main/resources/mapper/ProductSpuMapper.xml
+0
-120
UserProductSpuCollectionsMapper.xml
...main/resources/mapper/UserProductSpuCollectionsMapper.xml
+0
-41
mybatis-config.xml
...roduct-service-impl/src/main/resources/mybatis-config.xml
+0
-20
没有找到文件。
management-web-app/src/main/java/cn/iocoder/mall/managementweb/controller/product/ProductSpuController.http
浏览文件 @
e107b42f
...
...
@@ -3,5 +3,21 @@ GET {{baseUrl}}/product-spu/page?pageNo=1&pageSize=10
Content-Type: application/x-www-form-urlencoded
Authorization: Bearer {{accessToken}}
###
### /product-spu/page 成功(有库存 + 上架)
GET {{baseUrl}}/product-spu/page?pageNo=1&pageSize=10&hasQuantity=true&visible=true
Content-Type: application/x-www-form-urlencoded
Authorization: Bearer {{accessToken}}
### /product-spu/page 成功(无库存 + 下架)
GET {{baseUrl}}/product-spu/page?pageNo=1&pageSize=10&hasQuantity=false&visible=false
Content-Type: application/x-www-form-urlencoded
Authorization: Bearer {{accessToken}}
### /product-spu/create 成功
POST {{baseUrl}}/product-spu/create
Content-Type: application/x-www-form-urlencoded
Authorization: Bearer {{accessToken}}
name=测试商品标题&description=测试商品描述&cid=637&sellPoint=丑&picUrls=1,2,3&visible=true&skus[0].price=1&skus[0].quantity=100&skus[0].attrValueIds=1,3
###
management-web-app/src/main/java/cn/iocoder/mall/managementweb/controller/product/ProductSpuController.java
浏览文件 @
e107b42f
...
...
@@ -61,6 +61,9 @@ public class ProductSpuController {
@GetMapping
(
"/page"
)
@ApiOperation
(
"获得商品 SPU 分页"
)
public
CommonResult
<
PageResult
<
ProductSpuRespVO
>>
pageProductSpu
(
ProductSpuPageReqVO
pageVO
)
{
//
//
//
return
success
(
productSpuManager
.
pageProductSpu
(
pageVO
));
}
...
...
management-web-app/src/main/java/cn/iocoder/mall/managementweb/controller/product/vo/spu/ProductSpuCreateReqVO.java
浏览文件 @
e107b42f
...
...
@@ -3,15 +3,45 @@ package cn.iocoder.mall.managementweb.controller.product.vo.spu;
import
io.swagger.annotations.ApiModel
;
import
io.swagger.annotations.ApiModelProperty
;
import
lombok.Data
;
import
lombok.experimental.Accessors
;
import
javax.validation.Valid
;
import
javax.validation.constraints.Min
;
import
javax.validation.constraints.NotEmpty
;
import
javax.validation.constraints.NotNull
;
import
java.util.List
;
@ApiModel
(
"商品 SPU创建 Request VO"
)
@ApiModel
(
"商品 SPU
创建 Request VO"
)
@Data
public
class
ProductSpuCreateReqVO
{
/**
* SKU 信息
*/
@Data
@Accessors
(
chain
=
true
)
public
static
class
Sku
{
/**
* 规格值数组
*/
@NotNull
(
message
=
"规格值数组不能为空"
)
private
List
<
Integer
>
attrValueIds
;
/**
* 价格,单位:分
*/
@NotNull
(
message
=
"价格不能为空"
)
@Min
(
value
=
1L
,
message
=
"最小价格为 1"
)
private
Integer
price
;
/**
* 库存数量
*/
@NotNull
(
message
=
"库存数量不能为空"
)
@Min
(
value
=
1L
,
message
=
"最小库存为 1"
)
private
Integer
quantity
;
}
@ApiModelProperty
(
value
=
"SPU 名字"
,
required
=
true
)
@NotEmpty
(
message
=
"SPU 名字不能为空"
)
private
String
name
;
...
...
@@ -30,14 +60,14 @@ public class ProductSpuCreateReqVO {
@ApiModelProperty
(
value
=
"是否上架商品"
,
required
=
true
)
@NotNull
(
message
=
"是否上架商品不能为空"
)
private
Boolean
visible
;
@ApiModelProperty
(
value
=
"排序字段"
,
required
=
true
)
@NotNull
(
message
=
"排序字段不能为空"
)
private
Integer
sort
;
@ApiModelProperty
(
value
=
"价格"
,
required
=
true
)
@NotNull
(
message
=
"价格不能为空"
)
private
Integer
price
;
@
ApiModelProperty
(
value
=
"库存数量"
,
required
=
true
)
@
NotNull
(
message
=
"库存数量不能为空"
)
private
Integer
quantity
;
// ========== SKU =========
/**
* SKU 数组
*/
@
NotNull
(
message
=
"SKU 不能为空"
)
@
Valid
private
List
<
Sku
>
skus
;
}
management-web-app/src/main/java/cn/iocoder/mall/managementweb/controller/product/vo/spu/ProductSpuPageReqVO.java
浏览文件 @
e107b42f
...
...
@@ -11,23 +11,13 @@ import lombok.EqualsAndHashCode;
@EqualsAndHashCode
(
callSuper
=
true
)
public
class
ProductSpuPageReqVO
extends
PageParam
{
@ApiModelProperty
(
value
=
"SPU 名字"
,
required
=
true
)
@ApiModelProperty
(
value
=
"SPU 名字"
,
notes
=
"模糊匹配"
,
example
=
"艿艿"
)
private
String
name
;
@ApiModelProperty
(
value
=
"卖点"
,
required
=
true
)
private
String
sellPoint
;
@ApiModelProperty
(
value
=
"描述"
,
required
=
true
)
private
String
description
;
@ApiModelProperty
(
value
=
"分类编号"
,
required
=
true
)
@ApiModelProperty
(
value
=
"分类编号"
,
example
=
"1024"
)
private
Integer
cid
;
@ApiModelProperty
(
value
=
"商品主图地址"
,
required
=
true
)
private
String
picUrls
;
@ApiModelProperty
(
value
=
"是否上架商品"
,
required
=
true
)
private
Integer
visible
;
@ApiModelProperty
(
value
=
"排序字段"
,
required
=
true
)
private
Integer
sort
;
@ApiModelProperty
(
value
=
"价格"
,
required
=
true
)
private
Integer
price
;
@ApiModelProperty
(
value
=
"库存数量"
,
required
=
true
)
private
Integer
quantity
;
@ApiModelProperty
(
value
=
"是否上架商品"
,
example
=
"true"
)
private
Boolean
visible
;
@ApiModelProperty
(
value
=
"是否有库存"
,
example
=
"true"
)
private
Boolean
hasQuantity
;
}
management-web-app/src/main/java/cn/iocoder/mall/managementweb/convert/product/ProductSpuConvert.java
浏览文件 @
e107b42f
...
...
@@ -5,7 +5,7 @@ import cn.iocoder.mall.managementweb.controller.product.vo.spu.ProductSpuCreateR
import
cn.iocoder.mall.managementweb.controller.product.vo.spu.ProductSpuPageReqVO
;
import
cn.iocoder.mall.managementweb.controller.product.vo.spu.ProductSpuRespVO
;
import
cn.iocoder.mall.managementweb.controller.product.vo.spu.ProductSpuUpdateReqVO
;
import
cn.iocoder.mall.productservice.rpc.spu.dto.ProductSpuCreateReqDTO
;
import
cn.iocoder.mall.productservice.rpc.spu.dto.ProductSpu
AndSku
CreateReqDTO
;
import
cn.iocoder.mall.productservice.rpc.spu.dto.ProductSpuPageReqDTO
;
import
cn.iocoder.mall.productservice.rpc.spu.dto.ProductSpuRespDTO
;
import
cn.iocoder.mall.productservice.rpc.spu.dto.ProductSpuUpdateReqDTO
;
...
...
@@ -19,7 +19,7 @@ public interface ProductSpuConvert {
ProductSpuConvert
INSTANCE
=
Mappers
.
getMapper
(
ProductSpuConvert
.
class
);
ProductSpuCreateReqDTO
convert
(
ProductSpuCreateReqVO
bean
);
ProductSpu
AndSku
CreateReqDTO
convert
(
ProductSpuCreateReqVO
bean
);
ProductSpuUpdateReqDTO
convert
(
ProductSpuUpdateReqVO
bean
);
...
...
product-service-project/product-service-api/src/main/java/cn/iocoder/mall/productservice/enums/ProductErrorCodeConstants.java
浏览文件 @
e107b42f
...
...
@@ -18,15 +18,15 @@ public interface ProductErrorCodeConstants {
ErrorCode
PRODUCT_CATEGORY_PARENT_CAN_NOT_BE_LEVEL2
=
new
ErrorCode
(
1002001005
,
"父分类必须是一级分类"
);
// ========== PRODUCT SPU + SKU 模块 ==========
ErrorCode
PRODUCT_SKU_ATTR_CANT_NOT_DUPLICATE
=
new
ErrorCode
(
1003002000
,
"一个 S
ku
下,不能有重复的规格"
);
ErrorCode
PRODUCT_SPU_ATTR_NUMBERS_MUST_BE_EQUALS
=
new
ErrorCode
(
1003002001
,
"一个 Spu 下的每个 S
ku
,其规格数必须一致"
);
ErrorCode
PRODUCT_SPU_SKU_
_NOT_DUPLICATE
=
new
ErrorCode
(
1003002002
,
"一个 Spu 下的每个 Sku
,必须不重复"
);
ErrorCode
PRODUCT_SPU_NOT_EXISTS
=
new
ErrorCode
(
1003002003
,
"S
pu
不存在"
);
ErrorCode
PRODUCT_SPU_CATEGORY_MUST_BE_LEVEL2
=
new
ErrorCode
(
1003002003
,
"S
pu
只能添加在二级分类下"
);
ErrorCode
PRODUCT_SKU_ATTR_CANT_NOT_DUPLICATE
=
new
ErrorCode
(
1003002000
,
"一个 S
KU
下,不能有重复的规格"
);
ErrorCode
PRODUCT_SPU_ATTR_NUMBERS_MUST_BE_EQUALS
=
new
ErrorCode
(
1003002001
,
"一个 Spu 下的每个 S
KU
,其规格数必须一致"
);
ErrorCode
PRODUCT_SPU_SKU_
NOT_DUPLICATE
=
new
ErrorCode
(
1003002002
,
"一个 SPU 下的每个 SKU
,必须不重复"
);
ErrorCode
PRODUCT_SPU_NOT_EXISTS
=
new
ErrorCode
(
1003002003
,
"S
PU
不存在"
);
ErrorCode
PRODUCT_SPU_CATEGORY_MUST_BE_LEVEL2
=
new
ErrorCode
(
1003002003
,
"S
PU
只能添加在二级分类下"
);
// ========== PRODUCT ATTR + ATTR_VALUE 模块 ==========
ErrorCode
PRODUCT_ATTR_VALUE_NOT_EXIST
=
new
ErrorCode
(
1003003000
,
"商品属性值不存在"
);
ErrorCode
PRODUCT_ATTR_NOT_EXIST
=
new
ErrorCode
(
1003003001
,
"商品属性值不存在"
);
ErrorCode
PRODUCT_ATTR_VALUE_NOT_EXIST
=
new
ErrorCode
(
1003003000
,
"商品属性值不存在"
);
ErrorCode
PRODUCT_ATTR_
KEY_
NOT_EXIST
=
new
ErrorCode
(
1003003001
,
"商品属性值不存在"
);
ErrorCode
PRODUCT_ATTR_EXISTS
=
new
ErrorCode
(
1003003002
,
"商品规格已经存在"
);
ErrorCode
PRODUCT_ATTR_STATUS_EQUALS
=
new
ErrorCode
(
1003003003
,
"商品规格已经是该状态"
);
ErrorCode
PRODUCT_ATTR_VALUE_EXISTS
=
new
ErrorCode
(
1003003004
,
"商品规格值已经存在"
);
...
...
product-service-project/product-service-api/src/main/java/cn/iocoder/mall/productservice/rpc/spu/ProductSpuRpc.java
浏览文件 @
e107b42f
...
...
@@ -2,7 +2,7 @@ package cn.iocoder.mall.productservice.rpc.spu;
import
cn.iocoder.common.framework.vo.CommonResult
;
import
cn.iocoder.common.framework.vo.PageResult
;
import
cn.iocoder.mall.productservice.rpc.spu.dto.ProductSpuCreateReqDTO
;
import
cn.iocoder.mall.productservice.rpc.spu.dto.ProductSpu
AndSku
CreateReqDTO
;
import
cn.iocoder.mall.productservice.rpc.spu.dto.ProductSpuPageReqDTO
;
import
cn.iocoder.mall.productservice.rpc.spu.dto.ProductSpuRespDTO
;
import
cn.iocoder.mall.productservice.rpc.spu.dto.ProductSpuUpdateReqDTO
;
...
...
@@ -20,7 +20,7 @@ public interface ProductSpuRpc {
* @param createDTO 创建商品 SPU DTO
* @return 商品 SPU编号
*/
CommonResult
<
Integer
>
createProductSpu
(
ProductSpuCreateReqDTO
createDTO
);
CommonResult
<
Integer
>
createProductSpu
(
ProductSpu
AndSku
CreateReqDTO
createDTO
);
/**
* 更新商品 SPU
...
...
product-service-project/product-service-api/src/main/java/cn/iocoder/mall/productservice/rpc/spu/dto/ProductSpuCreateReqDTO.java
→
product-service-project/product-service-api/src/main/java/cn/iocoder/mall/productservice/rpc/spu/dto/ProductSpu
AndSku
CreateReqDTO.java
浏览文件 @
e107b42f
...
...
@@ -3,18 +3,48 @@ package cn.iocoder.mall.productservice.rpc.spu.dto;
import
lombok.Data
;
import
lombok.experimental.Accessors
;
import
javax.validation.Valid
;
import
javax.validation.constraints.Min
;
import
javax.validation.constraints.NotEmpty
;
import
javax.validation.constraints.NotNull
;
import
java.io.Serializable
;
import
java.util.List
;
/**
* 商品 SPU 创建 Request DTO
* 商品 SPU
和 SKU
创建 Request DTO
*/
@Data
@Accessors
(
chain
=
true
)
public
class
ProductSpuCreateReqDTO
implements
Serializable
{
public
class
ProductSpu
AndSku
CreateReqDTO
implements
Serializable
{
/**
* SKU 信息
*/
@Data
@Accessors
(
chain
=
true
)
public
static
class
Sku
implements
Serializable
{
/**
* 规格值数组
*/
@NotNull
(
message
=
"规格值数组不能为空"
)
private
List
<
Integer
>
attrValueIds
;
/**
* 价格,单位:分
*/
@NotNull
(
message
=
"价格不能为空"
)
@Min
(
value
=
1L
,
message
=
"最小价格为 1"
)
private
Integer
price
;
/**
* 库存数量
*/
@NotNull
(
message
=
"库存数量不能为空"
)
@Min
(
value
=
1L
,
message
=
"最小库存为 1"
)
private
Integer
quantity
;
}
// ========== 基本信息 =========
/**
* SPU 名字
*/
...
...
@@ -40,25 +70,21 @@ public class ProductSpuCreateReqDTO implements Serializable {
*/
@NotEmpty
(
message
=
"商品主图地址不能为空"
)
private
List
<
String
>
picUrls
;
// ========== 其他信息 =========
/**
* 是否上架商品
*/
@NotNull
(
message
=
"是否上架商品不能为空"
)
private
Boolean
visible
;
// ========== SKU =========
/**
* 排序字段
*/
@NotNull
(
message
=
"排序字段不能为空"
)
private
Integer
sort
;
/**
* 价格
*/
@NotNull
(
message
=
"价格不能为空"
)
private
Integer
price
;
/**
* 库存数量
* SKU 数组
*/
@NotNull
(
message
=
"库存数量不能为空"
)
private
Integer
quantity
;
@NotNull
(
message
=
"SKU 不能为空"
)
@Valid
private
List
<
Sku
>
skus
;
}
product-service-project/product-service-api/src/main/java/cn/iocoder/mall/productservice/rpc/spu/dto/ProductSpuPageReqDTO.java
浏览文件 @
e107b42f
...
...
@@ -17,6 +17,14 @@ public class ProductSpuPageReqDTO extends PageParam {
* SPU 名字
*/
private
String
name
;
/**
* 分类编号
*/
private
Integer
cid
;
/**
* 是否可见
*/
private
Boolean
visible
;
/**
* 是否有库存
*/
...
...
product-service-project/product-service-app/src/main/java/cn/iocoder/mall/productservice/convert/sku/ProductSkuConvert.java
0 → 100644
浏览文件 @
e107b42f
package
cn
.
iocoder
.
mall
.
productservice
.
convert
.
sku
;
import
cn.iocoder.common.framework.util.StringUtils
;
import
cn.iocoder.mall.productservice.dal.mysql.dataobject.spu.ProductSkuDO
;
import
cn.iocoder.mall.productservice.service.sku.bo.ProductSkuCreateOrUpdateBO
;
import
org.mapstruct.Mapper
;
import
org.mapstruct.Mapping
;
import
org.mapstruct.Named
;
import
org.mapstruct.factory.Mappers
;
import
java.util.List
;
@Mapper
public
interface
ProductSkuConvert
{
ProductSkuConvert
INSTANCE
=
Mappers
.
getMapper
(
ProductSkuConvert
.
class
);
List
<
ProductSkuDO
>
convertList
(
List
<
ProductSkuCreateOrUpdateBO
>
list
);
@Mapping
(
source
=
"attrValueIds"
,
target
=
"attrs"
,
qualifiedByName
=
"translatePicUrlsFromStringList"
)
ProductSkuDO
convertList
(
ProductSkuCreateOrUpdateBO
bean
);
@Named
(
"translateAttrValueIdsFromString"
)
default
List
<
String
>
translateAttrValueIdsFromString
(
String
attrValueIdsStar
)
{
return
StringUtils
.
split
(
attrValueIdsStar
,
","
);
}
@Named
(
"translateAttrValueIdsFromList"
)
default
String
translateAttrValueIdsFromList
(
List
<
Integer
>
attrValueIds
)
{
return
StringUtils
.
join
(
attrValueIds
,
","
);
}
}
product-service-project/product-service-app/src/main/java/cn/iocoder/mall/productservice/convert/spu/ProductSpuConvert.java
浏览文件 @
e107b42f
...
...
@@ -3,7 +3,8 @@ package cn.iocoder.mall.productservice.convert.spu;
import
cn.iocoder.common.framework.util.StringUtils
;
import
cn.iocoder.common.framework.vo.PageResult
;
import
cn.iocoder.mall.productservice.dal.mysql.dataobject.spu.ProductSpuDO
;
import
cn.iocoder.mall.productservice.rpc.spu.dto.ProductSpuCreateReqDTO
;
import
cn.iocoder.mall.productservice.service.sku.bo.ProductSkuCreateOrUpdateBO
;
import
cn.iocoder.mall.productservice.rpc.spu.dto.ProductSpuAndSkuCreateReqDTO
;
import
cn.iocoder.mall.productservice.rpc.spu.dto.ProductSpuPageReqDTO
;
import
cn.iocoder.mall.productservice.rpc.spu.dto.ProductSpuRespDTO
;
import
cn.iocoder.mall.productservice.rpc.spu.dto.ProductSpuUpdateReqDTO
;
...
...
@@ -38,7 +39,7 @@ public interface ProductSpuConvert {
@Mapping
(
source
=
"records"
,
target
=
"list"
)
PageResult
<
ProductSpuBO
>
convertPage
(
IPage
<
ProductSpuDO
>
page
);
ProductSpuCreateBO
convert
(
ProductSpuCreateReqDTO
bean
);
ProductSpuCreateBO
convert
(
ProductSpu
AndSku
CreateReqDTO
bean
);
ProductSpuUpdateBO
convert
(
ProductSpuUpdateReqDTO
bean
);
...
...
@@ -51,13 +52,15 @@ public interface ProductSpuConvert {
PageResult
<
ProductSpuRespDTO
>
convertPage
(
PageResult
<
ProductSpuBO
>
page
);
@Named
(
"translatePicUrlsFromString"
)
default
List
<
String
>
translatePicUrlsFrom
String
(
String
picUrls
)
{
default
List
<
String
>
translatePicUrlsFrom
List
(
String
picUrls
)
{
return
StringUtils
.
split
(
picUrls
,
","
);
}
@Named
(
"translatePicUrlsFromStringList"
)
default
String
translatePicUrlsFrom
String
(
List
<
String
>
picUrls
)
{
default
String
translatePicUrlsFrom
List
(
List
<
String
>
picUrls
)
{
return
StringUtils
.
join
(
picUrls
,
","
);
}
List
<
ProductSkuCreateOrUpdateBO
>
convert
(
List
<
ProductSpuAndSkuCreateReqDTO
.
Sku
>
list
);
}
product
/product-biz/src/main/java/cn/iocoder/mall/product/biz/dataobject/attr/ProductAttr
DO.java
→
product
-service-project/product-service-app/src/main/java/cn/iocoder/mall/productservice/dal/mysql/dataobject/attr/ProductAttrKey
DO.java
浏览文件 @
e107b42f
package
cn
.
iocoder
.
mall
.
product
.
biz
.
dataobject
.
attr
;
package
cn
.
iocoder
.
mall
.
product
service
.
dal
.
mysql
.
dataobject
.
attr
;
import
cn.iocoder.common.framework.enums.CommonStatusEnum
;
import
cn.iocoder.mall.mybatis.core.dataobject.DeletableDO
;
import
com.baomidou.mybatisplus.annotation.TableName
;
import
lombok.Data
;
import
lombok.EqualsAndHashCode
;
import
lombok.experimental.Accessors
;
/**
* Product 规格
* Product 规格
键 DO
*/
@TableName
(
"product_attr_key"
)
@Data
@Accessors
(
chain
=
true
)
public
class
ProductAttrDO
extends
DeletableDO
{
@EqualsAndHashCode
(
callSuper
=
true
)
public
class
ProductAttrKeyDO
extends
DeletableDO
{
/**
* 规格编号
...
...
@@ -22,8 +27,7 @@ public class ProductAttrDO extends DeletableDO {
/**
* 状态
*
* 1-开启
* 2-禁用
* 枚举 {@link CommonStatusEnum}
*/
private
Integer
status
;
...
...
product
/product-biz/src/main/java/cn/iocoder/mall/product/biz
/dataobject/attr/ProductAttrValueDO.java
→
product
-service-project/product-service-app/src/main/java/cn/iocoder/mall/productservice/dal/mysql
/dataobject/attr/ProductAttrValueDO.java
浏览文件 @
e107b42f
package
cn
.
iocoder
.
mall
.
product
.
biz
.
dataobject
.
attr
;
package
cn
.
iocoder
.
mall
.
product
service
.
dal
.
mysql
.
dataobject
.
attr
;
import
cn.iocoder.common.framework.enums.CommonStatusEnum
;
import
cn.iocoder.mall.mybatis.core.dataobject.DeletableDO
;
import
com.baomidou.mybatisplus.annotation.TableName
;
import
lombok.Data
;
import
lombok.EqualsAndHashCode
;
import
lombok.experimental.Accessors
;
/**
*
Product 规格值
*
商品规格值 DO
*/
@TableName
(
"product_attr_value"
)
@Data
@EqualsAndHashCode
(
callSuper
=
true
)
@Accessors
(
chain
=
true
)
...
...
@@ -27,9 +30,8 @@ public class ProductAttrValueDO extends DeletableDO {
private
String
name
;
/**
* 状态
* <p>
* 1-正常
* 2-禁用
*
* 枚举 {@link CommonStatusEnum}
*/
private
Integer
status
;
...
...
product-service-project/product-service-app/src/main/java/cn/iocoder/mall/productservice/dal/mysql/dataobject/spu/ProductSkuDO.java
浏览文件 @
e107b42f
package
cn
.
iocoder
.
mall
.
productservice
.
dal
.
mysql
.
dataobject
.
spu
;
import
cn.iocoder.common.framework.enums.CommonStatusEnum
;
import
cn.iocoder.mall.mybatis.core.dataobject.DeletableDO
;
import
cn.iocoder.mall.productservice.dal.mysql.dataobject.attr.ProductAttrValueDO
;
import
com.baomidou.mybatisplus.annotation.TableName
;
import
lombok.Data
;
import
lombok.EqualsAndHashCode
;
...
...
@@ -29,8 +31,7 @@ public class ProductSkuDO extends DeletableDO {
/**
* 状态
*
* 1-正常
* 2-禁用
* 枚举 {@link CommonStatusEnum}
*/
private
Integer
status
;
/**
...
...
@@ -38,7 +39,7 @@ public class ProductSkuDO extends DeletableDO {
*/
private
String
picUrl
;
/**
* 规格值({@link ProductAttr
DO
})数组
* 规格值({@link ProductAttr
ValueDO#getId()
})数组
*
* 数组,以逗号分隔
*/
...
...
product
/product-biz/src/main/java/cn/iocoder/mall/product/biz/dao/sku/ProductSpu
Mapper.java
→
product
-service-project/product-service-app/src/main/java/cn/iocoder/mall/productservice/dal/mysql/mapper/attr/ProductAttrKey
Mapper.java
浏览文件 @
e107b42f
package
cn
.
iocoder
.
mall
.
product
.
biz
.
dao
.
sku
;
package
cn
.
iocoder
.
mall
.
product
service
.
dal
.
mysql
.
mapper
.
attr
;
import
cn.iocoder.mall.product
.biz.dataobject.spu.ProductSpu
DO
;
import
cn.iocoder.mall.product
service.dal.mysql.dataobject.attr.ProductAttrKey
DO
;
import
com.baomidou.mybatisplus.core.mapper.BaseMapper
;
import
org.springframework.stereotype.Repository
;
@Repository
public
interface
ProductSpuMapper
extends
BaseMapper
<
ProductSpuDO
>
{
public
interface
ProductAttrKeyMapper
extends
BaseMapper
<
ProductAttrKeyDO
>
{
}
product
/product-biz/src/main/java/cn/iocoder/mall/product/biz/dao
/attr/ProductAttrValueMapper.java
→
product
-service-project/product-service-app/src/main/java/cn/iocoder/mall/productservice/dal/mysql/mapper
/attr/ProductAttrValueMapper.java
浏览文件 @
e107b42f
package
cn
.
iocoder
.
mall
.
product
.
biz
.
dao
.
attr
;
package
cn
.
iocoder
.
mall
.
product
service
.
dal
.
mysql
.
mapper
.
attr
;
import
cn.iocoder.mall.product
.biz
.dataobject.attr.ProductAttrValueDO
;
import
cn.iocoder.mall.product
service.dal.mysql
.dataobject.attr.ProductAttrValueDO
;
import
com.baomidou.mybatisplus.core.mapper.BaseMapper
;
import
org.springframework.stereotype.Repository
;
...
...
@@ -8,4 +8,4 @@ import org.springframework.stereotype.Repository;
public
interface
ProductAttrValueMapper
extends
BaseMapper
<
ProductAttrValueDO
>
{
}
\ No newline at end of file
}
product-service-project/product-service-app/src/main/java/cn/iocoder/mall/productservice/dal/mysql/mapper/sku/ProductSkuMapper.java
0 → 100644
浏览文件 @
e107b42f
package
cn
.
iocoder
.
mall
.
productservice
.
dal
.
mysql
.
mapper
.
sku
;
import
cn.iocoder.mall.mybatis.core.query.QueryWrapperX
;
import
cn.iocoder.mall.productservice.dal.mysql.dataobject.spu.ProductSkuDO
;
import
com.baomidou.mybatisplus.core.mapper.BaseMapper
;
import
org.apache.ibatis.annotations.Param
;
import
org.springframework.stereotype.Repository
;
import
java.util.List
;
@Repository
public
interface
ProductSkuMapper
extends
BaseMapper
<
ProductSkuDO
>
{
default
List
<
ProductSkuDO
>
selectListBySpuIdAndStatus
(
Integer
spuId
,
Integer
status
)
{
return
selectList
(
new
QueryWrapperX
<
ProductSkuDO
>().
eq
(
"spu_id"
,
spuId
)
.
eq
(
"status"
,
status
));
}
void
insertList
(
@Param
(
"productSkuDOs"
)
List
<
ProductSkuDO
>
productSkuDOs
);
}
product-service-project/product-service-app/src/main/java/cn/iocoder/mall/productservice/dal/mysql/mapper/spu/ProductSpuMapper.java
浏览文件 @
e107b42f
...
...
@@ -12,7 +12,8 @@ import org.springframework.stereotype.Repository;
public
interface
ProductSpuMapper
extends
BaseMapper
<
ProductSpuDO
>
{
default
IPage
<
ProductSpuDO
>
selectPage
(
ProductSpuPageBO
pageBO
)
{
QueryWrapperX
<
ProductSpuDO
>
query
=
new
QueryWrapperX
<
ProductSpuDO
>().
likeIfPresent
(
"name"
,
pageBO
.
getName
());
QueryWrapperX
<
ProductSpuDO
>
query
=
new
QueryWrapperX
<
ProductSpuDO
>().
likeIfPresent
(
"name"
,
pageBO
.
getName
())
.
eqIfPresent
(
"cid"
,
pageBO
.
getCid
()).
eqIfPresent
(
"visible"
,
pageBO
.
getVisible
());
// 库存过滤
if
(
pageBO
.
getHasQuantity
()
!=
null
)
{
if
(
pageBO
.
getHasQuantity
())
{
...
...
product-service-project/product-service-app/src/main/java/cn/iocoder/mall/productservice/manager/spu/ProductSpuManager.java
浏览文件 @
e107b42f
package
cn
.
iocoder
.
mall
.
productservice
.
manager
.
spu
;
import
cn.iocoder.common.framework.exception.util.ServiceExceptionUtil
;
import
cn.iocoder.common.framework.vo.PageResult
;
import
cn.iocoder.mall.productservice.convert.spu.ProductSpuConvert
;
import
cn.iocoder.mall.productservice.rpc.spu.dto.ProductSpuCreateReqDTO
;
import
cn.iocoder.mall.productservice.enums.category.ProductCategoryIdEnum
;
import
cn.iocoder.mall.productservice.rpc.spu.dto.ProductSpuAndSkuCreateReqDTO
;
import
cn.iocoder.mall.productservice.rpc.spu.dto.ProductSpuPageReqDTO
;
import
cn.iocoder.mall.productservice.rpc.spu.dto.ProductSpuRespDTO
;
import
cn.iocoder.mall.productservice.rpc.spu.dto.ProductSpuUpdateReqDTO
;
import
cn.iocoder.mall.productservice.service.attr.ProductAttrService
;
import
cn.iocoder.mall.productservice.service.attr.bo.ProductAttrKeyValueBO
;
import
cn.iocoder.mall.productservice.service.category.ProductCategoryService
;
import
cn.iocoder.mall.productservice.service.category.bo.ProductCategoryBO
;
import
cn.iocoder.mall.productservice.service.sku.ProductSkuService
;
import
cn.iocoder.mall.productservice.service.sku.bo.ProductSkuCreateOrUpdateBO
;
import
cn.iocoder.mall.productservice.service.spu.ProductSpuService
;
import
cn.iocoder.mall.productservice.service.spu.bo.ProductSpuBO
;
import
cn.iocoder.mall.productservice.service.spu.bo.ProductSpuCreateBO
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Service
;
import
org.springframework.transaction.annotation.Transactional
;
import
java.util.Comparator
;
import
java.util.HashSet
;
import
java.util.List
;
import
java.util.Set
;
import
static
cn
.
iocoder
.
mall
.
productservice
.
enums
.
ProductErrorCodeConstants
.
PRODUCT_CATEGORY_NOT_EXISTS
;
import
static
cn
.
iocoder
.
mall
.
productservice
.
enums
.
ProductErrorCodeConstants
.
PRODUCT_SPU_CATEGORY_MUST_BE_LEVEL2
;
/**
* 商品 SPU Manager
...
...
@@ -21,16 +37,46 @@ public class ProductSpuManager {
@Autowired
private
ProductSpuService
productSpuService
;
@Autowired
private
ProductSkuService
productSkuService
;
@Autowired
private
ProductCategoryService
productCategoryService
;
@Autowired
private
ProductAttrService
productAttrService
;
/**
* 创建商品 SPU
* 创建商品 SPU
和 SKU
*
* @param createDTO 创建商品 SPU DTO
* @param createDTO 创建商品 SPU
和 SKU
DTO
* @return 商品 SPU
*/
public
Integer
createProductSpu
(
ProductSpuCreateReqDTO
createDTO
)
{
ProductSpuBO
productSpuBO
=
productSpuService
.
createProductSpu
(
ProductSpuConvert
.
INSTANCE
.
convert
(
createDTO
));
return
productSpuBO
.
getId
();
@Transactional
public
Integer
createProductSpu
(
ProductSpuAndSkuCreateReqDTO
createDTO
)
{
// 校验商品分类分类存在
ProductCategoryBO
categoryBO
=
productCategoryService
.
getProductCategory
(
createDTO
.
getCid
());
if
(
categoryBO
==
null
)
{
// 不存在
throw
ServiceExceptionUtil
.
exception
(
PRODUCT_CATEGORY_NOT_EXISTS
);
}
if
(
ProductCategoryIdEnum
.
ROOT
.
getId
().
equals
(
categoryBO
.
getPid
()))
{
// 商品只能添加到二级分类下
throw
ServiceExceptionUtil
.
exception
(
PRODUCT_SPU_CATEGORY_MUST_BE_LEVEL2
);
}
// 校验规格是否存在
Set
<
Integer
>
attrValueIds
=
new
HashSet
<>();
createDTO
.
getSkus
().
forEach
(
productSkuAddDTO
->
attrValueIds
.
addAll
(
productSkuAddDTO
.
getAttrValueIds
()));
List
<
ProductAttrKeyValueBO
>
attrKeyValueBOs
=
productAttrService
.
validProductAttr
(
attrValueIds
,
true
);
// 创建商品 SKU 对象,并进行校验
List
<
ProductSkuCreateOrUpdateBO
>
skus
=
ProductSpuConvert
.
INSTANCE
.
convert
(
createDTO
.
getSkus
());
productSkuService
.
validProductSku
(
skus
,
attrKeyValueBOs
);
// 插入商品 SPU 记录
ProductSpuCreateBO
spuCreateBO
=
ProductSpuConvert
.
INSTANCE
.
convert
(
createDTO
).
setSort
(
0
);
spuCreateBO
.
setPrice
(
skus
.
stream
().
min
(
Comparator
.
comparing
(
ProductSkuCreateOrUpdateBO:
:
getPrice
)).
get
().
getPrice
());
// 求最小价格
spuCreateBO
.
setQuantity
(
skus
.
stream
().
mapToInt
(
ProductSkuCreateOrUpdateBO:
:
getQuantity
).
sum
());
// 求库存之和
ProductSpuBO
spuBO
=
productSpuService
.
createProductSpu
(
spuCreateBO
);
// 从插入商品 SKU 记录
productSkuService
.
createProductSkus
(
spuBO
.
getId
(),
skus
);
return
spuBO
.
getId
();
}
/**
...
...
@@ -71,7 +117,8 @@ public class ProductSpuManager {
* @return 商品 SPU分页结果
*/
public
PageResult
<
ProductSpuRespDTO
>
pageProductSpu
(
ProductSpuPageReqDTO
pageDTO
)
{
PageResult
<
ProductSpuBO
>
pageResultBO
=
productSpuService
.
pageProductSpu
(
ProductSpuConvert
.
INSTANCE
.
convert
(
pageDTO
));
PageResult
<
ProductSpuBO
>
pageResultBO
=
productSpuService
.
pageProductSpu
(
ProductSpuConvert
.
INSTANCE
.
convert
(
pageDTO
));
return
ProductSpuConvert
.
INSTANCE
.
convertPage
(
pageResultBO
);
}
}
product-service-project/product-service-app/src/main/java/cn/iocoder/mall/productservice/rpc/spu/ProductSpuRpcImpl.java
浏览文件 @
e107b42f
...
...
@@ -3,7 +3,7 @@ package cn.iocoder.mall.productservice.rpc.spu;
import
cn.iocoder.common.framework.vo.CommonResult
;
import
cn.iocoder.common.framework.vo.PageResult
;
import
cn.iocoder.mall.productservice.manager.spu.ProductSpuManager
;
import
cn.iocoder.mall.productservice.rpc.spu.dto.ProductSpuCreateReqDTO
;
import
cn.iocoder.mall.productservice.rpc.spu.dto.ProductSpu
AndSku
CreateReqDTO
;
import
cn.iocoder.mall.productservice.rpc.spu.dto.ProductSpuPageReqDTO
;
import
cn.iocoder.mall.productservice.rpc.spu.dto.ProductSpuRespDTO
;
import
cn.iocoder.mall.productservice.rpc.spu.dto.ProductSpuUpdateReqDTO
;
...
...
@@ -24,7 +24,7 @@ public class ProductSpuRpcImpl implements ProductSpuRpc {
private
ProductSpuManager
productSpuManager
;
@Override
public
CommonResult
<
Integer
>
createProductSpu
(
ProductSpuCreateReqDTO
createDTO
)
{
public
CommonResult
<
Integer
>
createProductSpu
(
ProductSpu
AndSku
CreateReqDTO
createDTO
)
{
return
success
(
productSpuManager
.
createProductSpu
(
createDTO
));
}
...
...
product-service-project/product-service-app/src/main/java/cn/iocoder/mall/productservice/service/attr/ProductAttrService.java
0 → 100644
浏览文件 @
e107b42f
package
cn
.
iocoder
.
mall
.
productservice
.
service
.
attr
;
import
cn.iocoder.common.framework.enums.CommonStatusEnum
;
import
cn.iocoder.common.framework.exception.util.ServiceExceptionUtil
;
import
cn.iocoder.common.framework.util.CollectionUtils
;
import
cn.iocoder.mall.productservice.dal.mysql.dataobject.attr.ProductAttrKeyDO
;
import
cn.iocoder.mall.productservice.dal.mysql.dataobject.attr.ProductAttrValueDO
;
import
cn.iocoder.mall.productservice.dal.mysql.mapper.attr.ProductAttrKeyMapper
;
import
cn.iocoder.mall.productservice.dal.mysql.mapper.attr.ProductAttrValueMapper
;
import
cn.iocoder.mall.productservice.service.attr.bo.ProductAttrKeyValueBO
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Service
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Set
;
import
java.util.stream.Collectors
;
import
static
cn
.
iocoder
.
mall
.
productservice
.
enums
.
ProductErrorCodeConstants
.
PRODUCT_ATTR_KEY_NOT_EXIST
;
import
static
cn
.
iocoder
.
mall
.
productservice
.
enums
.
ProductErrorCodeConstants
.
PRODUCT_ATTR_VALUE_NOT_EXIST
;
@Service
public
class
ProductAttrService
{
@Autowired
private
ProductAttrKeyMapper
productAttrKeyMapper
;
@Autowired
private
ProductAttrValueMapper
productAttrValueMapper
;
public
List
<
ProductAttrKeyValueBO
>
validProductAttr
(
Set
<
Integer
>
productAttrValueIds
,
boolean
validStatus
)
{
// 首先,校验规格 Value
List
<
ProductAttrValueDO
>
attrValues
=
productAttrValueMapper
.
selectBatchIds
(
productAttrValueIds
);
if
(
attrValues
.
size
()
!=
productAttrValueIds
.
size
())
{
throw
ServiceExceptionUtil
.
exception
(
PRODUCT_ATTR_VALUE_NOT_EXIST
);
}
if
(
validStatus
)
{
for
(
ProductAttrValueDO
attrValue
:
attrValues
)
{
// 同时,校验下状态
if
(
CommonStatusEnum
.
DISABLE
.
getValue
().
equals
(
attrValue
.
getStatus
()))
{
throw
ServiceExceptionUtil
.
exception
(
PRODUCT_ATTR_VALUE_NOT_EXIST
);
}
}
}
// 然后,校验规 Key
Set
<
Integer
>
attrKeyIds
=
CollectionUtils
.
convertSet
(
attrValues
,
ProductAttrValueDO:
:
getAttrId
);
List
<
ProductAttrKeyDO
>
attrKeys
=
productAttrKeyMapper
.
selectBatchIds
(
attrKeyIds
);
if
(
attrKeys
.
size
()
!=
attrKeyIds
.
size
())
{
throw
ServiceExceptionUtil
.
exception
(
PRODUCT_ATTR_KEY_NOT_EXIST
);
}
if
(
validStatus
)
{
for
(
ProductAttrKeyDO
attrKey
:
attrKeys
)
{
// 同时,校验下状态
if
(
CommonStatusEnum
.
DISABLE
.
getValue
().
equals
(
attrKey
.
getStatus
()))
{
throw
ServiceExceptionUtil
.
exception
(
PRODUCT_ATTR_KEY_NOT_EXIST
);
}
}
}
// 返回成功
Map
<
Integer
,
ProductAttrKeyDO
>
attrKeyMap
=
CollectionUtils
.
convertMap
(
attrKeys
,
ProductAttrKeyDO:
:
getId
,
attrKeyDO
->
attrKeyDO
);
// ProductAttrDO 的映射,方便查找。
return
attrValues
.
stream
().
map
(
attrValueDO
->
new
ProductAttrKeyValueBO
()
.
setAttrKeyId
(
attrValueDO
.
getAttrId
()).
setAttrKeyName
(
attrKeyMap
.
get
(
attrValueDO
.
getAttrId
()).
getName
())
.
setAttrValueId
(
attrValueDO
.
getId
()).
setAttrValueName
(
attrValueDO
.
getName
()))
.
collect
(
Collectors
.
toList
());
}
}
product
/product-service-api/src/main/java/cn/iocoder/mall/product/api/bo/ProductAttrAndValuePair
BO.java
→
product
-service-project/product-service-app/src/main/java/cn/iocoder/mall/productservice/service/attr/bo/ProductAttrKeyValue
BO.java
浏览文件 @
e107b42f
package
cn
.
iocoder
.
mall
.
product
.
api
.
bo
;
package
cn
.
iocoder
.
mall
.
product
service
.
service
.
attr
.
bo
;
import
lombok.Data
;
import
lombok.experimental.Accessors
;
...
...
@@ -6,26 +6,26 @@ import lombok.experimental.Accessors;
import
java.io.Serializable
;
/**
* 商品规格
明细
BO
* 商品规格
键值对
BO
*/
@Data
@Accessors
(
chain
=
true
)
public
class
ProductAttr
AndValuePair
BO
implements
Serializable
{
public
class
ProductAttr
KeyValue
BO
implements
Serializable
{
/**
* 规格编号
* 规格
Key
编号
*/
private
Integer
attrId
;
private
Integer
attr
Key
Id
;
/**
* 规格
名
* 规格
Key 名字
*/
private
String
attrName
;
private
String
attr
Key
Name
;
/**
* 规格
值
* 规格
Value 编号
*/
private
Integer
attrValueId
;
/**
* 规格
值名
* 规格
Value 名字
*/
private
String
attrValueName
;
...
...
product-service-project/product-service-app/src/main/java/cn/iocoder/mall/productservice/service/sku/ProductSkuService.java
0 → 100644
浏览文件 @
e107b42f
package
cn
.
iocoder
.
mall
.
productservice
.
service
.
sku
;
import
cn.iocoder.common.framework.enums.CommonStatusEnum
;
import
cn.iocoder.common.framework.exception.util.ServiceExceptionUtil
;
import
cn.iocoder.mall.productservice.convert.sku.ProductSkuConvert
;
import
cn.iocoder.mall.productservice.dal.mysql.dataobject.spu.ProductSkuDO
;
import
cn.iocoder.mall.productservice.dal.mysql.mapper.sku.ProductSkuMapper
;
import
cn.iocoder.mall.productservice.service.attr.bo.ProductAttrKeyValueBO
;
import
cn.iocoder.mall.productservice.service.sku.bo.ProductSkuCreateOrUpdateBO
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Service
;
import
java.util.HashSet
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Set
;
import
java.util.stream.Collectors
;
import
static
cn
.
iocoder
.
mall
.
productservice
.
enums
.
ProductErrorCodeConstants
.*;
@Service
public
class
ProductSkuService
{
@Autowired
private
ProductSkuMapper
productSkuMapper
;
public
void
createProductSkus
(
Integer
spuId
,
List
<
ProductSkuCreateOrUpdateBO
>
createBOs
)
{
List
<
ProductSkuDO
>
skus
=
ProductSkuConvert
.
INSTANCE
.
convertList
(
createBOs
);
skus
.
forEach
(
sku
->
{
sku
.
setStatus
(
CommonStatusEnum
.
ENABLE
.
getValue
());
sku
.
setSpuId
(
spuId
);
});
productSkuMapper
.
insertList
(
skus
);
}
public
void
updateProductSkus
(
Integer
spuId
,
List
<
ProductSkuCreateOrUpdateBO
>
createBOs
)
{
}
/**
* 校验 sku 是否合法
*
* @param skuBOs 商品 SKU 添加信息
* @param attrKeyValueBOs 商品规格明细数组
*/
public
void
validProductSku
(
List
<
ProductSkuCreateOrUpdateBO
>
skuBOs
,
List
<
ProductAttrKeyValueBO
>
attrKeyValueBOs
)
{
// 创建 ProductAttrDetailBO 的映射。其中,KEY 为 ProductAttrDetailBO.attrValueId ,即规格值的编号
Map
<
Integer
,
ProductAttrKeyValueBO
>
productAttrDetailBOMap
=
attrKeyValueBOs
.
stream
().
collect
(
Collectors
.
toMap
(
ProductAttrKeyValueBO:
:
getAttrValueId
,
productAttrDetailBO
->
productAttrDetailBO
));
// 1. 先校验,一个 Sku 下,没有重复的规格。校验方式是,遍历每个 Sku ,看看是否有重复的规格 attrId
for
(
ProductSkuCreateOrUpdateBO
sku
:
skuBOs
)
{
Set
<
Integer
>
attrIds
=
sku
.
getAttrValueIds
().
stream
().
map
(
attrValueId
->
productAttrDetailBOMap
.
get
(
attrValueId
).
getAttrKeyId
())
.
collect
(
Collectors
.
toSet
());
if
(
attrIds
.
size
()
!=
sku
.
getAttrValueIds
().
size
())
{
throw
ServiceExceptionUtil
.
exception
(
PRODUCT_SKU_ATTR_CANT_NOT_DUPLICATE
);
}
}
// 2. 再校验,每个 Sku 的规格值的数量,是一致的。
int
attrValueIdsSize
=
skuBOs
.
get
(
0
).
getAttrValueIds
().
size
();
for
(
int
i
=
1
;
i
<
skuBOs
.
size
();
i
++)
{
if
(
attrValueIdsSize
!=
skuBOs
.
get
(
i
).
getAttrValueIds
().
size
())
{
throw
ServiceExceptionUtil
.
exception
(
PRODUCT_SPU_ATTR_NUMBERS_MUST_BE_EQUALS
);
}
}
// 3. 最后校验,每个 Sku 之间不是重复的
Set
<
Set
<
Integer
>>
skuAttrValues
=
new
HashSet
<>();
// 每个元素,都是一个 Sku 的 attrValueId 集合。这样,通过最外层的 Set ,判断是否有重复的.
for
(
ProductSkuCreateOrUpdateBO
sku
:
skuBOs
)
{
if
(!
skuAttrValues
.
add
(
new
HashSet
<>(
sku
.
getAttrValueIds
())))
{
// 添加失败,说明重复
throw
ServiceExceptionUtil
.
exception
(
PRODUCT_SPU_SKU_NOT_DUPLICATE
);
}
}
}
}
product
/product-service-api/src/main/java/cn/iocoder/mall/product/api/dto/ProductSkuAddOrUpdateDT
O.java
→
product
-service-project/product-service-app/src/main/java/cn/iocoder/mall/productservice/service/sku/bo/ProductSkuCreateOrUpdateB
O.java
浏览文件 @
e107b42f
package
cn
.
iocoder
.
mall
.
product
.
api
.
dt
o
;
package
cn
.
iocoder
.
mall
.
product
service
.
service
.
sku
.
b
o
;
import
lombok.Data
;
import
lombok.experimental.Accessors
;
...
...
@@ -8,17 +8,19 @@ import javax.validation.constraints.NotNull;
import
java.util.List
;
/**
* 商品 Sku 添加 DTO
* 商品 SKU 创建或者修改 BO
*
* 注意,目前该对象是
*/
@Data
@Accessors
(
chain
=
true
)
public
class
ProductSku
AddOrUpdateDT
O
{
public
class
ProductSku
CreateOrUpdateB
O
{
/**
* 规格值数组
*/
@NotNull
(
message
=
"规格值数组不能为空"
)
private
List
<
Integer
>
attrs
;
private
List
<
Integer
>
attr
ValueId
s
;
/**
* 价格,单位:分
*/
...
...
product-service-project/product-service-app/src/main/java/cn/iocoder/mall/productservice/service/spu/bo/ProductSpuPageBO.java
浏览文件 @
e107b42f
...
...
@@ -17,6 +17,14 @@ public class ProductSpuPageBO extends PageParam {
* SPU 名字
*/
private
String
name
;
/**
* 分类编号
*/
private
Integer
cid
;
/**
* 是否可见
*/
private
Boolean
visible
;
/**
* 是否有库存
*/
...
...
product-service-project/product-service-app/src/main/resources/mapper/ProductSkuMapper.xml
0 → 100644
浏览文件 @
e107b42f
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper
namespace=
"cn.iocoder.mall.productservice.dal.mysql.mapper.sku.ProductSkuMapper"
>
<insert
id=
"insertList"
useGeneratedKeys=
"true"
keyColumn=
"id"
keyProperty=
"id"
>
INSERT INTO product_sku (
spu_id, status, pic_url, attrs, price,
quantity
) VALUES
<foreach
collection=
"productSkuDOs"
item=
"productSkuDO"
separator=
","
>
(#{productSkuDO.spuId}, #{productSkuDO.status}, #{productSkuDO.picUrl}, #{productSkuDO.attrs}, #{productSkuDO.price},
#{productSkuDO.quantity}
)
</foreach>
</insert>
</mapper>
product/product-biz/src/main/java/cn/iocoder/mall/product/biz/bo/product/ProductAttrAndValuePairBO.java
deleted
100644 → 0
浏览文件 @
be4b34c8
package
cn
.
iocoder
.
mall
.
product
.
biz
.
bo
.
product
;
import
lombok.Data
;
import
lombok.experimental.Accessors
;
import
java.io.Serializable
;
/**
* 商品规格明细 BO
*/
@Data
@Accessors
(
chain
=
true
)
public
class
ProductAttrAndValuePairBO
implements
Serializable
{
/**
* 规格编号
*/
private
Integer
attrId
;
/**
* 规格名
*/
private
String
attrName
;
/**
* 规格值
*/
private
Integer
attrValueId
;
/**
* 规格值名
*/
private
String
attrValueName
;
}
product/product-biz/src/main/java/cn/iocoder/mall/product/biz/dao/attr/ProductAttrMapper.java
deleted
100644 → 0
浏览文件 @
be4b34c8
package
cn
.
iocoder
.
mall
.
product
.
biz
.
dao
.
attr
;
import
cn.iocoder.mall.product.biz.dataobject.attr.ProductAttrDO
;
import
com.baomidou.mybatisplus.core.mapper.BaseMapper
;
import
org.springframework.stereotype.Repository
;
@Repository
public
interface
ProductAttrMapper
extends
BaseMapper
<
ProductAttrDO
>
{
}
\ No newline at end of file
product/product-biz/src/main/java/cn/iocoder/mall/product/biz/dto/product/ProductSkuAddOrUpdateDTO.java
deleted
100644 → 0
浏览文件 @
be4b34c8
package
cn
.
iocoder
.
mall
.
product
.
biz
.
dto
.
product
;
import
lombok.Data
;
import
lombok.experimental.Accessors
;
import
javax.validation.constraints.Min
;
import
javax.validation.constraints.NotNull
;
import
java.util.List
;
/**
* 商品 Sku 添加 DTO
*/
@Data
@Accessors
(
chain
=
true
)
public
class
ProductSkuAddOrUpdateDTO
{
/**
* 规格值数组
*/
@NotNull
(
message
=
"规格值数组不能为空"
)
private
List
<
Integer
>
attrs
;
/**
* 价格,单位:分
*/
@NotNull
(
message
=
"价格不能为空"
)
@Min
(
value
=
1L
,
message
=
"最小价格为 1"
)
private
Integer
price
;
/**
* 库存数量
*/
@NotNull
(
message
=
"库存数量不能为空"
)
@Min
(
value
=
1L
,
message
=
"最小库存为 1"
)
private
Integer
quantity
;
}
product/product-biz/src/main/java/cn/iocoder/mall/product/biz/dto/product/ProductSpuAddDTO.java
deleted
100644 → 0
浏览文件 @
be4b34c8
package
cn
.
iocoder
.
mall
.
product
.
biz
.
dto
.
product
;
import
lombok.Data
;
import
lombok.experimental.Accessors
;
import
javax.validation.constraints.NotEmpty
;
import
javax.validation.constraints.NotNull
;
import
java.util.List
;
/**
* 商品 SPU + SKU 添加 DTO
*/
@Data
@Accessors
(
chain
=
true
)
public
class
ProductSpuAddDTO
{
// ========== 基本信息 =========
/**
* SPU 名字
*/
@NotEmpty
(
message
=
"SPU 名字不能为空"
)
private
String
name
;
/**
* 卖点
*/
@NotEmpty
(
message
=
"卖点不能为空"
)
private
String
sellPoint
;
/**
* 描述
*/
@NotEmpty
(
message
=
"描述不能为空"
)
private
String
description
;
/**
* 分类编号
*/
@NotNull
(
message
=
"分类不能为空"
)
private
Integer
cid
;
/**
* 商品主图地址
*/
@NotNull
(
message
=
"商品主图不能为空"
)
private
List
<
String
>
picUrls
;
// ========== 其他信息 =========
/**
* 是否上架商品(是否可见)。
*
* true 为已上架
* false 为已下架
*/
@NotNull
(
message
=
"是否上架不能为空"
)
private
Boolean
visible
;
// ========== SKU =========
/**
* SKU 数组
*/
@NotNull
(
message
=
"SKU 不能为空"
)
private
List
<
ProductSkuAddOrUpdateDTO
>
skus
;
}
product/product-biz/src/main/java/cn/iocoder/mall/product/biz/dto/sku/ProductSkuAddOrUpdateDTO.java
deleted
100644 → 0
浏览文件 @
be4b34c8
package
cn
.
iocoder
.
mall
.
product
.
biz
.
dto
.
sku
;
import
lombok.Data
;
import
lombok.experimental.Accessors
;
import
javax.validation.constraints.Min
;
import
javax.validation.constraints.NotNull
;
import
java.util.List
;
/**
* 商品 Sku 添加 DTO
*/
@Data
@Accessors
(
chain
=
true
)
public
class
ProductSkuAddOrUpdateDTO
{
/**
* 规格值数组
*/
@NotNull
(
message
=
"规格值数组不能为空"
)
private
List
<
Integer
>
attrs
;
/**
* 价格,单位:分
*/
@NotNull
(
message
=
"价格不能为空"
)
@Min
(
value
=
1L
,
message
=
"最小价格为 1"
)
private
Integer
price
;
/**
* 库存数量
*/
@NotNull
(
message
=
"库存数量不能为空"
)
@Min
(
value
=
1L
,
message
=
"最小库存为 1"
)
private
Integer
quantity
;
}
product/product-biz/src/main/java/cn/iocoder/mall/product/biz/dto/sku/ProductSpuAddDTO.java
deleted
100644 → 0
浏览文件 @
be4b34c8
package
cn
.
iocoder
.
mall
.
product
.
biz
.
dto
.
sku
;
import
lombok.Data
;
import
lombok.experimental.Accessors
;
import
javax.validation.constraints.NotEmpty
;
import
javax.validation.constraints.NotNull
;
import
java.util.List
;
/**
* 商品 SPU + SKU 添加 DTO
*/
@Data
@Accessors
(
chain
=
true
)
// TODO FROM 芋艿 to sunderui && q2118cs:貌似重复了,只要保留一个哈
public
class
ProductSpuAddDTO
{
// ========== 基本信息 =========
/**
* SPU 名字
*/
@NotEmpty
(
message
=
"SPU 名字不能为空"
)
private
String
name
;
/**
* 卖点
*/
@NotEmpty
(
message
=
"卖点不能为空"
)
private
String
sellPoint
;
/**
* 描述
*/
@NotEmpty
(
message
=
"描述不能为空"
)
private
String
description
;
/**
* 分类编号
*/
@NotNull
(
message
=
"分类不能为空"
)
private
Integer
cid
;
/**
* 商品主图地址
*/
@NotNull
(
message
=
"商品主图不能为空"
)
private
List
<
String
>
picUrls
;
// ========== 其他信息 =========
/**
* 是否上架商品(是否可见)。
*
* true 为已上架
* false 为已下架
*/
@NotNull
(
message
=
"是否上架不能为空"
)
private
Boolean
visible
;
// ========== SKU =========
/**
* SKU 数组
*/
@NotNull
(
message
=
"SKU 不能为空"
)
private
List
<
ProductSkuAddOrUpdateDTO
>
skus
;
}
product/product-biz/src/main/java/cn/iocoder/mall/product/biz/dto/sku/ProductSpuUpdateDTO.java
deleted
100644 → 0
浏览文件 @
be4b34c8
package
cn
.
iocoder
.
mall
.
product
.
biz
.
dto
.
sku
;
import
cn.iocoder.mall.product.biz.dto.product.ProductSkuAddOrUpdateDTO
;
import
lombok.Data
;
import
lombok.experimental.Accessors
;
import
javax.validation.constraints.NotEmpty
;
import
javax.validation.constraints.NotNull
;
import
java.util.List
;
/**
* 商品 SPU + SKU 更新 DTO
*/
@Data
@Accessors
(
chain
=
true
)
public
class
ProductSpuUpdateDTO
{
/**
* Spu 编号
*/
@NotNull
(
message
=
"SPU 编号不能为空"
)
private
Integer
id
;
// ========== 基本信息 =========
/**
* SPU 名字
*/
@NotEmpty
(
message
=
"SPU 名字不能为空"
)
private
String
name
;
/**
* 卖点
*/
@NotEmpty
(
message
=
"卖点不能为空"
)
private
String
sellPoint
;
/**
* 描述
*/
@NotEmpty
(
message
=
"描述不能为空"
)
private
String
description
;
/**
* 分类编号
*/
@NotNull
(
message
=
"分类不能为空"
)
private
Integer
cid
;
/**
* 商品主图地址
*/
@NotNull
(
message
=
"商品主图不能为空"
)
private
List
<
String
>
picUrls
;
// ========== 其他信息 =========
/**
* 是否上架商品(是否可见)。
*
* true 为已上架
* false 为已下架
*/
@NotNull
(
message
=
"是否上架不能为空"
)
private
Boolean
visible
;
// ========== SKU =========
/**
* SKU 数组
*/
@NotNull
(
message
=
"SKU 不能为空"
)
private
List
<
ProductSkuAddOrUpdateDTO
>
skus
;
}
product/product-biz/src/main/resources/mapper/ProductSpuMapper.xml
deleted
100644 → 0
浏览文件 @
be4b34c8
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper
namespace=
"cn.iocoder.mall.product.biz.dao.sku.ProductSpuMapper"
>
</mapper>
product/product-service-api/src/main/java/cn/iocoder/mall/product/api/ProductSpuService.java
浏览文件 @
e107b42f
...
...
@@ -22,8 +22,6 @@ public interface ProductSpuService {
*/
List
<
ProductSpuDetailBO
>
getProductSpuDetailListForSync
(
Integer
lastId
,
Integer
limit
);
ProductSpuPageBO
getProductSpuPage
(
ProductSpuPageDTO
productSpuPageDTO
);
List
<
ProductSpuBO
>
getProductSpuSearchList
(
ProductSpuSearchListDTO
productSpuSearchListDTO
);
List
<
ProductSpuBO
>
getProductSpuList
(
Collection
<
Integer
>
ids
);
...
...
product/product-service-api/src/main/java/cn/iocoder/mall/product/api/bo/ProductSpuBO.java
deleted
100644 → 0
浏览文件 @
be4b34c8
package
cn
.
iocoder
.
mall
.
product
.
api
.
bo
;
import
lombok.Data
;
import
lombok.experimental.Accessors
;
import
java.io.Serializable
;
import
java.util.List
;
/**
* 商品 SPU BO
*/
@Data
@Accessors
(
chain
=
true
)
public
class
ProductSpuBO
implements
Serializable
{
/**
* SPU 编号
*/
private
Integer
id
;
// ========== 基本信息 =========
/**
* SPU 名字
*/
private
String
name
;
/**
* 卖点
*/
private
String
sellPoint
;
/**
* 描述
*/
private
String
description
;
/**
* 分类编号
*/
private
Integer
cid
;
/**
* 商品主图地址
*
* 数组,以逗号分隔
*
* 建议尺寸:800*800像素,你可以拖拽图片调整顺序,最多上传15张
*/
private
List
<
String
>
picUrls
;
// ========== 其他信息 =========
/**
* 是否上架商品(是否可见)。
*
* true 为已上架
* false 为已下架
*/
private
Boolean
visible
;
/**
* 排序字段
*/
private
Integer
sort
;
// ========== Sku 相关字段 =========
/**
* 价格
*
* 目前的计算方式是,以 Sku 最小价格为准
*/
private
Integer
price
;
/**
* 库存数量
*
* 目前的计算方式是,以 Sku 库存累加为准
*/
private
Integer
quantity
;
}
product/product-service-api/src/main/java/cn/iocoder/mall/product/api/bo/ProductSpuPageBO.java
deleted
100644 → 0
浏览文件 @
be4b34c8
package
cn
.
iocoder
.
mall
.
product
.
api
.
bo
;
import
lombok.Data
;
import
lombok.experimental.Accessors
;
import
java.io.Serializable
;
import
java.util.List
;
/**
* 商品 SPU 分页 BO
*/
@Data
@Accessors
(
chain
=
true
)
public
class
ProductSpuPageBO
implements
Serializable
{
/**
* Spu 数组
*/
private
List
<
ProductSpuBO
>
list
;
/**
* 总量
*/
private
Integer
total
;
}
product/product-service-api/src/main/java/cn/iocoder/mall/product/api/dto/ProductSpuAddDTO.java
deleted
100644 → 0
浏览文件 @
be4b34c8
package
cn
.
iocoder
.
mall
.
product
.
api
.
dto
;
import
lombok.Data
;
import
lombok.experimental.Accessors
;
import
javax.validation.constraints.NotEmpty
;
import
javax.validation.constraints.NotNull
;
import
java.util.List
;
/**
* 商品 SPU + SKU 添加 DTO
*/
@Data
@Accessors
(
chain
=
true
)
public
class
ProductSpuAddDTO
{
// ========== 基本信息 =========
/**
* SPU 名字
*/
@NotEmpty
(
message
=
"SPU 名字不能为空"
)
private
String
name
;
/**
* 卖点
*/
@NotEmpty
(
message
=
"卖点不能为空"
)
private
String
sellPoint
;
/**
* 描述
*/
@NotEmpty
(
message
=
"描述不能为空"
)
private
String
description
;
/**
* 分类编号
*/
@NotNull
(
message
=
"分类不能为空"
)
private
Integer
cid
;
/**
* 商品主图地址
*/
@NotNull
(
message
=
"商品主图不能为空"
)
private
List
<
String
>
picUrls
;
// ========== 其他信息 =========
/**
* 是否上架商品(是否可见)。
*
* true 为已上架
* false 为已下架
*/
@NotNull
(
message
=
"是否上架不能为空"
)
private
Boolean
visible
;
// ========== SKU =========
/**
* SKU 数组
*/
@NotNull
(
message
=
"SKU 不能为空"
)
private
List
<
ProductSkuAddOrUpdateDTO
>
skus
;
}
product/product-service-api/src/main/java/cn/iocoder/mall/product/api/dto/ProductSpuPageDTO.java
deleted
100644 → 0
浏览文件 @
be4b34c8
package
cn
.
iocoder
.
mall
.
product
.
api
.
dto
;
import
lombok.Data
;
import
lombok.experimental.Accessors
;
import
javax.validation.constraints.NotNull
;
/**
* 商品 Spu 分页 DTO
*/
@Data
@Accessors
(
chain
=
true
)
public
class
ProductSpuPageDTO
{
/**
* 商品名
*
* 模糊匹配
*/
private
String
name
;
/**
* 分类编号
*/
private
Integer
cid
;
/**
* 是否可见
*/
private
Boolean
visible
;
/**
* 是否有库存
*
* 允许为空。空时,不进行筛选
*/
private
Boolean
hasQuantity
;
@NotNull
(
message
=
"页码不能为空"
)
private
Integer
pageNo
;
@NotNull
(
message
=
"每页条数不能为空"
)
private
Integer
pageSize
;
}
product/product-service-impl/src/main/java/cn/iocoder/mall/product/dao/ProductSpuMapper.java
浏览文件 @
e107b42f
...
...
@@ -10,10 +10,6 @@ import java.util.List;
@Repository
public
interface
ProductSpuMapper
{
ProductSpuDO
selectById
(
Integer
id
);
List
<
ProductSpuDO
>
selectByIds
(
@Param
(
"ids"
)
Collection
<
Integer
>
ids
);
/**
* 获得大于 id 的商品编号数组
*
...
...
@@ -24,21 +20,4 @@ public interface ProductSpuMapper {
List
<
Integer
>
selectIdListByIdGt
(
@Param
(
"id"
)
Integer
id
,
@Param
(
"limit"
)
Integer
limit
);
void
insert
(
ProductSpuDO
productSpuDO
);
void
update
(
ProductSpuDO
productSpuDO
);
// TODO 芋艿,需要捉摸下,怎么优化下。参数有点多
List
<
ProductSpuDO
>
selectListByNameLikeOrderBySortAsc
(
@Param
(
"name"
)
String
name
,
@Param
(
"cid"
)
Integer
cid
,
@Param
(
"visible"
)
Boolean
visible
,
@Param
(
"hasQuantity"
)
Boolean
hasQuantity
,
@Param
(
"offset"
)
Integer
offset
,
@Param
(
"limit"
)
Integer
limit
);
Integer
selectCountByNameLike
(
@Param
(
"name"
)
String
name
,
@Param
(
"cid"
)
Integer
cid
,
@Param
(
"hasQuantity"
)
Boolean
hasQuantity
,
@Param
(
"visible"
)
Boolean
visible
);
}
product/product-service-impl/src/main/java/cn/iocoder/mall/product/service/ProductAttrServiceImpl.java
浏览文件 @
e107b42f
...
...
@@ -35,39 +35,6 @@ public class ProductAttrServiceImpl implements ProductAttrService {
@Autowired
private
ProductAttrValueMapper
productAttrValueMapper
;
public
List
<
ProductAttrAndValuePairBO
>
validProductAttrAndValue
(
Set
<
Integer
>
productAttrValueIds
,
boolean
validStatus
)
{
// 首先,校验规格值
List
<
ProductAttrValueDO
>
attrValues
=
productAttrValueMapper
.
selectListByIds
(
productAttrValueIds
);
if
(
attrValues
.
size
()
!=
productAttrValueIds
.
size
())
{
throw
ServiceExceptionUtil
.
exception
(
ProductErrorCodeEnum
.
PRODUCT_ATTR_VALUE_NOT_EXIST
.
getCode
());
}
if
(
validStatus
)
{
for
(
ProductAttrValueDO
attrValue
:
attrValues
)
{
// 同时,校验下状态
if
(
ProductAttrConstants
.
ATTR_STATUS_DISABLE
.
equals
(
attrValue
.
getStatus
()))
{
throw
ServiceExceptionUtil
.
exception
(
ProductErrorCodeEnum
.
PRODUCT_ATTR_VALUE_NOT_EXIST
.
getCode
());
}
}
}
// 然后,校验规格
Set
<
Integer
>
attrIds
=
attrValues
.
stream
().
map
(
ProductAttrValueDO:
:
getAttrId
).
collect
(
Collectors
.
toSet
());
List
<
ProductAttrDO
>
attrs
=
productAttrMapper
.
selectListByIds
(
attrIds
);
if
(
attrs
.
size
()
!=
attrIds
.
size
())
{
throw
ServiceExceptionUtil
.
exception
(
ProductErrorCodeEnum
.
PRODUCT_ATTR_NOT_EXIST
.
getCode
());
}
if
(
validStatus
)
{
for
(
ProductAttrDO
attr
:
attrs
)
{
// 同时,校验下状态
if
(
ProductAttrConstants
.
ATTR_VALUE_STATUS_DISABLE
.
equals
(
attr
.
getStatus
()))
{
throw
ServiceExceptionUtil
.
exception
(
ProductErrorCodeEnum
.
PRODUCT_ATTR_NOT_EXIST
.
getCode
());
}
}
}
// 返回成功
Map
<
Integer
,
ProductAttrDO
>
attrMap
=
attrs
.
stream
().
collect
(
Collectors
.
toMap
(
ProductAttrDO:
:
getId
,
productAttrDO
->
productAttrDO
));
// ProductAttrDO 的映射,方便查找。
return
attrValues
.
stream
().
map
(
productAttrValueDO
->
new
ProductAttrAndValuePairBO
()
.
setAttrId
(
productAttrValueDO
.
getAttrId
()).
setAttrName
(
attrMap
.
get
(
productAttrValueDO
.
getAttrId
()).
getName
())
.
setAttrValueId
(
productAttrValueDO
.
getId
()).
setAttrValueName
(
productAttrValueDO
.
getName
())).
collect
(
Collectors
.
toList
());
}
@Override
public
ProductAttrPageBO
getProductAttrPage
(
ProductAttrPageDTO
productAttrPageDTO
)
{
ProductAttrPageBO
productAttrPageBO
=
new
ProductAttrPageBO
();
...
...
product/product-service-impl/src/main/java/cn/iocoder/mall/product/service/ProductSpuServiceImpl.java
浏览文件 @
e107b42f
...
...
@@ -96,45 +96,6 @@ public class ProductSpuServiceImpl implements ProductSpuService {
return
productSpuDetailBO
;
}
@SuppressWarnings
(
"Duplicates"
)
@Transactional
public
ProductSpuDetailBO
addProductSpu0
(
Integer
adminId
,
ProductSpuAddDTO
productSpuAddDTO
)
{
// 校验商品分类分类存在
ProductCategoryDO
category
=
productCategoryService
.
validProductCategory
(
productSpuAddDTO
.
getCid
());
if
(
ProductCategoryConstants
.
PID_ROOT
.
equals
(
category
.
getPid
()))
{
// 商品只能添加到二级分类下
throw
ServiceExceptionUtil
.
exception
(
ProductErrorCodeEnum
.
PRODUCT_SPU_CATEGORY_MUST_BE_LEVEL2
.
getCode
());
}
// 校验规格是否存在
Set
<
Integer
>
productAttrValueIds
=
new
HashSet
<>();
productSpuAddDTO
.
getSkus
().
forEach
(
productSkuAddDTO
->
productAttrValueIds
.
addAll
(
productSkuAddDTO
.
getAttrs
()));
List
<
ProductAttrAndValuePairBO
>
attrAndValuePairList
=
productAttrService
.
validProductAttrAndValue
(
productAttrValueIds
,
true
);
// 读取规格时,需要考虑规格是否被禁用
// 保存 Spu
ProductSpuDO
spu
=
ProductSpuConvert
.
INSTANCE
.
convert
(
productSpuAddDTO
)
.
setPicUrls
(
StringUtil
.
join
(
productSpuAddDTO
.
getPicUrls
(),
","
))
.
setSort
(
0
);
// 排序为 0
spu
.
setCreateTime
(
new
Date
());
spu
.
setDeleted
(
DeletedStatusEnum
.
DELETED_NO
.
getValue
());
initSpuFromSkus
(
spu
,
productSpuAddDTO
.
getSkus
());
// 初始化 sku 相关信息到 spu 中
productSpuMapper
.
insert
(
spu
);
// 保存 Sku
List
<
ProductSkuDO
>
skus
=
productSpuAddDTO
.
getSkus
().
stream
().
map
(
productSkuAddDTO
->
{
ProductSkuDO
sku
=
ProductSpuConvert
.
INSTANCE
.
convert
(
productSkuAddDTO
)
.
setSpuId
(
spu
.
getId
())
.
setStatus
(
ProductSpuConstants
.
SKU_STATUS_ENABLE
)
.
setAttrs
(
StringUtil
.
join
(
productSkuAddDTO
.
getAttrs
(),
","
));
sku
.
setCreateTime
(
new
Date
());
sku
.
setDeleted
(
DeletedStatusEnum
.
DELETED_NO
.
getValue
());
return
sku
;
}).
collect
(
Collectors
.
toList
());
// 校验 Sku 规格
validProductSku
(
productSpuAddDTO
.
getSkus
(),
attrAndValuePairList
);
// 插入 SKU 到数据库
productSkuMapper
.
insertList
(
skus
);
// 返回成功
return
ProductSpuConvert
.
INSTANCE
.
convert2
(
spu
,
skus
,
attrAndValuePairList
,
category
);
}
@Override
public
void
updateProductSpu
(
Integer
adminId
,
ProductSpuUpdateDTO
productSpuUpdateDTO
)
{
// 更新商品
...
...
@@ -276,43 +237,6 @@ public class ProductSpuServiceImpl implements ProductSpuService {
return
ProductSpuConvert
.
INSTANCE
.
convert3
(
skus
,
spus
,
attrAndValuePairList
);
}
/**
* 校验 sku 是否合法
*
* @param productSkuAddDTOs sku 添加或修改信息
* @param productAttrDetailBOs 商品规格明细数组
* @return 是否校验通过
*/
private
Boolean
validProductSku
(
List
<
ProductSkuAddOrUpdateDTO
>
productSkuAddDTOs
,
List
<
ProductAttrAndValuePairBO
>
productAttrDetailBOs
)
{
// 创建 ProductAttrDetailBO 的映射。其中,KEY 为 ProductAttrDetailBO.attrValueId ,即规格值的编号
Map
<
Integer
,
ProductAttrAndValuePairBO
>
productAttrDetailBOMap
=
productAttrDetailBOs
.
stream
().
collect
(
Collectors
.
toMap
(
ProductAttrAndValuePairBO:
:
getAttrValueId
,
productAttrDetailBO
->
productAttrDetailBO
));
// 1. 先校验,一个 Sku 下,没有重复的规格。校验方式是,遍历每个 Sku ,看看是否有重复的规格 attrId
for
(
ProductSkuAddOrUpdateDTO
sku
:
productSkuAddDTOs
)
{
Set
<
Integer
>
attrIds
=
sku
.
getAttrs
().
stream
().
map
(
attrValueId
->
productAttrDetailBOMap
.
get
(
attrValueId
).
getAttrId
())
.
collect
(
Collectors
.
toSet
());
if
(
attrIds
.
size
()
!=
sku
.
getAttrs
().
size
())
{
throw
ServiceExceptionUtil
.
exception
(
ProductErrorCodeEnum
.
PRODUCT_SKU_ATTR_CANT_NOT_DUPLICATE
.
getCode
());
}
}
// 2. 再校验,每个 Sku 的规格值的数量,是一致的。
int
attrSize
=
productSkuAddDTOs
.
get
(
0
).
getAttrs
().
size
();
for
(
int
i
=
1
;
i
<
productSkuAddDTOs
.
size
();
i
++)
{
if
(
attrSize
!=
productSkuAddDTOs
.
get
(
i
).
getAttrs
().
size
())
{
throw
ServiceExceptionUtil
.
exception
(
ProductErrorCodeEnum
.
PRODUCT_SPU_ATTR_NUMBERS_MUST_BE_EQUALS
.
getCode
());
}
}
// 3. 最后校验,每个 Sku 之间不是重复的
Set
<
Set
<
Integer
>>
skuAttrValues
=
new
HashSet
<>();
// 每个元素,都是一个 Sku 的 attrValueId 集合。这样,通过最外层的 Set ,判断是否有重复的.
for
(
ProductSkuAddOrUpdateDTO
sku
:
productSkuAddDTOs
)
{
if
(!
skuAttrValues
.
add
(
new
HashSet
<>(
sku
.
getAttrs
())))
{
// 添加失败,说明重复
throw
ServiceExceptionUtil
.
exception
(
ProductErrorCodeEnum
.
PRODUCT_SPU_SKU__NOT_DUPLICATE
.
getCode
());
}
}
// 校验通过
return
true
;
}
/**
* 获得 sku 数组中,指定规格的 sku
*
...
...
@@ -335,18 +259,6 @@ public class ProductSpuServiceImpl implements ProductSpuService {
return
null
;
}
/**
* 根据 sku 数组,计算相关的字段到 spu 中。
*
* @param spu spu
* @param skus sku 数组
*/
private
void
initSpuFromSkus
(
ProductSpuDO
spu
,
List
<
ProductSkuAddOrUpdateDTO
>
skus
)
{
assert
skus
.
size
()
>
0
;
// 写个断言,避免下面警告
spu
.
setPrice
(
skus
.
stream
().
min
(
Comparator
.
comparing
(
ProductSkuAddOrUpdateDTO:
:
getPrice
)).
get
().
getPrice
());
// 求最小价格
spu
.
setQuantity
(
skus
.
stream
().
mapToInt
(
ProductSkuAddOrUpdateDTO:
:
getQuantity
).
sum
());
// 求库存之和
}
private
boolean
sendProductUpdateMessage
(
Integer
id
)
{
// 创建 Message 对象
ProductUpdateMessage
message
=
new
ProductUpdateMessage
().
setId
(
id
);
...
...
product/product-service-impl/src/main/resources/mapper/ProductSpuMapper.xml
浏览文件 @
e107b42f
...
...
@@ -8,25 +8,6 @@
create_time
</sql>
<select
id=
"selectById"
parameterType=
"Integer"
resultType=
"ProductSpuDO"
>
SELECT
<include
refid=
"FIELDS"
/>
FROM product_spu
WHERE id = #{id}
AND deleted = 0
</select>
<select
id=
"selectByIds"
resultType=
"ProductSpuDO"
>
SELECT
<include
refid=
"FIELDS"
/>
FROM product_spu
WHERE id IN
<foreach
item=
"id"
collection=
"ids"
separator=
","
open=
"("
close=
")"
index=
""
>
#{id}
</foreach>
AND deleted = 0
</select>
<select
id=
"selectIdListByIdGt"
parameterType=
"Integer"
resultType=
"Integer"
>
SELECT
<include
refid=
"FIELDS"
/>
...
...
@@ -41,105 +22,4 @@
LIMIT #{limit}
</select>
<insert
id=
"insert"
parameterType=
"ProductSpuDO"
useGeneratedKeys=
"true"
keyColumn=
"id"
keyProperty=
"id"
>
INSERT INTO product_spu (
name, sell_point, description, cid, pic_urls,
visible, sort, price, quantity,
deleted, create_time
) VALUES (
#{name}, #{sellPoint}, #{description}, #{cid}, #{picUrls},
#{visible}, #{sort}, #{price}, #{quantity},
#{deleted}, #{createTime}
)
</insert>
<update
id=
"update"
parameterType=
"ProductSpuDO"
>
UPDATE product_spu
<set>
<if
test=
"name != null"
>
name = #{name},
</if>
<if
test=
"sellPoint != null"
>
sell_point = #{sellPoint},
</if>
<if
test=
"description != null"
>
description = #{description},
</if>
<if
test=
"cid != null"
>
cid = #{cid},
</if>
<if
test=
"picUrls != null"
>
pic_urls = #{picUrls},
</if>
<if
test=
"visible != null"
>
visible = #{visible},
</if>
<if
test=
"price != null"
>
price = #{price},
</if>
<if
test=
"quantity != null"
>
quantity = #{quantity},
</if>
<if
test=
"sort != null"
>
sort = #{sort},
</if>
<if
test=
"deleted != null"
>
deleted = #{deleted}
</if>
</set>
WHERE id = #{id}
</update>
<select
id=
"selectListByNameLikeOrderBySortAsc"
resultType=
"ProductSpuDO"
>
SELECT
<include
refid=
"FIELDS"
/>
FROM product_spu
<where>
<if
test=
"name != null"
>
name LIKE "%"#{name}"%"
</if>
<if
test=
"cid != null"
>
AND cid = #{cid}
</if>
<if
test=
"visible != null"
>
AND visible = #{visible}
</if>
<if
test=
"hasQuantity == true"
>
AND quantity > 0
</if>
<if
test=
"hasQuantity == false"
>
AND quantity = 0
</if>
AND deleted = 0
</where>
ORDER BY sort ASC
<if
test=
"offset != null and limit != null"
>
LIMIT #{offset}, #{limit}
</if>
</select>
<select
id=
"selectCountByNameLike"
resultType=
"Integer"
>
SELECT
COUNT(1)
FROM product_spu
<where>
<if
test=
"name != null"
>
name LIKE "%"#{name}"%"
</if>
<if
test=
"cid != null"
>
AND cid = #{cid}
</if>
<if
test=
"visible != null"
>
AND visible = #{visible}
</if>
<if
test=
"hasQuantity == true"
>
AND quantity > 0
</if>
<if
test=
"hasQuantity == false"
>
AND quantity = 0
</if>
AND deleted = 0
</where>
</select>
</mapper>
product/product-service-impl/src/main/resources/mapper/UserProductSpuCollectionsMapper.xml
deleted
100644 → 0
浏览文件 @
be4b34c8
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper
namespace=
"cn.iocoder.mall.product.dao.UserProductSpuCollectionsMapper"
>
<sql
id=
"FIELDS"
>
id, user_id, nickname, spu_id, spu_name,
spu_image,sell_point,price, create_time, update_time,
deleted
</sql>
<select
id=
"selectById"
parameterType=
"Integer"
resultType=
"UserProductSpuCollectionsDO"
>
SELECT
<include
refid=
"FIELDS"
/>
FROM user_spu_collections
WHERE id = #{id}
AND deleted = 0
</select>
<select
id=
"selectListByUser"
resultType=
"UserProductSpuCollectionsDO"
>
SELECT
<include
refid=
"FIELDS"
/>
FROM user_spu_collections
<where>
user_id = #{userId} AND deleted = 0
</where>
<if
test=
"offset != null and limit != null"
>
LIMIT #{offset}, #{limit}
</if>
</select>
<select
id=
"selectCountByUser"
resultType=
"Integer"
>
SELECT
COUNT(1)
FROM user_spu_collections
<where>
user_id = #{userId} AND deleted = 0
</where>
</select>
</mapper>
product/product-service-impl/src/main/resources/mybatis-config.xml
deleted
100644 → 0
浏览文件 @
be4b34c8
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<!-- 使用驼峰命名法转换字段。 -->
<setting
name=
"mapUnderscoreToCamelCase"
value=
"true"
/>
</settings>
<typeAliases>
<typeAlias
alias=
"Integer"
type=
"java.lang.Integer"
/>
<typeAlias
alias=
"Long"
type=
"java.lang.Long"
/>
<typeAlias
alias=
"HashMap"
type=
"java.util.HashMap"
/>
<typeAlias
alias=
"LinkedHashMap"
type=
"java.util.LinkedHashMap"
/>
<typeAlias
alias=
"ArrayList"
type=
"java.util.ArrayList"
/>
<typeAlias
alias=
"LinkedList"
type=
"java.util.LinkedList"
/>
</typeAliases>
</configuration>
\ No newline at end of file
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论