Skip to content

優惠結果詳細說明

讓我們用 2 個簡單的例子說明。

假設商品資料為:

ts
const a30: Commodity = {
  key: '1',
  name: 'A-30ml',
  price: 6000
}

const a50: Commodity = {
  key: '2',
  name: 'A-50ml',
  price: 9000
}

優惠為「A 商品 30ml、50ml,任兩件 85 折」

ts
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

可以預期一定符合優惠,這時候得到的結果為:

ts
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。

json
"originalItems": [
  {
    "commodity": a30,
    "quantity": 2
  }
],

remainingItems

此欄位表示沒有套用優惠,被剩下來的商品。

由於 2 個 A 30ml 都被加入優惠,沒有剩下任何商品,所以會得到空矩陣。

json
"remainingItems": [],

promotedList

此欄位表示被套用優惠的商品與詳細商品細節。

其中 appliedList 為被套用的商品,也就是 2 個 A 30ml。

json
{
  "appliedList": [
    {
      "item": {
        "commodity": a30,
        "quantity": 2
      }
    }
  ],
  ...
}

剩下的欄位其實很單純:

  • promotedContent 表示實際上符合的 contents
  • promotion 則是優惠本體

所以那個很長的結果其實完全等效於以下內容:

json
{
  "promotedContent": promotionAnyTwoA15Off.contents[0],
  "promotion": promotionAnyTwoA15Off
}

3 個 A 30ml

和剛剛的例子只差在多了 1 個 A,可以預期 2 個 A 有套用優惠,最後剩下 1 個 A。

讓我們來看看結果:

ts
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 沒錯。

json
"originalItems": [
  {
    "commodity": a30,
    "quantity": 3
  }
],

remainingItems

由於 2 個 A 30ml 都被加入優惠,剩下 1 個 A

json
"remainingItems": [
  {
    "commodity": a30,
    "quantity": 1
  }
],

promotedList

一樣套用了 2 個 A,所以會與上一個例子相同。

json
{
  "appliedList": [
    {
      "item": {
        "commodity": a30,
        "quantity": 2
      }
    }
  ],
  "promotedContent": promotionAnyTwoA15Off.contents[0],
  "promotion": promotionAnyTwoA15Off
}

贈品自動抵銷

autoOffsetMode 有以下模式:

  • single-type:

    贈品種類只有一種時,自動抵銷商品。超過一種則不抵銷,同一般贈品。

  • multiple-types-from-highest:

    不管種類多寡,都從價值最高的贈品開始抵銷。

使用範例

ts
const offsetPromotions = getPromotionsRanking({
  items,
  promotions,
  autoOffsetMode: 'multiple-types-from-highest',
})

假設有以下優惠:

ts
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 種,所以不管是哪一種模式結果都會相同。

ts
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 種,所以不會自動抵銷。

ts
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。

ts
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 了。