優惠結果詳細說明
讓我們用 2 個簡單的例子說明。
假設商品資料為:
const a30: Commodity = {
key: '1',
name: 'A-30ml',
price: 6000
}
const a50: Commodity = {
key: '2',
name: 'A-50ml',
price: 9000
}優惠為「A 商品 30ml、50ml,任兩件 85 折」
const promotionAnyTwoA15Off: Promotion = {
key: '5',
type: 'commodity-offer',
name: 'A 商品優惠',
description: '30ml、50ml,任兩件 85 折',
contents: [
{
condition: [
{
list: [a50, a30],
comparison: {
logic: 'equal',
target: 'purchase-quantity',
value: 2
}
}
],
result: {
operator: 'mul',
value: 0.85
}
}
]
}一般結果
2 個 A 30ml
可以預期一定符合優惠,這時候得到的結果為:
const result = [
{
giveawayList: [],
offsetList: [],
originalItems: [
{
commodity: a30,
quantity: 2
}
],
remainingItems: [],
promotedList: [
{
appliedList: [
{
item: {
commodity: a30,
quantity: 2
}
}
],
promotedContent: {
condition: [
{
list: [
{
key: '1',
name: 'A',
specifications: [
'30ml'
],
price: 6000
},
{
key: '2',
name: 'A',
specifications: [
'50ml'
],
price: 9000
}
],
comparison: {
logic: 'equal',
target: 'purchase-quantity',
value: 2
}
}
],
result: {
operator: 'mul',
value: 0.85
}
},
promotion: {
key: '5',
type: 'commodity-offer',
name: 'A 商品優惠',
description: '30ml、50ml,任兩件 85 折',
contents: [
{
condition: [
{
list: [
{
key: '1',
name: 'A',
specifications: [
'30ml'
],
price: 6000
},
{
key: '2',
name: 'A',
specifications: [
'50ml'
],
price: 9000
}
],
comparison: {
logic: 'equal',
target: 'purchase-quantity',
value: 2
}
}
],
result: {
operator: 'mul',
value: 0.85
}
}
]
}
}
]
}
]很長很長,讓我們一項一項看。
由於沒有贈品,所以 giveawayList 和 offsetList 都是空矩陣,所以這兩者先跳過不看。
originalItems
此欄位等於原始購買內容,所以就是 2 個 A 30ml。
"originalItems": [
{
"commodity": a30,
"quantity": 2
}
],remainingItems
此欄位表示沒有套用優惠,被剩下來的商品。
由於 2 個 A 30ml 都被加入優惠,沒有剩下任何商品,所以會得到空矩陣。
"remainingItems": [],promotedList
此欄位表示被套用優惠的商品與詳細商品細節。
其中 appliedList 為被套用的商品,也就是 2 個 A 30ml。
{
"appliedList": [
{
"item": {
"commodity": a30,
"quantity": 2
}
}
],
...
}剩下的欄位其實很單純:
- promotedContent 表示實際上符合的 contents
- promotion 則是優惠本體
所以那個很長的結果其實完全等效於以下內容:
{
"promotedContent": promotionAnyTwoA15Off.contents[0],
"promotion": promotionAnyTwoA15Off
}3 個 A 30ml
和剛剛的例子只差在多了 1 個 A,可以預期 2 個 A 有套用優惠,最後剩下 1 個 A。
讓我們來看看結果:
const result = [
{
giveawayList: [],
offsetList: [],
originalItems: [
{
commodity: a30,
quantity: 3
}
],
remainingItems: [
{
commodity: a30,
quantity: 1
}
],
promotedList: [
{
appliedList: [
{
item: {
commodity: a30,
quantity: 2
}
}
],
promotedContent: promotionAnyTwoA15Off.contents[0],
promotion: promotionAnyTwoA15Off
}
]
}
]originalItems
3 個 A 30ml 沒錯。
"originalItems": [
{
"commodity": a30,
"quantity": 3
}
],remainingItems
由於 2 個 A 30ml 都被加入優惠,剩下 1 個 A
"remainingItems": [
{
"commodity": a30,
"quantity": 1
}
],promotedList
一樣套用了 2 個 A,所以會與上一個例子相同。
{
"appliedList": [
{
"item": {
"commodity": a30,
"quantity": 2
}
}
],
"promotedContent": promotionAnyTwoA15Off.contents[0],
"promotion": promotionAnyTwoA15Off
}贈品自動抵銷
autoOffsetMode 有以下模式:
single-type:
贈品種類只有一種時,自動抵銷商品。超過一種則不抵銷,同一般贈品。
multiple-types-from-highest:
不管種類多寡,都從價值最高的贈品開始抵銷。
使用範例
const offsetPromotions = getPromotionsRanking({
items,
promotions,
autoOffsetMode: 'multiple-types-from-highest',
})假設有以下優惠:
const promotion01: Promotion = {
key: '5',
type: 'commodity-offer',
name: 'A 商品優惠',
description: '買 A 系列 50ml 2 瓶,送 1 瓶 30ml',
contents: [
{
condition: [
{
list: [a50],
comparison: {
logic: 'equal',
target: 'purchase-quantity',
value: 2
}
}
],
result: {
commodities: [a30],
quantity: 1,
}
}
]
}
const promotion02: Promotion = {
key: '6',
type: 'commodity-offer',
name: 'A 商品優惠',
description: '買 A 系列任 5 瓶,送 A 系列任選 1 瓶',
contents: [
{
condition: [
{
list: [a50, a30],
comparison: {
logic: 'equal',
target: 'purchase-quantity',
value: 5
}
}
],
result: {
commodities: [a30, a50],
quantity: 1,
}
}
]
}2 瓶 A 50ml、1 瓶 A 30ml
這裡使用 promotion01 優惠,不難看出 1 瓶 A 30ml 會被自動抵銷。
由於贈品只有 1 種,所以不管是哪一種模式結果都會相同。
const result: PromotionResult = {
giveawayList: [],
offsetList: [
{
item: { commodity: a30, quantity: 1 },
promotedContent: promotion01.contents[0],
promotion: promotion01,
},
],
originalItems: [
{ commodity: a50, quantity: 2 },
{ commodity: a30, quantity: 1 },
],
remainingItems: [],
promotedList: [
{
appliedList: [
{ item: { commodity: a50, quantity: 2 } }
],
promotedContent: promotion01.contents[0],
promotion: promotion01,
}
]
}可以看到 a30 跑到 offsetList 裡面去了。ლ(╹◡╹ლ)
6 瓶 A 50ml、1 瓶 A 30ml
這裡使用 promotion02 優惠,由於贈品有 2 種,所以這次不同模式結果會不同。
single-type
由於贈品有 2 種,所以不會自動抵銷。
const result: PromotionResult = {
giveawayList: [
{
item: {
commodities: [ a30, a50 ], quantity: 1,
},
promotedContent: promotion01.contents[0],
promotion: promotion01,
},
],
offsetList: [],
originalItems: [
{ commodity: a50, quantity: 6 },
{ commodity: a30, quantity: 1 },
],
remainingItems: [
{ commodity: a50, quantity: 1 },
{ commodity: a30, quantity: 1 },
],
promotedList: [
{
appliedList: [
{
item: { commodity: a50, quantity: 5 }
}
],
promotedContent: promotion02.contents[0],
promotion: promotion02,
}
]
}可以看到 giveawayList 裡有東西了。(。・∀・)ノ゙
multiple-types-from-highest
此模式會從最貴的商品開始抵銷,所以會抵銷 a50,而非 a30。
const result: PromotionResult = {
giveawayList: [],
offsetList: [
{
item: { commodity: a50, quantity: 1 },
promotedContent: promotion02.contents[0],
promotion: promotion02,
}
],
originalItems: [
{ commodity: a50, quantity: 6 },
{ commodity: a30, quantity: 1 },
],
remainingItems: [
{ commodity: a30, quantity: 1 },
],
promotedList: [
{
appliedList: [
{
item: { commodity: a50, quantity: 5 }
}
],
promotedContent: promotion02.contents[0],
promotion: promotion02,
}
]
}可以看到剩下的那一個 a50 跑到 offsetList 了。