dimesum

ホーム / ブログ / お金

お金

共有費用を編集するときに分担をやり直す理由

· 読了 約5分 ·

編集時のデフォルトは金額の不具合になり得るため、Dimesum はすべての費用 PATCH で participants と split_type を必須にし、あわせて base_version が古い編集をマージせず却下します。

誤字の修正が、誰がいくら負担するかを変えてはいけません。Dimesum では、共有費用を編集すると分担全体をやり直します。participantssplit_type はすべての PATCH で必須で、どちらかを省いた編集はデフォルトで補われるのではなく 400 が返ります。作成時のデフォルトは現在の全メンバーと均等割りで、編集ではこれらが金額の不具合になります。

2つの失敗が、これを具体的に示します。8月に参加した同居人が7月の食事に引き込まれます。「現在の全メンバー」は費用を書いたときではなく、編集が届いたときに評価されるからです。意図した 70/30 の家賃の分担が 50/50 に均されます。split_type が無いと EQUAL を意味するからです。どちらの失敗もエラーを出さず、いずれも実際のお金を動かします。

立場

編集のデフォルトは金額の不具合です。作成時のデフォルトは、作成者がいままさに見ているグループについて推測します。編集は後から、状況が変わったグループに対して届き、同じ推測が誰の負担かを静かに書き換えます。

作成時のデフォルトは新しい費用を表し、古い費用は表さない

作成時にはデフォルトは正直です。作成者は現状のグループを見ており、全員での均等割りが一般的なケースなので、Dimesum は両方を補います。費用は結果だけでなく入力を保存します。splits.percent_bpsplits.weightsplits.exact_minor がユーザーの入力した内容を保持するので、後の編集で再び開けます。

編集は別の行為です。同じ費用は数週間後、新しい同居人が参加したり、ゴーストメンバーが引き受けられたりした後に訂正されることがあります。メンバー構成は動く的で、分担はそうではありません。作成時のデフォルトを使い回すことは、古い費用がすでに答えた問いを、いまのグループに答えさせることになります。

同じ編集の2つのバージョン。引き継いだデフォルトはすべての取り分を変え、やり直した分担は説明だけを変える 編集が作成時のデフォルトを引き継ぐ 編集が分担をやり直す 家賃、20,000円、7月 家賃、20,000円、7月 v1 Asha 70%、14,000 Bhavna 30%、6,000 v1 Asha 70%、14,000 Bhavna 30%、6,000 Chetan が8月に入居する。 Chetan が8月に入居する。 PATCH が誤字を修正し、分担を送らない。 PATCH が誤字を修正し、分担を送る: participants: Asha, Bhavna split_type: PERCENT 7000 / 3000 v2 Asha 6,667 Bhavna 6,667 Chetan 6,666 v2 Asha 70%、14,000 Bhavna 30%、6,000 Chetan は住んでいない月の負担を負う。 変わったのは説明だけ。
同じ1文字の編集を2回。作成時のデフォルトを引き継ぐと 20,000円 を3等分し、1か月後に参加したメンバーに請求します。分担をやり直すと、どの取り分にも手を付けません。

推測を拒むのは、ここが初めてではありません。複数支払者の費用は、その支払者もやり直す必要があります。soleStoredPayer は費用の支払者がちょうど1人のときだけ保存済みの支払者を再利用するので、2人の支払者について黙ったままの編集は、割り当て直されるのではなく却下されます。支払者について何も言わない編集は、その費用自身の支払者を保ち、編集している人を支払者にはしません。

API は分担をやり直さない編集を却下する

ゲートウェイのチェックは、金額が計算される前に走ります。participants が空か split_type が空白のとき、リクエストはコード invalid_expense とメッセージ「an edit must restate the split: participants and split_type are required」とともに 400 で返ります。費用サービスは validateAmend で同じルールを繰り返すので、別の経路でサービスに到達した呼び出し元も同じ却下に出会います。

作成が送る内容と、編集がやり直す必要がある内容の対比。POST と PATCH /v1/groups/{id}/expenses にて。
フィールド作成時編集時デフォルトの代償
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つ目の表明ができ、どちらの作成者も見覚えのない取り分になります。却下は、その対立を解決できる唯一の人に差し戻します。

2人の作成者がバージョン3を読み、最初の編集がバージョン4を投稿し、2つ目は 409 stale_version で却下される expense, version 3 作成者 A PATCH base_version: 3 200 OK, version 4 作成者 B PATCH base_version: 3 409 stale_version 台帳、1トランザクション: EXPENSE_REVERSAL of v3 EXPENSE v4 作成者 B はバージョン4を読み直し、 変更を再適用して送る base_version: 4
費用に対する楽観的並行制御。負けた編集は、作り直すべきバージョンとともに作成者に差し戻されます。勝った編集は、更新ではなく取り消しと再投稿として台帳に届きます。

冪等性と並行性は意図的に分けられています。リビジョンの挿入はバージョンチェックの前に走ります。再試行された編集は最初に読んだベースバージョンを持っており、それはいまや古いからです。再送は対立ではなく再送として読まれる必要があるので、revision_id が先に答え、保存済みの結果を返します。

レスポンスは次の編集に必要なものをすでに持っている

PATCH でより多くのフィールドを要求するのは、クライアントがそれらを安く得られる場合にだけ公正です。すべての費用レスポンスは version を持つので、費用を書いたばかりのクライアントは2度目の読み取りなしに編集できます。作成レスポンス、修正レスポンス、そしてすべての一覧の行が同じフィールドを持ちます。

費用を書いたばかりではないクライアントには、GET /v1/groups/{id}/expenses/{id} がバージョン、計算された取り分、そしてその背後の入力を返します。入力は PATCH が受け付けるのと同じ名前で返ります。participantssplit_typepercentsweightssharesitemspools です。クライアントは1つの形を読み、編集を加えて投稿し直します。1つの請求について2つの語彙を訳し分けることはありません。

GET レスポンスと PATCH リクエストは同じフィールド名を使い、version だけ base_version に改名される GET が返す PATCH が受け付ける version base_version participants participants split_type split_type percents, weights, shares percents, weights, shares items, pools items, pools 改名
1つの語彙、2つの方向。往復で名前が変わるのは version フィールドだけなので、編集クライアントは読むものと書くものの間に変換層を保つ必要がありません。

この対称性が最も効くのは、再構成できない分担です。PERCENT の分担や品目ごとの請求は、解決済みの取り分だけからはやり直せません。丸めがすでに適用され、ベーシスポイントと明細行が失われているからです。リビジョンのスナップショットは入力も持つので、履歴シートは過去のどのバージョンで何が品目化されていたかを示せます。

後から要件は足せないので、いま必須にする

初日にフィールドを必須にするのは、今日についてではなく将来についての決定です。必須のフィールドを後から緩めるのは後方互換です。クライアントはすでにそれを送っており、サーバーはそれなしのリクエストを受け付け始めます。要件を後から足すことは、古いデフォルトに頼っていたすべてのクライアントを壊します。

だから方向は一度、早い段階で選ばれます。Dimesum は、クライアント数がまだ変更できるほど小さいうちに、編集で participantssplit_typebase_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 の仕訳です。UPDATEDELETE は台帳自身のデータベースロールから取り消されているので、不具合のあるコードでも書き換えは不可能です。表示されるのは編集済みのバッジと履歴シートです。

共有費用を編集する前にもう1回 API を呼ぶ必要がありますか?

いいえ、費用を書いたばかりのクライアントは、編集に必要なバージョンをすでに持っています。すべての費用レスポンスは version を持ち、これが次の PATCH が base_version として送るものです。費用を書いていないクライアントは GET /v1/groups/{id}/expenses/{id} を呼び、これはバージョンに加えて、PATCH が受け付けるのと同じフィールド名で分担の入力を返します。

participants と split_type を後から追加せず、いま必須にするのはなぜですか?

初日にフィールドを必須にするのは元に戻せますが、後から追加するのは戻せません。必須のフィールドを後から緩めるのは後方互換です。クライアントはすでにそれを送っており、サーバーはそれなしのリクエストを受け付け始めます。要件を後から足すことは、古いデフォルトに頼っていたすべてのクライアントを壊し、金額を扱う API では、その破損は誰かの残高が間違うまで表に出ません。