達標提示是對購物車的唯讀投影,不是另外寫一份判斷。


購物車頁很常需要這種提示:

✓ 滿 3000 折扣 10%
  滿 5000 送旅行組,還差 $1,400

這個功能看起來很單純,所以通常是前端工程師或某個趕時間的人,隨手在 blade 裡寫一段判斷:

@if ($subtotal >= 5000)

然後過一陣子客服就會收到客訴:「你們網站說我滿額有送贈品,我結帳完沒有。」

原因幾乎都一樣:提示用的基準金額,跟計價用的基準金額不是同一個。 例如提示算的是「含加價購」的小計,計價規則算的是「不含加價購」的商品金額。差一個加價購的 99 元,客戶就跨過了門檻,但實際入帳沒有。

我的處理方式是,把這個提示當成對購物車的唯讀投影,寫成一個純函式,跟計價規則放在一起:

PromotionStatus::forCart($promos, $state): PromotionProgress[]

每一筆 progress 就四件事:文案、有沒有達標、還差多少、門檻是多少。

description   "滿 5000 送旅行組"
met           false
remaining     1400
threshold     5000

關鍵在第一行:

$base = $state->linesSubtotal();

跟計價規則用的是同一個方法。 滿額折扣用 linesSubtotal()、滿額禮用 linesSubtotal()、達標提示也用 linesSubtotal()。三個地方不可能算出不同答案,因為它們讀的是同一顆數字。

我在 CartState 上刻意分了兩個名字,就是為了這件事:

itemsSubtotal()   // 商品 + 加價購,用來算應付金額
linesSubtotal()   // 只算商品,用來當所有滿額門檻的基準

為什麼加價購不算進門檻?因為加價購是「因為你達標了所以給你的優惠」,讓它反過來幫你達標,邏輯上是繞回去的,而且客戶會拿 99 元的加購品去湊 5000 的贈品門檻。

至於「不含加價購」這個決策本身對不對,其實不是重點。重點是這個決策只存在一個地方,而畫面上的提示是從那個地方投影出來的,不是另外抄一份。

順帶一提,這個投影還會回傳 kind(discount / gift),前端拿它決定要顯示哪個 icon。文案跟排序在後端決定,前端只負責畫。前端不做促銷判斷——這是我的底線。


⭐️ Shopify 網站開發服務(給品牌)
https://job.turn.tw/shopify-services

⭐️ 川川電商事務所(全客製電商開發服務)
https://chuanchuan.tw

⭐️ 台灣 Shopify 商家交流 LINE 群(非官方)
https://line.me/ti/g2/PZ_1LILWVWWuzZQ50HNpYA-A3k6QXWF6znqoBQ

⭐️ 台灣 Shopify 開發者 LINE 群(非官方)
https://line.me/ti/g2/YUasX5K3CJ4QdIx76zppjHlh3-q8w-xkSyK1LA

共有 0 則留言


⭐️ Shopify 網站開發服務(給品牌)
https://job.turn.tw/shopify-services

⭐️ 川川電商事務所(全客製電商開發服務)
https://chuanchuan.tw

⭐️ 台灣 Shopify 商家交流 LINE 群(非官方)
https://line.me/ti/g2/PZ_1LILWVWWuzZQ50HNpYA-A3k6QXWF6znqoBQ

⭐️ 台灣 Shopify 開發者 LINE 群(非官方)
https://line.me/ti/g2/YUasX5K3CJ4QdIx76zppjHlh3-q8w-xkSyK1LA
🏆 本月排行榜
🥇
站長阿川
📝45   💬1  
643
評分標準:發文×10 + 留言×3 + 獲讚×5 + 點讚×1 + 瀏覽數÷10
本數據每小時更新一次