imp: -I can now be overridden by -s or the check command

This enables a "relaxed" workflow where you delay balance assertions
checking until strict mode is turned on: always run hledger -I, and
add -s when you're ready.
This commit is contained in:
Simon Michael 2024-05-07 15:44:06 -10:00
parent 0fedc35a95
commit b7e5c05da2
4 changed files with 40 additions and 20 deletions

View File

@ -320,19 +320,28 @@ initialiseAndParseJournal parser iopts f txt =
-- Others (commodities, accounts) are done later by journalStrictChecks.
--
journalFinalise :: InputOpts -> FilePath -> Text -> ParsedJournal -> ExceptT String IO Journal
journalFinalise iopts@InputOpts{..} f txt pj = do
t <- liftIO getPOSIXTime
journalFinalise iopts@InputOpts{auto_,balancingopts_,infer_costs_,infer_equity_,strict_,verbose_tags_,_ioDay} f txt pj = do
let
BalancingOpts{commodity_styles_, ignore_assertions_} = balancingopts_
fname = "journalFinalise " <> takeFileName f
lbl = lbl_ fname
-- We want to know when certain checks have been explicitly requested with the check command,
-- but it does not run until later. For now, hackily inspect the command line with unsafePerformIO.
checking checkname = "check" `elem` args && checkname `elem` args where args = progArgs
-- We will check ordered dates when "check ordereddates" is used.
checkordereddates = checking "ordereddates"
-- We will check balance assertions by default, unless -I is used, but always if -s or "check assertions" are used.
checkassertions = not ignore_assertions_ || strict_ || checking "assertions"
t <- liftIO getPOSIXTime
liftEither $
pj{jglobalcommoditystyles=fromMaybe mempty $ commodity_styles_ balancingopts_}
pj{jglobalcommoditystyles=fromMaybe mempty commodity_styles_}
& journalSetLastReadTime t -- save the last read time
& journalAddFile (f, txt) -- save the main file's info
& journalReverse -- convert all lists to the order they were parsed
& journalAddAccountTypes -- build a map of all known account types
& journalStyleAmounts -- Infer and apply commodity styles (but don't round) - should be done early
<&> journalAddForecast (verbose_tags_) (forecastPeriod iopts pj) -- Add forecast transactions if enabled
<&> journalAddForecast verbose_tags_ (forecastPeriod iopts pj) -- Add forecast transactions if enabled
<&> journalPostingsAddAccountTags -- Add account tags to postings, so they can be matched by auto postings.
>>= journalMarkRedundantCosts -- Mark redundant costs, to help journalBalanceTransactions ignore them.
-- (Later, journalInferEquityFromCosts will do a similar pass, adding missing equity postings.)
@ -344,16 +353,8 @@ 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)
-- 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.
>>= (\j -> if checkordereddates then journalCheckOrdereddates j <&> const j else Right j) -- check ordereddates before assertions. The outer parentheses are needed.
>>= journalBalanceTransactions balancingopts_{ignore_assertions_=not checkassertions} -- infer balance assignments and missing amounts, and maybe 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

View File

@ -157,8 +157,8 @@ inputflags = [
,flagReq ["rules-file"] (\s opts -> Right $ setopt "rules-file" s opts) "RFILE" "CSV conversion rules file (default: FILE.rules)"
,flagReq ["alias"] (\s opts -> Right $ setopt "alias" s opts) "OLD=NEW" "rename accounts named OLD to NEW"
,flagReq ["pivot"] (\s opts -> Right $ setopt "pivot" s opts) "TAGNAME" "use some other field/tag for account names"
,flagNone ["ignore-assertions","I"] (setboolopt "ignore-assertions") "ignore any balance assertions"
,flagNone ["strict","s"] (setboolopt "strict") "do extra error checking (check that all posted accounts are declared)"
,flagNone ["ignore-assertions","I"] (setboolopt "ignore-assertions") "don't check balance assertions by default"
,flagNone ["strict","s"] (setboolopt "strict") "do extra error checks, incl. balance assertions"
]
-- | Common report-related flags: --period, --cost, etc.

View File

@ -6,7 +6,7 @@ _FLAGS
hledger provides a number of built-in correctness checks to help validate your data and prevent errors.
Some are run automatically, some when you enable `--strict` mode;
or you can run any of them on demand with this `check` command.
or you can run any of them on demand by providing them as arguments to the `check` command.
`check` produces no output and a zero exit code if all is well.
Eg:
@ -37,13 +37,14 @@ These important checks are performed by default, by almost all hledger commands:
- **assertions** - all [balance assertions] in the journal are passing.
Balance assertions are like canaries in your journal, they catch many problems.
This check sometimes gets in the way, eg when troubleshooting bookkeeping errors,
or parsing a journal fragment; you can disable it temporarily with `-I`/`--ignore-assertions`.
They can get in the way sometimes; you can disable them temporarily with `-I`/`--ignore-assertions`
(unless overridden with `-s`/`--strict` or `hledger check assertions`).
### Strict checks
These additional checks are performed by any command when the `-s`/`--strict` flag is used ([strict mode]).
They provide extra error-catching power when you are serious about keeping your data clean and free of typos:
Strict mode always enables the balance assertions check, also.
These provide extra error-catching power when you are serious about keeping your data clean and free of typos:
- **balanced** - like `autobalanced`, but in [conversion transactions](#recording-costs),
costs must be written explicitly. This ensures some redundancy in the entry, which helps prevent typos.

View File

@ -475,3 +475,21 @@ $ hledger -f- print -x date:2022-01-02
e
$ hledger -f - check
# ** 30. -s overrides -I
<
2024-01-01
(a) 1 = 2
$ hledger -f - check -I -s
>2 /Balance assertion failed/
>=1
# ** 31. hledger check assertions overrides -I
<
2024-01-01
(a) 1 = 2
$ hledger -f - check assertions -I
>2 /Balance assertion failed/
>=1