付与・消費・変換のイベント記録設計

「いつ・誰が・どの操作で・何ポイント」を漏れなく残すイベントスキーマの設計

イベント記録付与消費変換データ設計
読了時間: 8分

はじめに

ポイント監査ログの心臓部は、「1つの出来事をどう1行のデータにするか」です。ここの設計が甘いと、後から「なぜこの残高になったの?」に答えられません。

この記事では、POS(スマレジ)とECをまたいでポイントを運用したプロジェクトで、私が実際に設計したイベント記録のスキーマを解説します。付与・消費・変換という3つの操作を、どれも同じ形で残す。そのための考え方を、なるべく具体的にお伝えします。

イベントを記録するという発想

残高を「上書き」せず「積み上げる」

多くのシステムは、顧客ごとに「残高:1000」という数字を1つ持ち、増減のたびに上書きします。シンプルですが、上書きは過去を消してしまうのが弱点です。

私が採った設計は逆で、残高そのものは持たず、増減の記録だけを1行ずつ積み上げます。「+100」「-500」「+300」というイベントの合計が、その時点の残高になる。銀行の通帳と同じで、行を消さない限り履歴は永遠に追えます。この積み上げ方式こそが、監査可能性の出発点なんです。

3つの操作を同じ形で残す

ポイントの動きは、突き詰めると3種類です。付与(増える)、消費(減る)、変換(クーポンなどに引き換える)。これらを別々のテーブルで管理すると、突合のたびに3つを見比べる羽目になります。

そこで、3つとも「操作種別」という項目で区別する1つのログにまとめました。同じ形なら、合計するだけで残高が出ますし、一覧で眺めたときも流れが読めます。

1イベントに持たせる項目

最低限そろえたい5W1H

イベントの1行は、後から見て「誰が読んでも意味が分かる」ことが理想です。私は5W1Hを埋めるつもりで項目を決めました。

特に balance_after(操作後の残高)は省略されがちですが、これがあると「この行の直後にいくつだったか」が一目で分かり、障害時の突合がぐっと楽になります。

付与ソースを必ず残す

source(付与ソース)は、不正やミスを見抜くための重要な項目です。同じ「+100」でも、購入によるものと手動付与では意味がまったく違います。

手動付与だけを後から抽出できれば、「誰がどれだけ手で付けたか」が見えます。金銭を発行する操作なのですから、その出所を必ず記録に残す。これはセキュリティというより、あって当たり前の会計的な作法だと考えています。

参照キーで元の取引とつなぐ

イベント単体だと「なぜ付いたのか」までは分かりません。そこで、元になった注文番号やキャンペーンIDを reference として持たせます。

この参照キーは、後述する二重付与の防止にも使えます。「この注文に対する付与イベント」を一意に決められるので、同じ注文で二度付与しそうになったときに気づけるんです。

冪等性で「二重記録」を防ぐ

なぜ同じイベントが2回来るのか

システム連携では、ネットワークのタイムアウトや再送で「同じ操作の指示が2回届く」ことが日常的に起こります。素直に2回記録すると、ポイントも2回付いてしまいます。

再送が起きても1回だけ記録する
一意キーを決める

「注文123の付与」のように操作を一意に表すキーを作る

登録時に重複チェック

同じキーのイベントが既にあれば、それは再送とみなす

初回だけ確定

重複なら黙って無視し、残高は動かさない

キー設計が冪等性のカギ

冪等性を効かせられるかは、この一意キーの設計にかかっています。「顧客ID+注文番号+操作種別」のように、業務的に重複しない組み合わせで作るのがコツです。

このキーをデータベース側で「重複禁止」に設定しておけば、万一チェックをすり抜けても、登録の段階で二重記録を止められます。二段構えにしておくと安心です。

まとめ

イベント記録の設計で私が大事にしたのは、次の3点です。

  1. 残高を上書きせず、増減を積み上げる — 履歴が消えないので後から追える
  2. 付与・消費・変換を同じ形で残す — 合計するだけで残高が出る
  3. 一意キーで冪等性を担保する — 再送が来ても二重記録しない

こうして残したイベントは、障害時の強い味方になります。ズレた残高をログから再構築する具体的な手順は「障害時の突合・復旧に使えるログの持ち方」で解説します。全体像を振り返りたい方は、ハブ記事「ポイント監査ログ」もあわせてどうぞ。