Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
Y
yudao-cloud
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
hblj
yudao-cloud
Commits
7277ecb2
提交
7277ecb2
authored
4月 18, 2019
作者:
YunaiV
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
前后端:商品确认页,增加优惠劵接入
后端:修改了价格计算的逻辑
上级
8962631b
隐藏空白字符变更
内嵌
并排
正在显示
34 个修改的文件
包含
548 行增加
和
148 行删除
+548
-148
package-info.java
...mpl/src/main/java/cn/iocoder/mall/admin/package-info.java
+0
-2
promotion.js
mobile-web/src/api/promotion.js
+0
-1
main.js
mobile-web/src/main.js
+2
-0
index.vue
mobile-web/src/page/cart/index.vue
+8
-7
detail.vue
mobile-web/src/page/product/detail.vue
+3
-3
order.vue
mobile-web/src/page/shipping/order.vue
+82
-14
list.vue
mobile-web/src/page/user/coupon/list.vue
+1
-1
UsersCartController.java
...der/application/controller/users/UsersCartController.java
+12
-2
CartConvert.java
...n/iocoder/mall/order/application/convert/CartConvert.java
+18
-0
UsersCalcSkuPriceVO.java
...ocoder/mall/order/application/vo/UsersCalcSkuPriceVO.java
+1
-1
UsersCartDetailVO.java
.../iocoder/mall/order/application/vo/UsersCartDetailVO.java
+34
-22
UsersOrderConfirmCreateVO.java
.../mall/order/application/vo/UsersOrderConfirmCreateVO.java
+38
-6
CalcOrderPriceBO.java
...n/java/cn/iocoder/mall/order/api/bo/CalcOrderPriceBO.java
+42
-22
CalcSkuPriceBO.java
...ain/java/cn/iocoder/mall/order/api/bo/CalcSkuPriceBO.java
+2
-2
OrderItemDO.java
...ava/cn/iocoder/mall/order/biz/dataobject/OrderItemDO.java
+45
-1
OrderPreferentialDO.java
...ocoder/mall/order/biz/dataobject/OrderPreferentialDO.java
+46
-0
package-info.java
...src/main/java/cn/iocoder/mall/order/biz/package-info.java
+0
-6
CartServiceImpl.java
...va/cn/iocoder/mall/order/biz/service/CartServiceImpl.java
+50
-31
OrderServiceImpl.java
...a/cn/iocoder/mall/order/biz/service/OrderServiceImpl.java
+3
-1
package-info.java
...rc/main/java/cn/iocoder/mall/pay/biz/mq/package-info.java
+0
-2
package-info.java
...l/src/main/java/cn/iocoder/mall/product/package-info.java
+0
-2
CouponService.java
...ain/java/cn/iocoder/mall/promotion/api/CouponService.java
+14
-4
CouponCardAvailableBO.java
.../iocoder/mall/promotion/api/bo/CouponCardAvailableBO.java
+24
-0
CouponCardSpuDTO.java
...a/cn/iocoder/mall/promotion/api/dto/CouponCardSpuDTO.java
+39
-0
CouponCardConvert.java
...iocoder/mall/promotion/biz/convert/CouponCardConvert.java
+4
-0
CouponCardMapper.java
...a/cn/iocoder/mall/promotion/biz/dao/CouponCardMapper.java
+3
-0
CouponTemplateMapper.java
.../iocoder/mall/promotion/biz/dao/CouponTemplateMapper.java
+3
-0
package-info.java
...main/java/cn/iocoder/mall/promotion/biz/package-info.java
+0
-2
CouponServiceImpl.java
...iocoder/mall/promotion/biz/service/CouponServiceImpl.java
+50
-6
CouponCardMapper.xml
...rvice-impl/src/main/resources/mapper/CouponCardMapper.xml
+14
-0
CouponTemplateMapper.xml
...e-impl/src/main/resources/mapper/CouponTemplateMapper.xml
+10
-0
package-info.java
...test/java/cn/iocoder/mall/promotion/biz/package-info.java
+0
-1
package-info.java
.../src/main/java/cn/iocoder/mall/user/sdk/package-info.java
+0
-7
package-info.java
.../src/main/java/cn/iocoder/mall/user/biz/package-info.java
+0
-2
没有找到文件。
admin/admin-service-impl/src/main/java/cn/iocoder/mall/admin/package-info.java
deleted
100644 → 0
浏览文件 @
8962631b
package
cn
.
iocoder
.
mall
.
admin
;
\ No newline at end of file
mobile-web/src/api/promotion.js
浏览文件 @
7277ecb2
...
...
@@ -16,7 +16,6 @@ export function getProductRecommendList() {
url
:
'/promotion-api/users/product_recommend/list'
,
method
:
'get'
,
params
:
{
id
,
}
});
}
...
...
mobile-web/src/main.js
浏览文件 @
7277ecb2
...
...
@@ -6,6 +6,7 @@ import App from './App.vue';
import
VueLazyload
from
'vue-lazyload'
import
components
from
'./config/components.js'
;
import
{
Dialog
}
from
'vant'
;
import
{
CouponCell
,
CouponList
}
from
'vant'
;
import
{
formatDate
}
from
'./utils/date.js'
;
...
...
@@ -13,6 +14,7 @@ Vue.use(components);
Vue
.
use
(
VueLazyload
);
Vue
.
use
(
Dialog
);
Vue
.
use
(
CouponCell
).
use
(
CouponList
);
new
Vue
({
router
,
...
...
mobile-web/src/page/cart/index.vue
浏览文件 @
7277ecb2
...
...
@@ -133,13 +133,14 @@ export default {
}
return
text
;
},
formatItemGroupDiscountPriceText
()
{
let
price
=
0
;
for
(
let
i
in
this
.
itemGroups
)
{
let
itemGroup
=
this
.
itemGroups
[
i
];
price
+=
itemGroup
.
fee
.
discountTotal
;
}
return
price
>
0
?
'立减 '
+
price
/
100.0
+
' 元'
:
''
;
//
let price = 0;
//
for (let i in this.itemGroups) {
//
let itemGroup = this.itemGroups[i];
// price += itemGroup.activityDiscountTotal || 0
;
//
}
return
this
.
fee
.
discountTotal
>
0
?
'立减 '
+
this
.
fee
.
discountTotal
/
100.0
+
' 元'
:
''
;
},
calCheckedItemIds
()
{
...
...
@@ -226,7 +227,7 @@ export default {
return
{
...
item
.
spu
,
quantity
:
item
.
buyQuantity
,
price
:
item
.
discount
Price
||
item
.
price
,
price
:
item
.
buy
Price
||
item
.
price
,
sku
:
{
...
item
,
spu
:
undefined
,
...
...
mobile-web/src/page/product/detail.vue
浏览文件 @
7277ecb2
...
...
@@ -9,8 +9,8 @@
<!-- TODO 这里需要优化下,芋艿 -->
<van-cell-group>
<van-cell>
<div
v-if=
"calSkuPriceResult.originalPrice && calSkuPriceResult.originalPrice !== calSkuPriceResult.
present
Price"
>
<span
class=
"goods-price"
>
{{
formatPrice
(
calSkuPriceResult
.
present
Price
)
}}
</span>
<div
v-if=
"calSkuPriceResult.originalPrice && calSkuPriceResult.originalPrice !== calSkuPriceResult.
buy
Price"
>
<span
class=
"goods-price"
>
{{
formatPrice
(
calSkuPriceResult
.
buy
Price
)
}}
</span>
<span
class=
"goods-market-price"
>
{{
formatPrice
(
calSkuPriceResult
.
originalPrice
)
}}
</span>
</div>
<div
v-else
>
...
...
@@ -283,7 +283,7 @@
for
(
let
i
in
this
.
vanSku
.
list
)
{
let
sku
=
this
.
vanSku
.
list
[
i
];
if
(
sku
.
id
===
skuId
)
{
sku
.
price
=
data
.
present
Price
;
sku
.
price
=
data
.
buy
Price
;
break
;
}
}
...
...
mobile-web/src/page/shipping/order.vue
浏览文件 @
7277ecb2
...
...
@@ -43,21 +43,36 @@
/>
</van-cell-group>
<div
style=
"height:15px;"
></div>
<van-cell-group
class=
"total"
>
<van-cell
title=
"优惠券"
is-link
value=
"抵扣¥5.00"
/>
</van-cell-group>
<!-- 优惠券单元格 -->
<van-coupon-cell
:coupons=
"coupons"
:chosen-coupon=
"chosenCoupon"
@
click=
"showCouponPopup = true"
/>
<!-- 优惠券列表 -->
<van-popup
v-model=
"showCouponPopup"
position=
"bottom"
>
<van-coupon-list
:coupons=
"coupons"
:chosen-coupon=
"chosenCoupon"
:disabled-coupons=
"disabledCoupons"
@
change=
"onCouponChange"
@
exchange=
"onCouponExchange"
/>
</van-popup>
<div
style=
"height:15px;"
></div>
<van-cell-group
class=
"total"
>
<van-cell
title=
"商品总额"
:value=
"fee.
originalTotal
"
/>
<van-cell
title=
"运费"
:value=
"+ fee.postageTotal"
/>
<van-cell
title=
"折扣"
:value=
"- fee.discountTotal"
/>
<van-cell
title=
"实付金额"
:value=
"fee.presentTotal"
style=
"font-weight: 700;"
/>
<van-cell
title=
"商品总额"
:value=
"fee.
buyTotal / 100.0
"
/>
<van-cell
title=
"运费"
:value=
"+ fee.postageTotal
/ 100.0
"
/>
<van-cell
title=
"折扣"
:value=
"- fee.discountTotal
/ 100.0
"
/>
<van-cell
title=
"实付金额"
:value=
"fee.presentTotal
/ 100.0
"
style=
"font-weight: 700;"
/>
</van-cell-group>
<div
style=
"height:50px;"
></div>
<van-submit-bar
:price=
"
3050
"
:price=
"
fee.presentTotal
"
button-text=
"提交订单"
label=
'实付金额:'
@
submit=
"onSubmit"
...
...
@@ -75,7 +90,8 @@
createOrderFromCart
}
from
'../../api/order'
;
import
{
GetDefaultAddress
}
from
'../../api/user'
;
import
orderStore
from
'../../store/order'
import
orderStore
from
'../../store/order'
;
import
{
Dialog
}
from
'vant'
;
export
default
{
data
()
{
...
...
@@ -89,6 +105,8 @@
addressData
:
{
},
// 商品 + 促销相关
itemGroups
:
[],
fee
:
{
originalTotal
:
undefined
,
...
...
@@ -96,12 +114,36 @@
postageTotal
:
undefined
,
presentTotal
:
undefined
,
},
products
:
[],
// products: [], // 应该没用了
// 优惠劵相关
showCouponPopup
:
false
,
coupons
:
[],
disabledCoupons
:
[],
chosenCoupon
:
-
1
,
};
},
methods
:
{
onCouponChange
(
a
,
b
,
c
)
{
debugger
;
},
onCouponExchange
(
a
,
b
,
c
)
{
Dialog
.
alert
({
title
:
'系统提示'
,
message
:
'暂未开发'
,
// TODO 芋艿
});
},
onSubmit
()
{
const
userAddressId
=
this
.
addressData
.
id
;
if
(
!
userAddressId
)
{
Dialog
.
alert
({
title
:
'系统提示'
,
message
:
'请选择收获地址'
,
});
return
;
}
const
remark
=
''
;
if
(
this
.
from
===
'direct_order'
)
{
...
...
@@ -116,7 +158,7 @@
remark
,
}).
then
(
result
=>
{
if
(
result
)
{
const
{
orderNo
}
=
result
;
//
const { orderNo } = result;
this
.
$router
.
push
({
//核心语句
path
:
`/order/success`
,
//跳转的路径
query
:{
//路由传参时push和query搭配使用 ,作用时传递参数
...
...
@@ -128,7 +170,7 @@
}
else
if
(
this
.
from
===
'cart'
)
{
createOrderFromCart
(
userAddressId
,
remark
).
then
(
result
=>
{
if
(
result
)
{
const
{
orderNo
}
=
result
;
//
const { orderNo } = result;
this
.
$router
.
push
({
//核心语句
path
:
`/order/success`
,
//跳转的路径
query
:{
//路由传参时push和query搭配使用 ,作用时传递参数
...
...
@@ -140,16 +182,34 @@
}
},
convertProduct
(
item
)
{
// debugger;
return
{
...
item
.
spu
,
quantity
:
item
.
buyQuantity
,
price
:
item
.
price
,
price
:
item
.
buyPrice
||
item
.
price
,
sku
:
{
...
item
,
spu
:
undefined
,
}
};
},
convertCouponList
(
cards
)
{
let
newCards
=
[];
for
(
let
i
in
cards
)
{
let
card
=
cards
[
i
];
newCards
.
push
({
id
:
card
.
id
,
name
:
card
.
title
,
condition
:
'满 '
+
card
.
priceAvailable
/
100.0
+
' 元可用'
,
startAt
:
card
.
validStartTime
/
1000
,
endAt
:
card
.
validEndTime
/
1000
,
// description: '述信息,优惠券可用时展示',
reason
:
card
.
unavailableReason
,
value
:
card
.
preferentialType
===
1
?
card
.
priceOff
:
card
.
percentOff
,
valueDesc
:
card
.
preferentialType
===
1
?
card
.
priceOff
/
100
:
card
.
percentOff
/
10.0
,
unitDesc
:
card
.
preferentialType
===
1
?
'元'
:
'折'
})
}
return
newCards
;
}
},
mounted
:
function
()
{
...
...
@@ -166,11 +226,19 @@
getOrderConfirmCreateOrder
(
this
.
skuId
,
this
.
quantity
).
then
(
data
=>
{
this
.
itemGroups
=
data
.
itemGroups
;
this
.
fee
=
data
.
fee
;
// 获得优惠劵列表
})
}
else
if
(
this
.
from
===
'cart'
)
{
getCartConfirmCreateOrder
().
then
(
data
=>
{
this
.
itemGroups
=
data
.
itemGroups
;
this
.
fee
=
data
.
fee
;
// 获得优惠劵列表
this
.
coupons
=
this
.
convertCouponList
(
data
.
couponCards
.
filter
(
function
(
element
)
{
return
element
.
available
;
}));
this
.
disabledCoupons
=
this
.
convertCouponList
(
data
.
couponCards
.
filter
(
function
(
element
)
{
return
!
element
.
available
;
}));
})
}
},
...
...
mobile-web/src/page/user/coupon/list.vue
浏览文件 @
7277ecb2
...
...
@@ -33,7 +33,7 @@
<span
class=
"amountSign"
>
折
</span>
</div>
<div
class=
"condition"
>
<span>
满
{{
item
.
priceAvailable
}}
元可用
</span>
<span>
满
{{
item
.
priceAvailable
/
100.0
}}
元可用
</span>
</div>
</div>
</div>
...
...
order/order-application/src/main/java/cn/iocoder/mall/order/application/controller/users/UsersCartController.java
浏览文件 @
7277ecb2
...
...
@@ -11,6 +11,8 @@ import cn.iocoder.mall.order.application.convert.CartConvert;
import
cn.iocoder.mall.order.application.vo.UsersCalcSkuPriceVO
;
import
cn.iocoder.mall.order.application.vo.UsersCartDetailVO
;
import
cn.iocoder.mall.order.application.vo.UsersOrderConfirmCreateVO
;
import
cn.iocoder.mall.promotion.api.CouponService
;
import
cn.iocoder.mall.promotion.api.bo.CouponCardAvailableBO
;
import
cn.iocoder.mall.user.sdk.context.UserSecurityContextHolder
;
import
com.alibaba.dubbo.config.annotation.Reference
;
import
org.springframework.web.bind.annotation.*
;
...
...
@@ -28,6 +30,8 @@ public class UsersCartController {
private
CartService
cartService
;
@Reference
(
validation
=
"true"
)
private
OrderService
orderService
;
@Reference
(
validation
=
"true"
)
private
CouponService
couponService
;
@PostMapping
(
"add"
)
public
CommonResult
<
Integer
>
add
(
@RequestParam
(
"skuId"
)
Integer
skuId
,
...
...
@@ -102,8 +106,9 @@ public class UsersCartController {
@GetMapping
(
"/confirm_create_order"
)
public
CommonResult
<
UsersOrderConfirmCreateVO
>
getConfirmCreateOrder
()
{
Integer
userId
=
UserSecurityContextHolder
.
getContext
().
getUserId
();
// 获得购物车中选中的
List
<
CartItemBO
>
cartItems
=
cartService
.
list
(
UserSecurityContextHolder
.
getContext
().
getUserId
()
,
true
).
getData
();
List
<
CartItemBO
>
cartItems
=
cartService
.
list
(
userId
,
true
).
getData
();
// 购物车为空时,构造空的 UsersOrderConfirmCreateVO 返回
if
(
cartItems
.
isEmpty
())
{
UsersOrderConfirmCreateVO
result
=
new
UsersOrderConfirmCreateVO
();
...
...
@@ -116,8 +121,13 @@ public class UsersCartController {
if
(
calcOrderPriceResult
.
isError
())
{
return
CommonResult
.
error
(
calcOrderPriceResult
);
}
// 获得优惠劵
CalcOrderPriceBO
calcOrderPrice
=
calcOrderPriceResult
.
getData
();
List
<
CouponCardAvailableBO
>
couponCards
=
couponService
.
getCouponCardList
(
userId
,
CartConvert
.
INSTANCE
.
convertList
(
calcOrderPrice
.
getItemGroups
())).
getData
();
// 执行数据拼装
return
CommonResult
.
success
(
CartConvert
.
INSTANCE
.
convert
(
calcOrderPriceResult
.
getData
()));
return
CommonResult
.
success
(
CartConvert
.
INSTANCE
.
convert
(
calcOrderPrice
)
.
setCouponCards
(
couponCards
));
}
private
CommonResult
<
CalcOrderPriceBO
>
list0
(
List
<
CartItemBO
>
cartItems
)
{
...
...
order/order-application/src/main/java/cn/iocoder/mall/order/application/convert/CartConvert.java
浏览文件 @
7277ecb2
...
...
@@ -5,9 +5,14 @@ import cn.iocoder.mall.order.api.bo.CalcSkuPriceBO;
import
cn.iocoder.mall.order.application.vo.UsersCalcSkuPriceVO
;
import
cn.iocoder.mall.order.application.vo.UsersCartDetailVO
;
import
cn.iocoder.mall.order.application.vo.UsersOrderConfirmCreateVO
;
import
cn.iocoder.mall.promotion.api.dto.CouponCardSpuDTO
;
import
org.mapstruct.Mapper
;
import
org.mapstruct.factory.Mappers
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.stream.Collectors
;
@Mapper
public
interface
CartConvert
{
...
...
@@ -19,4 +24,17 @@ public interface CartConvert {
UsersCalcSkuPriceVO
convert2
(
CalcSkuPriceBO
calcSkuPriceBO
);
default
List
<
CouponCardSpuDTO
>
convertList
(
List
<
CalcOrderPriceBO
.
ItemGroup
>
itemGroups
)
{
List
<
CouponCardSpuDTO
>
items
=
new
ArrayList
<>();
itemGroups
.
forEach
(
itemGroup
->
items
.
addAll
(
itemGroup
.
getItems
().
stream
().
map
(
item
->
new
CouponCardSpuDTO
()
.
setSpuId
(
item
.
getSpu
().
getId
())
.
setSkuId
(
item
.
getId
())
.
setCategoryId
(
item
.
getSpu
().
getCid
())
.
setPrice
(
item
.
getBuyPrice
())
.
setQuantity
(
item
.
getBuyQuantity
()))
.
collect
(
Collectors
.
toList
())));
return
items
;
}
}
order/order-application/src/main/java/cn/iocoder/mall/order/application/vo/UsersCalcSkuPriceVO.java
浏览文件 @
7277ecb2
...
...
@@ -29,6 +29,6 @@ public class UsersCalcSkuPriceVO {
/**
* 最终价格,单位:分。
*/
private
Integer
present
Price
;
private
Integer
buy
Price
;
}
order/order-application/src/main/java/cn/iocoder/mall/order/application/vo/UsersCartDetailVO.java
浏览文件 @
7277ecb2
...
...
@@ -36,25 +36,16 @@ public class UsersCartDetailVO {
*/
private
PromotionActivityBO
activity
;
// TODO 芋艿,偷懒
/**
*
优惠活动是否生效
*
促销减少的金额
*
* 多个商品,参与某个活动,因为并发达到条件,所以会存在未生效的情况。所以一共有三种情况
*
* 1. activity 非空,activityEffectEffective 为 true,参与活动,且生效
* 2. activity 非空,activityEffectEffective 为 false ,参与活动,并未生效
* 3. activity 为空,activityEffectEffective 为空,并未参与活动。
* 1. 若未参与促销活动,或不满足促销条件,返回 null
* 2. 该金额,已经分摊到每个 Item 的 discountTotal ,需要注意。
*/
private
Boolean
activityEffectEffective
;
private
Integer
activityDiscountTotal
;
/**
* 商品数组
*/
private
List
<
Sku
>
items
;
/**
* 费用
*
* TODO 芋艿,这里先偷懒,postageTotal 字段用不到。
*/
private
Fee
fee
;
}
...
...
@@ -103,15 +94,36 @@ public class UsersCartDetailVO {
*/
private
PromotionActivityBO
activity
;
/**
* 折扣价
* 原始单价,单位:分。
*/
private
Integer
originPrice
;
/**
* 购买单价,单位:分
*/
private
Integer
buyPrice
;
/**
* 最终价格,单位:分。
*/
private
Integer
discou
ntPrice
;
private
Integer
prese
ntPrice
;
/**
*
费用
*
购买总金额,单位:分
*
*
TODO 芋艿,这里先偷懒,postageTotal 字段用不到。
*
用途类似 {@link #presentTotal}
*/
private
Fee
fee
;
private
Integer
buyTotal
;
/**
* 优惠总金额,单位:分。
*/
private
Integer
discountTotal
;
/**
* 最终总金额,单位:分。
*
* 注意,presentPrice * quantity 不一定等于 presentTotal 。
* 因为,存在无法整除的情况。
* 举个例子,presentPrice = 8.33 ,quantity = 3 的情况,presentTotal 有可能是 24.99 ,也可能是 25 。
* 所以,需要存储一个该字段。
*/
private
Integer
presentTotal
;
}
...
...
@@ -152,9 +164,9 @@ public class UsersCartDetailVO {
public
static
class
Fee
{
/**
* 总价
*
购买
总价
*/
private
Integer
original
Total
;
private
Integer
buy
Total
;
/**
* 优惠总价
*
...
...
@@ -175,8 +187,8 @@ public class UsersCartDetailVO {
public
Fee
()
{
}
public
Fee
(
Integer
original
Total
,
Integer
discountTotal
,
Integer
postageTotal
,
Integer
presentTotal
)
{
this
.
originalTotal
=
original
Total
;
public
Fee
(
Integer
buy
Total
,
Integer
discountTotal
,
Integer
postageTotal
,
Integer
presentTotal
)
{
this
.
buyTotal
=
buy
Total
;
this
.
discountTotal
=
discountTotal
;
this
.
postageTotal
=
postageTotal
;
this
.
presentTotal
=
presentTotal
;
...
...
order/order-application/src/main/java/cn/iocoder/mall/order/application/vo/UsersOrderConfirmCreateVO.java
浏览文件 @
7277ecb2
package
cn
.
iocoder
.
mall
.
order
.
application
.
vo
;
import
cn.iocoder.mall.product.api.bo.ProductAttrAndValuePairBO
;
import
cn.iocoder.mall.promotion.api.bo.CouponCardAvailableBO
;
import
cn.iocoder.mall.promotion.api.bo.PromotionActivityBO
;
import
lombok.Data
;
import
lombok.experimental.Accessors
;
...
...
@@ -19,6 +20,10 @@ public class UsersOrderConfirmCreateVO {
* 费用
*/
private
Fee
fee
;
/**
* 优惠劵列表 TODO 芋艿,后续改改
*/
private
List
<
CouponCardAvailableBO
>
couponCards
;
/**
* 商品分组
...
...
@@ -79,9 +84,36 @@ public class UsersOrderConfirmCreateVO {
*/
private
Integer
buyQuantity
;
/**
* 折扣价
* 原始单价,单位:分。
*/
private
Integer
originPrice
;
/**
* 购买单价,单位:分
*/
private
Integer
buyPrice
;
/**
* 最终价格,单位:分。
*/
private
Integer
presentPrice
;
/**
* 购买总金额,单位:分
*
* 用途类似 {@link #presentTotal}
*/
private
Integer
buyTotal
;
/**
* 优惠总金额,单位:分。
*/
private
Integer
discountTotal
;
/**
* 最终总金额,单位:分。
*
* 注意,presentPrice * quantity 不一定等于 presentTotal 。
* 因为,存在无法整除的情况。
* 举个例子,presentPrice = 8.33 ,quantity = 3 的情况,presentTotal 有可能是 24.99 ,也可能是 25 。
* 所以,需要存储一个该字段。
*/
private
Integer
discountPrice
;
private
Integer
presentTotal
;
}
...
...
@@ -122,9 +154,9 @@ public class UsersOrderConfirmCreateVO {
public
static
class
Fee
{
/**
* 总价
*
购买
总价
*/
private
Integer
original
Total
;
private
Integer
buy
Total
;
/**
* 优惠总价
*
...
...
@@ -145,8 +177,8 @@ public class UsersOrderConfirmCreateVO {
public
Fee
()
{
}
public
Fee
(
Integer
original
Total
,
Integer
discountTotal
,
Integer
postageTotal
,
Integer
presentTotal
)
{
this
.
originalTotal
=
original
Total
;
public
Fee
(
Integer
buy
Total
,
Integer
discountTotal
,
Integer
postageTotal
,
Integer
presentTotal
)
{
this
.
buyTotal
=
buy
Total
;
this
.
discountTotal
=
discountTotal
;
this
.
postageTotal
=
postageTotal
;
this
.
presentTotal
=
presentTotal
;
...
...
order/order-service-api/src/main/java/cn/iocoder/mall/order/api/bo/CalcOrderPriceBO.java
浏览文件 @
7277ecb2
...
...
@@ -20,6 +20,8 @@ public class CalcOrderPriceBO {
private
List
<
ItemGroup
>
itemGroups
;
/**
* 邮费信息
*
* TODO 芋艿,暂时未弄
*/
private
Postage
postage
;
/**
...
...
@@ -42,25 +44,22 @@ public class CalcOrderPriceBO {
// TODO 芋艿,目前只会有【满减送】的情况,未来有新的促销方式,可能需要改成数组
private
PromotionActivityBO
activity
;
/**
* 优惠活动是否生效
*
* 多个商品,参与某个活动,因为并发达到条件,所以会存在未生效的情况。所以一共有三种情况
* 促销减少的金额
*
* 1. activity 非空,activityEffectEffective 为 true,参与活动,且生效
* 2. activity 非空,activityEffectEffective 为 false ,参与活动,并未生效
* 3. activity 为空,activityEffectEffective 为空,并未参与活动。
* 1. 若未参与促销活动,或不满足促销条件,返回 null
* 2. 该金额,已经分摊到每个 Item 的 discountTotal ,需要注意。
*/
private
Boolean
activityEffectEffective
;
private
Integer
activityDiscountTotal
;
/**
* 商品数组
*/
private
List
<
Item
>
items
;
/**
* 费用
*
* TODO 芋艿,这里先偷懒,postageTotal 字段用不到。
*/
private
Fee
fee
;
//
/**
//
* 费用
//
*
//
* TODO 芋艿,这里先偷懒,postageTotal 字段用不到。
//
*/
// private Fee fee; // 注释原因,不用这里了
}
...
...
@@ -81,15 +80,36 @@ public class CalcOrderPriceBO {
*/
private
PromotionActivityBO
activity
;
/**
* 费用
* 原始单价,单位:分。
*/
private
Integer
originPrice
;
/**
* 购买单价,单位:分
*/
private
Integer
buyPrice
;
/**
* 最终价格,单位:分。
*/
private
Integer
presentPrice
;
/**
* 购买总金额,单位:分
*
* TODO 芋艿,这里先偷懒,postageTotal 字段用不到。
* 用途类似 {@link #presentTotal}
*/
private
Integer
buyTotal
;
/**
* 优惠总金额,单位:分。
*/
private
Fee
fee
;
private
Integer
discountTotal
;
/**
* 折扣价
* 最终总金额,单位:分。
*
* 注意,presentPrice * quantity 不一定等于 presentTotal 。
* 因为,存在无法整除的情况。
* 举个例子,presentPrice = 8.33 ,quantity = 3 的情况,presentTotal 有可能是 24.99 ,也可能是 25 。
* 所以,需要存储一个该字段。
*/
private
Integer
discountPrice
;
private
Integer
presentTotal
;
}
...
...
@@ -101,9 +121,9 @@ public class CalcOrderPriceBO {
public
static
class
Fee
{
/**
* 总价
*
购买
总价
*/
private
Integer
original
Total
;
private
Integer
buy
Total
;
/**
* 优惠总价
*
...
...
@@ -124,8 +144,8 @@ public class CalcOrderPriceBO {
public
Fee
()
{
}
public
Fee
(
Integer
original
Total
,
Integer
discountTotal
,
Integer
postageTotal
,
Integer
presentTotal
)
{
this
.
originalTotal
=
original
Total
;
public
Fee
(
Integer
buy
Total
,
Integer
discountTotal
,
Integer
postageTotal
,
Integer
presentTotal
)
{
this
.
buyTotal
=
buy
Total
;
this
.
discountTotal
=
discountTotal
;
this
.
postageTotal
=
postageTotal
;
this
.
presentTotal
=
presentTotal
;
...
...
order/order-service-api/src/main/java/cn/iocoder/mall/order/api/bo/CalcSkuPriceBO.java
浏览文件 @
7277ecb2
...
...
@@ -24,8 +24,8 @@ public class CalcSkuPriceBO {
*/
private
Integer
originalPrice
;
/**
*
最终
价格,单位:分。
*
购买
价格,单位:分。
*/
private
Integer
present
Price
;
private
Integer
buy
Price
;
}
order/order-service-impl/src/main/java/cn/iocoder/mall/order/biz/dataobject/OrderItemDO.java
浏览文件 @
7277ecb2
...
...
@@ -49,18 +49,62 @@ public class OrderItemDO extends DeletableDO {
*/
private
Integer
quantity
;
/**
*
价格
(分)
*
商品成交单价
(分)
*/
@Deprecated
private
Integer
price
;
/**
* 支付金额(实付金额)
*/
@Deprecated
private
Integer
payAmount
;
/**
* 物流金额 (分)
*/
@Deprecated
private
Integer
logisticsPrice
;
/**
* 原始单价,单位:分。
*/
private
Integer
originPrice
;
/**
* 购买单价,单位:分
*/
private
Integer
buyPrice
;
/**
* 最终价格,单位:分。
*/
private
Integer
presentPrice
;
/**
* 购买总金额,单位:分
*
* 用途类似 {@link #presentTotal}
*/
private
Integer
buyTotal
;
/**
* 优惠总金额,单位:分。
*/
private
Integer
discountTotal
;
/**
* 最终总金额,单位:分。
*
* 注意,presentPrice * quantity 不一定等于 presentTotal 。
* 因为,存在无法整除的情况。
* 举个例子,presentPrice = 8.33 ,quantity = 3 的情况,presentTotal 有可能是 24.99 ,也可能是 25 。
* 所以,需要存储一个该字段。
*/
private
Integer
presentTotal
;
// 如上字段,举个例子:
// 假设购买三个,即 quantity = 3 。
// originPrice = 15
// 使用限时折扣(单品优惠)8 折,buyPrice = 12
// 开始算总的价格
// buyTotal = buyPrice * quantity = 12 * 3 = 36
// discountTotal ,假设有满减送(分组优惠)满 20 减 10 ,并且使用优惠劵满 1.01 减 1 ,则 discountTotal = 10 + 1 = 11
// presentTotal = buyTotal - discountTotal = 24 - 11 = 13
// 最终 presentPrice = presentTotal / quantity = 13 / 3 = 4.33
///
/// 时间信息
...
...
order/order-service-impl/src/main/java/cn/iocoder/mall/order/biz/dataobject/OrderPreferentialDO.java
0 → 100644
浏览文件 @
7277ecb2
package
cn
.
iocoder
.
mall
.
order
.
biz
.
dataobject
;
/**
* 订单优惠明细
*/
// TODO 芋艿 后续在完善
public
class
OrderPreferentialDO
{
/**
* 编号
*/
private
Integer
id
;
/**
* 类型
*
* 1 - 促销活动
* 2 - 优惠劵
*/
private
Integer
type
;
// TODO 芋艿 优惠劵编号 or 促销活动编号
/**
* 订单编号
*/
private
Integer
orderId
;
/**
* 商品 SPU 编号
*/
private
Integer
spuId
;
/**
* 商品 SKU 编号
*/
private
Integer
skuId
;
/**
* 商品数量
*/
private
Integer
quantity
;
/**
* 传入时的价格
*/
private
Integer
originTotal
;
/**
* 总优惠价格
*/
private
Integer
discountTotal
;
}
order/order-service-impl/src/main/java/cn/iocoder/mall/order/biz/package-info.java
deleted
100644 → 0
浏览文件 @
8962631b
/**
* @author Sin
* @time 2019-03-16 13:49
*/
package
cn
.
iocoder
.
mall
.
order
.
biz
;
\ No newline at end of file
order/order-service-impl/src/main/java/cn/iocoder/mall/order/biz/service/CartServiceImpl.java
浏览文件 @
7277ecb2
...
...
@@ -178,17 +178,17 @@ public class CartServiceImpl implements CartService {
List
<
CalcOrderPriceBO
.
ItemGroup
>
itemGroups
=
groupByFullPrivilege
(
items
,
activityList
);
calcOrderPriceBO
.
setItemGroups
(
itemGroups
);
// 4. 计算最终的价格
Integer
original
Total
=
0
;
Integer
prese
ntTotal
=
0
;
Integer
discou
ntTotal
=
0
;
int
buy
Total
=
0
;
int
discou
ntTotal
=
0
;
int
prese
ntTotal
=
0
;
for
(
CalcOrderPriceBO
.
ItemGroup
itemGroup
:
calcOrderPriceBO
.
getItemGroups
())
{
originalTotal
+=
itemGroup
.
getItems
().
stream
().
mapToInt
(
item
->
item
.
getSelected
()
?
item
.
getFee
().
getOriginal
Total
()
:
0
).
sum
();
discountTotal
+=
itemGroup
.
get
Fee
().
getDiscountTotal
()
+
itemGroup
.
getItems
().
stream
().
mapToInt
(
item
->
item
.
getSelected
()
?
item
.
getFee
()
.
getDiscountTotal
()
:
0
).
sum
();
presentTotal
+=
itemGroup
.
get
Fee
().
getPresentTotal
();
buyTotal
+=
itemGroup
.
getItems
().
stream
().
mapToInt
(
item
->
item
.
getSelected
()
?
item
.
getBuy
Total
()
:
0
).
sum
();
discountTotal
+=
itemGroup
.
get
Items
().
stream
().
mapToInt
(
item
->
item
.
getSelected
()
?
item
.
getDiscountTotal
()
:
0
).
sum
();
presentTotal
+=
itemGroup
.
get
Items
().
stream
().
mapToInt
(
item
->
item
.
getSelected
()
?
item
.
getPresentTotal
()
:
0
).
sum
();
}
Assert
.
isTrue
(
original
Total
-
discountTotal
==
presentTotal
,
String
.
format
(
"价格合计( %d - %d == %d )不正确"
,
original
Total
,
discountTotal
,
presentTotal
));
calcOrderPriceBO
.
setFee
(
new
CalcOrderPriceBO
.
Fee
(
original
Total
,
discountTotal
,
0
,
presentTotal
));
Assert
.
isTrue
(
buy
Total
-
discountTotal
==
presentTotal
,
String
.
format
(
"价格合计( %d - %d == %d )不正确"
,
buy
Total
,
discountTotal
,
presentTotal
));
calcOrderPriceBO
.
setFee
(
new
CalcOrderPriceBO
.
Fee
(
buy
Total
,
discountTotal
,
0
,
presentTotal
));
// 返回
return
CommonResult
.
success
(
calcOrderPriceBO
);
}
...
...
@@ -215,7 +215,7 @@ public class CartServiceImpl implements CartService {
// 如果无促销活动,则直接返回默认结果即可
List
<
PromotionActivityBO
>
activityList
=
activityListResult
.
getData
();
if
(
activityList
.
isEmpty
())
{
return
CommonResult
.
success
(
new
CalcSkuPriceBO
().
setOriginalPrice
(
sku
.
getPrice
()).
set
Present
Price
(
sku
.
getPrice
()));
return
CommonResult
.
success
(
new
CalcSkuPriceBO
().
setOriginalPrice
(
sku
.
getPrice
()).
set
Buy
Price
(
sku
.
getPrice
()));
}
// 如果有促销活动,则开始做计算 TODO 芋艿,因为现在暂时只有限时折扣 + 满减送。所以写的比较简单先
PromotionActivityBO
fullPrivilege
=
findPromotionActivityByType
(
activityList
,
PromotionActivityTypeEnum
.
FULL_PRIVILEGE
);
...
...
@@ -223,7 +223,7 @@ public class CartServiceImpl implements CartService {
Integer
presentPrice
=
calcSkuPriceByTimeLimitDiscount
(
sku
,
timeLimitedDiscount
);
// 返回结果
return
CommonResult
.
success
(
new
CalcSkuPriceBO
().
setFullPrivilege
(
fullPrivilege
).
setTimeLimitedDiscount
(
timeLimitedDiscount
)
.
setOriginalPrice
(
sku
.
getPrice
()).
set
Present
Price
(
presentPrice
));
.
setOriginalPrice
(
sku
.
getPrice
()).
set
Buy
Price
(
presentPrice
));
}
private
List
<
CalcOrderPriceBO
.
Item
>
initCalcOrderPriceItems
(
List
<
ProductSkuDetailBO
>
skus
,
...
...
@@ -237,10 +237,12 @@ public class CartServiceImpl implements CartService {
item
.
setSelected
(
calcOrderItem
.
getSelected
());
item
.
setBuyQuantity
(
calcOrderItem
.
getQuantity
());
// 计算初始价格
CalcOrderPriceBO
.
Fee
fee
=
new
CalcOrderPriceBO
.
Fee
(
0
,
0
,
0
,
0
);
fee
.
setOriginalTotal
(
item
.
getPrice
()
*
item
.
getBuyQuantity
());
fee
.
setPresentTotal
(
fee
.
getOriginalTotal
());
item
.
setFee
(
fee
);
item
.
setOriginPrice
(
sku
.
getPrice
());
item
.
setBuyPrice
(
sku
.
getPrice
());
item
.
setPresentPrice
(
sku
.
getPrice
());
item
.
setBuyTotal
(
sku
.
getPrice
()
*
calcOrderItem
.
getQuantity
());
item
.
setDiscountTotal
(
0
);
item
.
setPresentTotal
(
item
.
getBuyTotal
());
}
return
items
;
}
...
...
@@ -264,10 +266,10 @@ public class CartServiceImpl implements CartService {
// 设置优惠
item
.
setActivity
(
timeLimitedDiscount
);
// 设置价格
item
.
set
Discount
Price
(
newPrice
);
CalcOrderPriceBO
.
Fee
fee
=
item
.
getFee
(
);
fee
.
setDiscountTotal
(
fee
.
getDiscountTotal
()
+
(
item
.
getPrice
()
-
newPrice
)
*
item
.
getBuyQuantity
());
fee
.
setPresentTotal
(
fee
.
getOriginalTotal
()
-
fee
.
getDiscountTotal
()
+
fee
.
getPostageTotal
());
item
.
set
Buy
Price
(
newPrice
);
item
.
setBuyTotal
(
newPrice
*
item
.
getBuyQuantity
()
);
item
.
setPresentTotal
(
item
.
getBuyTotal
()
-
item
.
getDiscountTotal
());
item
.
setPresentPrice
(
item
.
getPresentTotal
()
/
item
.
getBuyQuantity
());
}
}
...
...
@@ -302,14 +304,11 @@ public class CartServiceImpl implements CartService {
}
// 处理未参加活动的商品,形成一个分组
if
(!
items
.
isEmpty
())
{
CalcOrderPriceBO
.
ItemGroup
itemGroup
=
new
CalcOrderPriceBO
.
ItemGroup
()
.
setItems
(
items
);
itemGroups
.
add
(
itemGroup
);
itemGroups
.
add
(
new
CalcOrderPriceBO
.
ItemGroup
().
setItems
(
items
));
}
// 计算每个分组的价格
for
(
CalcOrderPriceBO
.
ItemGroup
itemGroup
:
itemGroups
)
{
itemGroup
.
setFee
(
calcSkuPriceByFullPrivilege
(
itemGroup
));
itemGroup
.
setActivityEffectEffective
(
itemGroup
.
getFee
().
getDiscountTotal
()
>
0
);
itemGroup
.
setActivityDiscountTotal
(
calcSkuPriceByFullPrivilege
(
itemGroup
));
}
// 返回结果
return
itemGroups
;
...
...
@@ -346,17 +345,18 @@ public class CartServiceImpl implements CartService {
throw
new
IllegalArgumentException
(
String
.
format
(
"折扣活动(%s) 的优惠类型不正确"
,
timeLimitedDiscount
.
toString
()));
}
private
CalcOrderPriceBO
.
Fee
calcSkuPriceByFullPrivilege
(
CalcOrderPriceBO
.
ItemGroup
itemGroup
)
{
private
Integer
calcSkuPriceByFullPrivilege
(
CalcOrderPriceBO
.
ItemGroup
itemGroup
)
{
if
(
itemGroup
.
getActivity
()
==
null
)
{
Integer
originalTotal
=
itemGroup
.
getItems
().
stream
().
mapToInt
(
item
->
item
.
getSelected
()
?
item
.
getFee
().
getPresentTotal
()
:
0
).
sum
();
return
new
CalcOrderPriceBO
.
Fee
(
originalTotal
,
0
,
0
,
originalTotal
);
return
null
;
}
PromotionActivityBO
activity
=
itemGroup
.
getActivity
();
Assert
.
isTrue
(
PromotionActivityTypeEnum
.
FULL_PRIVILEGE
.
getValue
().
equals
(
activity
.
getActivityType
()),
"传入的必须的满减送活动必须是满减送"
);
// 获得优惠信息
Integer
itemCnt
=
itemGroup
.
getItems
().
stream
().
mapToInt
(
item
->
item
.
getSelected
()
?
item
.
getBuyQuantity
()
:
0
).
sum
();
Integer
originalTotal
=
itemGroup
.
getItems
().
stream
().
mapToInt
(
item
->
item
.
getSelected
()
?
item
.
getFee
().
getPresentTotal
()
:
0
).
sum
();
List
<
CalcOrderPriceBO
.
Item
>
items
=
itemGroup
.
getItems
().
stream
().
filter
(
item
->
!
item
.
getSelected
())
.
collect
(
Collectors
.
toList
());
Integer
itemCnt
=
items
.
stream
().
mapToInt
(
CalcOrderPriceBO
.
Item
::
getBuyQuantity
).
sum
();
Integer
originalTotal
=
items
.
stream
().
mapToInt
(
CalcOrderPriceBO
.
Item
::
getPresentTotal
).
sum
();
List
<
PromotionActivityBO
.
FullPrivilege
.
Privilege
>
privileges
=
activity
.
getFullPrivilege
().
getPrivileges
().
stream
()
.
filter
(
privilege
->
{
if
(
MeetTypeEnum
.
PRICE
.
getValue
().
equals
(
privilege
.
getMeetType
()))
{
...
...
@@ -369,7 +369,7 @@ public class CartServiceImpl implements CartService {
}).
collect
(
Collectors
.
toList
());
// 获得不到优惠信息,返回原始价格
if
(
privileges
.
isEmpty
())
{
return
n
ew
CalcOrderPriceBO
.
Fee
(
originalTotal
,
0
,
0
,
originalTotal
)
;
return
n
ull
;
}
// 获得到优惠信息,进行价格计算
PromotionActivityBO
.
FullPrivilege
.
Privilege
privilege
=
privileges
.
get
(
privileges
.
size
()
-
1
);
...
...
@@ -393,7 +393,26 @@ public class CartServiceImpl implements CartService {
}
else
{
throw
new
IllegalArgumentException
(
String
.
format
(
"满减送促销(%s) 的优惠类型不正确"
,
activity
.
toString
()));
}
return
new
CalcOrderPriceBO
.
Fee
(
originalTotal
,
originalTotal
-
presentTotal
,
0
,
presentTotal
);
Integer
discountTotal
=
originalTotal
-
presentTotal
;
if
(
discountTotal
==
0
)
{
return
null
;
}
// 按比例,拆分 presentTotal
for
(
int
i
=
0
;
i
<
items
.
size
();
i
++)
{
CalcOrderPriceBO
.
Item
item
=
items
.
get
(
i
);
Integer
discountPart
;
if
(
i
<
items
.
size
()
-
1
)
{
// 减一的原因,是因为拆分时,如果按照比例,可能会出现.所以最后一个,使用反减
discountPart
=
(
int
)
(
discountTotal
*
(
1.0
D
*
item
.
getPresentTotal
()
/
presentTotal
));
discountTotal
-=
discountPart
;
}
else
{
discountPart
=
discountTotal
;
}
Assert
.
isTrue
(
discountPart
>
0
,
"优惠金额必须大于 0"
);
item
.
setDiscountTotal
(
item
.
getDiscountTotal
()
+
discountPart
);
item
.
setPresentTotal
(
item
.
getBuyTotal
()
-
item
.
getDiscountTotal
());
item
.
setPresentPrice
(
item
.
getPresentTotal
()
/
item
.
getBuyQuantity
());
}
return
originalTotal
-
presentTotal
;
}
private
PromotionActivityBO
findPromotionActivityByType
(
List
<
PromotionActivityBO
>
activityList
,
PromotionActivityTypeEnum
type
)
{
...
...
order/order-service-impl/src/main/java/cn/iocoder/mall/order/biz/service/OrderServiceImpl.java
浏览文件 @
7277ecb2
...
...
@@ -212,6 +212,8 @@ public class OrderServiceImpl implements OrderService {
return
ServiceExceptionUtil
.
error
(
OrderErrorCodeEnum
.
ORDER_GET_GOODS_INFO_INCORRECT
.
getCode
());
}
//
// 设置 orderItem
Map
<
Integer
,
ProductSkuDetailBO
>
productSpuBOMap
=
productResult
.
getData
()
...
...
@@ -293,7 +295,7 @@ public class OrderServiceImpl implements OrderService {
.
setDeleted
(
DeletedStatusEnum
.
DELETED_NO
.
getValue
())
.
setCreateTime
(
new
Date
())
.
setUpdateTime
(
null
);
orderItemMapper
.
insert
(
orderItemDO
);
orderItemMapper
.
insert
(
orderItemDO
);
// TODO 芋艿,需要改成一次性插入
});
// 创建预订单
...
...
pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/mq/package-info.java
deleted
100644 → 0
浏览文件 @
8962631b
package
cn
.
iocoder
.
mall
.
pay
.
biz
.
mq
;
\ No newline at end of file
product/product-service-impl/src/main/java/cn/iocoder/mall/product/package-info.java
deleted
100644 → 0
浏览文件 @
8962631b
package
cn
.
iocoder
.
mall
.
product
;
\ No newline at end of file
promotion/promotion-service-api/src/main/java/cn/iocoder/mall/promotion/api/CouponService.java
浏览文件 @
7277ecb2
...
...
@@ -2,13 +2,12 @@ package cn.iocoder.mall.promotion.api;
import
cn.iocoder.common.framework.validator.InEnum
;
import
cn.iocoder.common.framework.vo.CommonResult
;
import
cn.iocoder.mall.promotion.api.bo.CouponCardBO
;
import
cn.iocoder.mall.promotion.api.bo.CouponCardPageBO
;
import
cn.iocoder.mall.promotion.api.bo.CouponTemplateBO
;
import
cn.iocoder.mall.promotion.api.bo.CouponTemplatePageBO
;
import
cn.iocoder.mall.promotion.api.bo.*
;
import
cn.iocoder.mall.promotion.api.constant.CouponTemplateStatusEnum
;
import
cn.iocoder.mall.promotion.api.dto.*
;
import
java.util.List
;
public
interface
CouponService
{
// ========== 优惠劵(码)模板 ==========
...
...
@@ -93,6 +92,17 @@ public interface CouponService {
*/
CommonResult
<
Boolean
>
cancelUseCouponCard
(
Integer
userId
,
Integer
couponCardId
);
/**
* 获得用户所有优惠劵,并标明是否可用
*
* 注意,spus 是作为条件,判断优惠劵是否可用
*
* @param userId 用户编号
* @param spus 匹配的商品/分类
* @return 优惠劵列表
*/
CommonResult
<
List
<
CouponCardAvailableBO
>>
getCouponCardList
(
Integer
userId
,
List
<
CouponCardSpuDTO
>
spus
);
// ========== 优惠码 ==========
/**
...
...
promotion/promotion-service-api/src/main/java/cn/iocoder/mall/promotion/api/bo/CouponCardAvailableBO.java
0 → 100644
浏览文件 @
7277ecb2
package
cn
.
iocoder
.
mall
.
promotion
.
api
.
bo
;
import
lombok.Data
;
import
lombok.experimental.Accessors
;
/**
* 可用优惠劵 BO
*
* 注意,如果优惠劵不可用,标记 available = false ,并写明 unavailableReason 原因
*/
@Data
@Accessors
(
chain
=
true
)
public
class
CouponCardAvailableBO
extends
CouponCardBO
{
/**
* 是否可用
*/
private
Boolean
available
;
/**
* 不可用原因
*/
private
String
unavailableReason
;
}
promotion/promotion-service-api/src/main/java/cn/iocoder/mall/promotion/api/dto/CouponCardSpuDTO.java
0 → 100644
浏览文件 @
7277ecb2
package
cn
.
iocoder
.
mall
.
promotion
.
api
.
dto
;
import
lombok.Data
;
import
lombok.experimental.Accessors
;
import
java.io.Serializable
;
import
java.util.List
;
/**
* 优惠劵商品 DTO
*
* 主要用于 {@link cn.iocoder.mall.promotion.api.CouponService#getCouponCardList(Integer, List)}
*/
@Data
@Accessors
(
chain
=
true
)
public
class
CouponCardSpuDTO
implements
Serializable
{
/**
* 商品 SPU 编号
*/
private
Integer
spuId
;
/**
* 商品 SKU 编号
*/
private
Integer
skuId
;
/**
* 分类编号
*/
private
Integer
categoryId
;
/**
* 价格
*/
private
Integer
price
;
/**
* 数量
*/
private
Integer
quantity
;
}
promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/convert/CouponCardConvert.java
浏览文件 @
7277ecb2
package
cn
.
iocoder
.
mall
.
promotion
.
biz
.
convert
;
import
cn.iocoder.mall.promotion.api.bo.CouponCardAvailableBO
;
import
cn.iocoder.mall.promotion.api.bo.CouponCardBO
;
import
cn.iocoder.mall.promotion.biz.dataobject.CouponCardDO
;
import
org.mapstruct.Mapper
;
...
...
@@ -22,4 +23,7 @@ public interface CouponCardConvert {
@Mappings
({})
CouponCardBO
convert
(
CouponCardDO
card
);
@Mappings
({})
CouponCardAvailableBO
convert2
(
CouponCardDO
card
,
boolean
x
);
// TODO 芋艿,临时用来解决 mapstruct 无法正确匹配方法的问题
}
promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/dao/CouponCardMapper.java
浏览文件 @
7277ecb2
...
...
@@ -11,6 +11,9 @@ public interface CouponCardMapper {
CouponCardDO
selectById
(
@Param
(
"id"
)
Integer
id
);
List
<
CouponCardDO
>
selectListByUserIdAndStatus
(
@Param
(
"userId"
)
Integer
userId
,
@Param
(
"status"
)
Integer
status
);
List
<
CouponCardDO
>
selectListByPage
(
@Param
(
"userId"
)
Integer
userId
,
@Param
(
"status"
)
Integer
status
,
@Param
(
"offset"
)
Integer
offset
,
...
...
promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/dao/CouponTemplateMapper.java
浏览文件 @
7277ecb2
...
...
@@ -4,6 +4,7 @@ import cn.iocoder.mall.promotion.biz.dataobject.CouponTemplateDO;
import
org.apache.ibatis.annotations.Param
;
import
org.springframework.stereotype.Repository
;
import
java.util.Collection
;
import
java.util.List
;
@Repository
...
...
@@ -11,6 +12,8 @@ public interface CouponTemplateMapper {
CouponTemplateDO
selectById
(
@Param
(
"id"
)
Integer
id
);
List
<
CouponTemplateDO
>
selectListByIds
(
@Param
(
"ids"
)
Collection
<
Integer
>
ids
);
List
<
CouponTemplateDO
>
selectListByPage
(
@Param
(
"type"
)
Integer
type
,
@Param
(
"title"
)
String
title
,
@Param
(
"status"
)
Integer
status
,
...
...
promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/package-info.java
deleted
100644 → 0
浏览文件 @
8962631b
package
cn
.
iocoder
.
mall
.
promotion
.
biz
;
\ No newline at end of file
promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/service/CouponServiceImpl.java
浏览文件 @
7277ecb2
...
...
@@ -3,12 +3,10 @@ package cn.iocoder.mall.promotion.biz.service;
import
cn.iocoder.common.framework.constant.SysErrorCodeEnum
;
import
cn.iocoder.common.framework.util.DateUtil
;
import
cn.iocoder.common.framework.util.ServiceExceptionUtil
;
import
cn.iocoder.common.framework.util.StringUtil
;
import
cn.iocoder.common.framework.vo.CommonResult
;
import
cn.iocoder.mall.promotion.api.CouponService
;
import
cn.iocoder.mall.promotion.api.bo.CouponCardBO
;
import
cn.iocoder.mall.promotion.api.bo.CouponCardPageBO
;
import
cn.iocoder.mall.promotion.api.bo.CouponTemplateBO
;
import
cn.iocoder.mall.promotion.api.bo.CouponTemplatePageBO
;
import
cn.iocoder.mall.promotion.api.bo.*
;
import
cn.iocoder.mall.promotion.api.constant.*
;
import
cn.iocoder.mall.promotion.api.dto.*
;
import
cn.iocoder.mall.promotion.biz.convert.CouponCardConvert
;
...
...
@@ -22,8 +20,8 @@ import org.springframework.beans.factory.annotation.Autowired;
import
org.springframework.stereotype.Service
;
import
org.springframework.transaction.annotation.Transactional
;
import
java.util.
Calendar
;
import
java.util.
Date
;
import
java.util.
*
;
import
java.util.
stream.Collectors
;
@Service
// 实际上不用添加。添加的原因是,必须 Spring 报错提示
@com
.
alibaba
.
dubbo
.
config
.
annotation
.
Service
(
validation
=
"true"
)
...
...
@@ -252,6 +250,23 @@ public class CouponServiceImpl implements CouponService {
return
null
;
}
@Override
public
CommonResult
<
List
<
CouponCardAvailableBO
>>
getCouponCardList
(
Integer
userId
,
List
<
CouponCardSpuDTO
>
spus
)
{
// 查询用户未使用的优惠劵列表
List
<
CouponCardDO
>
cards
=
couponCardMapper
.
selectListByUserIdAndStatus
(
userId
,
CouponCardStatusEnum
.
UNUSED
.
getValue
());
Map
<
Integer
,
CouponTemplateDO
>
templates
=
couponTemplateMapper
.
selectListByIds
(
cards
.
stream
().
map
(
CouponCardDO:
:
getTemplateId
).
collect
(
Collectors
.
toSet
()))
.
stream
().
collect
(
Collectors
.
toMap
(
CouponTemplateDO:
:
getId
,
template
->
template
));
// 逐个判断是否可用
List
<
CouponCardAvailableBO
>
availableCards
=
cards
.
stream
().
map
(
card
->
{
CouponCardAvailableBO
availableCard
=
CouponCardConvert
.
INSTANCE
.
convert2
(
card
,
true
);
availableCard
.
setUnavailableReason
(
isMatch
(
card
,
templates
.
get
(
card
.
getTemplateId
()),
spus
));
availableCard
.
setAvailable
(
availableCard
.
getUnavailableReason
()
==
null
);
return
availableCard
;
}).
collect
(
Collectors
.
toList
());
// 返回结果
return
CommonResult
.
success
(
availableCards
);
}
private
void
setCouponCardValidTime
(
CouponCardDO
card
,
CouponTemplateDO
template
)
{
if
(
CouponTemplateDateTypeEnum
.
FIXED_DATE
.
getValue
().
equals
(
template
.
getDateType
()))
{
card
.
setValidStartTime
(
template
.
getValidStartTime
()).
setValidEndTime
(
template
.
getValidEndTime
());
...
...
@@ -263,6 +278,35 @@ public class CouponServiceImpl implements CouponService {
}
}
// 如果匹配,则返回 null 即可。
private
String
isMatch
(
CouponCardDO
card
,
CouponTemplateDO
template
,
List
<
CouponCardSpuDTO
>
spus
)
{
int
totalPrice
=
0
;
if
(
RangeTypeEnum
.
ALL
.
getValue
().
equals
(
template
.
getRangeType
()))
{
totalPrice
=
spus
.
stream
().
mapToInt
(
spu
->
spu
.
getPrice
()
*
spu
.
getQuantity
()).
sum
();
}
else
if
(
RangeTypeEnum
.
PRODUCT_INCLUDE_PART
.
getValue
().
equals
(
template
.
getRangeType
()))
{
List
<
Integer
>
spuIds
=
StringUtil
.
splitToInt
(
template
.
getRangeValues
(),
","
);
totalPrice
=
spus
.
stream
().
mapToInt
(
spu
->
spuIds
.
contains
(
spu
.
getSpuId
())
?
spu
.
getPrice
()
*
spu
.
getQuantity
()
:
0
).
sum
();
}
else
if
(
RangeTypeEnum
.
PRODUCT_EXCLUDE_PART
.
getValue
().
equals
(
template
.
getRangeType
()))
{
List
<
Integer
>
spuIds
=
StringUtil
.
splitToInt
(
template
.
getRangeValues
(),
","
);
totalPrice
=
spus
.
stream
().
mapToInt
(
spu
->
!
spuIds
.
contains
(
spu
.
getSpuId
())
?
spu
.
getPrice
()
*
spu
.
getQuantity
()
:
0
).
sum
();
}
else
if
(
RangeTypeEnum
.
CATEGORY_INCLUDE_PART
.
getValue
().
equals
(
template
.
getRangeType
()))
{
List
<
Integer
>
spuIds
=
StringUtil
.
splitToInt
(
template
.
getRangeValues
(),
","
);
totalPrice
=
spus
.
stream
().
mapToInt
(
spu
->
spuIds
.
contains
(
spu
.
getCategoryId
())
?
spu
.
getPrice
()
*
spu
.
getQuantity
()
:
0
).
sum
();
}
else
if
(
RangeTypeEnum
.
CATEGORY_EXCLUDE_PART
.
getValue
().
equals
(
template
.
getRangeType
()))
{
List
<
Integer
>
spuIds
=
StringUtil
.
splitToInt
(
template
.
getRangeValues
(),
","
);
totalPrice
=
spus
.
stream
().
mapToInt
(
spu
->
!
spuIds
.
contains
(
spu
.
getCategoryId
())
?
spu
.
getPrice
()
*
spu
.
getQuantity
()
:
0
).
sum
();
}
// 总价为 0 时,说明优惠劵丫根不匹配
if
(
totalPrice
==
0
)
{
return
"优惠劵不匹配"
;
}
// 如果不满足金额
if
(
totalPrice
<
card
.
getPriceAvailable
())
{
return
String
.
format
(
"差 %1$,.2f 元可用优惠劵"
,
(
card
.
getPriceAvailable
()
-
totalPrice
)
/
100
D
);
}
return
null
;
}
// ========== 优惠码 ==========
@Override
...
...
promotion/promotion-service-impl/src/main/resources/mapper/CouponCardMapper.xml
浏览文件 @
7277ecb2
...
...
@@ -33,6 +33,20 @@
WHERE id = #{id}
</select>
<select
id=
"selectListByUserIdAndStatus"
resultType=
"CouponCardDO"
>
SELECT
<include
refid=
"FIELDS"
/>
FROM coupon_card
<where>
<if
test=
"userId != null"
>
AND user_id = #{userId}
</if>
<if
test=
"status != null"
>
AND status = #{status}
</if>
</where>
</select>
<select
id=
"selectListByPage"
resultType=
"CouponCardDO"
>
SELECT
<include
refid=
"FIELDS"
/>
...
...
promotion/promotion-service-impl/src/main/resources/mapper/CouponTemplateMapper.xml
浏览文件 @
7277ecb2
...
...
@@ -34,6 +34,16 @@
WHERE id = #{id}
</select>
<select
id=
"selectListByIds"
resultType=
"CouponTemplateDO"
>
SELECT
<include
refid=
"FIELDS"
/>
FROM coupon_template
WHERE id IN
<foreach
item=
"id"
collection=
"ids"
separator=
","
open=
"("
close=
")"
index=
""
>
#{id}
</foreach>
</select>
<select
id=
"selectListByPage"
resultType=
"CouponTemplateDO"
>
SELECT
<include
refid=
"FIELDS"
/>
...
...
promotion/promotion-service-impl/src/test/java/cn/iocoder/mall/promotion/biz/package-info.java
deleted
100644 → 0
浏览文件 @
8962631b
package
cn
.
iocoder
.
mall
.
promotion
.
biz
;
user/user-sdk/src/main/java/cn/iocoder/mall/user/sdk/package-info.java
deleted
100644 → 0
浏览文件 @
8962631b
/**
* 提供 SDK 给其它服务,使用如下功能:
*
* 1. 通过 {@link cn.iocoder.mall.user.sdk.interceptor.UserSecurityInterceptor} 拦截器,实现需要登陆 URL 的鉴权
*/
package
cn
.
iocoder
.
mall
.
user
.
sdk
;
\ No newline at end of file
user/user-service-impl/src/main/java/cn/iocoder/mall/user/biz/package-info.java
deleted
100644 → 0
浏览文件 @
8962631b
package
cn
.
iocoder
.
mall
.
user
.
biz
;
\ No newline at end of file
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论