The fair Christmas problem: splitting expenses automatically

38 views
Skip to first unread message

Uwe Brauer

unread,
Dec 29, 2021, 11:45:05 AM12/29/21
to ledge...@googlegroups.com
Hi

I am not sure whether this is the right place to ask this, but anyhow.
I don't really use ledger, I use emacs org mode, that allows me via its
babel extension to connect to ledger and perform certain very simple
operations.

Be it as it may, I have a conceptual question, that I explain using the
following example.

Suppose two friends want to buy Christmas presents, but when they have
finished, they want to have spent the same amount of money. If they
don't a compensation must be transferred.

Here is an example

** Start

#+name: presents
#+begin_src ledger

2010/01/01 * Starting balance
assets:bank:savings 0
income:starting balances
2021/12/01 User1:Jacket
expenses:User1:Jacket 80
income:User1:creditcard1
2010/07/24 User1:Pajama
expenses:User1:Pajama 30
income:User1:creditcard1
2010/07/23 User2:Flowers
expenses:User2:Flowers 20
income:User2:creditcard2
2010/07/23 User2:ChristmasTree
expenses:User2:ChristmasTree 40.00
income:User2:creditcard2
#+end_src

#+RESULTS: presents
#+begin_example

170 expenses
110 User1
80 Jacket
30 Pajama
60 User2
40 ChristmasTree
20 Flowers
-170 income
-110 User1:creditcard1
-60 User2:creditcard2
--------------------
0
#+end_example

So user1 spent 110, while user2 spent 60

** Compensation manually
So the compensation is (trivally)
that is org's version of a spreadsheet.

| User1 | User2 | User2-->Uwer1 |
|-------+-------+---------------|
| 110 | 60 | -25 |

#+TBLFM: $3=($2-$1)/2;f2

Leading to

#+name: compensated
#+begin_src ledger

2010/01/01 * Starting balance
assets:bank:savings 0
income:starting balances
2021/12/01 User1:Jacket
expenses:User1:Jacket 80
income:User1:creditcard1
2010/07/24 User1:Pajama
expenses:User1:Pajama 30
income:User1:creditcard1
2010/07/23 User2:Flowers
expenses:User2:Flowers 20
income:User2:creditcard2
2010/07/23 User2:ChristmasTree
expenses:User2:ChristmasTree 40.00
income:User2:creditcard2
2010/07/23 User2:User1-Compensation
expenses:User2:User1-Compensation 25.00
expenses:User1:User1-Compensation
#+end_src

#+RESULTS: compensated
#+begin_example

170 expenses
85 User1
80 Jacket
30 Pajama
-25 User1-Compensation
85 User2
40 ChristmasTree
20 Flowers
25 User1-Compensation
-170 income
-110 User1:creditcard1
-60 User2:creditcard2
--------------------
0
#+end_example




The question is can this be done automatically?

By this I mean
can
2010/07/23 User2:User1-Compensation
expenses:User2:User1-Compensation 25.00
expenses:User1:User1-Compensation

Somehow be generated automatically?

Regards

Uwe Brauer


Uwe Brauer

unread,
Dec 29, 2021, 1:58:43 PM12/29/21
to ledge...@googlegroups.com
>>> "UB" == Uwe Brauer <o...@mat.ucm.es> writes:

I realized that in gnucash I can have entries that are simple
operations, like 100/5 or something like this.

That seems not to work in ledger please see the last entry

#+name: compensated
#+begin_src ledger


2010/01/01 * Starting balance
assets:bank:savings 0
income:starting balances
2021/12/01 User1:Jacket
expenses:User1:Jacket 80
income:User1:creditcard1
2010/07/24 User1:Pajama
expenses:User1:Pajama 30
income:User1:creditcard1
2010/07/23 User2:Flowers
expenses:User2:Flowers 20
income:User2:creditcard2
2010/07/23 User2:ChristmasTree
expenses:User2:ChristmasTree 40.00
income:User2:creditcard2
2010/07/23 User2:User1-Compensation
expenses:User2:User1-Compensation 25.00/2
expenses:User1:User1-Compensation
#+end_src

The entry 25.00/2 is not interpreted.

Anyway to achieve that?

Martin Michlmayr

unread,
Dec 29, 2021, 5:57:12 PM12/29/21
to ledge...@googlegroups.com
* Uwe Brauer <o...@mat.ucm.es> [2021-12-29 19:58]:
> expenses:User2:User1-Compensation 25.00/2
>
> The entry 25.00/2 is not interpreted.

You have to this use syntax:

2010/07/23 User2:User1-Compensation
expenses:User2:User1-Compensation (25.00/2)
expenses:User1:User1-Compensation

--
Martin Michlmayr
https://www.cyrius.com/

Tobias Pfeiffer

unread,
Dec 30, 2021, 12:44:36 AM12/30/21
to ledge...@googlegroups.com
Hi,

Am Mittwoch, den 29.12.2021, 17:41 +0100 schrieb Uwe Brauer:
> The question is can this be done automatically?
>
> By this I mean
> can
> 2010/07/23 User2:User1-Compensation
> expenses:User2:User1-Compensation 25.00
> expenses:User1:User1-Compensation
>
> Somehow be generated automatically?

For a similar use case I use automated transactions
https://www.ledger-cli.org/3.0/doc/ledger3.html#Automated-Transactions
that split every transaction in two parts, like

```
= expr account =~ /Liabilities:[a-zA-z0-9]*$/ and aux_date >= [2020/05]
$account -1.0
$account:from User1 (roundto(0.6*amount, 0))
$account:from User2 (amount-roundto(0.6*amount, 0))
```

where the 0.6 means that User1 should cover 60% of the costs and User2
only 40%. If the two should pay the same then just use 0.5. Also, if
your currency uses fractional parts (as in your example) then the
second parameter to `roundto()` should not be 0, probably 2.

Then if all your transactions look like

```
2021-12-03=2021-12-05 Amazon
Expenses:Presents 2000 JPY
Liabilities:User1

2021-12-05=2021-12-07 eBay
Expenses:Presents 3000 JPY
Liabilities:User2
```

then you get a balance such as

```
5000 JPY Expenses:Presents
-5000 JPY Liabilities
-2000 JPY User1
-1200 JPY from User1
-800 JPY from User2
-3000 JPY User2
-1800 JPY from User1
-1200 JPY from User2
--------------------
0
```

and then you can look at the minimum of "User1:from User2" and
"User2:from User1" and compute the reimbursement account.

I guess this is more complicated than what you need for your use case,
but it served me well because it generalizes well to non-equal
contributions, and also I can have a User3 make some purchases that
will then be reimbursed by User1 and User2 in the same ratio as
everything else.

Hope it helps
Tobias

signature.asc

Uwe Brauer

unread,
Dec 30, 2021, 2:20:49 AM12/30/21
to ledge...@googlegroups.com
>>> "MM" == Martin Michlmayr <tbm-R+vWnYXSF...@public.gmane.org> writes:

Thanks


> * Uwe Brauer <o...@mat.ucm.es> [2021-12-29 19:58]:
>> expenses:User2:User1-Compensation 25.00/2
>>
>> The entry 25.00/2 is not interpreted.

> You have to this use syntax:

> 2010/07/23 User2:User1-Compensation
> expenses:User2:User1-Compensation (25.00/2)
> expenses:User1:User1-Compensation

Well 25 is already the result it should have been 50/2 😉

I also found out that

2010/07/23 User2:User1-Compensation
expenses:User2:User1-Compensation ((110/2)-(60/2))
expenses:User1:User1-Compensation


Works

But

2010/07/23 User2:User1-Compensation
expenses:User2:User1-Compensation ((110-60)*0.5))
expenses:User1:User1-Compensation


Does not, a bit strange

Uwe Brauer

unread,
Dec 30, 2021, 2:25:06 AM12/30/21
to ledge...@googlegroups.com
>>> "TP" == Tobias Pfeiffer <tgpfe...@web.de> writes:

> Hi,
> Am Mittwoch, den 29.12.2021, 17:41 +0100 schrieb Uwe Brauer:
>> The question is can this be done automatically?
>>
>> By this I mean
>> can
>> 2010/07/23 User2:User1-Compensation
>> expenses:User2:User1-Compensation 25.00
>> expenses:User1:User1-Compensation
>>
>> Somehow be generated automatically?

> For a similar use case I use automated transactions
> https://www.ledger-cli.org/3.0/doc/ledger3.html#Automated-Transactions
> that split every transaction in two parts, like

> ```
> = expr account =~ /Liabilities:[a-zA-z0-9]*$/ and aux_date >= [2020/05]
> $account -1.0
> $account:from User1 (roundto(0.6*amount, 0))
> $account:from User2 (amount-roundto(0.6*amount, 0))
> ```

That looks very interesting and I will try it out later.

thanks

Yuri Khan

unread,
Dec 30, 2021, 2:47:33 AM12/30/21
to Ledger
On Thu, 30 Dec 2021 at 14:20, Uwe Brauer <o...@mat.ucm.es> wrote:

> expenses:User2:User1-Compensation ((110/2)-(60/2))
>
> Works
> But
>
> expenses:User2:User1-Compensation ((110-60)*0.5))
>
> Does not, a bit strange

You should probably balance the parentheses :)

Uwe Brauer

unread,
Dec 30, 2021, 12:23:52 PM12/30/21
to ledge...@googlegroups.com
>>> "YK" == Yuri Khan <yuri.v.khan-Re5JQ...@public.gmane.org> writes:

> On Thu, 30 Dec 2021 at 14:20, Uwe Brauer <oub-YB6e1s5WF/He5aOf...@public.gmane.org> wrote:
>> expenses:User2:User1-Compensation ((110/2)-(60/2))
>>
>> Works
>> But
>>
>> expenses:User2:User1-Compensation ((110-60)*0.5))
>>
>> Does not, a bit strange

> You should probably balance the parentheses :)

Good point, but even

2010/07/23 User2:User1-Compensation
expenses:User2:User1-Compensation ((110-60)*0.5)
expenses:User1:User1-Compensation


Does not work!

John Wiegley

unread,
Dec 31, 2021, 2:26:06 AM12/31/21
to ledge...@googlegroups.com
>>>>> "UB" == Uwe Brauer <o...@mat.ucm.es> writes:

UB> 2010/07/23 User2:User1-Compensation
UB> expenses:User2:User1-Compensation ((110-60)*0.5)
UB> expenses:User1:User1-Compensation

UB> Does not work!

I'm not entirely sure why, but Ledger doesn't like the absence of spaces
around the '-' sign. This does work:

((110 - 60)*0.5)

Btw, you see what Ledger is thinking using:

ledger expr "((110-60)*0.5)"

This seems like a parsing bug to me.

John
signature.asc

Uwe Brauer

unread,
Dec 31, 2021, 2:45:17 AM12/31/21
to ledge...@googlegroups.com
>>> "JW" == John Wiegley <jwie...@gmail.com> writes:

>>>>>> "UB" == Uwe Brauer <o...@mat.ucm.es> writes:
UB> 2010/07/23 User2:User1-Compensation
UB> expenses:User2:User1-Compensation ((110-60)*0.5)
UB> expenses:User1:User1-Compensation

UB> Does not work!

> I'm not entirely sure why, but Ledger doesn't like the absence of spaces
> around the '-' sign. This does work:

> ((110 - 60)*0.5)

Confirmed. This

2010/07/23 User2:User1-Compensation
expenses:User2:User1-Compensation ((110 - 60)*0.5)
expenses:User1:User1-Compensation


Indeed does work, thanks.

> Btw, you see what Ledger is thinking using:

> ledger expr "((110-60)*0.5)"

> This seems like a parsing bug to me.

ok

> John

Martin Michlmayr

unread,
Dec 31, 2021, 7:49:11 AM12/31/21
to ledge...@googlegroups.com
* John Wiegley <jwie...@gmail.com> [2021-12-30 23:25]:
> UB> Does not work!
>
> I'm not entirely sure why, but Ledger doesn't like the absence of spaces
> around the '-' sign. This does work:
>
> ((110 - 60)*0.5)

This got fixed recently
https://github.com/ledger/ledger/issues/2001

Uwe Brauer

unread,
Dec 31, 2021, 8:25:04 AM12/31/21
to ledge...@googlegroups.com
>>> "MM" == Martin Michlmayr <tbm-R+vWnYXSF...@public.gmane.org> writes:

> * John Wiegley <jwie...@gmail.com> [2021-12-30 23:25]:
UB> Does not work!
>>
>> I'm not entirely sure why, but Ledger doesn't like the absence of spaces
>> around the '-' sign. This does work:
>>
>> ((110 - 60)*0.5)

> This got fixed recently
> https://github.com/ledger/ledger/issues/2001

Thanks for pointing it out.

Uwe Brauer

unread,
Dec 31, 2021, 11:47:36 AM12/31/21
to ledge...@googlegroups.com
Hi

I tried out your example


#+begin_src ledger
= expr account =~ /Liabilities:[a-zA-z0-9]*$/ and aux_date >= [2020/05]
$account -1.0
$account:from User1 (roundto(0.5*amount, 2))
$account:from User2 (amount-roundto(0.5*amount, 2))
2021-12-03=2021-12-05 Amazon
Expenses:Presents 2000 JPY
Liabilities:User1
2021-12-05=2021-12-07 eBay
Expenses:Presents 3000 JPY
Liabilities:User2
#+end_src

#+RESULTS:
#+begin_example
5000 JPY Expenses:Presents
-5000 JPY Liabilities
-2000 JPY User1
-1000 JPY from User1
-1000 JPY from User2
-3000 JPY User2
-1500 JPY from User1
-1500 JPY from User2
--------------------
0
#+end_example


I rather don't know how to interpret the result, I hoped I would
automatically know who has to pay whom, what amount. But it seems that
further investigation is necessary, as you seem to indicate
by saying

,----
| and then you can look at the minimum of "User1:from User2" and
| "User2:from User1" and compute the reimbursement account.
`----

In my approach I had also to calculate the money to be transferred from
one user to the other.

Now what puzzles me is

#+begin_src ledger
= expr account =~ /Liabilities:[a-zA-z0-9]*$/ and aux_date >= [2020/05]
$account -1.0
$account:from User1 (roundto(0.5*amount, 0))
$account:from User2 (amount-roundto(0.5*amount, 0))
2021-12-05=2021-12-07 User1
expenses:Jacket 80
Liabilities:User1
2021-12-05=2021-12-07 User1
expenses:Pajama 30
Liabilities:User1
2021-12-05=2021-12-07 User2
expenses:Flowers 20
Liabilities:User2
2021-12-05=2021-12-07 User2
expenses:ChristmasTree 40.00
Liabilities:User2
#+end_src



Here, ledger does not do anything.




Tobias Pfeiffer

unread,
Dec 31, 2021, 11:49:53 PM12/31/21
to ledge...@googlegroups.com
Hi,

a couple of things, I am not sure I can bring it into a well structured
message ;-)

First,

> Now what puzzles me is
>
> #+begin_src ledger
> = expr account =~ /Liabilities:[a-zA-z0-9]*$/ and aux_date >=
> [2020/05]
> $account -1.0
> $account:from User1 (roundto(0.5*amount, 0))
> $account:from User2 (amount-roundto(0.5*amount, 0))
> 2021-12-05=2021-12-07 User1
> expenses:Jacket 80
> Liabilities:User1
> 2021-12-05=2021-12-07 User1
> expenses:Pajama 30
> Liabilities:User1
> 2021-12-05=2021-12-07 User2
> expenses:Flowers 20
> Liabilities:User2
> 2021-12-05=2021-12-07 User2
> expenses:ChristmasTree 40.00
> Liabilities:User2
> #+end_src
>
> Here, ledger does not do anything.

Well, it does *something*, it prints a lot of error messages about
unbalanced transactions. I don't know why, but it seems you need a
currency here. If I just add "JPY" after every number in your example,
`ledger bal` shows

```
-170.00 JPY Liabilities
-110.00 JPY User1
-55.00 JPY from User1
-55.00 JPY from User2
-60.00 JPY User2
-30.00 JPY from User1
-30.00 JPY from User2
170.00 JPY expenses
40.00 JPY ChristmasTree
20.00 JPY Flowers
80.00 JPY Jacket
30.00 JPY Pajama
--------------------
0
```

as expected.

Now, as you wrote:

> I rather don't know how to interpret the result, I hoped I would
> automatically know who has to pay whom, what amount.

That is certainly true, and I have to admit I should have elaborated
more on the clearing process.

"Liabilities:User1:from User1" means "this is the amount of User1's
expenses that he should actually pay by himself according to the
decided ratio". That's a bit silly and if there are only the two users
involved maybe a better way to formulate the automated transaction
would be:

```
= expr account =~ /Liabilities:User1$/
$account -1.0
Income:User1 (roundto(0.5*amount, 0))
$account:from User2 (amount-roundto(0.5*amount, 0))

= expr account =~ /Liabilities:User2$/
$account -1.0
$account:from User1 (roundto(0.5*amount, 0))
Income:User2 (amount-roundto(0.5*amount, 0))
```

Then your balance does not have the silly "liabilities towards self"
lines any more:

```
-85.00 JPY Income
-55.00 JPY User1
-30.00 JPY User2
-85.00 JPY Liabilities
-55.00 JPY User1
-55.00 JPY from User2
-30.00 JPY User2
-30.00 JPY from User1
170.00 JPY expenses
40.00 JPY ChristmasTree
20.00 JPY Flowers
80.00 JPY Jacket
30.00 JPY Pajama
--------------------
0
```

However, you still need to do some manual balancing of
"Liabilities:User1:from User2" and "Liabilities:User2:from User1",
concretely you would need two transactions:

```
# this is just for internal accounting purposes, no money
# is handed over to anyone
2021-12-08=2021-12-08 Counterbalancing
Income:User1 -30 JPY
Liabilities:User2:from User1 30 JPY
Income:User2 -30 JPY
Liabilities:User1:from User2 30 JPY

# this is the thing that you are actually interested in:
# User2 needs to pay User1 an additional 25 JPY
2021-12-08=2021-12-08 Payback Time
Income:User2 -25 JPY
Liabilities:User1:from User2 25 JPY
```

If you do that, then the balance looks as you would like:

```
-170.00 JPY Income
-85.00 JPY User1
-85.00 JPY User2
170.00 JPY expenses
40.00 JPY ChristmasTree
20.00 JPY Flowers
80.00 JPY Jacket
30.00 JPY Pajama
--------------------
0
```

However, you understandably would like to avoid the manual computations
needed with this process. The key to that is to
1. use only a single account for liabilities between user, and use
the sign of this account's amount to determine who needs to pay
whom, and
2. do the counterbalancing implicitly in each transaction.

However, I feel that in particular (1) is somewhat contrary to the idea
of double-entry accounting, and by using only a single account for
directional liabilities you get quite a bit of asymmetry into the
automated transactions.

Consider

```
= expr account =~ /Liabilities:User1$/
$account -1.0
Income:User1 1.0
Liabilities:User1-from-User2 (-(amount-roundto(0.5*amount, 0)))
Income:User2 (amount-roundto(0.5*amount, 0))

= expr account =~ /Liabilities:User2$/
$account -1.0
Income:User2 (amount-roundto(0.5*amount, 0))
Liabilities:User1-from-User2 (roundto(0.5*amount, 0))
```

then your example transactions leave you with a balance (before
clearing) of

```
-195.00 JPY Income
-110.00 JPY User1
-85.00 JPY User2
25.00 JPY Liabilities:User1-from-User2
170.00 JPY expenses
40.00 JPY ChristmasTree
20.00 JPY Flowers
80.00 JPY Jacket
30.00 JPY Pajama
--------------------
0
```

so you can see easily that User1 gets 25 JPY from User2, which is
realized by the following clearing transaction:

```
# User2 needs to pay User1 an additional 25 JPY
2021-12-08=2021-12-08 Payback Time
Income:User1 25 JPY
Liabilities:User1-from-User2 -25 JPY
```

I think this is fairly close to what you imagined, but personally I
feel that
- the automated transactions are hard to understand
- maybe it's just a matter of naming accounts, but I think there
are some postings now that do not reflect the actual situation in
anyone's wallet,
so I think I'd still prefer the method of two liabilities accounts that
are then counterbalanced against each other, but maybe you can build a
flow that works well for you based on this.

Hope this helps
Tobias

signature.asc

Uwe Brauer

unread,
Jan 1, 2022, 12:58:01 PMJan 1
to ledge...@googlegroups.com
Hi,


> Hi,
> a couple of things, I am not sure I can bring it into a well structured
> message ;-)

You most certainly do! 😃, I appreciate your answer
> First,


> Well, it does *something*, it prints a lot of error messages about
> unbalanced transactions. I don't know why, but it seems you need a
> currency here. If I just add "JPY" after every number in your example,
> `ledger bal` shows

> ```
> -170.00 JPY Liabilities
> -110.00 JPY User1
> -55.00 JPY from User1
> -55.00 JPY from User2
> -60.00 JPY User2
> -30.00 JPY from User1
> -30.00 JPY from User2
> 170.00 JPY expenses
> 40.00 JPY ChristmasTree
> 20.00 JPY Flowers
> 80.00 JPY Jacket
> 30.00 JPY Pajama
> --------------------
> 0
> ```

Aha, thanks out of ignorance what currency is JPY supposed to be?


> Consider

> ```
> = expr account =~ /Liabilities:User1$/
> $account -1.0
> Income:User1 1.0
> Liabilities:User1-from-User2 (-(amount-roundto(0.5*amount, 0)))
> Income:User2 (amount-roundto(0.5*amount, 0))

> = expr account =~ /Liabilities:User2$/
> $account -1.0
> Income:User2 (amount-roundto(0.5*amount, 0))
> Liabilities:User1-from-User2 (roundto(0.5*amount, 0))
> ```

> then your example transactions leave you with a balance (before
> clearing) of

> ```
> -195.00 JPY Income
> -110.00 JPY User1
> -85.00 JPY User2
> 25.00 JPY Liabilities:User1-from-User2
> 170.00 JPY expenses
> 40.00 JPY ChristmasTree
> 20.00 JPY Flowers
> 80.00 JPY Jacket
> 30.00 JPY Pajama
> --------------------
> 0
> ```

Great, I think this is already enough, the payback time is nice, but I
think this solution is already good and clear enough.
Out of personal taste I prefer, though:

#+begin_src ledger
= expr account =~ /Liabilities:User1$/
$account -1.0
Income:User1 1.0
Liabilities:User1-from-User2 (-(amount-roundto(0.5*amount, 0)))
Income:User2 (amount-roundto(0.5*amount, 0))
= expr account =~ /Liabilities:User2$/
$account -1.0
Income:User2 (amount-roundto(0.5*amount, 0))
Liabilities:User1-from-User2 (roundto(0.5*amount, 0))
2021-12-05=2021-12-07 User1
expenses:User1:Jacket 80 EUR
Liabilities:User1
2021-12-05=2021-12-07 User1
expenses:User1:Pajama 30 EUR
Liabilities:User1
2021-12-05=2021-12-07 User2
expenses:User2:Flowers 20 EUR
Liabilities:User2
2021-12-05=2021-12-07 User2
expenses:User2:ChristmasTree 40.00 EUR
Liabilities:User2
#+end_src

#+RESULTS:
#+begin_example
-195.00 EUR Income
-110.00 EUR User1
-85.00 EUR User2
25.00 EUR Liabilities:User1-from-User2
170.00 EUR expenses
110.00 EUR User1
80.00 EUR Jacket
30.00 EUR Pajama
60.00 EUR User2
40.00 EUR ChristmasTree
20.00 EUR Flowers
--------------------
0
#+end_example

The advantage is that I can control who spent money on what

In any case this is very nice thanks

Uwe

Tobias Pfeiffer

unread,
Jan 2, 2022, 8:34:38 PMJan 2
to ledge...@googlegroups.com
Hi,

Am Samstag, den 01.01.2022, 18:57 +0100 schrieb Uwe Brauer:
> Aha, thanks out of ignorance what currency is JPY supposed to be?

That would be Japanese Yen :-)

> Great, I think this is already enough, the payback time is nice, but
> I think this solution is already good and clear enough.

Good to hear, happy I could help.

Tobias
signature.asc

Uwe Brauer

unread,
Jan 4, 2022, 5:11:28 AMJan 4
to ledge...@googlegroups.com
>>> "UB" == Uwe Brauer <o...@mat.ucm.es> writes:
Tobias,

Out of curiosity (I am not so acquainted with ledger)

You made the following comment

,----
| However, you understandably would like to avoid the manual computations
| needed with this process. The key to that is to
| 1. use only a single account for liabilities between user, and use
| the sign of this account's amount to determine who needs to pay
| whom, and
| 2. do the counterbalancing implicitly in each transaction.
|
| However, I feel that in particular (1) is somewhat contrary to the idea
| of double-entry accounting, and by using only a single account for
| directional liabilities you get quite a bit of asymmetry into the
| automated transactions.
`----


So I understand that using the solution below, in particular:


$account -1.0

Means that I only use one account which is a bit contrary to the idea of
double-entry accounting?

But the second solution you propose looks complicated to me.

I wounder that this common situation is so hm difficult to achieve

Thanks again

Tobias Pfeiffer

unread,
Jan 7, 2022, 10:19:58 PMJan 7
to ledge...@googlegroups.com
Hi,

sorry it took a while.


Am Dienstag, den 04.01.2022, 11:11 +0100 schrieb Uwe Brauer:
> So I understand that using the solution below, in particular:
>
> $account -1.0
>
> Means that I only use one account which is a bit contrary to the idea
> of double-entry accounting?

Ah, not exactly. First, automated transaction rules apply to
*postings*, i.e., the individual rows of transactions. So the automated
transaction

```
= expr account =~ /Liabilities:User2$/
$account -1.0
Income:User2 (amount-roundto(0.5*amount, 0))
Liabilities:User1-from-User2 (roundto(0.5*amount, 0))
```

matches postings where the account "Liabilities:User2" is used. Then
the line `$account -1.0` means "add the negative of the involved
amount (the -1.0 multiple) to the same account". You can actually check
that with `ledger reg`:

For the input

```
2021-12-05=2021-12-07 User2
expenses:Flowers 20 EUR
Liabilities:User2
```

the `ledger reg` output is

```
21-Dec-05 User2 expenses:Flowers 20 EUR 20 EUR
Liabilities:User2 -20 EUR 0
Liabilities:User2 20 EUR 20 EUR
Income:User2 -10 EUR 10 EUR
Liabi:User1-from-User2 -10 EUR 0
```

so `$account -1.0` effectively removes the matched posting, but you
have to add other postings with the same value sum in order to balance.


> I wounder that this common situation is so hm difficult to achieve

I am no accountant, a lot of the vocabulary around accounting is
foreign to me, and I guess it doesn't help that the way of doing things
is closely coupled to each country's legislation; so take everything I
write with a bucket of salt.

However, my understanding of double-entry accounting is that it is
usually used to manage finances of *one* entity. There is an inherently
one-sided view of writing things down, credit and debit flip meaning
(or sign) once you view from the other side. I am not sure how well
this way of writing things down works when you want to describe a
"global state" of things, rather than the view from one single entity.
This is what I meant when I said "somewhat contrary to the idea of
double-entry accounting".

I think in my first attempt to address this,

```
= expr account =~ /Liabilities:[a-zA-z0-9]*$/ and aux_date >= [2020/05]
$account -1.0
$account:from User1 (roundto(0.6*amount, 0))
$account:from User2 (amount-roundto(0.6*amount, 0))
```

the entity that I am implicitly modelling is a virtual "shared wallet",
so I have income from one user, I have expenses, and the wallet is also
somehow responsible for keeping track of how each expense distributes
across participants. (This would be similar to apps like Kittysplit <
https://www.kittysplit.com/en/> where each expense of one user is split
between participants and then settled at the end. Note that settling
expenses is not a trivial problem once more than two players are
involved, cf. <https://stackoverflow.com/q/877728/3663881>)

You could also model this from the perspective of one of the involved
users. Rather than keeping the expense as a whole and splitting the
income side of things in automated transactions so that it becomes
something like

```
2021-12-05 Flowers
Expenses:Flowers 20 EUR
Income:User1 -10 EUR
Liabilities:User1-from-User2 -10 EUR
```

or the like, you would note things purely from the view of User1:

```
2021-12-05 Flowers (paid by me)
Expenses:Flowers 10 EUR ; this is only half the price
Liabilities:User2 10 EUR ; this is the other half
Assets:Cash -20 EUR ; this is what went out of your wallet

2021-12-05 Christmas Tree (paid by User2)
Expenses:Tree 70 EUR ; this is only half the price
Liabilities:User2 -70 EUR ; namely, your share
```

Even though in the global view of things, flowers for 20 EUR and a tree
for 140 EUR were bought, in your expenses account only your share of
things ever shows up, not the total price. I think this may be much
simpler, but you don't have the total overview of what was paid or
whether a credit card was used by User2 etc. You could still try to
write automated transactions so that your ledger file contains all that
information and is just transformed into the simple shape above.

Hope that helps
Tobias


Uwe Brauer

unread,
Jan 12, 2022, 12:46:21 PM (11 days ago) Jan 12
to ledge...@googlegroups.com
>>> "TP" == Tobias Pfeiffer <tgpfe...@web.de> writes:

> Hi,
> sorry it took a while.
No worries, I am quite busy myself..

[Snip]...

Thanks for this explanation.

>> I wounder that this common situation is so hm difficult to achieve


> However, my understanding of double-entry accounting is that it is
> usually used to manage finances of *one* entity. There is an inherently
> one-sided view of writing things down, credit and debit flip meaning
> (or sign) once you view from the other side. I am not sure how well
> this way of writing things down works when you want to describe a
> "global state" of things, rather than the view from one single entity.
> This is what I meant when I said "somewhat contrary to the idea of
> double-entry accounting".


I see, that make sense.

> across participants. (This would be similar to apps like Kittysplit <
> https://www.kittysplit.com/en/> where each expense of one user is split
> between participants and then settled at the end. Note that settling
> expenses is not a trivial problem once more than two players are
> involved, cf. <https://stackoverflow.com/q/877728/3663881>)

Very interesting thanks


> You could also model this from the perspective of one of the involved
> users. Rather than keeping the expense as a whole and splitting the
> income side of things in automated transactions so that it becomes

[Snip]...


> Even though in the global view of things, flowers for 20 EUR and a tree
> for 140 EUR were bought, in your expenses account only your share of
> things ever shows up, not the total price. I think this may be much
> simpler, but you don't have the total overview of what was paid or
> whether a credit card was used by User2 etc.

Right this is why I stick to your solution, thanks again.
Reply all
Reply to author
Forward
0 new messages