From ea58a7ccd7d55e4c676807ac3dcae85073bb3f4c Mon Sep 17 00:00:00 2001 From: Simon Michael Date: Thu, 2 May 2024 20:21:54 -1000 Subject: [PATCH] imp: check: check ordereddates before balance assertions, when both are enabled --- hledger-lib/Hledger/Data/JournalChecks.hs | 3 +-- hledger-lib/Hledger/Read.hs | 1 + hledger-lib/Hledger/Read/Common.hs | 19 ++++++++++++++---- hledger/Hledger/Cli/Commands/Check.hs | 3 +-- hledger/Hledger/Cli/Commands/Check.md | 2 ++ hledger/test/check-commodities.test | 5 +++++ hledger/test/check-ordereddates.test | 24 +++++++++++++++++++++++ 7 files changed, 49 insertions(+), 8 deletions(-) diff --git a/hledger-lib/Hledger/Data/JournalChecks.hs b/hledger-lib/Hledger/Data/JournalChecks.hs index e122ad3e8..d0c3e5eb2 100644 --- a/hledger-lib/Hledger/Data/JournalChecks.hs +++ b/hledger-lib/Hledger/Data/JournalChecks.hs @@ -48,8 +48,7 @@ import Hledger.Data.Balancing (journalBalanceTransactions, defbalancingopts) journalStrictChecks :: Journal -> Either String () journalStrictChecks j = do -- keep the order of checks here synced with Check.md and Hledger.Cli.Commands.Check.Check. - -- journalCheckOrdereddates j - -- journalCheckBalanceAssertions j + -- balanced is checked earlier, in journalFinalise journalCheckCommodities j journalCheckAccounts j diff --git a/hledger-lib/Hledger/Read.hs b/hledger-lib/Hledger/Read.hs index f68ab5225..1c0159db9 100644 --- a/hledger-lib/Hledger/Read.hs +++ b/hledger-lib/Hledger/Read.hs @@ -228,6 +228,7 @@ readJournal iopts@InputOpts{strict_} mpath txt = do -- | Read a Journal from this file, or from stdin if the file path is -, -- with strict checks if enabled, or return an error message. +-- (Note strict checks are disabled temporarily here when this is called by readJournalFiles). -- The file path can have a READER: prefix. -- -- The reader (data format) to use is determined from (in priority order): diff --git a/hledger-lib/Hledger/Read/Common.hs b/hledger-lib/Hledger/Read/Common.hs index d4820e1df..719962dea 100644 --- a/hledger-lib/Hledger/Read/Common.hs +++ b/hledger-lib/Hledger/Read/Common.hs @@ -313,9 +313,11 @@ initialiseAndParseJournal parser iopts f txt = -- -- - infer market prices from costs if enabled -- --- - check all accounts have been declared if in strict mode --- --- - check all commodities have been declared if in strict mode +-- One correctness check (parseable) has already passed when this function is called. +-- Up to three more are performed here: +-- - ordereddates (when enabled), done before balance assertions +-- - autobalanced (and with --strict, balanced ?), in the journalBalanceTransactions step. +-- Others (commodities, accounts) are done later by journalStrictChecks. -- journalFinalise :: InputOpts -> FilePath -> Text -> ParsedJournal -> ExceptT String IO Journal journalFinalise iopts@InputOpts{..} f txt pj = do @@ -342,7 +344,16 @@ journalFinalise iopts@InputOpts{..} f txt pj = do -- >>= Right . dbg0With (concatMap (T.unpack.showTransaction).jtxns) -- >>= \j -> deepseq (concatMap (T.unpack.showTransaction).jtxns $ j) (return j) <&> dbg9With (lbl "amounts after styling, forecasting, auto-posting".showJournalAmountsDebug) - >>= journalBalanceTransactions balancingopts_ -- infer balance assignments and missing amounts and maybe check balance assertions. + + -- Ensure ordereddates is checked before balance assertions. + -- Currently ordereddates is not part of strict mode and can only be enabled by the check command, + -- and that will not run for a while yet. So for now, this dirty hack (uses unsafePerformIO): + >>= (\j -> let args = progArgs in + if "check" `elem` args && "ordereddates" `elem` args + then journalCheckOrdereddates j <&> const j + else Right j) -- the outer parentheses are needed + + >>= journalBalanceTransactions balancingopts_ -- infer balance assignments and missing amounts and (unless disabled) check balance assertions. <&> dbg9With (lbl "amounts after transaction-balancing".showJournalAmountsDebug) -- <&> dbg9With (("journalFinalise amounts after styling, forecasting, auto postings, transaction balancing"<>).showJournalAmountsDebug) >>= journalInferCommodityStyles -- infer commodity styles once more now that all posting amounts are present diff --git a/hledger/Hledger/Cli/Commands/Check.hs b/hledger/Hledger/Cli/Commands/Check.hs index 896d4582f..089258938 100644 --- a/hledger/Hledger/Cli/Commands/Check.hs +++ b/hledger/Hledger/Cli/Commands/Check.hs @@ -96,12 +96,11 @@ runCheck _opts j (chck,_) = do d <- getCurrentDay let results = case chck of - -- these checks are assumed to have passed earlier during journal parsing: + -- these checks are assumed to have passed earlier during journal parsing (if enabled): Parseable -> Right () Autobalanced -> Right () Balanced -> Right () Assertions -> Right () - Accounts -> journalCheckAccounts j Commodities -> journalCheckCommodities j Ordereddates -> journalCheckOrdereddates j diff --git a/hledger/Hledger/Cli/Commands/Check.md b/hledger/Hledger/Cli/Commands/Check.md index 4a890ea66..359ec2b10 100644 --- a/hledger/Hledger/Cli/Commands/Check.md +++ b/hledger/Hledger/Cli/Commands/Check.md @@ -61,6 +61,8 @@ These other checks are not wanted by everyone, but can be run using the `check` - **ordereddates** - within each file, transactions are ordered by date. This is a simple and effective error catcher, and you should use it. Alas! not everyone wants it. If you do, use `hledger check -s ordereddates`. + Note, this check is performed early, before balance assertions + (because copy-pasted dates are often the root cause of balance assertion failures). - **payees** - all payees used by transactions [must be declared](#payee-directive). This will force you to always use known/declared payee names. diff --git a/hledger/test/check-commodities.test b/hledger/test/check-commodities.test index 4c49719e6..fa249b935 100644 --- a/hledger/test/check-commodities.test +++ b/hledger/test/check-commodities.test @@ -30,3 +30,8 @@ $ hledger -f- check commodities $ hledger -f- check commodities >2 /commodity "\$" has not been declared/ >=1 + +# ** 5. The commodities check is enabled in strict mode, ahead of accounts. +$ hledger -f- check -s +>2 /commodity "\$" has not been declared/ +>=1 diff --git a/hledger/test/check-ordereddates.test b/hledger/test/check-ordereddates.test index 996387d64..efe30061c 100644 --- a/hledger/test/check-ordereddates.test +++ b/hledger/test/check-ordereddates.test @@ -24,6 +24,30 @@ $ hledger -f- check ordereddates --date2 >2 /date .*is out of order/ >=1 +# ** 4. ordereddates is checked before balance assertions, when both are enabled +< +2024-01-02 + (a) 1 = 9 + +2024-01-01 + (a) 1 + +$ hledger -f - check assertions ordereddates +>2 /date .*is out of order/ +>=1 + +# ** 5. enabling the ordereddates check does not disable the balance assertions check +< +2024-01-01 + (a) 1 + +2024-01-02 + (a) 1 = 9 + +$ hledger -f - check assertions ordereddates +>2 /Balance assertion failed/ +>=1 + # XXX not supported: With a query, only matched transactions' dates are checked. # < # 2020-01-01 a