Fix bug where .total used in value exprs breaks totals
* Re-initialize (to VOID) totals for the account and its ancestors on adding postings. Otherwise the cache intended for use by recursive calls of C++ function total() in computing family (i.e. account hierarchy) totals is incorrectly retained from one top-level call to the next, causing inconsistent and broken behaviour. * Re-initialize (to false) calculated and gathered. Otherwise we won't e.g. recalculate stale totals for ancestor accounts (e.g. won't recalculate Assets:Savings total if Assets:Savings changes via a posting). Although the value expression total function is used by ledger itself in computing totals, this bug would only appear on use of .total in user-supplied value expressions computed *during parsing* of ledger files, rather than after parsing (I believe ledger only ever calls it for internal purposes after parsing is complete). It is possible this bug also affected other functions than total (perhaps even in circumstances other than analagous to that described in the preceding paragraph). I have not checked that.
This commit is contained in:
parent
b41454477a
commit
de1b48a013
3 changed files with 71 additions and 0 deletions
|
|
@ -136,6 +136,19 @@ void account_t::add_post(post_t * post)
|
|||
xdata_->self_details.calculated = false;
|
||||
xdata_->family_details.gathered = false;
|
||||
xdata_->family_details.calculated = false;
|
||||
if (! xdata_->family_details.total.is_null()) {
|
||||
xdata_->family_details.total = ledger::value_t();
|
||||
}
|
||||
account_t *ancestor = this;
|
||||
while (ancestor->parent) {
|
||||
ancestor = ancestor->parent;
|
||||
if (ancestor->has_xdata()) {
|
||||
xdata_t &xdata = ancestor->xdata();
|
||||
xdata.family_details.gathered = false;
|
||||
xdata.family_details.calculated = false;
|
||||
xdata.family_details.total = ledger::value_t();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
28
test/regress/total-1.test
Normal file
28
test/regress/total-1.test
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
; Test that calling total does not affect future calls to that function via a
|
||||
; stale cache entry for the totalled account, because of a change to that same
|
||||
; account
|
||||
|
||||
2017-10-01 * Opening Balance
|
||||
Assets:Current Account $1000.00
|
||||
Equity:Opening Balances
|
||||
|
||||
2017-10-02 * Savings
|
||||
Assets:Savings $100.00
|
||||
Assets:Current Account
|
||||
|
||||
assert account("Assets:Current Account").total == $900.00
|
||||
|
||||
2017-10-03 * Savings
|
||||
Assets:Savings $100.00
|
||||
Assets:Current Account
|
||||
|
||||
assert account("Assets:Current Account").total == $800.00
|
||||
|
||||
test bal
|
||||
$1000.00 Assets
|
||||
$800.00 Current Account
|
||||
$200.00 Savings
|
||||
$-1000.00 Equity:Opening Balances
|
||||
--------------------
|
||||
0
|
||||
end test
|
||||
30
test/regress/total-2.test
Normal file
30
test/regress/total-2.test
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
; Test that calling total does not affect future calls to that function via a
|
||||
; stale cache entry for the totalled account, because of a change to an
|
||||
; descendant (Assets:Current:Unallocated) of that account (Assets:Current)
|
||||
|
||||
2017-10-01 * Opening entry
|
||||
Assets:Current:Unallocated $2000.00
|
||||
Equity:Opening Balances
|
||||
|
||||
2017-10-02 * Initial savings
|
||||
Assets:Current:Savings $1000.00
|
||||
Assets:Current:Unallocated
|
||||
|
||||
assert account("Assets:Current").total == $2000.00
|
||||
|
||||
2017-10-03 * Balance
|
||||
Assets:Current:Unallocated $1.00
|
||||
Equity:Adjustments
|
||||
|
||||
assert account("Assets:Current").total == $2001.00
|
||||
|
||||
test bal
|
||||
$2001.00 Assets:Current
|
||||
$1000.00 Savings
|
||||
$1001.00 Unallocated
|
||||
$-2001.00 Equity
|
||||
$-1.00 Adjustments
|
||||
$-2000.00 Opening Balances
|
||||
--------------------
|
||||
0
|
||||
end test
|
||||
Loading…
Add table
Reference in a new issue