Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
Y
yudao-cloud
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
hblj
yudao-cloud
Commits
1c5f413c
提交
1c5f413c
authored
4月 25, 2019
作者:
sin
浏览文件
操作
浏览文件
下载
差异文件
Merge remote-tracking branch 'origin/master'
上级
718554bc
6fb6f52b
全部展开
隐藏空白字符变更
内嵌
并排
正在显示
43 个修改的文件
包含
510 行增加
和
133 行删除
+510
-133
DateUtil.java
.../main/java/cn/iocoder/common/framework/util/DateUtil.java
+17
-0
search.js
mobile-web/src/api/search.js
+10
-0
productcard.vue
mobile-web/src/components/common/productcard.vue
+0
-6
list.vue
mobile-web/src/page/product/list.vue
+55
-15
search.vue
mobile-web/src/page/product/search.vue
+0
-0
OrderController.java
...l/order/application/controller/users/OrderController.java
+1
-0
OrderServiceImpl.java
...a/cn/iocoder/mall/order/biz/service/OrderServiceImpl.java
+13
-4
PayTransactionPaySuccessMessage.java
...mall/pay/api/message/PayTransactionPaySuccessMessage.java
+5
-8
MQConstant.java
...ain/java/cn/iocoder/mall/pay/biz/constant/MQConstant.java
+0
-14
PayTransactionConvert.java
...n/iocoder/mall/pay/biz/convert/PayTransactionConvert.java
+2
-3
PayTransactionPaySuccessConsumer.java
...der/mall/pay/biz/mq/PayTransactionPaySuccessConsumer.java
+3
-3
PayTransactionNotifyJob.java
...coder/mall/pay/biz/scheduler/PayTransactionNotifyJob.java
+3
-4
PayServiceImpl.java
.../java/cn/iocoder/mall/pay/biz/service/PayServiceImpl.java
+2
-2
UsersProductSpuController.java
...plication/controller/users/UsersProductSpuController.java
+1
-0
ProductCategoryService.java
...a/cn/iocoder/mall/product/api/ProductCategoryService.java
+10
-2
ProductUpdateMessage.java
...ocoder/mall/product/api/message/ProductUpdateMessage.java
+20
-0
pom.xml
product/product-service-impl/pom.xml
+5
-0
ProductCategoryMapper.java
...va/cn/iocoder/mall/product/dao/ProductCategoryMapper.java
+4
-2
ProductCategoryServiceImpl.java
...oder/mall/product/service/ProductCategoryServiceImpl.java
+7
-0
ProductSpuServiceImpl.java
...n/iocoder/mall/product/service/ProductSpuServiceImpl.java
+35
-4
application.yaml
...t-service-impl/src/main/resources/config/application.yaml
+8
-2
ProductCategoryMapper.xml
...-impl/src/main/resources/mapper/ProductCategoryMapper.xml
+12
-2
UsersCouponCardVO.java
...all/promotion/application/vo/users/UsersCouponCardVO.java
+0
-5
CouponService.java
...ain/java/cn/iocoder/mall/promotion/api/CouponService.java
+1
-3
CouponCardBO.java
...n/java/cn/iocoder/mall/promotion/api/bo/CouponCardBO.java
+0
-12
PromotionErrorCodeEnum.java
...r/mall/promotion/api/constant/PromotionErrorCodeEnum.java
+2
-0
CouponCardMapper.java
...a/cn/iocoder/mall/promotion/biz/dao/CouponCardMapper.java
+4
-0
CouponCardDO.java
...n/iocoder/mall/promotion/biz/dataobject/CouponCardDO.java
+8
-8
CouponServiceImpl.java
...iocoder/mall/promotion/biz/service/CouponServiceImpl.java
+41
-3
CouponCardMapper.xml
...rvice-impl/src/main/resources/mapper/CouponCardMapper.xml
+17
-9
SearchApplication.java
...cn/iocoder/mall/search/application/SearchApplication.java
+2
-0
UsersProductSearchController.java
...cation/controller/users/UsersProductSearchController.java
+19
-8
ProductSearchService.java
...java/cn/iocoder/mall/search/api/ProductSearchService.java
+14
-2
ProductBO.java
...rc/main/java/cn/iocoder/mall/search/api/bo/ProductBO.java
+1
-1
ProductConditionBO.java
...ava/cn/iocoder/mall/search/api/bo/ProductConditionBO.java
+35
-0
ProductPageBO.java
...ain/java/cn/iocoder/mall/search/api/bo/ProductPageBO.java
+2
-2
ProductConditionDTO.java
...a/cn/iocoder/mall/search/api/dto/ProductConditionDTO.java
+29
-0
pom.xml
search/search-service-impl/pom.xml
+5
-0
ProductSearchConvert.java
...iocoder/mall/search/biz/convert/ProductSearchConvert.java
+2
-2
ProductRepository.java
...ava/cn/iocoder/mall/search/biz/dao/ProductRepository.java
+5
-3
PayTransactionPaySuccessConsumer.java
.../mall/search/biz/mq/PayTransactionPaySuccessConsumer.java
+28
-0
ProductSearchServiceImpl.java
...der/mall/search/biz/service/ProductSearchServiceImpl.java
+75
-3
application.yaml
...h-service-impl/src/main/resources/config/application.yaml
+7
-1
没有找到文件。
common/common-framework/src/main/java/cn/iocoder/common/framework/util/DateUtil.java
浏览文件 @
1c5f413c
package
cn
.
iocoder
.
common
.
framework
.
util
;
import
org.springframework.util.Assert
;
import
java.text.SimpleDateFormat
;
import
java.util.Calendar
;
import
java.util.Date
;
...
...
@@ -116,4 +118,19 @@ public class DateUtil {
calendar
.
set
(
Calendar
.
MILLISECOND
,
milliSecond
);
}
/**
* 判断当前时间,是否在该时间范围内
*
* @param beginTime 开始时间
* @param endTime 结束时间
* @return 是否在
*/
public
static
boolean
isBetween
(
Date
beginTime
,
Date
endTime
)
{
Assert
.
notNull
(
beginTime
,
"开始时间不能为空"
);
Assert
.
notNull
(
endTime
,
"结束时间不能为空"
);
Date
now
=
new
Date
();
return
beginTime
.
getTime
()
<=
now
.
getTime
()
&&
now
.
getTime
()
<=
endTime
.
getTime
();
}
}
mobile-web/src/api/search.js
浏览文件 @
1c5f413c
...
...
@@ -14,3 +14,13 @@ export function getProductPage({cid, keyword, pageNo, pageSize, sortField, sortO
}
});
}
export
function
getProductCondition
({
keyword
})
{
return
request
({
url
:
'/search-api/users/product/condition'
,
method
:
'get'
,
params
:
{
keyword
,
}
});
}
mobile-web/src/components/common/productcard.vue
浏览文件 @
1c5f413c
...
...
@@ -9,16 +9,10 @@
>
<template
slot=
"thumb"
>
<img
:src=
"product.picUrls && product.picUrls ? product.picUrls[0] : ''"
/>
<!-- TODO 芋艿 暂时去掉 -->
<!--
<p
v-if=
"product.imageTag!=null&&product.imageTag!=''"
class=
"image_tag"
>
{{
product
.
imageTag
}}
</p>
-->
</
template
>
<
template
slot=
"tags"
>
<p
class=
"price"
v-if=
"product.buyPrice || product.price"
>
¥
<span>
{{
product
.
buyPrice
?
product
.
buyPrice
/
100.00
:
product
.
price
/
100.00
}}
</span>
<!-- TODO 芋艿 暂时去掉 -->
<!--
<van-tag
v-if=
"product.tags!=null"
v-for=
"tag in product.tags"
:key=
"tag"
plain
type=
"danger"
>
-->
<!--
{{
tag
}}
-->
<!--
</van-tag>
-->
<van-tag
v-if=
"product.promotionActivityTitle"
plain
type=
"danger"
>
{{
product
.
promotionActivityTitle
}}
</van-tag>
...
...
mobile-web/src/page/product/list.vue
浏览文件 @
1c5f413c
...
...
@@ -8,14 +8,26 @@
<van-tab
v-for=
"category in childCategories"
:title=
"category.name"
/>
</van-tabs>
<div
v-for=
"(product,i) in products"
:key=
"i"
>
<product-card
:product=
'product'
@
click=
"showProduct(product)"
/>
</div>
<!--
<div
v-for=
"(product,i) in products"
:key=
"i"
>
-->
<!--
<product-card
:product=
'product'
@
click=
"showProduct(product)"
/>
-->
<!--
</div>
-->
<van-list
v-model=
"loading"
:finished=
"finished"
finished-text=
"没有更多了"
@
load=
"onLoad"
>
<div
v-for=
"(product,i) in products"
:key=
"i"
>
<product-card
:product=
'product'
@
click=
"showProduct(product)"
/>
</div>
</van-list>
</div>
</
template
>
<
script
>
import
{
getProductCategoryList
,
getProductSpuPage
}
from
'../../api/product'
;
import
{
getProductPage
}
from
"../../api/search"
;
export
default
{
data
()
{
...
...
@@ -28,8 +40,14 @@ export default {
id
:
parseInt
(
this
.
$route
.
query
.
cidSecond
),
},
childCategories
:
[],
active
:
2
,
active
:
-
1
,
products
:
[],
page
:
0
,
pageSize
:
10
,
loading
:
false
,
finished
:
false
,
};
},
methods
:
{
...
...
@@ -41,18 +59,40 @@ export default {
this
.
active
=
key
;
// 加载商品
this
.
products
=
[];
this
.
loadProductList
(
this
.
childCategories
[
key
].
id
);
// 加载商品
this
.
loadProductList
(
this
.
childCategories
[
key
].
id
,
1
);
},
loadProductList
(
categoryId
)
{
// 设置当前选中的分类
loadProductList
(
categoryId
,
page
)
{
this
.
childCategory
.
id
=
categoryId
;
// 读取商品
// alert('商品分类:' + categoryId);
let
response
=
getProductSpuPage
(
categoryId
);
response
.
then
(
data
=>
{
this
.
products
.
push
(...
data
.
spus
);
})
}
getProductPage
({
pageNo
:
page
,
pageSize
:
this
.
pageSize
,
cid
:
this
.
childCategory
.
id
,
}).
then
(
data
=>
{
this
.
handleData
(
page
,
data
);
});
},
onLoad
()
{
// debugger;
// 进入下一页
let
page
=
this
.
page
+
1
;
// 加载商品
this
.
loadProductList
(
this
.
childCategory
.
id
,
page
);
},
handleData
(
page
,
data
)
{
this
.
loading
=
true
;
// 设置下页面
this
.
page
=
page
;
// 数据保存到 list 中
this
.
products
.
push
(...
data
.
list
);
// 判断页数
if
(
this
.
products
.
length
>=
data
.
total
)
{
this
.
finished
=
true
;
}
// 标记不在加载中
this
.
loading
=
false
;
},
},
mounted
()
{
let
response
=
getProductCategoryList
(
this
.
rootCategory
.
id
);
...
...
@@ -70,7 +110,7 @@ export default {
}
}
// 加载商品列表
this
.
loadProductList
(
this
.
childCategory
.
id
);
//
this.loadProductList(this.childCategory.id);
});
}
};
...
...
mobile-web/src/page/product/search.vue
浏览文件 @
1c5f413c
差异被折叠。
点击展开。
order/order-application/src/main/java/cn/iocoder/mall/order/application/controller/users/OrderController.java
浏览文件 @
1c5f413c
...
...
@@ -134,4 +134,5 @@ public class OrderController {
}
return
commonResult
;
}
}
order/order-service-impl/src/main/java/cn/iocoder/mall/order/biz/service/OrderServiceImpl.java
浏览文件 @
1c5f413c
...
...
@@ -18,6 +18,7 @@ import cn.iocoder.mall.pay.api.bo.PayTransactionBO;
import
cn.iocoder.mall.pay.api.dto.PayTransactionCreateDTO
;
import
cn.iocoder.mall.product.api.ProductSpuService
;
import
cn.iocoder.mall.product.api.bo.ProductSkuDetailBO
;
import
cn.iocoder.mall.promotion.api.CouponService
;
import
cn.iocoder.mall.user.api.UserAddressService
;
import
cn.iocoder.mall.user.api.bo.UserAddressBO
;
import
com.alibaba.dubbo.config.annotation.Reference
;
...
...
@@ -61,14 +62,17 @@ public class OrderServiceImpl implements OrderService {
@Autowired
private
OrderReturnMapper
orderReturnMapper
;
@Reference
private
ProductSpuService
productSpuService
;
@Autowired
private
CartServiceImpl
cartService
;
@Reference
@Reference
(
validation
=
"true"
)
private
ProductSpuService
productSpuService
;
@Reference
(
validation
=
"true"
)
private
UserAddressService
userAddressService
;
@Reference
(
validation
=
"true"
)
private
PayTransactionService
payTransactionService
;
@Reference
(
validation
=
"true"
)
private
CouponService
couponService
;
@Override
public
CommonResult
<
OrderPageBO
>
getOrderPage
(
OrderQueryDTO
orderQueryDTO
)
{
...
...
@@ -253,7 +257,12 @@ public class OrderServiceImpl implements OrderService {
.
setPresentTotal
(
priceItem
.
getPresentTotal
());
}
// TODO 芋艿,标记优惠劵使用
// 标记优惠劵已使用
CommonResult
<
Boolean
>
useCouponCardResult
=
couponService
.
useCouponCard
(
userId
,
orderCreateDTO
.
getCouponCardId
());
if
(
useCouponCardResult
.
isError
())
{
return
CommonResult
.
error
(
useCouponCardResult
);
}
// TODO 芋艿,扣除库存
// order
...
...
pay/pay-service-
impl/src/main/java/cn/iocoder/mall/pay/biz/mq
/PayTransactionPaySuccessMessage.java
→
pay/pay-service-
api/src/main/java/cn/iocoder/mall/pay/api/message
/PayTransactionPaySuccessMessage.java
浏览文件 @
1c5f413c
package
cn
.
iocoder
.
mall
.
pay
.
biz
.
mq
;
import
cn.iocoder.mall.pay.biz.dataobject.PayTransactionDO
;
package
cn
.
iocoder
.
mall
.
pay
.
api
.
message
;
/**
*
{@link cn.iocoder.mall.pay.biz.constant.MQConstant#TOPIC_PAY_TRANSACTION_PAY_SUCCESS}
的消息对象
*
支付交易单支付成功
的消息对象
*/
public
class
PayTransactionPaySuccessMessage
{
public
static
final
String
TOPIC
=
"PAY_TRANSACTION_PAY_SUCCESS"
;
/**
* 编号,自增
*/
private
Integer
id
;
/**
* 交易编号
*
* {@link PayTransactionDO#getId()}
*/
private
Integer
transactionId
;
/**
...
...
@@ -88,4 +86,4 @@ public class PayTransactionPaySuccessMessage {
return
this
;
}
}
\ No newline at end of file
}
pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/constant/MQConstant.java
deleted
100644 → 0
浏览文件 @
718554bc
package
cn
.
iocoder
.
mall
.
pay
.
biz
.
constant
;
/**
* MQ 枚举类
*/
public
class
MQConstant
{
/**
* Topic - 支付交易单支付成功
*/
public
static
final
String
TOPIC_PAY_TRANSACTION_PAY_SUCCESS
=
"PAY_TRANSACTION_PAY_SUCCESS"
;
}
\ No newline at end of file
pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/convert/PayTransactionConvert.java
浏览文件 @
1c5f413c
...
...
@@ -6,7 +6,7 @@ import cn.iocoder.mall.pay.api.dto.PayTransactionSubmitDTO;
import
cn.iocoder.mall.pay.biz.dataobject.PayTransactionDO
;
import
cn.iocoder.mall.pay.biz.dataobject.PayTransactionExtensionDO
;
import
cn.iocoder.mall.pay.biz.dataobject.PayTransactionNotifyTaskDO
;
import
cn.iocoder.mall.pay.
biz.mq
.PayTransactionPaySuccessMessage
;
import
cn.iocoder.mall.pay.
api.message
.PayTransactionPaySuccessMessage
;
import
org.mapstruct.Mapper
;
import
org.mapstruct.Mappings
;
import
org.mapstruct.factory.Mappers
;
...
...
@@ -28,4 +28,4 @@ public interface PayTransactionConvert {
@Mappings
({})
PayTransactionPaySuccessMessage
convert
(
PayTransactionNotifyTaskDO
payTransactionNotifyTaskDO
);
}
\ No newline at end of file
}
pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/mq/PayTransactionPaySuccessConsumer.java
浏览文件 @
1c5f413c
...
...
@@ -3,7 +3,7 @@ package cn.iocoder.mall.pay.biz.mq;
import
cn.iocoder.common.framework.util.DateUtil
;
import
cn.iocoder.common.framework.util.ExceptionUtil
;
import
cn.iocoder.mall.pay.api.constant.PayTransactionNotifyStatusEnum
;
import
cn.iocoder.mall.pay.
biz.constant.MQConstant
;
import
cn.iocoder.mall.pay.
api.message.PayTransactionPaySuccessMessage
;
import
cn.iocoder.mall.pay.biz.dao.PayTransactionMapper
;
import
cn.iocoder.mall.pay.biz.dao.PayTransactionNotifyLogMapper
;
import
cn.iocoder.mall.pay.biz.dao.PayTransactionNotifyTaskMapper
;
...
...
@@ -31,8 +31,8 @@ import java.util.Date;
@Service
@RocketMQMessageListener
(
topic
=
MQConstant
.
TOPIC_PAY_TRANSACTION_PAY_SUCCESS
,
consumerGroup
=
"pay-consumer-group-"
+
MQConstant
.
TOPIC_PAY_TRANSACTION_PAY_SUCCESS
topic
=
PayTransactionPaySuccessMessage
.
TOPIC
,
consumerGroup
=
"pay-consumer-group-"
+
PayTransactionPaySuccessMessage
.
TOPIC
)
public
class
PayTransactionPaySuccessConsumer
implements
RocketMQListener
<
PayTransactionPaySuccessMessage
>
{
...
...
pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/scheduler/PayTransactionNotifyJob.java
浏览文件 @
1c5f413c
package
cn
.
iocoder
.
mall
.
pay
.
biz
.
scheduler
;
import
cn.iocoder.mall.pay.
biz.constant.MQConstant
;
import
cn.iocoder.mall.pay.
api.message.PayTransactionPaySuccessMessage
;
import
cn.iocoder.mall.pay.biz.convert.PayTransactionConvert
;
import
cn.iocoder.mall.pay.biz.dao.PayTransactionNotifyTaskMapper
;
import
cn.iocoder.mall.pay.biz.dataobject.PayTransactionNotifyTaskDO
;
...
...
@@ -35,7 +35,7 @@ public class PayTransactionNotifyJob extends IJobHandler {
// 循环任务,发送通知
for
(
PayTransactionNotifyTaskDO
payTransactionNotifyTask
:
notifyTasks
)
{
// 发送 MQ
rocketMQTemplate
.
convertAndSend
(
MQConstant
.
TOPIC_PAY_TRANSACTION_PAY_SUCCESS
,
rocketMQTemplate
.
convertAndSend
(
PayTransactionPaySuccessMessage
.
TOPIC
,
PayTransactionConvert
.
INSTANCE
.
convert
(
payTransactionNotifyTask
));
// 更新最后通知时间
// 1. 这样操作,虽然可能会出现 MQ 消费快于下面 PayTransactionNotifyTaskDO 的更新语句。但是,因为更新字段不同,所以不会有问题。
...
...
@@ -48,4 +48,4 @@ public class PayTransactionNotifyJob extends IJobHandler {
return
new
ReturnT
<>(
"执行通知数:"
+
notifyTasks
.
size
());
}
}
\ No newline at end of file
}
pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/service/PayServiceImpl.java
浏览文件 @
1c5f413c
...
...
@@ -12,10 +12,10 @@ import cn.iocoder.mall.pay.api.constant.PayTransactionNotifyStatusEnum;
import
cn.iocoder.mall.pay.api.constant.PayTransactionStatusEnum
;
import
cn.iocoder.mall.pay.api.dto.PayTransactionCreateDTO
;
import
cn.iocoder.mall.pay.api.dto.PayTransactionSubmitDTO
;
import
cn.iocoder.mall.pay.api.message.PayTransactionPaySuccessMessage
;
import
cn.iocoder.mall.pay.biz.client.AbstractPaySDK
;
import
cn.iocoder.mall.pay.biz.client.PaySDKFactory
;
import
cn.iocoder.mall.pay.biz.client.TransactionPaySuccessBO
;
import
cn.iocoder.mall.pay.biz.constant.MQConstant
;
import
cn.iocoder.mall.pay.biz.convert.PayTransactionConvert
;
import
cn.iocoder.mall.pay.biz.dao.PayTransactionExtensionMapper
;
import
cn.iocoder.mall.pay.biz.dao.PayTransactionMapper
;
...
...
@@ -188,7 +188,7 @@ public class PayServiceImpl implements PayTransactionService {
payTransactionNotifyTaskMapper
.
insert
(
payTransactionNotifyTask
);
logger
.
info
(
"[updateTransactionPaySuccess][PayTransactionNotifyTaskDO({}) 新增一个任务]"
,
payTransactionNotifyTask
.
getId
());
// 3.2 发送 MQ
rocketMQTemplate
.
convertAndSend
(
MQConstant
.
TOPIC_PAY_TRANSACTION_PAY_SUCCESS
,
rocketMQTemplate
.
convertAndSend
(
PayTransactionPaySuccessMessage
.
TOPIC
,
PayTransactionConvert
.
INSTANCE
.
convert
(
payTransactionNotifyTask
));
logger
.
info
(
"[updateTransactionPaySuccess][PayTransactionNotifyTaskDO({}) 发送 MQ 任务]"
,
payTransactionNotifyTask
.
getId
());
// 返回结果
...
...
product/product-application/src/main/java/cn/iocoder/mall/product/application/controller/users/UsersProductSpuController.java
浏览文件 @
1c5f413c
...
...
@@ -42,6 +42,7 @@ public class UsersProductSpuController {
@ApiImplicitParam
(
name
=
"pageSize"
,
value
=
"每页条数"
,
required
=
true
,
example
=
"10"
),
})
@PermitAll
@Deprecated
// 使用商品搜索接口
public
CommonResult
<
UsersProductSpuPageVO
>
page
(
@RequestParam
(
value
=
"cid"
,
required
=
false
)
Integer
cid
,
@RequestParam
(
value
=
"pageNo"
,
defaultValue
=
"0"
)
Integer
pageNo
,
@RequestParam
(
value
=
"pageSize"
,
defaultValue
=
"10"
)
Integer
pageSize
)
{
...
...
product/product-service-api/src/main/java/cn/iocoder/mall/product/api/ProductCategoryService.java
浏览文件 @
1c5f413c
...
...
@@ -5,6 +5,7 @@ import cn.iocoder.mall.product.api.bo.ProductCategoryBO;
import
cn.iocoder.mall.product.api.dto.ProductCategoryAddDTO
;
import
cn.iocoder.mall.product.api.dto.ProductCategoryUpdateDTO
;
import
java.util.Collection
;
import
java.util.List
;
public
interface
ProductCategoryService
{
...
...
@@ -15,6 +16,14 @@ public interface ProductCategoryService {
*/
List
<
ProductCategoryBO
>
getListByPid
(
Integer
pid
);
/**
* 获得商品分类数组
*
* @param ids 商品分类编号
* @return 数组
*/
List
<
ProductCategoryBO
>
getListByIds
(
Collection
<
Integer
>
ids
);
/**
* @return 返回所有产品分类们
*/
...
...
@@ -28,4 +37,4 @@ public interface ProductCategoryService {
CommonResult
<
Boolean
>
deleteProductCategory
(
Integer
admin
,
Integer
productCategoryId
);
}
\ No newline at end of file
}
product/product-service-api/src/main/java/cn/iocoder/mall/product/api/message/ProductUpdateMessage.java
0 → 100644
浏览文件 @
1c5f413c
package
cn
.
iocoder
.
mall
.
product
.
api
.
message
;
import
lombok.Data
;
import
lombok.experimental.Accessors
;
/**
* 商品更新(包括创建)消息
*/
@Data
@Accessors
(
chain
=
true
)
public
class
ProductUpdateMessage
{
public
static
final
String
TOPIC
=
"ProductUpdate"
;
/**
* 商品编号
*/
private
Integer
id
;
}
product/product-service-impl/pom.xml
浏览文件 @
1c5f413c
...
...
@@ -42,6 +42,11 @@
<artifactId>
guava
</artifactId>
</dependency>
<dependency>
<groupId>
org.apache.rocketmq
</groupId>
<artifactId>
rocketmq-spring-boot-starter
</artifactId>
</dependency>
</dependencies>
<build>
...
...
product/product-service-impl/src/main/java/cn/iocoder/mall/product/dao/ProductCategoryMapper.java
浏览文件 @
1c5f413c
...
...
@@ -4,6 +4,7 @@ import cn.iocoder.mall.product.dataobject.ProductCategoryDO;
import
org.apache.ibatis.annotations.Param
;
import
org.springframework.stereotype.Repository
;
import
java.util.Collection
;
import
java.util.List
;
@Repository
...
...
@@ -16,8 +17,10 @@ public interface ProductCategoryMapper {
ProductCategoryDO
selectById
(
@Param
(
"id"
)
Integer
id
);
List
<
ProductCategoryDO
>
selectByIds
(
@Param
(
"ids"
)
Collection
<
Integer
>
ids
);
void
insert
(
ProductCategoryDO
productCategoryDO
);
int
update
(
ProductCategoryDO
productCategoryDO
);
}
\ No newline at end of file
}
product/product-service-impl/src/main/java/cn/iocoder/mall/product/service/ProductCategoryServiceImpl.java
浏览文件 @
1c5f413c
...
...
@@ -16,6 +16,7 @@ import cn.iocoder.mall.product.dataobject.ProductCategoryDO;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Service
;
import
java.util.Collection
;
import
java.util.Date
;
import
java.util.List
;
...
...
@@ -32,6 +33,12 @@ public class ProductCategoryServiceImpl implements ProductCategoryService {
return
ProductCategoryConvert
.
INSTANCE
.
convertToBO
(
categoryList
);
}
@Override
public
List
<
ProductCategoryBO
>
getListByIds
(
Collection
<
Integer
>
ids
)
{
List
<
ProductCategoryDO
>
categoryList
=
productCategoryMapper
.
selectByIds
(
ids
);
return
ProductCategoryConvert
.
INSTANCE
.
convertToBO
(
categoryList
);
}
@Override
public
CommonResult
<
List
<
ProductCategoryBO
>>
getAll
()
{
List
<
ProductCategoryDO
>
categoryList
=
productCategoryMapper
.
selectList
();
...
...
product/product-service-impl/src/main/java/cn/iocoder/mall/product/service/ProductSpuServiceImpl.java
浏览文件 @
1c5f413c
...
...
@@ -13,17 +13,20 @@ import cn.iocoder.mall.product.api.dto.ProductSkuAddOrUpdateDTO;
import
cn.iocoder.mall.product.api.dto.ProductSpuAddDTO
;
import
cn.iocoder.mall.product.api.dto.ProductSpuPageDTO
;
import
cn.iocoder.mall.product.api.dto.ProductSpuUpdateDTO
;
import
cn.iocoder.mall.product.api.message.ProductUpdateMessage
;
import
cn.iocoder.mall.product.convert.ProductSpuConvert
;
import
cn.iocoder.mall.product.dao.ProductSkuMapper
;
import
cn.iocoder.mall.product.dao.ProductSpuMapper
;
import
cn.iocoder.mall.product.dataobject.ProductCategoryDO
;
import
cn.iocoder.mall.product.dataobject.ProductSkuDO
;
import
cn.iocoder.mall.product.dataobject.ProductSpuDO
;
import
org.apache.rocketmq.spring.core.RocketMQTemplate
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Service
;
import
org.springframework.transaction.annotation.Transactional
;
import
org.springframework.util.Assert
;
import
javax.annotation.Resource
;
import
java.util.*
;
import
java.util.stream.Collectors
;
...
...
@@ -41,6 +44,9 @@ public class ProductSpuServiceImpl implements ProductSpuService {
@Autowired
private
ProductAttrServiceImpl
productAttrService
;
@Resource
private
RocketMQTemplate
rocketMQTemplate
;
// @Override
// public ProductSpuBO getProductSpuDetail(Integer id) {
// ProductSpuDO productSpuDO = productSpuMapper.selectById(id);
...
...
@@ -82,10 +88,20 @@ public class ProductSpuServiceImpl implements ProductSpuService {
return
CommonResult
.
success
(
spus
);
}
@SuppressWarnings
(
"Duplicates"
)
@Override
@Transactional
public
CommonResult
<
ProductSpuDetailBO
>
addProductSpu
(
Integer
adminId
,
ProductSpuAddDTO
productSpuAddDTO
)
{
CommonResult
<
ProductSpuDetailBO
>
result
=
addProductSpu0
(
adminId
,
productSpuAddDTO
);
// 如果新增生成,发送创建商品 Topic 消息
if
(
result
.
isSuccess
())
{
// TODO 芋艿,先不考虑事务的问题。等后面的 fescar 一起搞
sendProductUpdateMessage
(
result
.
getData
().
getId
());
}
return
result
;
}
@SuppressWarnings
(
"Duplicates"
)
@Transactional
public
CommonResult
<
ProductSpuDetailBO
>
addProductSpu0
(
Integer
adminId
,
ProductSpuAddDTO
productSpuAddDTO
)
{
// 校验商品分类分类存在
CommonResult
<
ProductCategoryDO
>
validCategoryResult
=
productCategoryService
.
validProductCategory
(
productSpuAddDTO
.
getCid
());
if
(
validCategoryResult
.
isError
())
{
...
...
@@ -129,10 +145,19 @@ public class ProductSpuServiceImpl implements ProductSpuService {
validCategoryResult
.
getData
()));
}
@SuppressWarnings
(
"Duplicates"
)
@Override
@Transactional
public
CommonResult
<
Boolean
>
updateProductSpu
(
Integer
adminId
,
ProductSpuUpdateDTO
productSpuUpdateDTO
)
{
CommonResult
<
Boolean
>
result
=
updateProductSpu0
(
adminId
,
productSpuUpdateDTO
);
if
(
result
.
isSuccess
())
{
// TODO 芋艿,先不考虑事务的问题。等后面的 fescar 一起搞
sendProductUpdateMessage
(
productSpuUpdateDTO
.
getId
());
}
return
result
;
}
@SuppressWarnings
(
"Duplicates"
)
@Transactional
public
CommonResult
<
Boolean
>
updateProductSpu0
(
Integer
adminId
,
ProductSpuUpdateDTO
productSpuUpdateDTO
)
{
// 校验 Spu 是否存在
if
(
productSpuMapper
.
selectById
(
productSpuUpdateDTO
.
getId
())
==
null
)
{
return
ServiceExceptionUtil
.
error
(
ProductErrorCodeEnum
.
PRODUCT_SPU_NOT_EXISTS
.
getCode
());
...
...
@@ -208,6 +233,8 @@ public class ProductSpuServiceImpl implements ProductSpuService {
// 更新排序
ProductSpuDO
updateSpu
=
new
ProductSpuDO
().
setId
(
spuId
).
setSort
(
sort
);
productSpuMapper
.
update
(
updateSpu
);
// 修改成功,发送商品 Topic 消息
sendProductUpdateMessage
(
spuId
);
// 返回成功
return
CommonResult
.
success
(
true
);
}
...
...
@@ -329,4 +356,8 @@ public class ProductSpuServiceImpl implements ProductSpuService {
spu
.
setQuantity
(
skus
.
stream
().
mapToInt
(
ProductSkuAddOrUpdateDTO:
:
getQuantity
).
sum
());
// 求库存之和
}
private
void
sendProductUpdateMessage
(
Integer
id
)
{
rocketMQTemplate
.
convertAndSend
(
ProductUpdateMessage
.
TOPIC
,
new
ProductUpdateMessage
().
setId
(
id
));
}
}
product/product-service-impl/src/main/resources/config/application.yaml
浏览文件 @
1c5f413c
...
...
@@ -22,4 +22,11 @@ dubbo:
port
:
-1
name
:
dubbo
scan
:
base-packages
:
cn.iocoder.mall.product.service
\ No newline at end of file
base-packages
:
cn.iocoder.mall.product.service
# rocketmq
rocketmq
:
name-server
:
127.0.0.1:9876
producer
:
group
:
product-producer-group
product/product-service-impl/src/main/resources/mapper/ProductCategoryMapper.xml
浏览文件 @
1c5f413c
...
...
@@ -32,6 +32,17 @@
AND deleted = 0
</select>
<select
id=
"selectByIds"
resultType=
"ProductCategoryDO"
>
SELECT
<include
refid=
"FIELDS"
/>
FROM product_category
WHERE id IN
<foreach
collection=
"ids"
item=
"id"
separator=
","
open=
"("
close=
")"
>
#{id}
</foreach>
AND deleted = 0
</select>
<insert
id=
"insert"
parameterType=
"ProductCategoryDO"
useGeneratedKeys=
"true"
keyColumn=
"id"
keyProperty=
"id"
>
INSERT INTO product_category (
pid, name, description, pic_url, sort,
...
...
@@ -70,4 +81,4 @@
WHERE id = #{id}
</update>
</mapper>
\ No newline at end of file
</mapper>
promotion/promotion-application/src/main/java/cn/iocoder/mall/promotion/application/vo/users/UsersCouponCardVO.java
浏览文件 @
1c5f413c
...
...
@@ -46,11 +46,6 @@ public class UsersCouponCardVO {
// ========== 使用效果 END ==========
// ========== 使用情况 BEGIN ==========
/**
* 是否使用
*/
@ApiModelProperty
(
value
=
"是否使用"
,
required
=
true
)
private
Boolean
used
;
// TODO 芋艿,后续要加优惠劵的使用日志,因为下单后,可能会取消。
...
...
promotion/promotion-service-api/src/main/java/cn/iocoder/mall/promotion/api/CouponService.java
浏览文件 @
1c5f413c
...
...
@@ -77,11 +77,9 @@ public interface CouponService {
*
* @param userId 用户编号
* @param couponCardId 优惠劵编号
* @param usedOrderId 下单的编号
* @param usedPrice 下单的价格
* @return 是否成功
*/
CommonResult
<
Boolean
>
useCouponCard
(
Integer
userId
,
Integer
couponCardId
,
Integer
usedOrderId
,
Integer
usedPrice
);
CommonResult
<
Boolean
>
useCouponCard
(
Integer
userId
,
Integer
couponCardId
);
/**
* 取消优惠劵的使用
...
...
promotion/promotion-service-api/src/main/java/cn/iocoder/mall/promotion/api/bo/CouponCardBO.java
浏览文件 @
1c5f413c
...
...
@@ -95,18 +95,6 @@ public class CouponCardBO implements Serializable {
// ========== 使用效果 END ==========
// ========== 使用情况 BEGIN ==========
/**
* 是否使用
*/
private
Boolean
used
;
/**
* 使用订单号
*/
private
Integer
usedOrderId
;
/**
* 订单中优惠面值,单位:分
*/
private
Integer
usedPrice
;
/**
* 使用时间
*/
...
...
promotion/promotion-service-api/src/main/java/cn/iocoder/mall/promotion/api/constant/PromotionErrorCodeEnum.java
浏览文件 @
1c5f413c
...
...
@@ -29,6 +29,8 @@ public enum PromotionErrorCodeEnum {
COUPON_CARD_NOT_EXISTS
(
1006003000
,
"优惠劵不存在"
),
COUPON_CARD_ERROR_USER
(
1006003001
,
"优惠劵不属于当前用户"
),
COUPON_CARD_NOT_MATCH
(
1006003002
,
"优惠劵不匹配,无法使用"
),
COUPON_CARD_STATUS_NOT_UNUSED
(
1006003003
,
"优惠劵不处于待使用状态"
),
COUPON_CARD_STATUS_NOT_USED
(
1006003004
,
"优惠劵不处于已使用状态"
),
;
...
...
promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/dao/CouponCardMapper.java
浏览文件 @
1c5f413c
...
...
@@ -29,4 +29,8 @@ public interface CouponCardMapper {
int
update
(
CouponCardDO
couponCardDO
);
int
updateByIdAndStatus
(
@Param
(
"id"
)
Integer
id
,
@Param
(
"status"
)
Integer
status
,
@Param
(
"updateObj"
)
CouponCardDO
updateObj
);
}
promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/dataobject/CouponCardDO.java
浏览文件 @
1c5f413c
...
...
@@ -99,14 +99,14 @@ public class CouponCardDO extends BaseDO {
// ========== 使用效果 END ==========
// ========== 使用情况 BEGIN ==========
/**
* 使用订单号
*/
private
Integer
usedOrderId
;
/**
* 订单中优惠面值,单位:分
*/
private
Integer
usedPrice
;
//
/**
//
* 使用订单号
//
*/
// private Integer usedOrderId; // TODO 芋艿,暂时不考虑这个字段
//
/**
//
* 订单中优惠面值,单位:分
//
*/
// private Integer usedPrice; // TODO 芋艿,暂时不考虑这个字段
/**
* 使用时间
*/
...
...
promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/service/CouponServiceImpl.java
浏览文件 @
1c5f413c
...
...
@@ -241,13 +241,51 @@ public class CouponServiceImpl implements CouponService {
}
@Override
public
CommonResult
<
Boolean
>
useCouponCard
(
Integer
userId
,
Integer
couponCardId
,
Integer
usedOrderId
,
Integer
usedPrice
)
{
return
null
;
public
CommonResult
<
Boolean
>
useCouponCard
(
Integer
userId
,
Integer
couponCardId
)
{
// 查询优惠劵
CouponCardDO
card
=
couponCardMapper
.
selectById
(
couponCardId
);
if
(
card
==
null
)
{
return
ServiceExceptionUtil
.
error
(
PromotionErrorCodeEnum
.
COUPON_CARD_NOT_EXISTS
.
getCode
());
}
if
(!
userId
.
equals
(
card
.
getUserId
()))
{
return
ServiceExceptionUtil
.
error
(
PromotionErrorCodeEnum
.
COUPON_CARD_ERROR_USER
.
getCode
());
}
if
(
CouponCardStatusEnum
.
UNUSED
.
getValue
().
equals
(
card
.
getStatus
()))
{
return
ServiceExceptionUtil
.
error
(
PromotionErrorCodeEnum
.
COUPON_CARD_STATUS_NOT_UNUSED
.
getCode
());
}
if
(
DateUtil
.
isBetween
(
card
.
getValidStartTime
(),
card
.
getValidEndTime
()))
{
// 为避免定时器没跑,实际优惠劵已经过期
return
ServiceExceptionUtil
.
error
(
PromotionErrorCodeEnum
.
COUPON_CARD_STATUS_NOT_UNUSED
.
getCode
());
}
// 更新优惠劵已使用
int
updateCount
=
couponCardMapper
.
updateByIdAndStatus
(
card
.
getId
(),
CouponCardStatusEnum
.
USED
.
getValue
(),
new
CouponCardDO
().
setStatus
(
CouponCardStatusEnum
.
USED
.
getValue
()).
setUsedTime
(
new
Date
()));
if
(
updateCount
==
0
)
{
return
ServiceExceptionUtil
.
error
(
PromotionErrorCodeEnum
.
COUPON_CARD_STATUS_NOT_UNUSED
.
getCode
());
}
return
CommonResult
.
success
(
true
);
}
@Override
public
CommonResult
<
Boolean
>
cancelUseCouponCard
(
Integer
userId
,
Integer
couponCardId
)
{
return
null
;
// 查询优惠劵
CouponCardDO
card
=
couponCardMapper
.
selectById
(
couponCardId
);
if
(
card
==
null
)
{
return
ServiceExceptionUtil
.
error
(
PromotionErrorCodeEnum
.
COUPON_CARD_NOT_EXISTS
.
getCode
());
}
if
(!
userId
.
equals
(
card
.
getUserId
()))
{
return
ServiceExceptionUtil
.
error
(
PromotionErrorCodeEnum
.
COUPON_CARD_ERROR_USER
.
getCode
());
}
if
(
CouponCardStatusEnum
.
USED
.
getValue
().
equals
(
card
.
getStatus
()))
{
return
ServiceExceptionUtil
.
error
(
PromotionErrorCodeEnum
.
COUPON_CARD_STATUS_NOT_USED
.
getCode
());
}
// 更新优惠劵已使用
int
updateCount
=
couponCardMapper
.
updateByIdAndStatus
(
card
.
getId
(),
CouponCardStatusEnum
.
UNUSED
.
getValue
(),
new
CouponCardDO
().
setStatus
(
CouponCardStatusEnum
.
USED
.
getValue
()));
// TODO 芋艿,usedTime 未设置空,后面处理。
if
(
updateCount
==
0
)
{
return
ServiceExceptionUtil
.
error
(
PromotionErrorCodeEnum
.
COUPON_CARD_STATUS_NOT_USED
.
getCode
());
}
// 有一点要注意,更新会未使用时,优惠劵可能已经过期了,直接让定时器跑过期,这里不做处理。
return
CommonResult
.
success
(
true
);
}
@Override
...
...
promotion/promotion-service-impl/src/main/resources/mapper/CouponCardMapper.xml
浏览文件 @
1c5f413c
...
...
@@ -5,7 +5,7 @@
<sql
id=
"FIELDS"
>
id, template_id, title, status, user_id, take_type,
price_available, valid_start_time, valid_end_time, preferential_type, percent_off, price_off,
discount_price_limit, used_
order_id, used_price, used_
time,
discount_price_limit, used_time,
create_time
</sql>
...
...
@@ -94,12 +94,12 @@
INSERT INTO coupon_card (
template_id, title, status, user_id, take_type,
price_available, valid_start_time, valid_end_time, preferential_type, percent_off, price_off,
discount_price_limit, used_
order_id, used_price, used_
time,
discount_price_limit, used_time,
create_time
) VALUES (
#{templateId}, #{title}, #{status}, #{userId}, #{takeType},
#{priceAvailable}, #{validStartTime}, #{validEndTime}, #{preferentialType}, #{percentOff}, #{priceOff},
#{discountPriceLimit}, #{used
OrderId}, #{usedPrice}, #{used
Time},
#{discountPriceLimit}, #{usedTime},
#{createTime}
)
</insert>
...
...
@@ -110,12 +110,6 @@
<if
test=
"status != null"
>
status = #{status},
</if>
<if
test=
"usedOrderId != null"
>
used_order_id = #{usedOrderId},
</if>
<if
test=
"usedPrice != null"
>
used_price = #{usedPrice},
</if>
<if
test=
"usedTime != null"
>
used_time = #{usedTime},
</if>
...
...
@@ -123,4 +117,18 @@
WHERE id = #{id}
</update>
<update
id=
"updateByIdAndStatus"
>
UPDATE coupon_card
<set>
<if
test=
"updateObj.status != null"
>
status = #{updateObj.status},
</if>
<if
test=
"updateObj.usedTime != null"
>
used_time = #{updateObj.usedTime},
</if>
</set>
WHERE id = #{id}
AND status = #{status}
</update>
</mapper>
search/search-application/src/main/java/cn/iocoder/mall/search/application/SearchApplication.java
浏览文件 @
1c5f413c
...
...
@@ -7,6 +7,8 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
public
class
SearchApplication
{
public
static
void
main
(
String
[]
args
)
{
// 解决 ES java.lang.IllegalStateException: availableProcessors is already
System
.
setProperty
(
"es.set.netty.runtime.available.processors"
,
"false"
);
SpringApplication
.
run
(
SearchApplication
.
class
,
args
);
}
...
...
search/search-application/src/main/java/cn/iocoder/mall/search/application/controller/users/UsersProductSearchController.java
浏览文件 @
1c5f413c
...
...
@@ -4,7 +4,9 @@ import cn.iocoder.common.framework.util.StringUtil;
import
cn.iocoder.common.framework.vo.CommonResult
;
import
cn.iocoder.common.framework.vo.SortingField
;
import
cn.iocoder.mall.search.api.ProductSearchService
;
import
cn.iocoder.mall.search.api.bo.ESProductPageBO
;
import
cn.iocoder.mall.search.api.bo.ProductConditionBO
;
import
cn.iocoder.mall.search.api.bo.ProductPageBO
;
import
cn.iocoder.mall.search.api.dto.ProductConditionDTO
;
import
cn.iocoder.mall.search.api.dto.ProductSearchPageDTO
;
import
com.alibaba.dubbo.config.annotation.Reference
;
import
io.swagger.annotations.Api
;
...
...
@@ -24,12 +26,12 @@ public class UsersProductSearchController {
private
ProductSearchService
productSearchService
;
@GetMapping
(
"/page"
)
// TODO 芋艿,后面把 BO 改成 VO
public
CommonResult
<
ES
ProductPageBO
>
page
(
@RequestParam
(
value
=
"cid"
,
required
=
false
)
Integer
cid
,
@RequestParam
(
value
=
"keyword"
,
required
=
false
)
String
keyword
,
@RequestParam
(
value
=
"pageNo"
,
required
=
false
)
Integer
pageNo
,
@RequestParam
(
value
=
"pageSize"
,
required
=
false
)
Integer
pageSize
,
@RequestParam
(
value
=
"sortField"
,
required
=
false
)
String
sortField
,
@RequestParam
(
value
=
"sortOrder"
,
required
=
false
)
String
sortOrder
)
{
public
CommonResult
<
ProductPageBO
>
page
(
@RequestParam
(
value
=
"cid"
,
required
=
false
)
Integer
cid
,
@RequestParam
(
value
=
"keyword"
,
required
=
false
)
String
keyword
,
@RequestParam
(
value
=
"pageNo"
,
required
=
false
)
Integer
pageNo
,
@RequestParam
(
value
=
"pageSize"
,
required
=
false
)
Integer
pageSize
,
@RequestParam
(
value
=
"sortField"
,
required
=
false
)
String
sortField
,
@RequestParam
(
value
=
"sortOrder"
,
required
=
false
)
String
sortOrder
)
{
// 创建 ProductSearchPageDTO 对象
ProductSearchPageDTO
productSearchPageDTO
=
new
ProductSearchPageDTO
().
setCid
(
cid
).
setKeyword
(
keyword
)
.
setPageNo
(
pageNo
).
setPageSize
(
pageSize
);
...
...
@@ -37,7 +39,16 @@ public class UsersProductSearchController {
productSearchPageDTO
.
setSorts
(
Collections
.
singletonList
(
new
SortingField
(
sortField
,
sortOrder
)));
}
// 执行搜索
return
productSearchService
.
searchPage
(
productSearchPageDTO
);
return
productSearchService
.
getSearchPage
(
productSearchPageDTO
);
}
@GetMapping
(
"/condition"
)
// TODO 芋艿,后面把 BO 改成 VO
public
CommonResult
<
ProductConditionBO
>
condition
(
@RequestParam
(
value
=
"keyword"
,
required
=
false
)
String
keyword
)
{
// 创建 ProductConditionDTO 对象
ProductConditionDTO
productConditionDTO
=
new
ProductConditionDTO
().
setKeyword
(
keyword
)
.
setFields
(
Collections
.
singleton
(
ProductConditionDTO
.
FIELD_CATEGORY
));
// 执行搜索
return
productSearchService
.
getSearchCondition
(
productConditionDTO
);
}
}
search/search-service-api/src/main/java/cn/iocoder/mall/search/api/ProductSearchService.java
浏览文件 @
1c5f413c
package
cn
.
iocoder
.
mall
.
search
.
api
;
import
cn.iocoder.common.framework.vo.CommonResult
;
import
cn.iocoder.mall.search.api.bo.ESProductPageBO
;
import
cn.iocoder.mall.search.api.bo.ProductConditionBO
;
import
cn.iocoder.mall.search.api.bo.ProductPageBO
;
import
cn.iocoder.mall.search.api.dto.ProductConditionDTO
;
import
cn.iocoder.mall.search.api.dto.ProductSearchPageDTO
;
public
interface
ProductSearchService
{
CommonResult
<
Integer
>
rebuild
();
CommonResult
<
ESProductPageBO
>
searchPage
(
ProductSearchPageDTO
searchPageDTO
);
/**
* 构建商品的搜索索引
*
* @param id 商品编号
* @return 构建结果
*/
CommonResult
<
Boolean
>
save
(
Integer
id
);
CommonResult
<
ProductPageBO
>
getSearchPage
(
ProductSearchPageDTO
searchPageDTO
);
CommonResult
<
ProductConditionBO
>
getSearchCondition
(
ProductConditionDTO
conditionDTO
);
}
search/search-service-api/src/main/java/cn/iocoder/mall/search/api/bo/
ES
ProductBO.java
→
search/search-service-api/src/main/java/cn/iocoder/mall/search/api/bo/ProductBO.java
浏览文件 @
1c5f413c
...
...
@@ -11,7 +11,7 @@ import java.util.List;
*/
@Data
@Accessors
(
chain
=
true
)
public
class
ES
ProductBO
implements
Serializable
{
public
class
ProductBO
implements
Serializable
{
private
Integer
id
;
...
...
search/search-service-api/src/main/java/cn/iocoder/mall/search/api/bo/ProductConditionBO.java
0 → 100644
浏览文件 @
1c5f413c
package
cn
.
iocoder
.
mall
.
search
.
api
.
bo
;
import
lombok.Data
;
import
lombok.experimental.Accessors
;
import
java.util.List
;
/**
* 商品搜索条件返回 BO
*/
@Data
@Accessors
(
chain
=
true
)
public
class
ProductConditionBO
{
/**
* 商品分类数组
*/
private
List
<
Category
>
categories
;
@Data
@Accessors
(
chain
=
true
)
public
static
class
Category
{
/**
* 分类编号
*/
private
Integer
id
;
/**
* 分类名称
*/
private
String
name
;
}
}
search/search-service-api/src/main/java/cn/iocoder/mall/search/api/bo/
ES
ProductPageBO.java
→
search/search-service-api/src/main/java/cn/iocoder/mall/search/api/bo/ProductPageBO.java
浏览文件 @
1c5f413c
...
...
@@ -8,12 +8,12 @@ import java.util.List;
@Data
@Accessors
(
chain
=
true
)
public
class
ES
ProductPageBO
implements
Serializable
{
public
class
ProductPageBO
implements
Serializable
{
/**
* 管理员数组
*/
private
List
<
ES
ProductBO
>
list
;
private
List
<
ProductBO
>
list
;
/**
* 总量
*/
...
...
search/search-service-api/src/main/java/cn/iocoder/mall/search/api/dto/ProductConditionDTO.java
0 → 100644
浏览文件 @
1c5f413c
package
cn
.
iocoder
.
mall
.
search
.
api
.
dto
;
import
lombok.Data
;
import
lombok.experimental.Accessors
;
import
java.util.Collection
;
/**
* 获得商品检索条件 DTO
*/
@Data
@Accessors
(
chain
=
true
)
public
class
ProductConditionDTO
{
/**
* Field - 商品分类
*/
public
static
final
String
FIELD_CATEGORY
=
"category"
;
/**
* 关键字
*/
private
String
keyword
;
/**
* 需要返回的搜索条件的 fields 名
*/
private
Collection
<
String
>
fields
;
}
search/search-service-impl/pom.xml
浏览文件 @
1c5f413c
...
...
@@ -43,6 +43,11 @@
<artifactId>
spring-boot-starter-data-elasticsearch
</artifactId>
</dependency>
<dependency>
<groupId>
org.apache.rocketmq
</groupId>
<artifactId>
rocketmq-spring-boot-starter
</artifactId>
</dependency>
<!-- test -->
<dependency>
<groupId>
org.springframework.boot
</groupId>
...
...
search/search-service-impl/src/main/java/cn/iocoder/mall/search/biz/convert/ProductSearchConvert.java
浏览文件 @
1c5f413c
...
...
@@ -3,7 +3,7 @@ package cn.iocoder.mall.search.biz.convert;
import
cn.iocoder.mall.order.api.bo.CalcSkuPriceBO
;
import
cn.iocoder.mall.product.api.bo.ProductSpuDetailBO
;
import
cn.iocoder.mall.promotion.api.bo.PromotionActivityBO
;
import
cn.iocoder.mall.search.api.bo.
ES
ProductBO
;
import
cn.iocoder.mall.search.api.bo.ProductBO
;
import
cn.iocoder.mall.search.biz.dataobject.ESProductDO
;
import
org.mapstruct.Mapper
;
import
org.mapstruct.Mappings
;
...
...
@@ -34,6 +34,6 @@ public interface ProductSearchConvert {
return
product
;
}
List
<
ES
ProductBO
>
convert
(
List
<
ESProductDO
>
list
);
List
<
ProductBO
>
convert
(
List
<
ESProductDO
>
list
);
}
search/search-service-impl/src/main/java/cn/iocoder/mall/search/biz/dao/ProductRepository.java
浏览文件 @
1c5f413c
...
...
@@ -54,11 +54,13 @@ public interface ProductRepository extends ElasticsearchRepository<ESProductDO,
nativeSearchQueryBuilder
.
withQuery
(
QueryBuilders
.
matchAllQuery
());
}
// 排序
if
(
CollectionUtil
.
isEmpty
(
sortFields
))
{
nativeSearchQueryBuilder
.
withSort
(
SortBuilders
.
scoreSort
().
order
(
SortOrder
.
DESC
));
}
else
{
if
(!
CollectionUtil
.
isEmpty
(
sortFields
))
{
sortFields
.
forEach
(
sortField
->
nativeSearchQueryBuilder
.
withSort
(
SortBuilders
.
fieldSort
(
sortField
.
getField
())
.
order
(
SortOrder
.
fromString
(
sortField
.
getOrder
()))));
}
else
if
(
StringUtil
.
hasText
(
keyword
))
{
nativeSearchQueryBuilder
.
withSort
(
SortBuilders
.
scoreSort
().
order
(
SortOrder
.
DESC
));
}
else
{
nativeSearchQueryBuilder
.
withSort
(
SortBuilders
.
fieldSort
(
"sort"
).
order
(
SortOrder
.
DESC
));
}
// 执行查询
return
search
(
nativeSearchQueryBuilder
.
build
());
...
...
search/search-service-impl/src/main/java/cn/iocoder/mall/search/biz/mq/PayTransactionPaySuccessConsumer.java
0 → 100644
浏览文件 @
1c5f413c
package
cn
.
iocoder
.
mall
.
search
.
biz
.
mq
;
import
cn.iocoder.common.framework.vo.CommonResult
;
import
cn.iocoder.mall.product.api.message.ProductUpdateMessage
;
import
cn.iocoder.mall.search.api.ProductSearchService
;
import
org.apache.rocketmq.spring.annotation.RocketMQMessageListener
;
import
org.apache.rocketmq.spring.core.RocketMQListener
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Service
;
import
org.springframework.util.Assert
;
@Service
@RocketMQMessageListener
(
topic
=
ProductUpdateMessage
.
TOPIC
,
consumerGroup
=
"search-consumer-group-"
+
ProductUpdateMessage
.
TOPIC
)
public
class
PayTransactionPaySuccessConsumer
implements
RocketMQListener
<
ProductUpdateMessage
>
{
@Autowired
private
ProductSearchService
productSearchService
;
@Override
public
void
onMessage
(
ProductUpdateMessage
message
)
{
CommonResult
<
Boolean
>
result
=
productSearchService
.
save
(
message
.
getId
());
Assert
.
isTrue
(
result
.
isSuccess
(),
String
.
format
(
"重构商品 ES 索引,必然成功。实际结果是 %s"
,
result
));
}
}
search/search-service-impl/src/main/java/cn/iocoder/mall/search/biz/service/ProductSearchServiceImpl.java
浏览文件 @
1c5f413c
package
cn
.
iocoder
.
mall
.
search
.
biz
.
service
;
import
cn.iocoder.common.framework.util.CollectionUtil
;
import
cn.iocoder.common.framework.util.StringUtil
;
import
cn.iocoder.common.framework.vo.CommonResult
;
import
cn.iocoder.common.framework.vo.SortingField
;
import
cn.iocoder.mall.order.api.CartService
;
import
cn.iocoder.mall.order.api.bo.CalcSkuPriceBO
;
import
cn.iocoder.mall.product.api.ProductCategoryService
;
import
cn.iocoder.mall.product.api.ProductSpuService
;
import
cn.iocoder.mall.product.api.bo.ProductCategoryBO
;
import
cn.iocoder.mall.product.api.bo.ProductSpuDetailBO
;
import
cn.iocoder.mall.search.api.ProductSearchService
;
import
cn.iocoder.mall.search.api.bo.ESProductPageBO
;
import
cn.iocoder.mall.search.api.bo.ProductConditionBO
;
import
cn.iocoder.mall.search.api.bo.ProductPageBO
;
import
cn.iocoder.mall.search.api.dto.ProductConditionDTO
;
import
cn.iocoder.mall.search.api.dto.ProductSearchPageDTO
;
import
cn.iocoder.mall.search.biz.convert.ProductSearchConvert
;
import
cn.iocoder.mall.search.biz.dao.ProductRepository
;
import
cn.iocoder.mall.search.biz.dataobject.ESProductDO
;
import
com.alibaba.dubbo.config.annotation.Reference
;
import
org.elasticsearch.index.query.QueryBuilders
;
import
org.elasticsearch.search.aggregations.Aggregation
;
import
org.elasticsearch.search.aggregations.AggregationBuilders
;
import
org.elasticsearch.search.aggregations.bucket.terms.LongTerms
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.data.domain.Page
;
import
org.springframework.data.elasticsearch.core.ElasticsearchTemplate
;
import
org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder
;
import
org.springframework.stereotype.Service
;
import
org.springframework.util.Assert
;
import
java.util.ArrayList
;
import
java.util.Comparator
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.stream.Collectors
;
@Service
...
...
@@ -31,10 +44,14 @@ public class ProductSearchServiceImpl implements ProductSearchService {
@Autowired
private
ProductRepository
productRepository
;
@Autowired
private
ElasticsearchTemplate
elasticsearchTemplate
;
// 因为需要使用到聚合操作,只好引入 ElasticsearchTemplate 。
@Reference
(
validation
=
"true"
)
private
ProductSpuService
productSpuService
;
@Reference
(
validation
=
"true"
)
private
ProductCategoryService
productCategoryService
;
@Reference
(
validation
=
"true"
)
private
CartService
cartService
;
@Override
...
...
@@ -57,9 +74,22 @@ public class ProductSearchServiceImpl implements ProductSearchService {
lastId
=
spus
.
get
(
spus
.
size
()
-
1
).
getId
();
}
}
// 返回成功
return
CommonResult
.
success
(
rebuildCounts
);
}
@Override
public
CommonResult
<
Boolean
>
save
(
Integer
id
)
{
// 获得商品性情
CommonResult
<
ProductSpuDetailBO
>
result
=
productSpuService
.
getProductSpuDetail
(
id
);
Assert
.
isTrue
(
result
.
isSuccess
(),
"获得商品详情必然成功"
);
// 存储到 ES 中
ESProductDO
product
=
convert
(
result
.
getData
());
productRepository
.
save
(
product
);
// 返回成功
return
CommonResult
.
success
(
Boolean
.
TRUE
);
}
@SuppressWarnings
(
"OptionalGetWithoutIsPresent"
)
private
ESProductDO
convert
(
ProductSpuDetailBO
spu
)
{
// 获得最小价格的 SKU ,用于下面的价格计算
...
...
@@ -72,13 +102,13 @@ public class ProductSearchServiceImpl implements ProductSearchService {
}
@Override
public
CommonResult
<
ESProductPageBO
>
s
earchPage
(
ProductSearchPageDTO
searchPageDTO
)
{
public
CommonResult
<
ProductPageBO
>
getS
earchPage
(
ProductSearchPageDTO
searchPageDTO
)
{
checkSortFieldInvalid
(
searchPageDTO
.
getSorts
());
// 执行查询
Page
<
ESProductDO
>
searchPage
=
productRepository
.
search
(
searchPageDTO
.
getCid
(),
searchPageDTO
.
getKeyword
(),
searchPageDTO
.
getPageNo
(),
searchPageDTO
.
getPageSize
(),
searchPageDTO
.
getSorts
());
// 转换结果
ESProductPageBO
resultPage
=
new
ES
ProductPageBO
()
ProductPageBO
resultPage
=
new
ProductPageBO
()
.
setList
(
ProductSearchConvert
.
INSTANCE
.
convert
(
searchPage
.
getContent
()))
.
setTotal
((
int
)
searchPage
.
getTotalElements
());
return
CommonResult
.
success
(
resultPage
);
...
...
@@ -92,4 +122,46 @@ public class ProductSearchServiceImpl implements ProductSearchService {
String
.
format
(
"排序字段(%s) 不在允许范围内"
,
sortingField
.
getField
())));
}
@Override
public
CommonResult
<
ProductConditionBO
>
getSearchCondition
(
ProductConditionDTO
conditionDTO
)
{
// 创建 ES 搜索条件
NativeSearchQueryBuilder
nativeSearchQueryBuilder
=
new
NativeSearchQueryBuilder
();
// 筛选
if
(
StringUtil
.
hasText
(
conditionDTO
.
getKeyword
()))
{
// 如果有 keyword ,就去匹配
nativeSearchQueryBuilder
.
withQuery
(
QueryBuilders
.
multiMatchQuery
(
conditionDTO
.
getKeyword
(),
"name"
,
"sellPoint"
,
"categoryName"
));
}
else
{
nativeSearchQueryBuilder
.
withQuery
(
QueryBuilders
.
matchAllQuery
());
}
// 聚合
if
(
conditionDTO
.
getFields
().
contains
(
ProductConditionDTO
.
FIELD_CATEGORY
))
{
// 商品分类
nativeSearchQueryBuilder
.
addAggregation
(
AggregationBuilders
.
terms
(
"cids"
).
field
(
"cid"
));
}
// 执行查询
ProductConditionBO
condition
=
elasticsearchTemplate
.
query
(
nativeSearchQueryBuilder
.
build
(),
response
->
{
ProductConditionBO
result
=
new
ProductConditionBO
();
// categoryIds 聚合
Aggregation
categoryIdsAggregation
=
response
.
getAggregations
().
get
(
"cids"
);
if
(
categoryIdsAggregation
!=
null
)
{
result
.
setCategories
(
new
ArrayList
<>());
for
(
LongTerms
.
Bucket
bucket
:
(((
LongTerms
)
categoryIdsAggregation
).
getBuckets
()))
{
result
.
getCategories
().
add
(
new
ProductConditionBO
.
Category
().
setId
(
bucket
.
getKeyAsNumber
().
intValue
()));
}
}
// 返回结果
return
result
;
});
// 聚合其它数据源
if
(!
CollectionUtil
.
isEmpty
(
condition
.
getCategories
()))
{
// 查询指定的 ProductCategoryBO 数组,并转换成 ProductCategoryBO Map
Map
<
Integer
,
ProductCategoryBO
>
categoryMap
=
productCategoryService
.
getListByIds
(
condition
.
getCategories
().
stream
().
map
(
ProductConditionBO
.
Category
::
getId
).
collect
(
Collectors
.
toList
()))
.
stream
().
collect
(
Collectors
.
toMap
(
ProductCategoryBO:
:
getId
,
category
->
category
));
// 设置分类名
condition
.
getCategories
().
forEach
(
category
->
category
.
setName
(
categoryMap
.
get
(
category
.
getId
()).
getName
()));
}
// 返回结果
return
CommonResult
.
success
(
condition
);
}
}
search/search-service-impl/src/main/resources/config/application.yaml
浏览文件 @
1c5f413c
...
...
@@ -3,7 +3,7 @@ spring:
data
:
elasticsearch
:
cluster-name
:
elasticsearch
cluster-nodes
:
1
92.168.88.10
:9300
cluster-nodes
:
1
80.167.213.26
:9300
repositories
:
enable
:
true
...
...
@@ -18,3 +18,9 @@ dubbo:
name
:
dubbo
scan
:
base-packages
:
cn.iocoder.mall.search.biz.service
# rocketmq
rocketmq
:
name-server
:
127.0.0.1:9876
producer
:
group
:
search-producer-group
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论