simonmichael / hledger

Robust, fast, intuitive plain text accounting tool with CLI, TUI and web interfaces.
https://hledger.org
GNU General Public License v3.0
2.91k stars 315 forks source link

transaction modifiers do not multiply total-priced amounts correctly #928

Closed DanMeakin closed 5 years ago

DanMeakin commented 5 years ago

I have encountered an issue since updating to the current version of hledger involving multiple currencies and automated postings. It is best illustrated with an example:

= ^Expenses:Joint
    Expenses:Joint                                               *-1
    Liabilities:Joint:Bob                                       *0.5
    Liabilities:Joint:Bill                                      *0.5
    Assets:Bob:Reimbursements:Joint                            *-0.5
    Expenses:Bob                                                *0.5
    Assets:Bill:Reimbursements:Joint                           *-0.5
    Expenses:Bill                                               *0.5

2018-01-01 * Acme
    Expenses:Joint:Widgets                                   $100.00
    Assets:Joint:Bank                                        -£50.00

Previously, an entry such as this was processed without any problem. However, right now running hledger bal --auto results in the following error:

could not balance this transaction (real postings are off by £50.00)
2018/01/01 * Acme
    Expenses:Joint:Widgets               $100.00 @@ £50.00
    Expenses:Joint                      $-100.00 @@ £50.00
    Liabilities:Joint:Bob                 $50.00 @@ £50.00
    Liabilities:Joint:Bill                $50.00 @@ £50.00
    Assets:Bob:Reimbursements:Joint      $-50.00 @@ £50.00
    Expenses:Bob                          $50.00 @@ £50.00
    Assets:Bill:Reimbursements:Joint     $-50.00 @@ £50.00
    Expenses:Bill                         $50.00 @@ £50.00
    Assets:Joint:Bank                              £-50.00

If the currency value is entered with a @ then there is no such problem.

simonmichael commented 5 years ago

Hi @DanMeakin. That's interesting, thanks for the report.

~/src/hledger$ hledger-1.10 -f b.j print -x 
2018/01/01 * Acme
    Expenses:Joint:Widgets    $100.00 @@ £50.00
    Assets:Joint:Bank                   £-50.00

~/src/hledger$ hledger-1.10 -f b.j print -x --auto
2018/01/01 * Acme
    Expenses:Joint:Widgets               $100.00 @ £0.5000
    Expenses:Joint                      $-100.00 @ £0.5000
    Liabilities:Joint:Bob                 $50.00 @ £0.5000
    Liabilities:Joint:Bill                $50.00 @ £0.5000
    Assets:Bob:Reimbursements:Joint      $-50.00 @ £0.5000
    Expenses:Bob                          $50.00 @ £0.5000
    Assets:Bill:Reimbursements:Joint     $-50.00 @ £0.5000
    Expenses:Bill                         $50.00 @ £0.5000
    Assets:Joint:Bank                              £-50.00
simonmichael commented 5 years ago
~/src/PLAINTEXTACCOUNTING/hledger$ cat $LEDGER_FILE
= ^Expenses:Joint
    Expenses:Joint                                               *-1
    Liabilities:Joint:Bob                                       *0.5
    Liabilities:Joint:Bill                                      *0.5

2018/01/01
    Expenses:Joint:Widgets                                   $100.00 @@ £50
    Assets:Joint:Bank                                        -£50.00

~/src/PLAINTEXTACCOUNTING/hledger$ hledger-1.9 print --auto
2018/01/01
    Expenses:Joint:Widgets     $100.00 @@ £50
    Assets:Joint:Bank                 £-50.00
    Expenses:Joint            $-100.00 @@ £50
    Liabilities:Joint:Bob       $50.00 @@ £50
    Liabilities:Joint:Bill      $50.00 @@ £50

~/src/PLAINTEXTACCOUNTING/hledger$ hledger-1.10 print --auto
hledger-1.10: could not balance this transaction (real postings are off by £50.00)
2018/01/01
    Expenses:Joint:Widgets     $100.00 @@ £50
    Expenses:Joint            $-100.00 @@ £50
    Liabilities:Joint:Bob       $50.00 @@ £50
    Liabilities:Joint:Bill      $50.00 @@ £50
    Assets:Joint:Bank                 £-50.00

~/src/PLAINTEXTACCOUNTING/hledger$ hledger-1.11 print --auto
hledger-1.11: "b.j" (lines 6-8)
could not balance this transaction (real postings are off by £50.00)
2018/01/01
    Expenses:Joint:Widgets     $100.00 @@ £50
    Expenses:Joint            $-100.00 @@ £50
    Liabilities:Joint:Bob       $50.00 @@ £50
    Liabilities:Joint:Bill      $50.00 @@ £50
    Assets:Joint:Bank                 £-50.00

I think: transaction modifiers with amount multipliers have never worked right if the amount has a @@ total price (and the syntax in @DanMeakin's original example is equivalent to that). hledger 1.5-1.9 generated wrongly-priced auto postings which don't balance, and didn't notice. hledger 1.10-1.11 also generate wrongly-priced auto postings but do notice that they are unbalanced.

simonmichael commented 5 years ago

Open question: is it robust to convert such total-priced amounts to unit-priced before multiplying them ? I think that'll "always" work.

simonmichael commented 5 years ago

I have pushed a fix to master. The first version generated postings with unit prices and one extra decimal place, like this:

2018/01/01
    Expenses:Joint:Widgets     $100.00 @@ £50
    Expenses:Joint            $-100.00 @ £0.5
    Liabilities:Joint:Bob       $50.00 @ £0.5
    Liabilities:Joint:Bill      $50.00 @ £0.5
    Assets:Joint:Bank                 £-50.00

The latest fix just multiplies the total price by the same factor, like this:

2018/01/01
    Expenses:Joint:Widgets     $100.00 @@ £50
    Expenses:Joint            $-100.00 @@ £50
    Liabilities:Joint:Bob       $50.00 @@ £25
    Liabilities:Joint:Bill      $50.00 @@ £25
    Assets:Joint:Bank                 £-50.00

Either of these is enough to make this example work, but I'm not sure how robust they are in general. More testing and feedback needed.

DanMeakin commented 5 years ago

Thanks very much for the very quick fixing of this!