From 3186ff514a19851266b5be63773a54086e2ae2d9 Mon Sep 17 00:00:00 2001 From: Pascal Fleury Date: Tue, 17 Jul 2018 21:59:01 +0200 Subject: amount_t -> balance_t. --- src/textual.cc | 43 ++++++++++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/src/textual.cc b/src/textual.cc index 8fbc5c08..5d7706ec 100644 --- a/src/textual.cc +++ b/src/textual.cc @@ -1644,9 +1644,9 @@ post_t * instance_t::parse_post(char * line, } DEBUG("textual.parse", "line " << context.linenum << ": " - << "POST assign: parsed amt = " << *post->assigned_amount); + << "POST assign: parsed balance amount = " << *post->assigned_amount); - amount_t& amt(*post->assigned_amount); + const amount_t& amt(*post->assigned_amount); value_t account_total (post->account->amount().strip_annotations(keep_details_t())); @@ -1655,18 +1655,19 @@ post_t * instance_t::parse_post(char * line, DEBUG("post.assign", "line " << context.linenum << ": " << "post amount = " << amt); - amount_t diff = amt; + balance_t diff = amt; switch (account_total.type()) { case value_t::AMOUNT: - if (account_total.as_amount().commodity_ptr() == diff.commodity_ptr()) - diff -= account_total.as_amount(); + diff -= account_total.as_amount(); + DEBUG("textual.parse", "line " << context.linenum << ": " + << "Subtracting amount " << account_total.as_amount() << " from diff, yielding " << diff); break; case value_t::BALANCE: - if (optional comm_bal = - account_total.as_balance().commodity_amount(amt.commodity())) - diff -= *comm_bal; + diff -= account_total.as_balance(); + DEBUG("textual.parse", "line " << context.linenum << ": " + << "Subtracting balance " << account_total.as_balance() << " from diff, yielding " << diff); break; default: @@ -1680,26 +1681,42 @@ post_t * instance_t::parse_post(char * line, // Subtract amounts from previous posts to this account in the xact. for (post_t* p : xact->posts) { - if (p->account == post->account && - p->amount.commodity_ptr() == diff.commodity_ptr()) { + if (p->account == post->account) { diff -= p->amount; DEBUG("textual.parse", "line " << context.linenum << ": " - << "Subtract " << p->amount << ", diff = " << diff); + << "Subtracting " << p->amount << ", diff = " << diff); } } if (post->amount.is_null()) { // balance assignment if (! diff.is_zero()) { - post->amount = diff; + // This will fail if there are more than 1 commodity in diff, which is wanted, + // as amount cannot store more than 1 commodity. + post->amount = diff.to_amount(); DEBUG("textual.parse", "line " << context.linenum << ": " << "Overwrite null posting"); } } else { // balance assertion diff -= post->amount; + // If amt has a commodity, restrict balancing to that. Otherwise, it's the blanket '0' and + // check that all of them are zero. + if (amt.has_commodity()) { + DEBUG("textual.parse", "line " << context.linenum << ": " + << "Finding commodity " << amt.commodity() << " (" << amt << ") in balance " << diff); + optional wanted_commodity = diff.commodity_amount(amt.commodity()); + if (!wanted_commodity) { + diff = amt - amt; // this is '0' with the correct commodity. + } else { + diff = *wanted_commodity; + } + DEBUG("textual.parse", "line " << context.linenum << ": " + << "Diff is now " << diff); + } if (! no_assertions && ! diff.is_zero()) { - amount_t tot = amt - diff; + balance_t tot = -diff + amt; + DEBUG("textual.parse", "Balance assertion: off by " << diff << " (expected to see " << tot << ")"); throw_(parse_error, _f("Balance assertion off by %1% (expected to see %2%)") % diff % tot); -- cgit v1.2.3 From 135a9e52ad0d753477aa4723f1ed23c16e8a3f32 Mon Sep 17 00:00:00 2001 From: Pascal Fleury Date: Tue, 17 Jul 2018 23:36:50 +0200 Subject: fix regression of test 1147_a --- src/textual.cc | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/src/textual.cc b/src/textual.cc index 5d7706ec..246db751 100644 --- a/src/textual.cc +++ b/src/textual.cc @@ -1652,8 +1652,8 @@ post_t * instance_t::parse_post(char * line, DEBUG("post.assign", "line " << context.linenum << ": " << "account balance = " << account_total); - DEBUG("post.assign", - "line " << context.linenum << ": " << "post amount = " << amt); + DEBUG("post.assign", "line " << context.linenum << ": " + << "post amount = " << amt << " (is_zero = " << amt.is_zero() << ")"); balance_t diff = amt; @@ -1688,6 +1688,21 @@ post_t * instance_t::parse_post(char * line, } } + // If amt has a commodity, restrict balancing to that. Otherwise, it's the blanket '0' and + // check that all of them are zero. + if (amt.has_commodity()) { + DEBUG("textual.parse", "line " << context.linenum << ": " + << "Finding commodity " << amt.commodity() << " (" << amt << ") in balance " << diff); + optional wanted_commodity = diff.commodity_amount(amt.commodity()); + if (!wanted_commodity) { + diff = amt - amt; // this is '0' with the correct commodity. + } else { + diff = *wanted_commodity; + } + DEBUG("textual.parse", "line " << context.linenum << ": " + << "Diff is now " << diff); + } + if (post->amount.is_null()) { // balance assignment if (! diff.is_zero()) { @@ -1700,26 +1715,12 @@ post_t * instance_t::parse_post(char * line, } else { // balance assertion diff -= post->amount; - // If amt has a commodity, restrict balancing to that. Otherwise, it's the blanket '0' and - // check that all of them are zero. - if (amt.has_commodity()) { - DEBUG("textual.parse", "line " << context.linenum << ": " - << "Finding commodity " << amt.commodity() << " (" << amt << ") in balance " << diff); - optional wanted_commodity = diff.commodity_amount(amt.commodity()); - if (!wanted_commodity) { - diff = amt - amt; // this is '0' with the correct commodity. - } else { - diff = *wanted_commodity; - } - DEBUG("textual.parse", "line " << context.linenum << ": " - << "Diff is now " << diff); - } if (! no_assertions && ! diff.is_zero()) { balance_t tot = -diff + amt; DEBUG("textual.parse", "Balance assertion: off by " << diff << " (expected to see " << tot << ")"); throw_(parse_error, _f("Balance assertion off by %1% (expected to see %2%)") - % diff % tot); + % diff.to_string() % tot.to_string()); } } -- cgit v1.2.3 From 4a54ac5cc68bcd7fda68610ca5089e3a06963c68 Mon Sep 17 00:00:00 2001 From: Pascal Fleury Date: Wed, 18 Jul 2018 00:04:02 +0200 Subject: Added more documentation about assertions. --- doc/ledger3.texi | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/doc/ledger3.texi b/doc/ledger3.texi index a094d977..45afe1ae 100644 --- a/doc/ledger3.texi +++ b/doc/ledger3.texi @@ -3230,6 +3230,45 @@ A balance assertion has this general form: This simply asserts that after subtracting $20.00 from Assets:Cash, that the resulting total matches $500.00. If not, it is an error. +The assertion has an effect only on the specified commodity. If an account has +multiple commodities, then only the one asserted is verified: + +@smallexample +2012-03-10 KFC New York + Expenses:Food $20.00 + Assets:Cash $-20.00 = $500.00 + +2012-03-11 KFC Montreal + Expenses:Food 15.00 CAD + Assets:Cash -15.00 CAD = $500.00 +@end smallexample + +In this case, the amount in USD of cash (which has not changed) is validated. +Nothing is asserted about the current amount of Canadian dollars in @samp{Asset:Cash}. + +@subsubsection Special assertion value 0 + +The only value that can be asserted without a commodity is @samp{0}. +This results in a cross-commodities assertion, which makes it possible to +assert that an account is totally empty. + +@smallexample +2012-03-09 Fill Wallet + Revenue $20.00 + Revenue 15.00 CAD + Assets:Cash + +2012-03-10 KFC New York + Expenses:Food $20.00 + Assets:Cash $-20.00 + +2012-03-11 KFC Montreal + Expenses:Food 15.00 CAD + Assets:Cash -15.00 CAD = 0 +@end smallexample + +The last transaction will assert that we are out of cash of any sort. + @node Balance assignments, Resetting a balance, Balance assertions, Balance verification @subsection Balance assignments -- cgit v1.2.3 From 3ee62bf84e1d67cc4bc1d151b60ddeaaeba7147c Mon Sep 17 00:00:00 2001 From: Pascal Fleury Date: Wed, 18 Jul 2018 00:08:56 +0200 Subject: Add the test to make sure it works in the future. --- test/regress/1187_5.test | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 test/regress/1187_5.test diff --git a/test/regress/1187_5.test b/test/regress/1187_5.test new file mode 100644 index 00000000..4aa5fdd8 --- /dev/null +++ b/test/regress/1187_5.test @@ -0,0 +1,36 @@ +2013/12/01 * Initial State + Crédit:Viseca:MasterCard P1 -618.50 CHF + Crédit:Viseca:MasterCard P2 -52.10 CHF + Equity:Opening Balances + +2013/12/15 * Buy Some Chocolate + Dépenses:Nourriture 19.00 EUR ; #1 + Crédit:Viseca:MasterCard P1 + +2013/12/15 * Buy Some Chocolate + Crédit:Viseca:MasterCard P1 18.00 EUR ; #2 + Recettes:Erreurs + +2013/12/23 * Facture Viseca + Crédit:Viseca:MasterCard P2 52.10 CHF = 0 ; #3 + Crédit:Viseca:MasterCard P1 618.50 CHF = 0 CHF ; #4 + Dépenses:Frais:Gestion Comptes 1.50 CHF + Crédit:Viseca -672.10 CHF + +2014/01/03 * Facture Viseca + Crédit:Viseca 672.10 CHF = 0 + Actif:Comptes:CP courant + +test bal + -672.10 CHF Actif:Comptes:CP courant + -1.00 EUR Crédit:Viseca + -1.00 EUR MasterCard P1 + 1.50 CHF + 19.00 EUR Dépenses + 1.50 CHF Frais:Gestion Comptes + 19.00 EUR Nourriture + 670.60 CHF Equity:Opening Balances + -18.00 EUR Recettes:Erreurs +-------------------- + 0 +end test -- cgit v1.2.3