From ef5c220690ae27243ed4d8da60fdd1e88ca2f2b8 Mon Sep 17 00:00:00 2001 From: Stephen Morgan Date: Wed, 27 Aug 2025 17:13:01 +0200 Subject: [PATCH] fix: balance: Clip account names in generateMultiBalanceAccount, not before (#2434) Previously accounts were clipped in getPostings, however compound balance reports re-use the output of getPostings for the different subreports. This caused a problem when clipping erased the information needed to determine the account type, as would be used by e.g. incomestatement. Add some extra tests for --count. --- .../Hledger/Reports/MultiBalanceReport.hs | 20 +++++++------- hledger/test/balance/balance.test | 18 ++++++++++++- hledger/test/incomestatement.test | 26 +++++++++++++++++++ 3 files changed, 54 insertions(+), 10 deletions(-) diff --git a/hledger-lib/Hledger/Reports/MultiBalanceReport.hs b/hledger-lib/Hledger/Reports/MultiBalanceReport.hs index 9573abcbf..1e95b83aa 100644 --- a/hledger-lib/Hledger/Reports/MultiBalanceReport.hs +++ b/hledger-lib/Hledger/Reports/MultiBalanceReport.hs @@ -143,9 +143,10 @@ compoundBalanceReportWith rspec' j priceoracle subreportspecs = cbr -- Add a restriction to this subreport to the report query. -- XXX in non-thorough way, consider updateReportSpec ? rspecsub = rspec{_rsReportOpts=ropts, _rsQuery=And [cbcsubreportquery, _rsQuery rspec]} + -- Match and postings for the subreport + subreportps = filter (matchesPostingExtra (journalAccountType j) cbcsubreportquery) ps -- Account representing this subreport - acct = generateMultiBalanceAccount rspecsub j priceoracle colspans $ - filter (matchesPostingExtra (journalAccountType j) cbcsubreportquery) ps + acct = generateMultiBalanceAccount rspecsub j priceoracle colspans subreportps -- Sum the subreport totals by column. Handle these cases: -- - no subreports @@ -178,14 +179,10 @@ makeReportQuery rspec reportspan -- | Gather postings matching the query within the report period. getPostings :: ReportSpec -> Journal -> PriceOracle -> DateSpan -> [Posting] getPostings rspec@ReportSpec{_rsQuery=query, _rsReportOpts=ropts} j priceoracle reportspan = - map clipPosting - . setPostingsCount + setPostingsCount . journalPostings $ journalValueAndFilterPostingsWith rspec' j priceoracle where - -- Clip posting names to the requested depth - clipPosting p = p{paccount = clipOrEllipsifyAccountName depthSpec $ paccount p} - -- If doing --count, set all posting amounts to "1". setPostingsCount = case balancecalc_ ropts of CalcPostingsCount -> map (postingTransformAmount (const $ mixed [num 1])) @@ -209,8 +206,6 @@ getPostings rspec@ReportSpec{_rsQuery=query, _rsReportOpts=ropts} j priceoracle -- handles the hledger-ui+future txns case above). depthlessq = dbg3 "getPostings depthlessq" $ filterQuery (not . queryIsDepth) query - depthSpec = dbg3 "getPostings depthSpec" . queryDepth $ filterQuery queryIsDepth query - fullreportspan = if requiresHistorical ropts then DateSpan Nothing (Exact <$> spanEnd reportspan) else reportspan fullreportspanq = (if date2_ ropts then Date2 else Date) $ case fullreportspan of DateSpan Nothing Nothing -> emptydatespan @@ -230,6 +225,13 @@ generateMultiBalanceAccount rspec@ReportSpec{_rsReportOpts=ropts} j priceoracle . mapAccounts (accountSetDeclarationInfo j) -- Process changes into normal, cumulative, or historical amounts, plus value them . calculateReportAccount rspec j priceoracle colspans + -- Clip account names + . map clipPosting + where + -- Clip postings to the requested depth according to the query + clipPosting p = p{paccount = clipOrEllipsifyAccountName depthSpec $ paccount p} + depthSpec = dbg3 "generateMultiBalanceAccount depthSpec" + . queryDepth . filterQuery queryIsDepth $ _rsQuery rspec -- | Add declared accounts to the account tree. addDeclaredAccounts :: Monoid a => ReportSpec -> Journal -> Account a -> Account a diff --git a/hledger/test/balance/balance.test b/hledger/test/balance/balance.test index aa0356dbc..1e997cbe9 100644 --- a/hledger/test/balance/balance.test +++ b/hledger/test/balance/balance.test @@ -201,13 +201,29 @@ $ hledger -f- bal -MT -O html a 10 a:aa 20 b +$ hledger -f- bal --count + 1 a + 1 a:aa + 1 b +-------------------- + 3 + +# ** 16. --count counts clipped postings. $ hledger -f- bal --count -1 2 a 1 b -------------------- 3 -# ** 16. Make sure that balance --flat --empty does not display implied +# ** 17. --count counts inclusive postings with --tree. +$ hledger -f- bal --count --tree + 2 a + 1 aa + 1 b +-------------------- + 3 + +# ** 18. Make sure that balance --flat --empty does not display implied # accounts (i.e. those with no postings, like "assets", here), but does show # accounts that have postings with zero balance (like "assets:bank:checking" # here). diff --git a/hledger/test/incomestatement.test b/hledger/test/incomestatement.test index 63a02fc57..e5d6c2871 100644 --- a/hledger/test/incomestatement.test +++ b/hledger/test/incomestatement.test @@ -304,3 +304,29 @@ Income Statement .. Expenses || -----------------++---- expenses || 0 + +# ** 10. Clipping too far doesn't erase account types (#2434) +< +account sm:assets ; type:A +account sm:revenues ; type:R + +2025-01-01 + sm:revenues -$1 + sm:assets $1 + +2025-01-02 + sm:revenues A -2 + sm:assets A 2 + +$ hledger -f - incomestatement -1 -N +Income Statement 2025-01-01..2025-01-02 + + || 2025-01-01..2025-01-02 +==========++======================== + Revenues || +----------++------------------------ + sm || $1, A 2 +==========++======================== + Expenses || +----------++------------------------ +