2026-04 Storefront 送料無料進捗表示仕様¶
目的¶
カート画面で、送料無料条件に対する現在の達成状況と残り必要金額を利用者へ明示し、注文継続の判断をしやすくする。
適用範囲¶
- 対象画面: Storefront のカート画面のみ
- 表示位置:
CartSummary内の進捗 block - 非対象:
- checkout sidebar
- カート投入直後の toast
- 商品詳細 / 一覧 / その他画面
判定の正本¶
- 送料無料判定の正本は backend の送料計算ルール とする
- 判定基準は
order.subTotal(税抜) - 実効しきい値の軸は 出荷モード (通常 / 直送) のみ
- 顧客ステータス別の閾値分岐は持たない(Issue #858 で撤去済み。顧客原本要件
docs/01-requirements/shipping-and-purchase-unit-requirements.mdに記述なし)
表示仕様¶
1. 未達¶
- 文言:
送料無料まであと¥X - 金額は 税込表示
2. 達成¶
- 文言:
送料無料条件を達成しています
3. 補助文言¶
現在のカート内容を基準にした税込表示です。
データ取得仕様¶
- Shop API に
activeOrderShippingProgressquery を追加する - query は以下を返す
qualifiedthresholdExTaxsubtotalExTaxremainingExTaxremainingDisplayWithTaxshippingMode- 金額 field はすべて Vendure Money 値で返す。たとえば表示上の残り
108円は API では10800。
税込表示の換算ルール¶
- 判定は税抜のまま変更しない
- 表示用の
remainingDisplayWithTaxは backend が算出する - 算出方法:
remainingExTaxを求める- 現在の注文の
subTotalWithTax / subTotalを表示用の実効税率比として使う Math.ceil((remainingExTax * subTotalWithTax) / subTotal)で 切り上げ て表示するsubTotalが 0、または比率を安全に出せない場合は 10% 税率相当で切り上げ る- 上記計算は円単位で行い、Shop API へ返す直前に
toVendureMoneyFromYen()で Vendure Money 値へ変換する。
GraphQL 追加仕様(Shop API)¶
type ActiveOrderShippingProgress {
qualified: Boolean!
thresholdExTax: Int!
subtotalExTax: Int!
remainingExTax: Int!
remainingDisplayWithTax: Int!
shippingMode: String!
}
extend type Query {
activeOrderShippingProgress: ActiveOrderShippingProgress
}
補足¶
- client 側で送料無料しきい値を再計算しない
- 送料計算と進捗表示は同じ server service を使い、表示と課金の乖離を防ぐ
- 円単位と Vendure Money 値の境界は Vendure Money 単位運用 を正本とする
しきい値の正本¶
軸は 出荷モード のみ。実装定数は packages/domain/src/rules/shipping.ts の
FREE_SHIPPING_THRESHOLDS、判定 helper は resolveFreeShippingThresholdByMode(mode)。
| 出荷モード | 閾値(税抜) | 上書きルール |
|---|---|---|
| 通常モード | ¥20,000 | ProvinceDeliveryProfile で都道府県別に上書き可能 (calculator 側) |
| 直送モード | ¥15,000 | (未満は ¥350(税込) を加算) |
- 進捗表示の閾値は
FreeShippingProgressService.resolveThreshold(ctx, order)が 返す。order のcustomFields.shippingModeをgetOrderShippingMode()で 解決し、未指定は通常モード扱い。 - 課金側の
ShippingCalculatorServiceも同じ service を経由するため、本表が 進捗表示・課金双方の SSoT。ProvinceDeliveryProfileの都道府県別上書きは calculator 側で適用される(進捗表示の baseline には反映しない)。 ZoneShippingRule.freeShippingThresholdがセットされている場合は、そのルール 内での無料化判定にのみ使われ、上記しきい値の上書きは行わない。- しきい値表の金額は円単位。Vendure Money 値として比較・返却する境界では
toVendureMoneyFromYen()/toYenFromVendureMoney()を使う。
撤去履歴¶
- 2026-05-28: 顧客ステータス別閾値 (
SPECIAL_OR_VIP=¥5,000/BULK=¥7,500) とresolveFreeShippingThreshold(statuses)helper を撤去 (Issue #858)。顧客原本 要件docs/01-requirements/shipping-and-purchase-unit-requirements.mdに 記述がない要件外実装だったため。 - Dashboard からの動的編集(Issue #852)は別 PR で対応予定。
更新日: 2026-05-28 (出荷モード別 SSoT へ整理、顧客ステータス別表を撤去)