New plugin and example: using beancount for shared expenses, and verifying income/expenses match

132 views
Skip to first unread message

James Cook

unread,
May 3, 2021, 6:28:46 PM5/3/21
to bean...@googlegroups.com
Hi beancount list,

I've been using a separate Beancount ledger to track shared expenses
and who-owes-what between my partner and myself, and today I wrote a
plugin to help by verifying a consistency property.

I thought I'd share, in case it's helpful to anyone else. The code is
at
https://hub.darcs.net/falsifian/misc-pub/browse/beancount_plugins/falsifian/balance_income_expense.py .

Here is a copy of the documentation. At the very bottom is an example
ledger showing how I use Beancount to track shared expenses.

Let me know if you find it useful! I'm also curious if people have
different ways to accomplish the same thing. This has been working
pretty well for me.

----

This plugin verifies that totals from all Income and Expense accounts balance
to zero. By default, the check is done at the end of each day, but the check
can be postponed for some transactions using tags.

It is intended for ledgers where the Asset/Liability accounts aren't intended
to accumulate balances over the long term. For example, a ledger used to track
shared expenses might have this property --- see the end of this doc comment
for a full example.

The plugin does not make any changes. All it does is raise an error if the
constraint is violated.

For example, the plugin accepts this silently:

plugin "falsifian.balance_income_expense"

2000-01-01 open Assets:A
2000-01-01 open Expenses:A
2000-01-01 open Income:A

2000-01-01 * "Expense"
Expenses:A 10.00 CAD
Assets:Chequing -10.00 CAD

2000-01-01 * "Income"
Income:A -10.00 CAD
Assets:Chequing 10.00 CAD

but this leads to an error, because the 10.00 CAD in Expenses:A is unbalanced
at the end of 2000-01-01:

plugin "falsifian.balance_income_expense"

2000-01-01 open Assets:A
2000-01-01 open Expenses:A
2000-01-01 open Income:A

2000-01-01 * "Expense"
Expenses:A 10.00 CAD
Assets:Chequing -10.00 CAD

2000-01-02 * "Income"
Income:A -10.00 CAD
Assets:Chequing 10.00 CAD

You can also delay the check for a subset of transactions by using tags
together with the "close_income_expense_tag" custom directive. For example:

plugin "falsifian.balance_income_expense"

2000-01-01 open Liabilities:Credit-card
2000-01-01 open Expenses:Groceries
2000-01-01 open Expenses:Utilities
2000-01-01 open Income:Contributions

2000-01-05 * "Groceries" #cc_bill_2000-01
Expenses:Groceries 50.00 CAD
Liabilities:Credit-card -50.00 CAD

2000-01-07 * "Electric bill" #cc_bill_2000-01
Expenses:Utilities 70.00 CAD
Liabilities:Credit-card -70.00 CAD

2000-01-30 * "Credit card bill paid"
Income:Contributions -120.00 CAD
Liabilities:Credit-card 120.00 CAD

2000-01-30 custom "close_income_expense_tag" "cc_bill_2000-01"

Here's an example of how this could be used to track shared expenses between
Alice and Bob:

plugin "falsifian.balance_income_expense"

option "operating_currency" "CAD"

; Assets:Alice-owes and Assets:Bob-owes track how much Alice and Bob each "owe"
; to the shared ledger. They will often be negative, meaning they are "owed"
; money.
;
; For example, if the sum of balances in Assets:Alice-owes and Assets:Bob-owes
; is zero, that just means Alice owes Bob, or vice versa.
;
; In the below ledger, the sum of the following three accounts should always be
; zero:
;
; * Assets:Alice-owes
; * Assets:Bob-owes
; * Liabilities:Credit-card
;
; For example, suppose the balances were as follows:
;
; Assets:Alice-owes 10.00 CAD
; Assets:Bob-owes 15.00 CAD
; Liabilities:Credit-card -25.00 CAD
;
; That would mean that the shared credit card has a balance of -25 CAD, and if
; they were to split the bill as $10 from Alice and $25 from Bob, no debt would
; remain (either to the credit card company or between Alice and Bob).

2000-01-01 open Assets:Alice-owes
2000-01-01 open Assets:Bob-owes

2000-01-01 open Liabilities:Credit-card

; Shared expenses
2000-01-01 open Expenses:Groceries
2000-01-01 open Expenses:Parking
2000-01-01 open Expenses:Utilities

; Income:Contributions represents what Alice and Bob have paid into the shared
; ledger. It is used in "settlement" transactions which exist to balance
; earlier (or simultaneous) Expense transactions. The account is only needed if
; you find it desirable for expenses and "income" to balance, or equivalently,
; for Assets:Alice-owes and Assets:Bob-owes to not accumulate long-term
; balances.
2000-01-01 open Income:Contributions


; Here's how credit card transctions could be represented:

2000-01-05 * "Groceries" #cc_bill_2000-01
Expenses:Groceries 50.00 CAD
Liabilities:Credit-card -50.00 CAD

2000-01-07 * "Electric bill" #cc_bill_2000-01
Expenses:Utilities 70.00 CAD
Liabilities:Credit-card -70.00 CAD

; The #cc_bill_2000-01 tag doesn't do anything here as far as the
; balance_income_expense plugin is concerned, but it doesn't hurt to be
; consistent.
2000-01-10 * "Bob uses the credit card for a personal expense." #cc_bill_2000-01
Assets:Bob-owes 20.00 CAD
Liabilities:Credit-card -20.00 CAD

2000-01-30 * "Alice pays the shared credit card bill" ^cc_payment_2000-01-30
Liabilities:Credit-card 140.00 CAD
Assets:Alice-owes -140.00 CAD

; The Income:Contributions leg in this transaction matches only the shared
; transactions. Bob's $20 personal expense is excluded.
2000-01-30 * "Settle credit card bill payment" ^cc_payment_2000-01-30
Income:Contributions -120.00 CAD
Assets:Alice-owes 120.00 / 2 CAD
Assets:Bob-owes 120.00 / 2 CAD

2000-01-30 custom "close_income_expense_tag" "cc_bill_2000-01"


; In the meantime, there might be some ad-hoc expenses that are settled
; immediately.

2000-01-20 * "Bob pays for parking" ^parking_2000-01-20
Expenses:Parking 5.00 CAD
Assets:Bob-owes -5.00 CAD

2000-01-20 * "Settle parking" ^parking_2000-01-20
Income:Contributions -5.00 CAD
Assets:Alice-owes 5.00 / 2 CAD
Assets:Bob-owes 5.00 / 2 CAD


; Record a payment from Bob to Alice.

2000-02-01 * "Bob pays Alice"
Assets:Alice-owes 77.50 CAD
Assets:Bob-owes -77.50 CAD

; All debts are now settled. In practice, this won't usually happen if the
; credit card account is active, because there will always be a balance in
; Liabilities:Credit-card. Still, the balance_income_expense plugin can give
; you some peace of mind that everything is balancing in the end.

2000-03-01 balance Assets:Alice-owes 0.00 CAD
2000-03-01 balance Assets:Bob-owes 0.00 CAD

--
James
Reply all
Reply to author
Forward
0 new messages