diff --git a/hledger-lib/Hledger/Data/Journal.hs b/hledger-lib/Hledger/Data/Journal.hs index 94d551bc0..7168d48d7 100644 --- a/hledger-lib/Hledger/Data/Journal.hs +++ b/hledger-lib/Hledger/Data/Journal.hs @@ -583,16 +583,25 @@ checkBalanceAssertion p@Posting{pbalanceassertion=Just (BalanceAssertion{baamoun | otherwise = [] checkBalanceAssertion _ _ = Right () +-- | Does the difference between the asserted balance +-- and (the corresponding part of) the actual balance +-- appear as zero, when rendered to the greater of +-- 1. the standard display precision for the commodity +-- 2. the full precision of the asserted amount ? +-- The posting is used when creating an error message. checkBalanceAssertionCommodity :: Posting -> Amount -> MixedAmount -> Either String () checkBalanceAssertionCommodity p assertedamt actualbal - -- this effectively compares the actual balance rounded to display precision (I believe), - -- with the asserted balance as written. See examples in balance assertions manual. | isZeroAmount diff = Right () | True = Left err where + diff = + -- traceWith (("diff:"++).showAmountDebug) $ + -- traceWith (("asserted:"++).showAmountDebug) + assertedamt - + -- traceWith (("actual:"++).showAmountDebug) + actualbalincommodity assertedcomm = acommodity assertedamt actualbalincommodity = fromMaybe nullamt $ find ((== assertedcomm) . acommodity) (amounts actualbal) - diff = assertedamt - actualbalincommodity diffplus | isNegativeAmount diff == False = "+" | otherwise = "" err = printf (unlines diff --git a/hledger-lib/hledger_journal.m4.md b/hledger-lib/hledger_journal.m4.md index 93e6a4884..ac997e3c6 100644 --- a/hledger-lib/hledger_journal.m4.md +++ b/hledger-lib/hledger_journal.m4.md @@ -468,10 +468,37 @@ flag or `real:` query. ### Assertions and precision -The calculated account balance is rounded to display precision before checking. -Eg: here the calculated balance is $1.006. The commodity directive causes -users, and balance assertions, to see this rounded to two decimal places, ie $1.01, -so this assertion passes: +A commodity directive which limits the display precision, can affect assertions. + +In general, hledger balance assertions should pass or fail as you would +expect from visual inspection and manual summing of the amounts shown +in reports and error messages. + +More specifically, assertions pass if the difference between asserted +and actual amounts appears to be zero, when rendered to the greater of +the standard display precision and the asserted amount's precision. + +Here are some examples of this in action. + +Asserting the exact balance: +```journal +commodity $1000.00 + +2019/01/01 + (a) $0.006 + +2019/01/02 + (a) $1.00 = $1.006 + +; Actual balance: 1.006 +; Asserted balence: 1.006 +; Difference: 0.000 +; Standard & asserted precisions: 2, 3 +; Difference rendered: 0.000 +; Result: pass +``` + +Asserting the balance rounded to fewer decimal places: ```journal commodity $1000.00 @@ -480,9 +507,16 @@ commodity $1000.00 2019/01/02 (a) $1.00 = $1.01 + +; Actual balance: 1.006 +; Asserted balence: 1.01 +; Difference: 0.004 +; Standard & asserted precisions: 2, 2 +; Difference rendered: 0.00 +; Result: pass ``` -The asserted balance is not rounded to display precision. So this assertion fails: +Asserting an inexact balance with too many decimal places (fails): ```journal commodity $1000.00 @@ -490,9 +524,14 @@ commodity $1000.00 (a) $0.006 2019/01/02 - (a) $1.00 = $1.007 -# calculated: $1.01 -# asserted: $1.007 (difference: +$0.001) + (a) $1.00 = $1.0061 + +; Actual balance: 1.006 +; Asserted balence: 1.0061 +; Difference: 0.0001 +; Standard & asserted precisions: 2, 4 +; Difference rendered: 0.0001 +; Result: fail ``` ## Balance Assignments diff --git a/tests/journal/balance-assertions.test b/tests/journal/balance-assertions.test index 5b52d86a4..2a42bbd74 100755 --- a/tests/journal/balance-assertions.test +++ b/tests/journal/balance-assertions.test @@ -366,9 +366,38 @@ hledger -f- stats >>>2 /unexpected '@'/ >>>=1 -# 21. The calculated balance is rounded to display precision before checking. -# Here the calculated balance is $1.005 but users, and balance assertions, -# see it as $1.00 (because the commodity directive set display precision to 2). +# 21. With a commodity directive limiting the display precision. +# Assertions pass if the difference between asserted and actual amounts +# appears to be zero, when rendered to the greater of the standard +# display precision and the asserted amount's precision. +# Here, +# Actual balance: 1.006 +# Asserted balence: 1.006 +# Difference: 0.000 +# Standard & asserted precisions: 2, 3 +# Difference rendered: 0.000 +# Result: pass +hledger -f- stats +<<< +commodity $1000.00 + +2019/01/01 + (a) $0.006 + +2019/01/02 + (a) $1.00 = $1.006 + +>>> /Transactions/ +>>>2 +>>>=0 + +# 22. A rounded assertion amount can also pass. Here, +# Actual balance: 1.006 +# Asserted balence: 1.01 +# Difference: 0.004 +# Standard & asserted precisions: 2, 2 +# Difference rendered: 0.00 +# Result: pass hledger -f- stats <<< commodity $1000.00 @@ -383,7 +412,13 @@ commodity $1000.00 >>>2 >>>=0 -# 22. The asserted balance is not rounded to display precision. +# 23. A more precise assertion amount can fail. Here, +# Actual balance: 1.006 +# Asserted balence: 1.0061 +# Difference: 0.0001 +# Standard & asserted precisions: 2, 4 +# Difference rendered: 0.0001 +# Result: fail hledger -f- stats <<< commodity $1000.00 @@ -392,8 +427,8 @@ commodity $1000.00 (a) $0.006 2019/01/02 - (a) $1.00 = $1.007 + (a) $1.00 = $1.0061 >>> ->>>2 /difference: \+\$0\.001/ +>>>2 /difference: \+\$0\.0001/ >>>=1