fix: check: recentassertions: drop the cleared requirement (#1899)
It was causing trouble and complicating things too much. I wanted it as another signal of being "caught up", but YAGNI.
This commit is contained in:
parent
fa31612b55
commit
910b37abf8
@ -7,6 +7,7 @@ Helpers for making error messages.
|
|||||||
module Hledger.Data.Errors (
|
module Hledger.Data.Errors (
|
||||||
makeTransactionErrorExcerpt,
|
makeTransactionErrorExcerpt,
|
||||||
makePostingErrorExcerpt,
|
makePostingErrorExcerpt,
|
||||||
|
makePostingAccountErrorExcerpt,
|
||||||
makeBalanceAssertionErrorExcerpt,
|
makeBalanceAssertionErrorExcerpt,
|
||||||
transactionFindPostingIndex,
|
transactionFindPostingIndex,
|
||||||
)
|
)
|
||||||
@ -22,6 +23,7 @@ import Hledger.Data.Types
|
|||||||
import Hledger.Utils
|
import Hledger.Utils
|
||||||
import Data.Maybe
|
import Data.Maybe
|
||||||
import Safe (headMay)
|
import Safe (headMay)
|
||||||
|
import Hledger.Data.Posting (isVirtual)
|
||||||
|
|
||||||
-- | Given a problem transaction and a function calculating the best
|
-- | Given a problem transaction and a function calculating the best
|
||||||
-- column(s) for marking the error region:
|
-- column(s) for marking the error region:
|
||||||
@ -103,6 +105,17 @@ transactionFindPostingIndex :: (Posting -> Bool) -> Transaction -> Maybe Int
|
|||||||
transactionFindPostingIndex ppredicate =
|
transactionFindPostingIndex ppredicate =
|
||||||
fmap fst . find (ppredicate.snd) . zip [1..] . tpostings
|
fmap fst . find (ppredicate.snd) . zip [1..] . tpostings
|
||||||
|
|
||||||
|
-- | From the given posting, make an error excerpt showing the transaction with
|
||||||
|
-- this posting's account part highlighted.
|
||||||
|
makePostingAccountErrorExcerpt :: Posting -> (FilePath, Int, Maybe (Int, Maybe Int), Text)
|
||||||
|
makePostingAccountErrorExcerpt p = makePostingErrorExcerpt p finderrcols
|
||||||
|
where
|
||||||
|
-- Calculate columns suitable for highlighting the synthetic excerpt.
|
||||||
|
finderrcols p _ _ = Just (col, Just col2)
|
||||||
|
where
|
||||||
|
col = 5 + if isVirtual p then 1 else 0
|
||||||
|
col2 = col + T.length (paccount p) - 1
|
||||||
|
|
||||||
-- | From the given posting, make an error excerpt showing the transaction with
|
-- | From the given posting, make an error excerpt showing the transaction with
|
||||||
-- the balance assertion highlighted.
|
-- the balance assertion highlighted.
|
||||||
makeBalanceAssertionErrorExcerpt :: Posting -> (FilePath, Int, Maybe (Int, Maybe Int), Text)
|
makeBalanceAssertionErrorExcerpt :: Posting -> (FilePath, Int, Maybe (Int, Maybe Int), Text)
|
||||||
|
|||||||
@ -32,7 +32,7 @@ import Hledger.Data.JournalChecks.Uniqueleafnames
|
|||||||
import Hledger.Data.Posting (isVirtual, postingDate, postingStatus)
|
import Hledger.Data.Posting (isVirtual, postingDate, postingStatus)
|
||||||
import Hledger.Data.Types
|
import Hledger.Data.Types
|
||||||
import Hledger.Data.Amount (amountIsZero, amountsRaw, missingamt)
|
import Hledger.Data.Amount (amountIsZero, amountsRaw, missingamt)
|
||||||
import Hledger.Data.Transaction (transactionPayee, showTransactionLineFirstPart, showTransaction)
|
import Hledger.Data.Transaction (transactionPayee, showTransactionLineFirstPart)
|
||||||
import Data.Time (Day, diffDays)
|
import Data.Time (Day, diffDays)
|
||||||
import Data.List.Extra
|
import Data.List.Extra
|
||||||
import Hledger.Utils (chomp, textChomp, sourcePosPretty)
|
import Hledger.Utils (chomp, textChomp, sourcePosPretty)
|
||||||
@ -55,14 +55,7 @@ journalCheckAccounts j = mapM_ checkacct (journalPostings j)
|
|||||||
,"account %s ; type:A ; (L,E,R,X,C,V)"
|
,"account %s ; type:A ; (L,E,R,X,C,V)"
|
||||||
]) f l ex (show a) a a
|
]) f l ex (show a) a a
|
||||||
where
|
where
|
||||||
(f,l,_mcols,ex) = makePostingErrorExcerpt p finderrcols
|
(f,l,_mcols,ex) = makePostingAccountErrorExcerpt p
|
||||||
-- Calculate columns suitable for highlighting the excerpt.
|
|
||||||
-- We won't show these in the main error line as they aren't
|
|
||||||
-- accurate for the actual data.
|
|
||||||
finderrcols p _ _ = Just (col, Just col2)
|
|
||||||
where
|
|
||||||
col = 5 + if isVirtual p then 1 else 0
|
|
||||||
col2 = col + T.length a - 1
|
|
||||||
|
|
||||||
-- | Check that all the commodities used in this journal's postings have been declared
|
-- | Check that all the commodities used in this journal's postings have been declared
|
||||||
-- by commodity directives, returning an error message otherwise.
|
-- by commodity directives, returning an error message otherwise.
|
||||||
@ -191,8 +184,10 @@ balanceAssertionInfo ps =
|
|||||||
where
|
where
|
||||||
ps' = sortOn postingDate ps
|
ps' = sortOn postingDate ps
|
||||||
mlatestp = lastMay ps'
|
mlatestp = lastMay ps'
|
||||||
mlatestassertp = lastMay $ filter (isJust.pbalanceassertion) ps
|
mlatestassertp = lastMay [p | p@Posting{pbalanceassertion=Just _} <- ps']
|
||||||
|
|
||||||
|
-- | The number of days allowed between an account's latest balance assertion
|
||||||
|
-- and latest posting.
|
||||||
maxlag = 7
|
maxlag = 7
|
||||||
|
|
||||||
-- | The number of days between this balance assertion and the latest posting in its account.
|
-- | The number of days between this balance assertion and the latest posting in its account.
|
||||||
@ -202,6 +197,20 @@ baiLag BAI{..} = diffDays baiLatestPostingDate baiLatestAssertionDate
|
|||||||
-- baiLagOkDate :: BalanceAssertionInfo -> Day
|
-- baiLagOkDate :: BalanceAssertionInfo -> Day
|
||||||
-- baiLagOkDate BAI{..} = addDays (-7) baiLatestPostingDate
|
-- baiLagOkDate BAI{..} = addDays (-7) baiLatestPostingDate
|
||||||
|
|
||||||
|
-- | Check that this latest assertion is close enough to the account's latest posting.
|
||||||
|
checkRecentAssertion :: BalanceAssertionInfo -> Either (BalanceAssertionInfo, String) ()
|
||||||
|
checkRecentAssertion bai@BAI{..}
|
||||||
|
| lag > maxlag =
|
||||||
|
Left (bai, printf (chomp $ unlines [
|
||||||
|
"the last balance assertion (%s) was %d days before"
|
||||||
|
,"the latest posting (%s)."
|
||||||
|
])
|
||||||
|
(show baiLatestAssertionDate) lag (show baiLatestPostingDate)
|
||||||
|
)
|
||||||
|
| otherwise = Right ()
|
||||||
|
where
|
||||||
|
lag = baiLag bai
|
||||||
|
|
||||||
-- | Check that all the journal's accounts with balance assertions have
|
-- | Check that all the journal's accounts with balance assertions have
|
||||||
-- an assertion no more than 7 days before their latest posting.
|
-- an assertion no more than 7 days before their latest posting.
|
||||||
-- Today's date is provided for error messages.
|
-- Today's date is provided for error messages.
|
||||||
@ -213,15 +222,14 @@ journalCheckRecentAssertions today j =
|
|||||||
in
|
in
|
||||||
case mapM_ checkRecentAssertion acctassertioninfos of
|
case mapM_ checkRecentAssertion acctassertioninfos of
|
||||||
Right () -> Right ()
|
Right () -> Right ()
|
||||||
Left (bai@BAI{..}, msg) -> Left errmsg
|
Left (BAI{..}, msg) -> Left errmsg
|
||||||
where
|
where
|
||||||
errmsg = chomp $ printf
|
errmsg = chomp $ printf
|
||||||
(unlines [
|
(unlines [
|
||||||
"%s:",
|
"%s:",
|
||||||
"%s\n",
|
"%s\n",
|
||||||
-- "In balance-asserted account %s,",
|
"The recentassertions check is enabled, so accounts with balance assertions must",
|
||||||
"The recentassertions check is enabled, so accounts with balance assertions",
|
"have a balance assertion no more than %d days before their latest posting date.",
|
||||||
"must have an assertion no more than %d days before their latest posting date.",
|
|
||||||
"In account %s,",
|
"In account %s,",
|
||||||
"%s",
|
"%s",
|
||||||
"",
|
"",
|
||||||
@ -236,50 +244,11 @@ journalCheckRecentAssertions today j =
|
|||||||
recommendation
|
recommendation
|
||||||
where
|
where
|
||||||
(_,_,_,excerpt) = makeBalanceAssertionErrorExcerpt baiLatestAssertionPosting
|
(_,_,_,excerpt) = makeBalanceAssertionErrorExcerpt baiLatestAssertionPosting
|
||||||
recommendation
|
recommendation = unlines [
|
||||||
| baiLag bai > maxlag = unlines [
|
"Consider adding a more recent balance assertion for this account. Eg:",
|
||||||
"Consider adding a more recent balance assertion for this account. Eg:",
|
"",
|
||||||
"",
|
printf "%s *\n %s $0 = $0 ; <- adjust" (show today) baiAccount
|
||||||
printf "%s *\n %s $0 = $0 ; <- adjust" (show today) baiAccount
|
]
|
||||||
]
|
|
||||||
| otherwise = unlines [
|
|
||||||
"Consider marking this posting or transaction cleared. Eg:",
|
|
||||||
"",
|
|
||||||
case ptransaction baiLatestAssertionPosting of
|
|
||||||
Nothing -> "(no transaction)" -- shouldn't happen
|
|
||||||
Just t -> T.unpack $ showTransaction t'
|
|
||||||
where
|
|
||||||
t' = t{tstatus=tstatus', tpostings=ps'}
|
|
||||||
where
|
|
||||||
-- clear just the posting if it was marked pending, otherwise clear the whole transaction
|
|
||||||
ispunmarked = pstatus baiLatestAssertionPosting == Unmarked
|
|
||||||
tstatus' = if ispunmarked then Cleared else tstatus t
|
|
||||||
pstatus' = if ispunmarked then Unmarked else Cleared
|
|
||||||
ps' = beforeps ++ [baiLatestAssertionPosting{pstatus=pstatus'}] ++ afterps
|
|
||||||
where
|
|
||||||
beforeps = takeWhile (/= baiLatestAssertionPosting) $ tpostings t
|
|
||||||
afterps = drop (length beforeps + 1) $ tpostings t
|
|
||||||
]
|
|
||||||
|
|
||||||
-- | Check that this latest assertion is close enough to the account's latest posting.
|
|
||||||
checkRecentAssertion :: BalanceAssertionInfo -> Either (BalanceAssertionInfo, String) ()
|
|
||||||
checkRecentAssertion bai@BAI{..}
|
|
||||||
| lag > maxlag =
|
|
||||||
Left (bai, printf (chomp $ unlines [
|
|
||||||
"the last balance assertion (%s) was %d days before"
|
|
||||||
,"the latest posting (%s)."
|
|
||||||
])
|
|
||||||
(show baiLatestAssertionDate) lag (show baiLatestPostingDate)
|
|
||||||
)
|
|
||||||
| baiLatestAssertionStatus /= Cleared =
|
|
||||||
Left (bai, printf "the last balance assertion's status is %s, should be * (cleared)"
|
|
||||||
(case baiLatestAssertionStatus of
|
|
||||||
Unmarked -> "unmarked" :: String
|
|
||||||
Pending -> "! (pending)"
|
|
||||||
Cleared -> "* (cleared)"))
|
|
||||||
| otherwise = Right ()
|
|
||||||
where
|
|
||||||
lag = baiLag bai
|
|
||||||
|
|
||||||
-- -- | Print the last balance assertion date & status of all accounts with balance assertions.
|
-- -- | Print the last balance assertion date & status of all accounts with balance assertions.
|
||||||
-- printAccountLastAssertions :: Day -> [BalanceAssertionInfo] -> IO ()
|
-- printAccountLastAssertions :: Day -> [BalanceAssertionInfo] -> IO ()
|
||||||
@ -287,6 +256,6 @@ checkRecentAssertion bai@BAI{..}
|
|||||||
-- forM_ acctassertioninfos $ \BAI{..} -> do
|
-- forM_ acctassertioninfos $ \BAI{..} -> do
|
||||||
-- putStr $ printf "%-30s %s %s, %d days ago\n"
|
-- putStr $ printf "%-30s %s %s, %d days ago\n"
|
||||||
-- baiAccount
|
-- baiAccount
|
||||||
-- (if baiLatestAssertionStatus==Unmarked then " " else show baiLatestAssertionStatus)
|
-- (if baiLatestClearedAssertionStatus==Unmarked then " " else show baiLatestClearedAssertionStatus)
|
||||||
-- (show baiLatestAssertionDate)
|
-- (show baiLatestClearedAssertionDate)
|
||||||
-- (diffDays today baiLatestAssertionDate)
|
-- (diffDays today baiLatestClearedAssertionDate)
|
||||||
|
|||||||
@ -62,7 +62,7 @@ They are more specialised and not desirable for everyone, therefore optional:
|
|||||||
- **payees** - all payees used by transactions [have been declared](#declaring-payees)
|
- **payees** - all payees used by transactions [have been declared](#declaring-payees)
|
||||||
|
|
||||||
- **recentassertions** - all accounts with balance assertions have a
|
- **recentassertions** - all accounts with balance assertions have a
|
||||||
(cleared) assertion no more than 7 days before their latest posting
|
balance assertion no more than 7 days before their latest posting
|
||||||
|
|
||||||
- **uniqueleafnames** - all account leaf names are unique
|
- **uniqueleafnames** - all account leaf names are unique
|
||||||
|
|
||||||
@ -80,15 +80,16 @@ See: Cookbook -> [Scripting](scripting.html).
|
|||||||
|
|
||||||
### More about specific checks
|
### More about specific checks
|
||||||
|
|
||||||
`hledger check recentassertions` will complain if any balance-asserted account does not have
|
`hledger check recentassertions` will complain if any balance-asserted account
|
||||||
a (cleared) balance assertion within 7 days before its latest posting.
|
does not have a balance assertion within 7 days before its latest posting.
|
||||||
This aims to prevent the situation where you are regularly updating your journal,
|
This aims to prevent the situation where you are regularly updating your journal,
|
||||||
but forgetting to check your balances against the real world,
|
but forgetting to check your balances against the real world,
|
||||||
then one day must dig back through months of data to find an error.
|
then one day must dig back through months of data to find an error.
|
||||||
It assumes that adding a balance assertion requires/reminds you to check the real-world balance.
|
It assumes that adding a balance assertion requires/reminds you to check the real-world balance.
|
||||||
This won't be true if you auto-generate balance assertions when importing bank data,
|
That may not be true if you auto-generate balance assertions from bank data;
|
||||||
but hopefully your auto-generated transactions are uncleared, and before manually marking them
|
in that case, I recommend to import transactions uncleared,
|
||||||
cleared you will remember to check the latest assertions against the real-world balances.
|
then use the manual-review-and-mark-cleared phase as a reminder
|
||||||
|
to check the latest assertions against real-world balances.
|
||||||
|
|
||||||
[add-on commands]: #add-on-commands
|
[add-on commands]: #add-on-commands
|
||||||
[balance assertions]: #balance-assertions
|
[balance assertions]: #balance-assertions
|
||||||
|
|||||||
@ -156,7 +156,7 @@ Click error names to see an example. The table headings mean:
|
|||||||
|
|
||||||
|
|
||||||
<!-- GENERATED: -->
|
<!-- GENERATED: -->
|
||||||
hledger 1.26.99-g99825d37f-20220731 error messages:
|
hledger 1.26.99-ge777ae46f-20220803 error messages:
|
||||||
|
|
||||||
### accounts
|
### accounts
|
||||||
```
|
```
|
||||||
@ -188,9 +188,9 @@ this balance was asserted: 1
|
|||||||
but the calculated balance is: 0
|
but the calculated balance is: 0
|
||||||
a difference of: 1
|
a difference of: 1
|
||||||
|
|
||||||
Consider viewing this account's register to troubleshoot. Eg:
|
Consider viewing this account's calculated balances to troubleshoot. Eg:
|
||||||
|
|
||||||
hledger reg -I 'a$' cur:''
|
hledger reg 'a$' cur: -I # -f FILE
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@ -304,20 +304,20 @@ payee p
|
|||||||
|
|
||||||
### recentassertions
|
### recentassertions
|
||||||
```
|
```
|
||||||
hledger: Error: /Users/simon/src/hledger/hledger/test/errors/./recentassertions.j:4:8:
|
hledger: Error: /Users/simon/src/hledger/hledger/test/errors/./recentassertions.j:5:8:
|
||||||
| 2022-01-01 *
|
| 2022-01-01 *
|
||||||
4 | a 0 = 0
|
5 | a 0 = 0
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
||||||
The recentassertions check is enabled, so accounts with balance assertions
|
The recentassertions check is enabled, so accounts with balance assertions must
|
||||||
must have an assertion no more than 7 days before their latest posting date.
|
have a balance assertion no more than 7 days before their latest posting date.
|
||||||
In account a,
|
In account a,
|
||||||
the last balance assertion (2022-01-01) was 8 days before
|
the last balance assertion (2022-01-01) was 8 days before
|
||||||
the latest posting (2022-01-09).
|
the latest posting (2022-01-09).
|
||||||
|
|
||||||
Consider adding a more recent balance assertion for this account. Eg:
|
Consider adding a more recent balance assertion for this account. Eg:
|
||||||
|
|
||||||
2022-07-31 *
|
2022-08-03 *
|
||||||
a $0 = $0 ; <- adjust
|
a $0 = $0 ; <- adjust
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
#!/usr/bin/env -S hledger check recentassertions -f
|
#!/usr/bin/env -S hledger check recentassertions -f
|
||||||
|
# Latest balance assertion more than 7 days behind latest posting.
|
||||||
|
|
||||||
2022-01-01 *
|
2022-01-01 *
|
||||||
a 0 = 0
|
a 0 = 0
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
$$$ hledger check recentassertions -f recentassertions.j
|
$$$ hledger check recentassertions -f recentassertions.j
|
||||||
>>>2 /hledger: Error: .*recentassertions.j:4:8:
|
>>>2 /hledger: Error: .*recentassertions.j:5:8:
|
||||||
\| 2022-01-01 \*
|
\| 2022-01-01 \*
|
||||||
4 \| a 0 = 0
|
5 \| a 0 = 0
|
||||||
\| \^\^\^
|
\| \^\^\^
|
||||||
|
|
||||||
The recentassertions check is enabled, so accounts with balance assertions
|
The recentassertions check is enabled, so accounts with balance assertions must
|
||||||
must have an assertion no more than 7 days before their latest posting date.
|
have a balance assertion no more than 7 days before their latest posting date.
|
||||||
In account a,
|
In account a,
|
||||||
the las/
|
/
|
||||||
>>>= 1
|
>>>= 1
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user