dimesum

ホーム / ブログ / お金

お金

取り分けなかった一皿がある割り勘の精算方法

· 読了 約6分 ·

取り分けなかった明細に食べた人を指定し、税金を消費に応じて配分することで、Dimesumは項目別の請求を1つの支出として公平に割ります。

6,300円のディナーを均等に割ると、一人が840円多く払うことになります。3人のうち2人が2,400円のシーフードの盛り合わせを食べ、残りの1人は食べていないのに、均等割りでは3人全員に2,100円が請求されます。Dimesumはこの請求を1つの支出として扱います。上位は均等、そして2,400円の明細は注文した2人だけが負担します。

共有されない明細が1つだけあるほぼ均等な請求は、割り勘アプリが求められる最も一般的なもので、Dimesumの最初のデータモデルはそれを表現できませんでした。以前の設計は ITEMIZED を割り方の一種とし、EQUALPERCENTSHARES と相互に排他的にしていました。実際のレストランの請求はその両方を同時に備えています。

項目別化は支出の詳細であって、別種の割り方ではない

Dimesumの項目別支出は、たまたま明細を持っているだけの通常の支出です。支出は、支出がすでに持つものをすべて保ちます。合計、参加者、割り方、1人または複数の支払者です。そこに品目、つまり請求の明細と、調整、つまりその下に印字される税金、チップ、手数料、割引が加わります。

そして2つのレベルがすべての金額を決めます。支出の割り方は、誰も指定されていない明細を割ります。指定者のいる明細は、その人たちだけが負担し、他の誰も負担しません。

docs/tech/18-itemized-expenses.md §1 より、明細の割り方を決める2つのレベル。
レベル決めること適用範囲
支出の割り方共有の費用をどう割るか。均等、割合、または加重シェアで指定者のいないすべての品目
品目の指定者この明細を誰がどの割合で消費したかその明細のみ
指定者のいない明細は支出の割り方で割られ、指定者のいる明細はそれが指定する人だけが負担する レベル1 明細に誰も指定されていない 取り分けた料理 3,600円 指定者なし 3人で均等 Asha 1,200円 Bhavna 1,200円 Chetan 1,200円 レベル2 明細が食べた人を指定する ノンベジ料理 2,400円 指定者 Asha, Bhavna 指定された2人 Asha 1,200円 Bhavna 1,200円 Chetan 0円
6,000円の料理に対する2つのレベルです。取り分けた料理は誰も指定しないので、EQUALが3人に割ります。シーフードの料理は2人を指定するので、Chetanの料理の小計は1,200円で止まります。

最も少なく食べた人が1,260円を払う6,300円のディナー

Asha、Bhavna、Chetanがディナーを食べ、上位は均等割りです。取り分けた料理は3,600円になります。シーフードの料理は2,400円で、食べたのはAshaとBhavnaだけです。サービス料は5%で、Chetanが6,300円全額を支払いました。

計算例。1つの請求、2つの明細、1つの調整、そして各人が負担する取り分。
明細金額AshaBhavnaChetan
取り分けた料理、指定者なし3,600円1,200円1,200円1,200円
シーフードの盛り合わせ、AshaとBhavna2,400円1,200円1,200円0円
小計6,000円2,400円2,400円1,200円
サービス料5%、小計に応じて300円120円120円60円
合計6,300円2,520円2,520円1,260円

Chetanは6,300円を支払い、負担は1,260円なので、5,040円を受け取ります。Ashaから2,520円、Bhavnaから2,520円です。誰が払ったかは、誰が負担するかとは無関係です。ほとんど食べなかった人が支払者であっても取り分は何も変わりません。だからDimesumは支払者を支出のレベルに、指定者を明細のレベルに置いています。

税金は人数ではなく、食べたものに従う

Chetanの300円のサービス料の負担は60円で、100円ではありません。すべての調整は各人の品目小計に応じて配分されるので、料理の200対200対100の割合がサービス料の割合も決めます。人数で配分すると、Chetanが手をつけていない料理の税金を気づかぬうちに請求してしまいます。

したがって何も注文しなかった人は税金を払わず、割引も受けません。重みは累計ではなく調整前の小計なので、各調整の丸めが次の調整の重みに積み重なることも防ぎます。

調整は順番に適用されるので、割引はGSTの課税基準を動かす

「12,000円、10%引き、5%のGSTを加算」と書かれた請求は、10,800円にGSTを課し、GSTの明細は540円です。2つを逆にすると、GSTは12,000円に課され、600円になります。調整は順序付きのリストで、割合はその位置での累計に適用されます。どちらの順序も実在する請求なので、リストは集合ではなく順序付きです。

同じ割引とGSTを2つの順序で示し、それぞれが課される基準と生じる合計を示す 割引が先 GSTが先 品目小計 12,000円 12,000円の10%引き 割引 1,200円 10,800円 10,800円の5%GSTを加算 GST 540円 11,340円 請求合計 11,340円 品目小計 12,000円 12,000円の5%GSTを加算 GST 600円 12,600円 12,600円の10%引き 割引 1,260円 11,340円 請求合計 11,340円 同じ請求 10%ではなく定額1,200円引き 1,200円引きの後にGST 11,340円 GSTの後に1,200円引き 11,400円
2つの割合は掛け算が可換なので同じ11,340円になりますが、GSTの明細は異なります。540円に対して600円です。割合の割引を定額1,200円に置き換えると、合計も分かれます。11,340円に対して11,400円です。ここでは順序は表示ではなく計算です。
なぜ順序を明示的に保存するのか

各調整はそれぞれの position を持ちます。挿入順や、ID生成器が単調増加のままであることに依存した順序付けは、データベースの復元後に各人の負担額を気づかぬうちに変えてしまいます。

入力ミスと計算の間には3つの検証があります。プールは定額か、ベーシスポイントでの率のいずれかを指定し、両方は決して指定しません。両方を保存することは、数値とその導出を同時に保存することだからです。負の金額は拒否され、減額を書く方法として DISCOUNT を示すエラーが出ます。100,000ベーシスポイントを超える率も拒否されます。これは100%を意味する10,000ベーシスポイントよりはるかに高い上限です。100%引きは実在する割引だからです。

internal/platform/splitcalc の4種類の調整と、それぞれが累計に与える影響。
種類累計への影響独立した種類である理由
TAX加算表記のみ。計算は同一
TIP加算表記のみ。計算は同一
FEE加算表記のみ。計算は同一
DISCOUNT減算計算を変える唯一の種類なので、方向は符号ではなく種類から決まる

合計は明細から生じ、入力された合計はチェックサムにすぎない

項目別の合計は導出されます。品目の合計に調整の合計を加えたものです。明細はすでに請求額を示しているので、別に記載された合計は、最初のものと食い違いうる第二の真実の源になります。請求を入力し間違えた人は明細を直します。そこが実際に間違いのある場所であり、合計はそれに従います。すでに登録された請求の訂正は、割り方を再記述する編集を通るので、訂正は上書きではなく新しいバージョンとして反映されます。

クライアントは amount_minor を送ることもできますが、Dimesumはそれを答えではなくチェックサムとして扱います。一致すれば、クライアントが同じ請求を読んだということです。不一致なら、お金が動く前に支出を止めます。

以前のバージョンは、記載された合計で説明できない分に対して「その他」の明細を自動で追加し、差が埋まるとその明細を削除していました。その明細は機能していましたが、今はありません。合計を導出することで、「その他」の明細が管理するために存在していた問題は解消しました。その問題は、合計が二度記載されたためにだけ生じていたものです。

なぜEXACTと品目は同時に拒否されるのか

EXACT は各メンバーの最終金額を指定します。品目は各メンバーの金額を導出します。両方を同時に使うのは過剰決定です。両者が一致するなら一方は冗長であり、食い違うなら支出は2つの答えを持ち、どちらが勝つかを決める規則はありません。Dimesumは、誰も覚えていない優先規則で決着をつけるのではなく、その組み合わせを入口で拒否します。

EQUALPERCENTSHARES はいずれも品目と組み合わせられます。それぞれが最終金額の集合ではなく、共有の費用を割るための規則だからです。

以前、割引が1円を失っていた箇所

すべての配分は最大剰余法を用い、それぞれが自身の合計を正確に保ちます。この方法での同点は、以前は最小のメンバーIDに割り当てられ、均等割りのたびにグループで最も古いメンバーに余分な1円を渡していました。同点は今では支出IDのハッシュで回されます。共有の明細はまとめて一度に割られ、明細ごとには割られないので、端数の1円が請求のすべての明細で同じメンバーに落ちることはありません。

私たちの apportion 関数には、ここに実際の欠陥がありました。Goの整数除算はゼロ方向に切り捨てるので、負の合計は誤った方向に丸められ、余りは決して配分されませんでした。100、200、300の重みに対する −1,000円 は −999円 として返ってきました。消えた1円は、正しく割引された請求を自身の合計チェックで失敗させ、ユーザーは自分の計算が間違っていると告げられていたでしょう。負の合計は今では大きさで配分され、符号を戻します。

請求は印字されたとおりに入力する

目に見える明細を入力し、取り分けられなかったものを食べた人を指定し、税金、チップ、手数料、割引をレシートが印字する順序で加えます。Dimesumは合計を導出し、各調整を各人が消費したものに応じて配分し、支払者はそこから外します。次に一皿が他の全員の注文の2倍かかるときは、2人の名前を付けた独立した明細として加えてください。

よくある質問

飲み会で一人だけ高い料理を頼んだときの割り勘のやり方は?

その料理を独立した明細にして、食べた人を指定します。Dimesumでは残りの請求は支出自身の規則、たいていは均等で割られ、指定された明細はその指定者だけが負担します。税金とサービス料は各人の小計に応じて配分されるので、その料理を食べなかった人は両方とも少なく払います

サービス料やチップは均等割りか、注文額に応じて割るか?

注文額に応じて割ります。Dimesumはすべての調整を人数ではなく各人の品目小計に比例して配分します。一人が1,200円分を食べた6,300円のディナーでは、その人は300円のサービス料のうち100円ではなく60円を負担します。何も注文しなかった人は税金を一切払いません

割引と税金の計算順序で請求額は変わるか?

変わります。調整は累計に対して順番に適用されるので、「12,000円、10%引き、5%のGSTを加算」という請求はGSTを10,800円に課し、GSTの明細は540円になります。GSTを先にすると12,000円に課され、600円になります。定額1,200円引きでも合計は異なり、11,340円に対して11,400円です

項目別の請求で正確な金額指定が使えないのはなぜか?

EXACTは各人の最終金額を指定し、品目はそれを導出するので、2つを合わせると1つの支出に2つの答えができてしまいます。Dimesumは、誰も覚えていない優先規則で勝者を選ぶのではなく、その組み合わせを拒否します。EQUAL、PERCENT、SHARESはいずれも品目と併用できます。それぞれが最終金額の集合ではなく、共有の明細を割るための規則だからです

項目別の請求で合計金額を入力する必要はあるか?

ありません。Dimesumは項目別の合計を、品目の合計に調整の合計を加えたものとして導出します。明細がすでに請求額を示しているからです。クライアントが送った合計はチェックサムとして照合され、不一致があればお金が動く前に支出を止めます。誤った数字の訂正は、その数字が生じた明細を訂正することを意味します