自社ECにポイントやリワード(商品交換)の仕組みを入れたい、という相談は多く、見積もりの席では決まって「購入金額の何%を付ける」といった付与のルールが議題になります。しかし当社の経験では、付与そのものはほとんど難所になりません。設計を難しくし、金額を大きく動かすのは、付与したポイントを取り消す場面と、店舗POSなど外部システムと残高をやり取りする場面です。この記事は、Shopifyでポイント・リワード機能を検討しているEC事業者と、その要件定義を担う技術者に向けて、設計に入る前に必ず潰しておくべき論点を整理します。ここを詰めずに走ると、リリース直前や運用開始後に厄介な形で表面化します。
返品で残高がマイナスになる問題
一番見落とされがちなのが、返品でポイントの取り消し原資が足りなくなるケースです。たとえば1ポイント1円・購入額の1%付与として、1万円の買い物で100ポイントが付き、その後お客様が100ポイントをリワード商品と交換して残高が0になり、さらにそのあと最初の買い物を返品したとします。返金する以上、付与した100ポイントは取り消すのが筋ですが、残高はすでに0で、取り消す原資がありません。この100ポイントをどう扱うかを、設計時に決めておく必要があります。
取りうる方式はいくつかあります。残高をマイナス(マイナス100ポイント)として次回付与で相殺する方式は会計上の辻褄が合い取りこぼしがない反面、「なぜマイナスなのか」という問い合わせを生みます。取り消しきれない分を諦めて0で止める方式は会員体験と実装が単純ですが、高額商品を買ってポイントを得てすぐリワードと交換し、元の商品を返品する、という悪用の余地が残ります。返金額から相殺する方式は最も公平ですが返金処理と連動させる必要があり実装が重く、管理者に通知して手動対応する方式は柔軟な一方で件数が多いと運用が回りません。
当社が実際に提案することが多いのは、これらの選択肢を選ぶ前に、そもそも問題自体を消してしまう設計です。ポイントの確定を「発送後14日経過時点」のように返品可能期間を過ぎてから行い、それまでは「獲得予定ポイント」として表示だけしておく。こうすれば取り消すべき確定ポイントが原理的に存在しなくなり、上の選択肢はほとんど発生しない例外の扱いに落とせるので、「管理者に通知して手動対応」で十分になります。実装も軽くなります。付与の話をするときに、いつ確定するかまで含めて決めるのが定石です。
外部POS連携は「残高の正データ」を一箇所に決める
実店舗のPOSとECでポイントを共通にしたい、という要望はよく出ますが、両システムが同じ残高を持ち続ける設計は整合性の担保が難しく、最も工数がかかる部分になります。当社が最初に確認するのは、「お客様が店舗で貯めたポイントをECでも使えるべきか」という業務上の問いと、「残高の正データをどこに一本化するか」という設計上の問いです。
たとえば「残高の正はEC側に一本化し、POS側のポイントは店舗で貯まった分を一時的に保持しているだけ。同期のタイミングでEC側へ吸い上げ、POS側は0にリセットする」と決められれば、残高の双方向同期という一番重い部分が不要になります。店舗購入へのポイント付与ロジックもPOS側が担ってくれるなら、こちらで作る必要がありません。要件を技術用語で聞く前に、業務としてどちらが正かを決めるだけで、見積もりの上限と下限が入れ替わるほど効きます。
「移管処理」はもっとも事故りやすい処理だと思って作る
残高を一箇所に寄せる設計にすると、今度は「POSから残高を読む → EC台帳に加算する → POS側を0にする」という移管処理が要になります。これは他システムのデータを書き換える三段階の処理で、途中で失敗したときの被害が大きい種類の処理です。加算は成功したのに0リセットに失敗すれば次回同期で二重に加算され、逆に0にしたあと加算が失敗すればポイントが消失し、しかも記録が残らずお客様に指摘されるまで気づけません。0にした直後に店舗で買い物が発生すれば、タイミング次第で取りこぼします。
ポイント消失は、クレームになったときに「元々いくつ持っていたか」を証明する手段がない状態で対応することになります。だから移管処理そのものに記録と復旧の仕組みを組み込む前提で設計します。あわせて確認すべきは、POS側のAPIが「0を書き込む(絶対値セット)」しかできないのか、「移管した分だけ減算する」ことができるのかです。後者ができるなら、途中で買い物が発生しても取りこぼしが起きず、安全性が大きく変わります。POS側に増減履歴が残るかどうかも、突き合わせと復旧の材料になるので押さえておきます。
会員規模がバッチ設計と移行を左右する
会員が数万件規模になると、それ自体が設計に効いてきます。日次バッチで全件をフルスキャンするのは現実的でないので、外部APIで「前回同期以降に更新された会員だけ」を取得できるかが重要になります。更新日時での絞り込みができない場合は全件走査を避ける別の方法が必要になり、工数が増えます。初期同期も、数万件をAPI経由で流し込むとレート制限次第で相当な時間がかかるため、移行当日のスケジュールに組み込んで見積もる必要があります。
この規模感は、「ポイント台帳をShopifyのメタフィールドに持たせない」という判断も裏付けます。数万件のメタフィールドを日次でスキャンするのはレート制限の面で無理があるので、台帳はアプリ側のデータストアに持つのが素直です。データ移行の見積もりでは、会員数だけでなくポイント履歴の件数も確認します。残高のみなら会員数ぶんで済みますが、履歴込みだと数十万〜数百万件になり得て、その場合はリハーサルが必須になります。
会計と規約という、技術の外側の確認
最後に、技術要件の外側にある論点も要件定義に含めておきます。未使用ポイントを負債として引当計上している事業者は、経理向けの集計機能が必要になり、これはリリース直前に発覚すると厄介です。有効期限や失効ルールは会員規約・ポイント規約に書かれていることが多く、勝手に変えられない一方、規約さえ入手できればこちらの確認項目がいくつも自動的に埋まります。受入テストを誰がどれくらいの期間で行うかも、公開日の可否に直結します。開発が終わってもテストが進まなければ公開できないからです。
まとめ
ポイント機能の設計は、付与のルールではなく、取り消し(返品時の残高マイナスと確定タイミング)と連携(残高の正の一本化と、破壊的な移管処理の安全設計)で難易度が決まります。当社では、要件定義の段階でこの二つと、大量会員のバッチ・移行、そして会計・規約という技術外の論点までを先に潰すことで、リリース直前の手戻りを防いでいます。付与の話が出たら確定タイミングまで、連携の話が出たら失敗時の復旧まで踏み込む。これがポイント機能を安全に着地させる順序です。

