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 ( | ||||
|   makeTransactionErrorExcerpt, | ||||
|   makePostingErrorExcerpt, | ||||
|   makePostingAccountErrorExcerpt, | ||||
|   makeBalanceAssertionErrorExcerpt, | ||||
|   transactionFindPostingIndex, | ||||
| ) | ||||
| @ -22,6 +23,7 @@ import Hledger.Data.Types | ||||
| import Hledger.Utils | ||||
| import Data.Maybe | ||||
| import Safe (headMay) | ||||
| import Hledger.Data.Posting (isVirtual) | ||||
| 
 | ||||
| -- | Given a problem transaction and a function calculating the best | ||||
| -- column(s) for marking the error region: | ||||
| @ -103,6 +105,17 @@ transactionFindPostingIndex :: (Posting -> Bool) -> Transaction -> Maybe Int | ||||
| transactionFindPostingIndex ppredicate =  | ||||
|   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 | ||||
| -- the balance assertion highlighted. | ||||
| 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.Types | ||||
| 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.List.Extra | ||||
| 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)" | ||||
|           ]) f l ex (show a) a a | ||||
|         where | ||||
|           (f,l,_mcols,ex) = makePostingErrorExcerpt p finderrcols | ||||
|           -- 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 | ||||
|           (f,l,_mcols,ex) = makePostingAccountErrorExcerpt p | ||||
| 
 | ||||
| -- | Check that all the commodities used in this journal's postings have been declared | ||||
| -- by commodity directives, returning an error message otherwise. | ||||
| @ -191,8 +184,10 @@ balanceAssertionInfo ps = | ||||
|   where | ||||
|     ps' = sortOn postingDate 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 | ||||
| 
 | ||||
| -- | 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 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 | ||||
| -- an assertion no more than 7 days before their latest posting. | ||||
| -- Today's date is provided for error messages. | ||||
| @ -213,15 +222,14 @@ journalCheckRecentAssertions today j = | ||||
|   in | ||||
|     case mapM_ checkRecentAssertion acctassertioninfos of | ||||
|       Right () -> Right () | ||||
|       Left (bai@BAI{..}, msg) -> Left errmsg | ||||
|       Left (BAI{..}, msg) -> Left errmsg | ||||
|         where | ||||
|           errmsg = chomp $ printf  | ||||
|             (unlines [ | ||||
|               "%s:", | ||||
|               "%s\n", | ||||
|               -- "In balance-asserted account %s,", | ||||
|               "The recentassertions check is enabled, so accounts with balance assertions", | ||||
|               "must have an assertion no more than %d days before their latest posting date.", | ||||
|               "The recentassertions check is enabled, so accounts with balance assertions must", | ||||
|               "have a balance assertion no more than %d days before their latest posting date.", | ||||
|               "In account %s,", | ||||
|               "%s", | ||||
|               "", | ||||
| @ -236,50 +244,11 @@ journalCheckRecentAssertions today j = | ||||
|             recommendation | ||||
|             where | ||||
|               (_,_,_,excerpt) = makeBalanceAssertionErrorExcerpt baiLatestAssertionPosting | ||||
|               recommendation | ||||
|                 | baiLag bai > maxlag = unlines [ | ||||
|                     "Consider adding a more recent balance assertion for this account. Eg:", | ||||
|                     "", | ||||
|                     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 | ||||
|               recommendation = unlines [ | ||||
|                 "Consider adding a more recent balance assertion for this account. Eg:", | ||||
|                 "", | ||||
|                 printf "%s *\n    %s    $0 = $0  ; <- adjust" (show today) baiAccount | ||||
|                 ] | ||||
| 
 | ||||
| -- -- | Print the last balance assertion date & status of all accounts with balance assertions. | ||||
| -- printAccountLastAssertions :: Day -> [BalanceAssertionInfo] -> IO () | ||||
| @ -287,6 +256,6 @@ checkRecentAssertion bai@BAI{..} | ||||
| --   forM_ acctassertioninfos $ \BAI{..} -> do | ||||
| --     putStr $ printf "%-30s  %s %s, %d days ago\n" | ||||
| --       baiAccount | ||||
| --       (if baiLatestAssertionStatus==Unmarked then " " else show baiLatestAssertionStatus) | ||||
| --       (show baiLatestAssertionDate) | ||||
| --       (diffDays today baiLatestAssertionDate) | ||||
| --       (if baiLatestClearedAssertionStatus==Unmarked then " " else show baiLatestClearedAssertionStatus) | ||||
| --       (show baiLatestClearedAssertionDate) | ||||
| --       (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) | ||||
| 
 | ||||
| - **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 | ||||
| 
 | ||||
| @ -80,15 +80,16 @@ See: Cookbook -> [Scripting](scripting.html). | ||||
| 
 | ||||
| ### More about specific checks | ||||
| 
 | ||||
| `hledger check recentassertions` will complain if any balance-asserted account does not have | ||||
| a (cleared) balance assertion within 7 days before its latest posting. | ||||
| `hledger check recentassertions` will complain if any balance-asserted account | ||||
| 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, | ||||
| but forgetting to check your balances against the real world, | ||||
| 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. | ||||
| This won't be true if you auto-generate balance assertions when importing bank data, | ||||
| but hopefully your auto-generated transactions are uncleared, and before manually marking them  | ||||
| cleared you will remember to check the latest assertions against the real-world balances. | ||||
| That may not be true if you auto-generate balance assertions from bank data; | ||||
| in that case, I recommend to import transactions uncleared,  | ||||
| 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 | ||||
| [balance assertions]: #balance-assertions | ||||
|  | ||||
| @ -156,7 +156,7 @@ Click error names to see an example. The table headings mean: | ||||
| 
 | ||||
| 
 | ||||
| <!-- GENERATED: --> | ||||
| hledger 1.26.99-g99825d37f-20220731 error messages: | ||||
| hledger 1.26.99-ge777ae46f-20220803 error messages: | ||||
| 
 | ||||
| ### accounts | ||||
| ``` | ||||
| @ -188,9 +188,9 @@ this balance was asserted:     1 | ||||
| but the calculated balance is: 0 | ||||
| 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 | ||||
| ``` | ||||
| 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 * | ||||
| 4 |     a               0 = 0 | ||||
| 5 |     a               0 = 0 | ||||
|   |                       ^^^ | ||||
| 
 | ||||
| The recentassertions check is enabled, so accounts with balance assertions | ||||
| must have an assertion no more than 7 days before their latest posting date. | ||||
| The recentassertions check is enabled, so accounts with balance assertions must | ||||
| have a balance assertion no more than 7 days before their latest posting date. | ||||
| In account a, | ||||
| the last balance assertion (2022-01-01) was 8 days before | ||||
| the latest posting (2022-01-09). | ||||
| 
 | ||||
| Consider adding a more recent balance assertion for this account. Eg: | ||||
| 
 | ||||
| 2022-07-31 * | ||||
| 2022-08-03 * | ||||
|     a    $0 = $0  ; <- adjust | ||||
| ``` | ||||
| 
 | ||||
|  | ||||
| @ -1,4 +1,5 @@ | ||||
| #!/usr/bin/env -S hledger check recentassertions -f | ||||
| # Latest balance assertion more than 7 days behind latest posting. | ||||
| 
 | ||||
| 2022-01-01 * | ||||
|   a  0 = 0 | ||||
|  | ||||
| @ -1,11 +1,11 @@ | ||||
| $$$ hledger check recentassertions -f recentassertions.j | ||||
| >>>2 /hledger: Error: .*recentassertions.j:4:8: | ||||
| >>>2 /hledger: Error: .*recentassertions.j:5:8: | ||||
|   \| 2022-01-01 \* | ||||
| 4 \|     a               0 = 0 | ||||
| 5 \|     a               0 = 0 | ||||
|   \|                       \^\^\^ | ||||
| 
 | ||||
| The recentassertions check is enabled, so accounts with balance assertions | ||||
| must have an assertion no more than 7 days before their latest posting date. | ||||
| The recentassertions check is enabled, so accounts with balance assertions must | ||||
| have a balance assertion no more than 7 days before their latest posting date. | ||||
| In account a, | ||||
| the las/ | ||||
| / | ||||
| >>>= 1 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user