共有費用を編集するときに分担をやり直す理由
編集時のデフォルトは金額の不具合になり得るため、Dimesum はすべての費用 PATCH で participants と split_type を必須にし、あわせて base_version が古い編集をマージせず却下します。
誤字の修正が、誰がいくら負担するかを変えてはいけません。Dimesum では、共有費用を編集すると分担全体をやり直します。participants と split_type はすべての PATCH で必須で、どちらかを省いた編集はデフォルトで補われるのではなく 400 が返ります。作成時のデフォルトは現在の全メンバーと均等割りで、編集ではこれらが金額の不具合になります。
2つの失敗が、これを具体的に示します。8月に参加した同居人が7月の食事に引き込まれます。「現在の全メンバー」は費用を書いたときではなく、編集が届いたときに評価されるからです。意図した 70/30 の家賃の分担が 50/50 に均されます。split_type が無いと EQUAL を意味するからです。どちらの失敗もエラーを出さず、いずれも実際のお金を動かします。
編集のデフォルトは金額の不具合です。作成時のデフォルトは、作成者がいままさに見ているグループについて推測します。編集は後から、状況が変わったグループに対して届き、同じ推測が誰の負担かを静かに書き換えます。
作成時のデフォルトは新しい費用を表し、古い費用は表さない
作成時にはデフォルトは正直です。作成者は現状のグループを見ており、全員での均等割りが一般的なケースなので、Dimesum は両方を補います。費用は結果だけでなく入力を保存します。splits.percent_bp、splits.weight、splits.exact_minor がユーザーの入力した内容を保持するので、後の編集で再び開けます。
編集は別の行為です。同じ費用は数週間後、新しい同居人が参加したり、ゴーストメンバーが引き受けられたりした後に訂正されることがあります。メンバー構成は動く的で、分担はそうではありません。作成時のデフォルトを使い回すことは、古い費用がすでに答えた問いを、いまのグループに答えさせることになります。
推測を拒むのは、ここが初めてではありません。複数支払者の費用は、その支払者もやり直す必要があります。soleStoredPayer は費用の支払者がちょうど1人のときだけ保存済みの支払者を再利用するので、2人の支払者について黙ったままの編集は、割り当て直されるのではなく却下されます。支払者について何も言わない編集は、その費用自身の支払者を保ち、編集している人を支払者にはしません。
API は分担をやり直さない編集を却下する
ゲートウェイのチェックは、金額が計算される前に走ります。participants が空か split_type が空白のとき、リクエストはコード invalid_expense とメッセージ「an edit must restate the split: participants and split_type are required」とともに 400 で返ります。費用サービスは validateAmend で同じルールを繰り返すので、別の経路でサービスに到達した呼び出し元も同じ却下に出会います。
| フィールド | 作成時 | 編集時 | デフォルトの代償 |
|---|---|---|---|
participants | 任意。現在の全メンバーがデフォルト | 必須 | 後から参加したメンバーが古い費用に加わる |
split_type | 任意。EQUAL がデフォルト | 必須 | 70/30 の分担が 50/50 に均される |
payers | 任意。作成者がデフォルト | 省略するとその費用の唯一の支払者を保つ。2人の支払者はやり直す必要がある | 編集者が支払者になり、誰が誰に負担するかが逆転する |
base_version | 送らない | 必須で、現在のバージョンと一致する必要がある | 古い編集が、作成者が読んでいない変更を上書きする |
revision_id | クライアントの UUIDv7、冪等キー | 同じ、バージョンごとに1つ | 再試行された編集がグループに二重請求する |
currency | 費用ごとに指定 | 一致する必要がある。変更は却下される | 残高の行はメンバーごとに1通貨を保持する |
通貨も同じ却下の一族に属します。編集は費用の通貨を付け替えられません。残高の行はメンバーごとに1通貨を保持するからです。書き込み側がその変更を却下し、追記専用の台帳は、万一そこに届いてもそのような修正を留め置きます。入口で拒むことで、2つの側が食い違わないようにします。
古い編集は作成者に差し戻され、決してマージされない
base_version は契約のもう半分です。すべての PATCH は作成者が読んだバージョンを持ち、checkTransition がそれをトランザクションがちょうどロックした行と比較します。等しければ、編集はバージョンに1を足して適用されます。異なれば、呼び出し元はコード stale_version とともに HTTP 409 を受け取ります。
マージは魅力的な代替案ですが、間違いです。1つの費用への2つの編集は、その請求が何を意味するかについての2つの完全な表明です。それらをマージすると、誰も書いていない3つ目の表明ができ、どちらの作成者も見覚えのない取り分になります。却下は、その対立を解決できる唯一の人に差し戻します。
冪等性と並行性は意図的に分けられています。リビジョンの挿入はバージョンチェックの前に走ります。再試行された編集は最初に読んだベースバージョンを持っており、それはいまや古いからです。再送は対立ではなく再送として読まれる必要があるので、revision_id が先に答え、保存済みの結果を返します。
レスポンスは次の編集に必要なものをすでに持っている
PATCH でより多くのフィールドを要求するのは、クライアントがそれらを安く得られる場合にだけ公正です。すべての費用レスポンスは version を持つので、費用を書いたばかりのクライアントは2度目の読み取りなしに編集できます。作成レスポンス、修正レスポンス、そしてすべての一覧の行が同じフィールドを持ちます。
費用を書いたばかりではないクライアントには、GET /v1/groups/{id}/expenses/{id} がバージョン、計算された取り分、そしてその背後の入力を返します。入力は PATCH が受け付けるのと同じ名前で返ります。participants、split_type、percents、weights、shares、items、pools です。クライアントは1つの形を読み、編集を加えて投稿し直します。1つの請求について2つの語彙を訳し分けることはありません。
この対称性が最も効くのは、再構成できない分担です。PERCENT の分担や品目ごとの請求は、解決済みの取り分だけからはやり直せません。丸めがすでに適用され、ベーシスポイントと明細行が失われているからです。リビジョンのスナップショットは入力も持つので、履歴シートは過去のどのバージョンで何が品目化されていたかを示せます。
後から要件は足せないので、いま必須にする
初日にフィールドを必須にするのは、今日についてではなく将来についての決定です。必須のフィールドを後から緩めるのは後方互換です。クライアントはすでにそれを送っており、サーバーはそれなしのリクエストを受け付け始めます。要件を後から足すことは、古いデフォルトに頼っていたすべてのクライアントを壊します。
だから方向は一度、早い段階で選ばれます。Dimesum は、クライアント数がまだ変更できるほど小さいうちに、編集で participants、split_type、base_version を必須にします。編集にとって安全なデフォルトがいつか見つかれば、これらのフィールドは任意になり、すでに出荷されたものは何も動かなくなりません。
編集にはその意味をやり直させる
デフォルトは作成に属します。そこでは作成者が、合意しようとしているグループを見られます。編集では、同じデフォルトはその後動いたグループについての推測です。次の一歩は、自分の読み取りエンドポイントを開き、書き込みエンドポイントが受け付けるのとまったく同じフィールド名で分担の入力を返しているか確かめることです。2つの間を訳さなければならないクライアントは、いずれそのどちらかを訳し間違えます。
よくある質問
共有費用の編集で participants と split_type が必須なのはなぜですか?
Dimesum が両方のフィールドを必須にするのは、作成時のデフォルトが編集には正しくないからです。作成時、Dimesum は現在の全メンバーへの均等割りをデフォルトにし、これは作成者が見ているグループと一致します。編集は数週間後、誰かが参加した後に届くことがあります。そのデフォルトを使い回すと、新しい同居人を古い食事に引き込み、意図した 70/30 の家賃の分担を、エラーも出さずに 50/50 に均してしまいます。
同じ費用を2人が同時に編集するとどうなりますか?
2つ目の編集は HTTP 409 とエラーコード stale_version で却下されます。すべての PATCH は作成者が読んだバージョンである base_version を持ち、修正の経路がそれをロックされた行と比較します。不一致は費用が動いたことを意味するので、編集は作成者がいま見えるバージョンに対して再適用するために差し戻されます。何もマージされません。
費用を編集すると台帳の行はその場で更新されますか?
いいえ、Dimesum では費用の編集が台帳の行を更新することは決してありません。編集は1つのトランザクションで2つの仕訳を投稿します。古いバージョンを一項目ずつ打ち消す EXPENSE_REVERSAL と、続いて新しいバージョンのための EXPENSE の仕訳です。UPDATE と DELETE は台帳自身のデータベースロールから取り消されているので、不具合のあるコードでも書き換えは不可能です。表示されるのは編集済みのバッジと履歴シートです。
共有費用を編集する前にもう1回 API を呼ぶ必要がありますか?
いいえ、費用を書いたばかりのクライアントは、編集に必要なバージョンをすでに持っています。すべての費用レスポンスは version を持ち、これが次の PATCH が base_version として送るものです。費用を書いていないクライアントは GET /v1/groups/{id}/expenses/{id} を呼び、これはバージョンに加えて、PATCH が受け付けるのと同じフィールド名で分担の入力を返します。
participants と split_type を後から追加せず、いま必須にするのはなぜですか?
初日にフィールドを必須にするのは元に戻せますが、後から追加するのは戻せません。必須のフィールドを後から緩めるのは後方互換です。クライアントはすでにそれを送っており、サーバーはそれなしのリクエストを受け付け始めます。要件を後から足すことは、古いデフォルトに頼っていたすべてのクライアントを壊し、金額を扱う API では、その破損は誰かの残高が間違うまで表に出ません。
人気の記事
- 割り勘の残高を正確に保つ追記専用の台帳読了 約6分
- 多通貨の割り勘に潜む6つの金額バグ読了 約6分
- 精算:グループの費用を少ない送金で清算する方法読了 約6分
- 取り分けなかった一皿がある割り勘の精算方法読了 約6分
- ルームシェアの家賃を公平に分ける完全ガイド読了 約6分