Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
Y
yudao-cloud
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
hblj
yudao-cloud
Commits
d672976b
提交
d672976b
authored
4月 17, 2019
作者:
YunaiV
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
后端:商品价格计算,接入促销活动
H5 前端:购物车接入促销
上级
355c53df
隐藏空白字符变更
内嵌
并排
正在显示
13 个修改的文件
包含
360 行增加
和
124 行删除
+360
-124
application.properties
...ice-impl/src/main/resources/config/application.properties
+0
-2
mybatis-config.xml
cart/cart-service-impl/src/main/resources/mybatis-config.xml
+0
-20
index.vue
mobile-web/src/page/cart/index.vue
+56
-16
detail.vue
mobile-web/src/page/product/detail.vue
+1
-1
UsersCartDetailVO.java
.../iocoder/mall/order/application/vo/UsersCartDetailVO.java
+36
-3
UsersOrderConfirmCreateVO.java
.../mall/order/application/vo/UsersOrderConfirmCreateVO.java
+11
-2
CalcOrderPriceBO.java
...n/java/cn/iocoder/mall/order/api/bo/CalcOrderPriceBO.java
+20
-0
CartBO.java
...pi/src/main/java/cn/iocoder/mall/order/api/bo/CartBO.java
+0
-24
FeeDetailBO.java
...c/main/java/cn/iocoder/mall/order/api/bo/FeeDetailBO.java
+0
-4
MerchantItemGroup.java
.../java/cn/iocoder/mall/order/api/bo/MerchantItemGroup.java
+0
-19
CartServiceImpl.java
...va/cn/iocoder/mall/order/biz/service/CartServiceImpl.java
+199
-33
PromotionActivityBO.java
...cn/iocoder/mall/promotion/api/bo/PromotionActivityBO.java
+4
-0
MeetTypeEnum.java
.../cn/iocoder/mall/promotion/api/constant/MeetTypeEnum.java
+33
-0
没有找到文件。
cart/cart-service-impl/src/main/resources/config/application.properties
deleted
100644 → 0
浏览文件 @
355c53df
#####################
业务模块
#####################
\ No newline at end of file
cart/cart-service-impl/src/main/resources/mybatis-config.xml
deleted
100644 → 0
浏览文件 @
355c53df
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<!-- 使用驼峰命名法转换字段。 -->
<setting
name=
"mapUnderscoreToCamelCase"
value=
"true"
/>
</settings>
<typeAliases>
<typeAlias
alias=
"Integer"
type=
"java.lang.Integer"
/>
<typeAlias
alias=
"Long"
type=
"java.lang.Long"
/>
<typeAlias
alias=
"HashMap"
type=
"java.util.HashMap"
/>
<typeAlias
alias=
"LinkedHashMap"
type=
"java.util.LinkedHashMap"
/>
<typeAlias
alias=
"ArrayList"
type=
"java.util.ArrayList"
/>
<typeAlias
alias=
"LinkedList"
type=
"java.util.LinkedList"
/>
</typeAliases>
</configuration>
\ No newline at end of file
mobile-web/src/page/cart/index.vue
浏览文件 @
d672976b
...
...
@@ -14,20 +14,19 @@
<!-- <van-checkbox :name="item.id" />-->
<!-- <product-card :product='item' :iscard='false' >-->
<!-- <template slot>-->
<!-- <van-cell value="修改" >-->
<!-- <template slot="title">-->
<!-- <van-tag type="danger">促销</van-tag>-->
<!-- <span class="van-cell-text" >满60元减5元</span>-->
<!-- </template>-->
<!-- </van-cell>-->
<!-- </template>-->
<!-- </product-card>-->
<!-- </div>-->
<div
v-for=
"(itemGroup, i) in itemGroups"
class=
"card-goods__item"
>
<van-cell
>
<
template
v-if=
"itemGroup.activity"
slot=
"title"
>
<van-tag
type=
"danger"
>
满减送
</van-tag>
<span
class=
"van-cell-text"
>
{{
formatFullPrivilegeText
(
itemGroup
.
activity
)
}}
</span>
</
template
>
</van-cell>
<div
class=
"card"
v-for=
"(item, j) in itemGroup.items"
:key=
"j"
>
<van-checkbox
:key=
"item.id"
:name=
"item.id"
v-model=
"item.selected"
style=
"position: relative;"
/>
<van-checkbox
:key=
"item.id"
:name=
"item.id"
v-model=
"item.selected"
style=
"position: relative;
top: 40px;
"
/>
<product-card
:product=
'convertProduct(item)'
/>
</div>
<div
style=
"height:15px;"
></div>
...
...
@@ -47,13 +46,14 @@
<div
style=
"height:50px;"
></div>
<van-submit-bar
:tip=
"this.formatItemGroupDiscountPriceText()"
:price=
"fee.presentTotal"
:disabled=
"!checkedItemIds || !checkedItemIds.length"
:button-text=
"submitBarText"
@
submit=
"onSubmit"
>
<
template
slot
>
<van-checkbox
v-model=
"checkedAll"
@
c
hange
=
"onSelectAll"
>
全选
</van-checkbox>
<van-checkbox
v-model=
"checkedAll"
@
c
lick
=
"onSelectAll"
>
全选
</van-checkbox>
</
template
>
</van-submit-bar>
</div>
...
...
@@ -87,6 +87,39 @@ export default {
},
},
methods
:
{
formatFullPrivilegeText
(
activity
)
{
let
text
=
''
;
let
fullPrivilege
=
activity
.
fullPrivilege
;
for
(
let
i
in
fullPrivilege
.
privileges
)
{
let
privilege
=
fullPrivilege
.
privileges
[
i
];
if
(
i
>
0
)
{
text
+=
';'
;
}
if
(
fullPrivilege
.
cycled
)
{
text
+=
'每'
;
}
if
(
privilege
.
meetType
===
1
)
{
text
+=
'满 '
+
privilege
.
meetValue
/
100.0
+
' 元,'
;
}
else
if
(
privilege
.
meetType
===
2
)
{
text
+=
'满 '
+
privilege
.
meetValue
+
' 件,'
;
}
if
(
privilege
.
preferentialType
===
1
)
{
text
+=
'减 '
+
privilege
.
preferentialValue
/
100.0
+
' 元'
;
}
else
if
(
privilege
.
preferentialType
===
2
)
{
text
+=
'打 '
+
privilege
.
preferentialValue
/
10.0
+
' 折'
;
}
}
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
+
' 元'
:
''
;
},
calCheckedItemIds
()
{
// debugger;
let
itemIds
=
[];
...
...
@@ -122,11 +155,10 @@ export default {
// 计算 checkedItemIds + checkedAll
this
.
calCheckedItemIds
();
},
onItemSelectedChange
(
newVal
)
{
onItemSelectedChange
(
newVal
)
{
// TODO 芋艿,后续研究下。这样的处理方式,很奇怪。
if
(
!
this
.
checkedItemIds
)
{
return
;
}
// debugger;
let
selected
;
let
diffItemIds
;
if
(
newVal
.
length
>
this
.
oldCheckedItemIds
.
length
)
{
// 新增
...
...
@@ -152,9 +184,17 @@ export default {
if
(
this
.
checkedAll
===
undefined
)
{
return
;
}
updateCartSelected
(
this
.
getItemIds
(),
newVal
).
then
(
data
=>
{
this
.
handleData
(
data
);
})
// debugger;
// updateCartSelected(this.getItemIds(), newVal).then(data => {
// this.handleData(data);
// })
if
(
newVal
)
{
this
.
onItemSelectedChange
(
this
.
getItemIds
());
}
else
{
// alert('有 bug ,后续修复');
// this.onItemSelectedChange(this.getItemIds());
// TODO 芋艿,暂时有 bug 。后续修复
}
},
onSubmit
()
{
this
.
$router
.
push
(
'/order?from=cart'
)
...
...
@@ -164,7 +204,7 @@ export default {
return
{
...
item
.
spu
,
quantity
:
item
.
buyQuantity
,
price
:
item
.
price
,
price
:
item
.
discountPrice
||
item
.
price
,
sku
:
{
...
item
,
spu
:
undefined
,
...
...
mobile-web/src/page/product/detail.vue
浏览文件 @
d672976b
...
...
@@ -248,7 +248,7 @@
text
+=
'每'
;
}
if
(
privilege
.
meetType
===
1
)
{
text
+=
'满 '
+
privilege
.
meetValue
+
' 元,'
;
text
+=
'满 '
+
privilege
.
meetValue
/
100.0
+
' 元,'
;
}
else
if
(
privilege
.
meetType
===
2
)
{
text
+=
'满 '
+
privilege
.
meetValue
+
' 件,'
;
}
...
...
order/order-application/src/main/java/cn/iocoder/mall/order/application/vo/UsersCartDetailVO.java
浏览文件 @
d672976b
package
cn
.
iocoder
.
mall
.
order
.
application
.
vo
;
import
cn.iocoder.mall.product.api.bo.ProductAttrAndValuePairBO
;
import
cn.iocoder.mall.promotion.api.bo.PromotionActivityBO
;
import
io.swagger.annotations.ApiModel
;
import
lombok.Data
;
import
lombok.experimental.Accessors
;
...
...
@@ -30,12 +31,30 @@ public class UsersCartDetailVO {
@Accessors
(
chain
=
true
)
public
static
class
ItemGroup
{
// TODO 优惠活动
private
Object
activity
;
/**
* 优惠活动
*/
private
PromotionActivityBO
activity
;
// TODO 芋艿,偷懒
/**
* 优惠活动是否生效
*
* 多个商品,参与某个活动,因为并发达到条件,所以会存在未生效的情况。所以一共有三种情况
*
* 1. activity 非空,activityEffectEffective 为 true,参与活动,且生效
* 2. activity 非空,activityEffectEffective 为 false ,参与活动,并未生效
* 3. activity 为空,activityEffectEffective 为空,并未参与活动。
*/
private
Boolean
activityEffectEffective
;
/**
* 商品数组
*/
private
List
<
Sku
>
items
;
/**
* 费用
*
* TODO 芋艿,这里先偷懒,postageTotal 字段用不到。
*/
private
Fee
fee
;
}
...
...
@@ -79,6 +98,20 @@ public class UsersCartDetailVO {
* 是否选中
*/
private
Boolean
selected
;
/**
* 优惠活动
*/
private
PromotionActivityBO
activity
;
/**
* 折扣价
*/
private
Integer
discountPrice
;
/**
* 费用
*
* TODO 芋艿,这里先偷懒,postageTotal 字段用不到。
*/
private
Fee
fee
;
}
...
...
@@ -151,7 +184,7 @@ public class UsersCartDetailVO {
}
/**
* 邮费信息
* 邮费信息
TODO 芋艿,未完成
*/
@Data
@Accessors
(
chain
=
true
)
...
...
order/order-application/src/main/java/cn/iocoder/mall/order/application/vo/UsersOrderConfirmCreateVO.java
浏览文件 @
d672976b
package
cn
.
iocoder
.
mall
.
order
.
application
.
vo
;
import
cn.iocoder.mall.product.api.bo.ProductAttrAndValuePairBO
;
import
cn.iocoder.mall.promotion.api.bo.PromotionActivityBO
;
import
lombok.Data
;
import
lombok.experimental.Accessors
;
...
...
@@ -28,8 +29,12 @@ public class UsersOrderConfirmCreateVO {
@Accessors
(
chain
=
true
)
public
static
class
ItemGroup
{
// TODO 优惠活动
private
Object
activity
;
/**
* 优惠活动
*/
// TODO 芋艿,目前只会有【满减送】的情况,未来有新的促销方式,可能需要改成数组
// TODO 芋艿,后面改成 VO
private
PromotionActivityBO
activity
;
/**
* 商品数组
*/
...
...
@@ -73,6 +78,10 @@ public class UsersOrderConfirmCreateVO {
* 购买数量
*/
private
Integer
buyQuantity
;
/**
* 折扣价
*/
private
Integer
discountPrice
;
}
...
...
order/order-service-api/src/main/java/cn/iocoder/mall/order/api/bo/CalcOrderPriceBO.java
浏览文件 @
d672976b
...
...
@@ -41,10 +41,26 @@ public class CalcOrderPriceBO {
*/
// TODO 芋艿,目前只会有【满减送】的情况,未来有新的促销方式,可能需要改成数组
private
PromotionActivityBO
activity
;
/**
* 优惠活动是否生效
*
* 多个商品,参与某个活动,因为并发达到条件,所以会存在未生效的情况。所以一共有三种情况
*
* 1. activity 非空,activityEffectEffective 为 true,参与活动,且生效
* 2. activity 非空,activityEffectEffective 为 false ,参与活动,并未生效
* 3. activity 为空,activityEffectEffective 为空,并未参与活动。
*/
private
Boolean
activityEffectEffective
;
/**
* 商品数组
*/
private
List
<
Item
>
items
;
/**
* 费用
*
* TODO 芋艿,这里先偷懒,postageTotal 字段用不到。
*/
private
Fee
fee
;
}
...
...
@@ -70,6 +86,10 @@ public class CalcOrderPriceBO {
* TODO 芋艿,这里先偷懒,postageTotal 字段用不到。
*/
private
Fee
fee
;
/**
* 折扣价
*/
private
Integer
discountPrice
;
}
...
...
order/order-service-api/src/main/java/cn/iocoder/mall/order/api/bo/CartBO.java
deleted
100644 → 0
浏览文件 @
355c53df
package
cn
.
iocoder
.
mall
.
order
.
api
.
bo
;
import
lombok.Data
;
import
lombok.experimental.Accessors
;
import
java.util.List
;
/**
* 购物车明细 BO
*/
@Data
@Accessors
(
chain
=
true
)
public
class
CartBO
{
/**
* 商品分组数组
*/
private
List
<
CartItemGroupBO
>
itemGroups
;
/**
* 费用
*/
private
FeeMessageBO
fee
;
}
order/order-service-api/src/main/java/cn/iocoder/mall/order/api/bo/FeeDetailBO.java
deleted
100644 → 0
浏览文件 @
355c53df
package
cn
.
iocoder
.
mall
.
order
.
api
.
bo
;
public
class
FeeDetailBO
{
}
order/order-service-api/src/main/java/cn/iocoder/mall/order/api/bo/MerchantItemGroup.java
deleted
100644 → 0
浏览文件 @
355c53df
package
cn
.
iocoder
.
mall
.
order
.
api
.
bo
;
import
java.util.List
;
/**
* 商家商品分组
*/
public
class
MerchantItemGroup
{
/**
* 商品分组数组
*/
private
List
<
CartItemGroupBO
>
itemGroups
;
/**
* 运费详情
*/
private
PostageDetailBO
postageDetail
;
}
order/order-service-impl/src/main/java/cn/iocoder/mall/order/biz/service/CartServiceImpl.java
浏览文件 @
d672976b
...
...
@@ -18,12 +18,11 @@ import cn.iocoder.mall.product.api.bo.ProductSkuBO;
import
cn.iocoder.mall.product.api.bo.ProductSkuDetailBO
;
import
cn.iocoder.mall.promotion.api.PromotionActivityService
;
import
cn.iocoder.mall.promotion.api.bo.PromotionActivityBO
;
import
cn.iocoder.mall.promotion.api.constant.PreferentialTypeEnum
;
import
cn.iocoder.mall.promotion.api.constant.PromotionActivityStatusEnum
;
import
cn.iocoder.mall.promotion.api.constant.PromotionActivityTypeEnum
;
import
cn.iocoder.mall.promotion.api.constant.*
;
import
com.alibaba.dubbo.config.annotation.Reference
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Service
;
import
org.springframework.util.Assert
;
import
java.util.*
;
import
java.util.stream.Collectors
;
...
...
@@ -155,43 +154,41 @@ public class CartServiceImpl implements CartService {
public
CommonResult
<
CalcOrderPriceBO
>
calcOrderPrice
(
CalcOrderPriceDTO
calcOrderPriceDTO
)
{
// 校验商品都存在
Map
<
Integer
,
CalcOrderPriceDTO
.
Item
>
calcOrderItemMap
=
calcOrderPriceDTO
.
getItems
().
stream
()
.
collect
(
Collectors
.
toMap
(
CalcOrderPriceDTO
.
Item
::
getSkuId
,
item
->
item
));
.
collect
(
Collectors
.
toMap
(
CalcOrderPriceDTO
.
Item
::
getSkuId
,
item
->
item
));
// KEY:skuId
List
<
ProductSkuDetailBO
>
skus
=
productSpuService
.
getProductSkuDetailList
(
calcOrderItemMap
.
keySet
()).
getData
();
if
(
skus
.
size
()
!=
calcOrderPriceDTO
.
getItems
().
size
())
{
return
ServiceExceptionUtil
.
error
(
OrderErrorCodeEnum
.
ORDER_ITEM_SOME_NOT_EXISTS
.
getCode
());
}
// TODO 库存相关
// TODO 获得促销活动
// TODO 处理促销相关信息
// 拼装结果
CalcOrderPriceBO
calcOrderPriceBO
=
new
CalcOrderPriceBO
();
// 1. 商品分组
CalcOrderPriceBO
.
ItemGroup
itemGroup0
=
new
CalcOrderPriceBO
.
ItemGroup
()
.
setItems
(
new
ArrayList
<>());
for
(
ProductSkuDetailBO
sku
:
skus
)
{
CalcOrderPriceBO
.
Item
item
=
CartConvert
.
INSTANCE
.
convert
(
sku
);
// 将是否选中,购物数量,复制到 item 中
CalcOrderPriceDTO
.
Item
calcOrderItem
=
calcOrderItemMap
.
get
(
sku
.
getId
());
item
.
setSelected
(
calcOrderItem
.
getSelected
());
item
.
setBuyQuantity
(
calcOrderItem
.
getQuantity
());
// 添加到 itemGroup 中
itemGroup0
.
getItems
().
add
(
item
);
// 查询促销活动
CommonResult
<
List
<
PromotionActivityBO
>>
activityListResult
=
promotionActivityService
.
getPromotionActivityListBySpuIds
(
skus
.
stream
().
map
(
sku
->
sku
.
getSpu
().
getId
()).
collect
(
Collectors
.
toSet
()),
Collections
.
singletonList
(
PromotionActivityStatusEnum
.
RUN
.
getValue
()));
if
(
activityListResult
.
isError
())
{
return
CommonResult
.
error
(
activityListResult
);
}
calcOrderPriceBO
.
setItemGroups
(
Collections
.
singletonList
(
itemGroup0
));
// 2. 计算价格
CalcOrderPriceBO
.
Fee
fee
=
new
CalcOrderPriceBO
.
Fee
(
0
,
0
,
0
,
0
);
List
<
PromotionActivityBO
>
activityList
=
activityListResult
.
getData
();
// 拼装结果(主要是计算价格)
CalcOrderPriceBO
calcOrderPriceBO
=
new
CalcOrderPriceBO
();
// 1. 创建初始的每一项的数组
List
<
CalcOrderPriceBO
.
Item
>
items
=
initCalcOrderPriceItems
(
skus
,
calcOrderItemMap
);
// 2. 计算【限时折扣】促销
modifyPriceByTimeLimitDiscount
(
items
,
activityList
);
// 3. 计算【满减送】促销
List
<
CalcOrderPriceBO
.
ItemGroup
>
itemGroups
=
groupByFullPrivilege
(
items
,
activityList
);
calcOrderPriceBO
.
setItemGroups
(
itemGroups
);
// 4. 计算最终的价格
Integer
originalTotal
=
0
;
Integer
presentTotal
=
0
;
Integer
discountTotal
=
0
;
for
(
CalcOrderPriceBO
.
ItemGroup
itemGroup
:
calcOrderPriceBO
.
getItemGroups
())
{
int
originalTotal
=
0
;
for
(
CalcOrderPriceBO
.
Item
item
:
itemGroup
.
getItems
())
{
if
(!
item
.
getSelected
())
{
// 未选中,则不计算到其中
continue
;
}
originalTotal
+=
item
.
getPrice
()
*
item
.
getBuyQuantity
();
}
fee
.
setOriginalTotal
(
fee
.
getOriginalTotal
()
+
originalTotal
);
fee
.
setPresentTotal
(
fee
.
getOriginalTotal
());
// TODO 芋艿,后续要计算优惠价格
originalTotal
+=
itemGroup
.
getItems
().
stream
().
mapToInt
(
item
->
item
.
getSelected
()
?
item
.
getFee
().
getOriginalTotal
()
:
0
).
sum
();
discountTotal
+=
itemGroup
.
getFee
().
getDiscountTotal
()
+
itemGroup
.
getItems
().
stream
().
mapToInt
(
item
->
item
.
getSelected
()
?
item
.
getFee
().
getDiscountTotal
()
:
0
).
sum
();
presentTotal
+=
itemGroup
.
getFee
().
getPresentTotal
();
}
calcOrderPriceBO
.
setFee
(
fee
);
Assert
.
isTrue
(
originalTotal
-
discountTotal
==
presentTotal
,
String
.
format
(
"价格合计( %d - %d == %d )不正确"
,
originalTotal
,
discountTotal
,
presentTotal
));
calcOrderPriceBO
.
setFee
(
new
CalcOrderPriceBO
.
Fee
(
originalTotal
,
discountTotal
,
0
,
presentTotal
));
// 返回
return
CommonResult
.
success
(
calcOrderPriceBO
);
}
...
...
@@ -229,7 +226,107 @@ public class CartServiceImpl implements CartService {
.
setOriginalPrice
(
sku
.
getPrice
()).
setPresentPrice
(
presentPrice
));
}
private
List
<
CalcOrderPriceBO
.
Item
>
initCalcOrderPriceItems
(
List
<
ProductSkuDetailBO
>
skus
,
Map
<
Integer
,
CalcOrderPriceDTO
.
Item
>
calcOrderItemMap
)
{
List
<
CalcOrderPriceBO
.
Item
>
items
=
new
ArrayList
<>();
for
(
ProductSkuDetailBO
sku
:
skus
)
{
CalcOrderPriceBO
.
Item
item
=
CartConvert
.
INSTANCE
.
convert
(
sku
);
items
.
add
(
item
);
// 将是否选中,购物数量,复制到 item 中
CalcOrderPriceDTO
.
Item
calcOrderItem
=
calcOrderItemMap
.
get
(
sku
.
getId
());
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
);
}
return
items
;
}
private
void
modifyPriceByTimeLimitDiscount
(
List
<
CalcOrderPriceBO
.
Item
>
items
,
List
<
PromotionActivityBO
>
activityList
)
{
for
(
CalcOrderPriceBO
.
Item
item
:
items
)
{
// 获得符合条件的限时折扣
PromotionActivityBO
timeLimitedDiscount
=
activityList
.
stream
()
.
filter
(
activity
->
PromotionActivityTypeEnum
.
TIME_LIMITED_DISCOUNT
.
getValue
().
equals
(
activity
.
getActivityType
())
&&
activity
.
getTimeLimitedDiscount
().
getItems
().
stream
().
anyMatch
(
item0
->
item0
.
getSpuId
().
equals
(
item
.
getSpu
().
getId
())))
.
findFirst
().
orElse
(
null
);
if
(
timeLimitedDiscount
==
null
)
{
continue
;
}
// 计算价格
ProductSkuBO
sku
=
new
ProductSkuBO
().
setId
(
item
.
getId
()).
setSpuId
(
item
.
getSpu
().
getId
()).
setPrice
(
item
.
getPrice
());
Integer
newPrice
=
calcSkuPriceByTimeLimitDiscount
(
sku
,
timeLimitedDiscount
);
if
(
newPrice
.
equals
(
item
.
getPrice
()))
{
continue
;
}
// 设置优惠
item
.
setActivity
(
timeLimitedDiscount
);
// 设置价格
item
.
setDiscountPrice
(
newPrice
);
CalcOrderPriceBO
.
Fee
fee
=
item
.
getFee
();
fee
.
setDiscountTotal
(
fee
.
getDiscountTotal
()
+
(
item
.
getPrice
()
-
newPrice
)
*
item
.
getBuyQuantity
());
fee
.
setPresentTotal
(
fee
.
getOriginalTotal
()
-
fee
.
getDiscountTotal
()
+
fee
.
getPostageTotal
());
}
}
private
List
<
CalcOrderPriceBO
.
ItemGroup
>
groupByFullPrivilege
(
List
<
CalcOrderPriceBO
.
Item
>
items
,
List
<
PromotionActivityBO
>
activityList
)
{
List
<
CalcOrderPriceBO
.
ItemGroup
>
itemGroups
=
new
ArrayList
<>();
// 获得所有满减送促销
List
<
PromotionActivityBO
>
fullPrivileges
=
activityList
.
stream
()
.
filter
(
activity
->
PromotionActivityTypeEnum
.
FULL_PRIVILEGE
.
getValue
().
equals
(
activity
.
getActivityType
()))
.
collect
(
Collectors
.
toList
());
// 基于满减送促销,进行分组
if
(!
fullPrivileges
.
isEmpty
())
{
items
=
new
ArrayList
<>(
items
);
// 因为下面会修改数组,进行浅拷贝,避免影响传入的 items 。
for
(
PromotionActivityBO
fullPrivilege
:
fullPrivileges
)
{
// 创建 fullPrivilege 对应的分组
CalcOrderPriceBO
.
ItemGroup
itemGroup
=
new
CalcOrderPriceBO
.
ItemGroup
()
.
setActivity
(
fullPrivilege
)
.
setItems
(
new
ArrayList
<>());
// 筛选商品到分组中
for
(
Iterator
<
CalcOrderPriceBO
.
Item
>
iterator
=
items
.
iterator
();
iterator
.
hasNext
();
)
{
CalcOrderPriceBO
.
Item
item
=
iterator
.
next
();
if
(!
isSpuMatchFullPrivilege
(
item
.
getSpu
().
getId
(),
fullPrivilege
))
{
continue
;
}
itemGroup
.
getItems
().
add
(
item
);
iterator
.
remove
();
}
// 如果匹配到,则添加到 itemGroups 中
if
(!
itemGroup
.
getItems
().
isEmpty
())
{
itemGroups
.
add
(
itemGroup
);
}
}
}
// 处理未参加活动的商品,形成一个分组
if
(!
items
.
isEmpty
())
{
CalcOrderPriceBO
.
ItemGroup
itemGroup
=
new
CalcOrderPriceBO
.
ItemGroup
()
.
setItems
(
items
);
itemGroups
.
add
(
itemGroup
);
}
// 计算每个分组的价格
for
(
CalcOrderPriceBO
.
ItemGroup
itemGroup
:
itemGroups
)
{
itemGroup
.
setFee
(
calcSkuPriceByFullPrivilege
(
itemGroup
));
itemGroup
.
setActivityEffectEffective
(
itemGroup
.
getFee
().
getDiscountTotal
()
>
0
);
}
// 返回结果
return
itemGroups
;
}
/**
* 计算指定 SKU 在限时折扣下的价格
*
* @param sku SKU
* @param timeLimitedDiscount 限时折扣促销。
* 传入的该活动,要保证该 SKU 在该促销下一定有优惠。
* @return 计算后的价格
*/
private
Integer
calcSkuPriceByTimeLimitDiscount
(
ProductSkuBO
sku
,
PromotionActivityBO
timeLimitedDiscount
)
{
if
(
timeLimitedDiscount
==
null
)
{
return
sku
.
getPrice
();
}
// 获得对应的优惠项
PromotionActivityBO
.
TimeLimitedDiscount
.
Item
item
=
timeLimitedDiscount
.
getTimeLimitedDiscount
().
getItems
().
stream
()
.
filter
(
item0
->
item0
.
getSpuId
().
equals
(
sku
.
getSpuId
()))
...
...
@@ -244,15 +341,84 @@ public class CartServiceImpl implements CartService {
return
presentPrice
>=
0
?
presentPrice
:
sku
.
getPrice
();
// 如果计算优惠价格小于 0 ,则说明无法使用优惠。
}
if
(
PreferentialTypeEnum
.
DISCOUNT
.
getValue
().
equals
(
item
.
getPreferentialType
()))
{
// 打折
return
sku
.
getPrice
()
*
item
.
getPreferentialValue
()
/
10
;
return
sku
.
getPrice
()
*
item
.
getPreferentialValue
()
/
10
0
;
}
throw
new
IllegalArgumentException
(
String
.
format
(
"折扣活动(%s) 的优惠类型不正确"
,
timeLimitedDiscount
.
toString
()));
}
private
CalcOrderPriceBO
.
Fee
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
);
}
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
<
PromotionActivityBO
.
FullPrivilege
.
Privilege
>
privileges
=
activity
.
getFullPrivilege
().
getPrivileges
().
stream
()
.
filter
(
privilege
->
{
if
(
MeetTypeEnum
.
PRICE
.
getValue
().
equals
(
privilege
.
getMeetType
()))
{
return
originalTotal
>=
privilege
.
getMeetValue
();
}
if
(
MeetTypeEnum
.
QUANTITY
.
getValue
().
equals
(
privilege
.
getMeetType
()))
{
return
itemCnt
>=
privilege
.
getMeetValue
();
}
throw
new
IllegalArgumentException
(
String
.
format
(
"满减送活动(%s) 的匹配(%s)不正确"
,
itemGroup
.
getActivity
().
toString
(),
privilege
.
toString
()));
}).
collect
(
Collectors
.
toList
());
// 获得不到优惠信息,返回原始价格
if
(
privileges
.
isEmpty
())
{
return
new
CalcOrderPriceBO
.
Fee
(
originalTotal
,
0
,
0
,
originalTotal
);
}
// 获得到优惠信息,进行价格计算
PromotionActivityBO
.
FullPrivilege
.
Privilege
privilege
=
privileges
.
get
(
privileges
.
size
()
-
1
);
Integer
presentTotal
;
if
(
PreferentialTypeEnum
.
PRICE
.
getValue
().
equals
(
privilege
.
getPreferentialType
()))
{
// 减价
// 计算循环次数。这样,后续优惠的金额就是相乘了
Integer
cycleCount
=
1
;
if
(
activity
.
getFullPrivilege
().
getCycled
())
{
if
(
MeetTypeEnum
.
PRICE
.
getValue
().
equals
(
privilege
.
getMeetType
()))
{
cycleCount
=
originalTotal
/
privilege
.
getMeetValue
();
}
else
if
(
MeetTypeEnum
.
QUANTITY
.
getValue
().
equals
(
privilege
.
getMeetType
()))
{
cycleCount
=
itemCnt
/
privilege
.
getMeetValue
();
}
}
presentTotal
=
originalTotal
-
cycleCount
*
privilege
.
getMeetValue
();
if
(
presentTotal
<
0
)
{
// 如果计算优惠价格小于 0 ,则说明无法使用优惠。
presentTotal
=
originalTotal
;
}
}
else
if
(
PreferentialTypeEnum
.
DISCOUNT
.
getValue
().
equals
(
privilege
.
getPreferentialType
()))
{
// 打折
presentTotal
=
originalTotal
*
privilege
.
getPreferentialValue
()
/
100
;
}
else
{
throw
new
IllegalArgumentException
(
String
.
format
(
"满减送促销(%s) 的优惠类型不正确"
,
activity
.
toString
()));
}
return
new
CalcOrderPriceBO
.
Fee
(
originalTotal
,
originalTotal
-
presentTotal
,
0
,
presentTotal
);
}
private
PromotionActivityBO
findPromotionActivityByType
(
List
<
PromotionActivityBO
>
activityList
,
PromotionActivityTypeEnum
type
)
{
return
activityList
.
stream
()
.
filter
(
activity
->
type
.
getValue
().
equals
(
activity
.
getActivityType
()))
.
findFirst
().
orElse
(
null
);
}
private
List
<
PromotionActivityBO
>
findPromotionActivityListByType
(
List
<
PromotionActivityBO
>
activityList
,
PromotionActivityTypeEnum
type
)
{
return
activityList
.
stream
()
.
filter
(
activity
->
type
.
getValue
().
equals
(
activity
.
getActivityType
()))
.
collect
(
Collectors
.
toList
());
}
private
boolean
isSpuMatchFullPrivilege
(
Integer
spuId
,
PromotionActivityBO
activity
)
{
Assert
.
isTrue
(
PromotionActivityTypeEnum
.
FULL_PRIVILEGE
.
getValue
().
equals
(
activity
.
getActivityType
()),
"传入的必须的促销活动必须是满减送"
);
PromotionActivityBO
.
FullPrivilege
fullPrivilege
=
activity
.
getFullPrivilege
();
if
(
RangeTypeEnum
.
ALL
.
getValue
().
equals
(
fullPrivilege
.
getRangeType
()))
{
return
true
;
}
else
if
(
RangeTypeEnum
.
PRODUCT_INCLUDE_PART
.
getValue
().
equals
(
fullPrivilege
.
getRangeType
()))
{
return
fullPrivilege
.
getRangeValues
().
contains
(
spuId
);
}
else
{
throw
new
IllegalArgumentException
(
String
.
format
(
"促销活动(%s) 可用范围的类型是不正确"
,
activity
.
toString
()));
}
}
}
promotion/promotion-service-api/src/main/java/cn/iocoder/mall/promotion/api/bo/PromotionActivityBO.java
浏览文件 @
d672976b
...
...
@@ -128,6 +128,10 @@ public class PromotionActivityBO implements Serializable {
* 指定可用商品列表
*/
private
List
<
Integer
>
rangeValues
;
/**
* 是否循环
*/
private
Boolean
cycled
;
/**
* 优惠数组
*/
...
...
promotion/promotion-service-api/src/main/java/cn/iocoder/mall/promotion/api/constant/MeetTypeEnum.java
0 → 100644
浏览文件 @
d672976b
package
cn
.
iocoder
.
mall
.
promotion
.
api
.
constant
;
/**
* 匹配类型枚举
*/
public
enum
MeetTypeEnum
{
PRICE
(
1
,
"金额"
),
QUANTITY
(
2
,
"数量"
),;
/**
* 值
*/
private
final
Integer
value
;
/**
* 名字
*/
private
final
String
name
;
MeetTypeEnum
(
Integer
value
,
String
name
)
{
this
.
value
=
value
;
this
.
name
=
name
;
}
public
Integer
getValue
()
{
return
value
;
}
public
String
getName
()
{
return
name
;
}
}
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论