Skip to content

Commit

Permalink
fix:bal:budget: don't omit necessary parent accounts in tree mode (#2071
Browse files Browse the repository at this point in the history
)

Parent accounts with no actual or goal amounts would ideally be shown
elided on the same line, but the budget report in tree mode was
omitting them completely. Now --budget always shows them.
The effect is much like forcing --no-elide on, except it might not
show goal amounts that --no-elide does show.

It's not a wonderful fix, but the budget report code is twisty and I
can't afford to spend more time on this.
  • Loading branch information
simonmichael committed Feb 25, 2024
1 parent c701e3a commit a871f27
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 12 deletions.
39 changes: 27 additions & 12 deletions hledger-lib/Hledger/Reports/BudgetReport.hs
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ combineBudgetAndActual ropts j
actualsplusgoals = [
-- dbg0With (("actualsplusgoals: "<>)._brrShowDebug) $
PeriodicReportRow acct amtandgoals totamtandgoal avgamtandgoal
| PeriodicReportRow acct actualamts actualtot actualavg <- actualrows -- XXX #2071 can miss budgeted rows with elided parent no actual
| PeriodicReportRow acct actualamts actualtot actualavg <- actualrows

, let mbudgetgoals = HM.lookup (displayFull acct) budgetGoalsByAcct :: Maybe ([BudgetGoal], BudgetTotal, BudgetAverage)
, let budgetmamts = maybe (Nothing <$ periods) (map Just . first3) mbudgetgoals :: [Maybe BudgetGoal]
Expand Down Expand Up @@ -398,8 +398,10 @@ budgetReportAsTable ReportOpts{..} (PeriodicReport spans items totrow) =
shownitems :: [[(AccountName, WideBuilder, BudgetDisplayRow)]]
shownitems =
map (\i ->
let addacctcolumn = map (\(cs, cvals) -> (renderacct i, cs, cvals))
in addacctcolumn . showrow . rowToBudgetCells $ i)
let
addacctcolumn = map (\(cs, cvals) -> (renderacct i, cs, cvals))
isunbudgetedrow = displayFull (prrName i) == unbudgetedAccountName
in addacctcolumn $ showrow isunbudgetedrow $ rowToBudgetCells i)
items
where
-- FIXME. Have to check explicitly for which to render here, since
Expand All @@ -412,7 +414,7 @@ budgetReportAsTable ReportOpts{..} (PeriodicReport spans items totrow) =
(totrowcs, totrowtexts) = unzip $ concat showntotrow
where
showntotrow :: [[(WideBuilder, BudgetDisplayRow)]]
showntotrow = [showrow $ rowToBudgetCells totrow]
showntotrow = [showrow False $ rowToBudgetCells totrow]

-- | Get the data cells from a row or totals row, maybe adding
-- the row total and/or row average depending on options.
Expand All @@ -422,14 +424,27 @@ budgetReportAsTable ReportOpts{..} (PeriodicReport spans items totrow) =
++ [rowavg | average_ && not (null as)]

-- | Render a row's data cells as "BudgetDisplayCell"s, and a rendered list of commodity symbols.
showrow :: [BudgetCell] -> [(WideBuilder, BudgetDisplayRow)]
showrow row =
let cs = budgetCellsCommodities row
(showmixed, percbudget) = mkBudgetDisplayFns cs
in zip (map wbFromText cs)
. transpose
. map (showcell showmixed percbudget)
$ row
-- Also requires a flag indicating whether this is the special <unbudgeted> row.
-- (The types make that hard to check here.)
showrow :: Bool -> [BudgetCell] -> [(WideBuilder, BudgetDisplayRow)]
showrow isunbudgetedrow cells =
let
cs = budgetCellsCommodities cells
-- #2071 If there are no commodities - because there are no actual or goal amounts -
-- the zipped list would be empty, causing this row not to be shown.
-- But rows like this sometimes need to be shown to preserve the account tree structure.
-- So, ensure 0 will be shown as actual amount(s).
-- Unfortunately this disables boring parent eliding, as if --no-elide had been used.
-- (Just turning on --no-elide higher up doesn't work right.)
-- Note, no goal amount will be shown for these rows,
-- whereas --no-elide is likely to show a goal amount aggregated from children.
cs1 = if null cs && not isunbudgetedrow then [""] else cs
(showmixed, percbudget) = mkBudgetDisplayFns cs1
in
zip (map wbFromText cs1) $
transpose $
map (showcell showmixed percbudget)
cells

budgetCellsCommodities :: [BudgetCell] -> [CommoditySymbol]
budgetCellsCommodities = S.toList . foldl' S.union mempty . map budgetCellCommodities
Expand Down
36 changes: 36 additions & 0 deletions hledger/test/balance/budget.test
Original file line number Diff line number Diff line change
Expand Up @@ -728,3 +728,39 @@ Budget performance in 2020-01-01..2020-02-29:
--------------++--------------
|| A 100 A 200
|| 0 B 200

# ** 40. In tree-mode budget reports, parent accounts with no actual or goal amounts
# are still shown, to preserve the tree structure. The effect is similar to --no-elide. (#2071)
<
2023-07-01
expenses:rent $100
income:gifts:cash

~ monthly 2023-08
(income:employment) $-100
(income:gifts:cash) $-100

$ hledger -f- bal --budget -p 202308 --tree
Budget performance in 2023-08:

|| Aug
==============++=================
income || 0 [0% of $-200]
employment || 0 [0% of $-100]
gifts || 0
cash || 0 [0% of $-100]
--------------++-----------------
|| 0 [0% of $-200]

# ** 41. But, not exactly the same; notice --no-elide shows a goal amount for gifts. (#2071)
$ hledger -f- bal --budget -p 202308 --tree --no-elide
Budget performance in 2023-08:

|| Aug
==============++=================
income || 0 [0% of $-200]
employment || 0 [0% of $-100]
gifts || 0 [0% of $-100]
cash || 0 [0% of $-100]
--------------++-----------------
|| 0 [0% of $-200]

0 comments on commit a871f27

Please sign in to comment.