mirror of
https://github.com/simonmichael/hledger.git
synced 2024-09-19 10:17:35 +03:00
fix: budget: Make sure boring parents of unbudgeted accounts are not
elided if they have a budget. (#1800) This only affects calls with --budget and -E, but not with --no-elide.
This commit is contained in:
parent
d9b0184720
commit
8cd9e81c34
@ -82,10 +82,12 @@ budgetReport rspec bopts reportspan j = dbg4 "sortedbudgetreport" budgetreport
|
||||
jperiodictxns j
|
||||
actualj = journalWithBudgetAccountNames budgetedaccts showunbudgeted j
|
||||
budgetj = journalAddBudgetGoalTransactions bopts ropts reportspan j
|
||||
actualreport@(PeriodicReport actualspans _ _) =
|
||||
dbg5 "actualreport" $ multiBalanceReport rspec{_rsReportOpts=ropts{empty_=True}} actualj
|
||||
priceoracle = journalPriceOracle (infer_prices_ ropts) j
|
||||
budgetgoalreport@(PeriodicReport _ budgetgoalitems budgetgoaltotals) =
|
||||
dbg5 "budgetgoalreport" $ multiBalanceReport rspec{_rsReportOpts=ropts{empty_=True}} budgetj
|
||||
dbg5 "budgetgoalreport" $ multiBalanceReportWith rspec{_rsReportOpts=ropts{empty_=True}} budgetj priceoracle mempty
|
||||
budgetedacctsseen = S.fromList $ map prrFullName budgetgoalitems
|
||||
actualreport@(PeriodicReport actualspans _ _) =
|
||||
dbg5 "actualreport" $ multiBalanceReportWith rspec{_rsReportOpts=ropts{empty_=True}} actualj priceoracle budgetedacctsseen
|
||||
budgetgoalreport'
|
||||
-- If no interval is specified:
|
||||
-- budgetgoalreport's span might be shorter actualreport's due to periodic txns;
|
||||
|
@ -47,6 +47,8 @@ import qualified Data.Map as M
|
||||
import Data.Maybe (fromMaybe, isJust, mapMaybe)
|
||||
import Data.Ord (Down(..))
|
||||
import Data.Semigroup (sconcat)
|
||||
import Data.Set (Set)
|
||||
import qualified Data.Set as Set
|
||||
import Data.Time.Calendar (fromGregorian)
|
||||
import Safe (lastDef, minimumMay)
|
||||
|
||||
@ -102,16 +104,16 @@ type ClippedAccountName = AccountName
|
||||
-- by the balance command (in multiperiod mode) and (via compoundBalanceReport)
|
||||
-- by the bs/cf/is commands.
|
||||
multiBalanceReport :: ReportSpec -> Journal -> MultiBalanceReport
|
||||
multiBalanceReport rspec j = multiBalanceReportWith rspec j (journalPriceOracle infer j)
|
||||
multiBalanceReport rspec j = multiBalanceReportWith rspec j (journalPriceOracle infer j) mempty
|
||||
where infer = infer_prices_ $ _rsReportOpts rspec
|
||||
|
||||
-- | A helper for multiBalanceReport. This one takes an extra argument,
|
||||
-- a PriceOracle to be used for looking up market prices. Commands which
|
||||
-- run multiple reports (bs etc.) can generate the price oracle just
|
||||
-- once for efficiency, passing it to each report by calling this
|
||||
-- function directly.
|
||||
multiBalanceReportWith :: ReportSpec -> Journal -> PriceOracle -> MultiBalanceReport
|
||||
multiBalanceReportWith rspec' j priceoracle = report
|
||||
-- | A helper for multiBalanceReport. This one takes some extra arguments,
|
||||
-- a 'PriceOracle' to be used for looking up market prices, and a set of
|
||||
-- 'AccountName's which should not be elided. Commands which run multiple
|
||||
-- reports (bs etc.) can generate the price oracle just once for efficiency,
|
||||
-- passing it to each report by calling this function directly.
|
||||
multiBalanceReportWith :: ReportSpec -> Journal -> PriceOracle -> Set AccountName -> MultiBalanceReport
|
||||
multiBalanceReportWith rspec' j priceoracle unelidableaccts = report
|
||||
where
|
||||
-- Queries, report/column dates.
|
||||
reportspan = dbg3 "reportspan" $ reportSpan j rspec'
|
||||
@ -127,7 +129,7 @@ multiBalanceReportWith rspec' j priceoracle = report
|
||||
|
||||
-- Generate and postprocess the report, negating balances and taking percentages if needed
|
||||
report = dbg4 "multiBalanceReportWith" $
|
||||
generateMultiBalanceReport rspec j priceoracle colps startbals
|
||||
generateMultiBalanceReport rspec j priceoracle unelidableaccts colps startbals
|
||||
|
||||
-- | Generate a compound balance report from a list of CBCSubreportSpec. This
|
||||
-- shares postings between the subreports.
|
||||
@ -159,7 +161,7 @@ compoundBalanceReportWith rspec' j priceoracle subreportspecs = cbr
|
||||
( cbcsubreporttitle
|
||||
-- Postprocess the report, negating balances and taking percentages if needed
|
||||
, cbcsubreporttransform $
|
||||
generateMultiBalanceReport rspecsub j priceoracle colps' startbals'
|
||||
generateMultiBalanceReport rspecsub j priceoracle mempty colps' startbals'
|
||||
, cbcsubreportincreasestotal
|
||||
)
|
||||
where
|
||||
@ -343,17 +345,17 @@ calculateReportMatrix rspec@ReportSpec{_rsReportOpts=ropts} j priceoracle startb
|
||||
-- | Lay out a set of postings grouped by date span into a regular matrix with rows
|
||||
-- given by AccountName and columns by DateSpan, then generate a MultiBalanceReport
|
||||
-- from the columns.
|
||||
generateMultiBalanceReport :: ReportSpec -> Journal -> PriceOracle
|
||||
generateMultiBalanceReport :: ReportSpec -> Journal -> PriceOracle -> Set AccountName
|
||||
-> [(DateSpan, [Posting])] -> HashMap AccountName Account
|
||||
-> MultiBalanceReport
|
||||
generateMultiBalanceReport rspec@ReportSpec{_rsReportOpts=ropts} j priceoracle colps startbals =
|
||||
generateMultiBalanceReport rspec@ReportSpec{_rsReportOpts=ropts} j priceoracle unelidableaccts colps startbals =
|
||||
report
|
||||
where
|
||||
-- Process changes into normal, cumulative, or historical amounts, plus value them
|
||||
matrix = calculateReportMatrix rspec j priceoracle startbals colps
|
||||
|
||||
-- All account names that will be displayed, possibly depth-clipped.
|
||||
displaynames = dbg5 "displaynames" $ displayedAccounts rspec matrix
|
||||
displaynames = dbg5 "displaynames" $ displayedAccounts rspec unelidableaccts matrix
|
||||
|
||||
-- All the rows of the report.
|
||||
rows = dbg5 "rows" . (if invert_ ropts then map (fmap maNegate) else id) -- Negate amounts if applicable
|
||||
@ -394,9 +396,11 @@ buildReportRows ropts displaynames =
|
||||
|
||||
-- | Calculate accounts which are to be displayed in the report, as well as
|
||||
-- their name and depth
|
||||
displayedAccounts :: ReportSpec -> HashMap AccountName (Map DateSpan Account)
|
||||
displayedAccounts :: ReportSpec
|
||||
-> Set AccountName
|
||||
-> HashMap AccountName (Map DateSpan Account)
|
||||
-> HashMap AccountName DisplayName
|
||||
displayedAccounts ReportSpec{_rsQuery=query,_rsReportOpts=ropts} valuedaccts
|
||||
displayedAccounts ReportSpec{_rsQuery=query,_rsReportOpts=ropts} unelidableaccts valuedaccts
|
||||
| depth == 0 = HM.singleton "..." $ DisplayName "..." "..." 1
|
||||
| otherwise = HM.mapWithKey (\a _ -> displayedName a) displayedAccts
|
||||
where
|
||||
@ -421,7 +425,8 @@ displayedAccounts ReportSpec{_rsQuery=query,_rsReportOpts=ropts} valuedaccts
|
||||
-- Accounts interesting for their own sake
|
||||
isInteresting name amts =
|
||||
d <= depth -- Throw out anything too deep
|
||||
&& ( (empty_ ropts && keepWhenEmpty amts) -- Keep empty accounts when called with --empty
|
||||
&& ( name `Set.member` unelidableaccts -- Unelidable accounts should be kept unless too deep
|
||||
||(empty_ ropts && keepWhenEmpty amts) -- Keep empty accounts when called with --empty
|
||||
|| not (isZeroRow balance amts) -- Keep everything with a non-zero balance in the row
|
||||
)
|
||||
where
|
||||
|
@ -409,7 +409,31 @@ Budget performance in 2019-01-01..2019-01-03:
|
||||
-------------------++---------------------------
|
||||
|| 0 [ 0]
|
||||
|
||||
# 20. Subaccounts + nested budgets
|
||||
# 20. Also should work when there are no postings directly in budgeted parents (#1800)
|
||||
$ hledger -f- bal -e 2019-01-02 --budget -E
|
||||
Budget performance in 2019-01-01:
|
||||
|
||||
|| 2019-01-01
|
||||
===============================++===========================
|
||||
expenses:personal || $10.00 [1% of $1,000.00]
|
||||
expenses:personal:electronics || $10.00
|
||||
liabilities || $-10.00 [1% of $-1000.00]
|
||||
-------------------------------++---------------------------
|
||||
|| 0 [ 0]
|
||||
|
||||
# 21. Also should work when there are no postings directly in budgeted parents with --tree (#1800)
|
||||
$ hledger -f- bal -e 2019-01-02 --budget --tree -E
|
||||
Budget performance in 2019-01-01:
|
||||
|
||||
|| 2019-01-01
|
||||
===================++===========================
|
||||
expenses:personal || $10.00 [1% of $1,000.00]
|
||||
electronics || $10.00
|
||||
liabilities || $-10.00 [1% of $-1000.00]
|
||||
-------------------++---------------------------
|
||||
|| 0 [ 0]
|
||||
|
||||
# 22. Subaccounts + nested budgets
|
||||
<
|
||||
~ monthly from 2019/01
|
||||
expenses:personal $1,000.00
|
||||
@ -439,7 +463,7 @@ Budget performance in 2019-01-01..2019-01-03:
|
||||
-------------------------------++----------------------------
|
||||
|| 0 [ 0]
|
||||
|
||||
# 21.
|
||||
# 23.
|
||||
$ hledger -f- bal --budget -E
|
||||
Budget performance in 2019-01-01..2019-01-03:
|
||||
|
||||
@ -452,7 +476,7 @@ Budget performance in 2019-01-01..2019-01-03:
|
||||
----------------------------------------++----------------------------
|
||||
|| 0 [ 0]
|
||||
|
||||
# 22.
|
||||
# 24.
|
||||
$ hledger -f- bal --budget --tree
|
||||
Budget performance in 2019-01-01..2019-01-03:
|
||||
|
||||
@ -464,7 +488,7 @@ Budget performance in 2019-01-01..2019-01-03:
|
||||
-------------------++----------------------------
|
||||
|| 0 [ 0]
|
||||
|
||||
# 23.
|
||||
# 25.
|
||||
$ hledger -f- bal --budget --tree -E
|
||||
Budget performance in 2019-01-01..2019-01-03:
|
||||
|
||||
@ -477,7 +501,7 @@ Budget performance in 2019-01-01..2019-01-03:
|
||||
-------------------++----------------------------
|
||||
|| 0 [ 0]
|
||||
|
||||
## 24. Zero budget == no budget
|
||||
# 26. Zero budget == no budget
|
||||
<
|
||||
~ monthly from 2019-01
|
||||
expenses:bills $100 ; bills has a $100 budget of its own, separate from subaccounts
|
||||
@ -515,7 +539,7 @@ Budget performance in 2019-01-01..2019-01-02:
|
||||
------------------++------------------------
|
||||
|| 0 [ 0]
|
||||
|
||||
# 25. -E shows d and e
|
||||
# 27. -E shows d and e
|
||||
$ hledger bal -f- --budget -E
|
||||
Budget performance in 2019-01-01..2019-01-02:
|
||||
|
||||
@ -532,7 +556,7 @@ Budget performance in 2019-01-01..2019-01-02:
|
||||
------------------++------------------------
|
||||
|| 0 [ 0]
|
||||
|
||||
# 26. The totals row shows correct totals.
|
||||
# 28. The totals row shows correct totals.
|
||||
# -T/--total and -A/--average adds those columns.
|
||||
$ hledger bal -f- --budget -TA not:income
|
||||
Budget performance in 2019-01-01..2019-01-02:
|
||||
@ -547,7 +571,7 @@ Budget performance in 2019-01-01..2019-01-02:
|
||||
------------------++--------------------------------------------------------------
|
||||
|| $80 [22% of $370] $80 [22% of $370] $80 [22% of $370]
|
||||
|
||||
# 27. CSV output works.
|
||||
# 29. CSV output works.
|
||||
$ hledger bal -f- --budget -TA not:income -O csv
|
||||
"Account","2019-01-01..2019-01-02","budget","Total","budget","Average","budget"
|
||||
"expenses:bills","$80","$370","$80","$370","$80","$370"
|
||||
@ -557,7 +581,7 @@ $ hledger bal -f- --budget -TA not:income -O csv
|
||||
"expenses:bills:f","$10","0","$10","0","$10","0"
|
||||
"Total:","$80","$370","$80","$370","$80","$370"
|
||||
|
||||
# 28. You would expect this to show a budget goal in jan, feb, mar.
|
||||
# 30. You would expect this to show a budget goal in jan, feb, mar.
|
||||
# But by the usual report date logic, which picks the oldest and newest
|
||||
# transaction date (1/15 and 3/15) as start and end date by default,
|
||||
# and since "monthly" generates transactions on the 1st,
|
||||
@ -585,7 +609,7 @@ Budget performance in 2020Q1:
|
||||
---------------++-----------------------------------------------------------
|
||||
|| 0 [ 0% of $500] 0 [0% of $500] 0 [ 0% of $500]
|
||||
|
||||
# 29. Specifying the report period works around it.
|
||||
# 31. Specifying the report period works around it.
|
||||
$ hledger -f- bal --budget -M date:2020q1
|
||||
Budget performance in 2020Q1:
|
||||
|
||||
@ -596,7 +620,7 @@ Budget performance in 2020Q1:
|
||||
---------------++-----------------------------------------------------------
|
||||
|| 0 [ 0% of $500] 0 [0% of $500] 0 [ 0% of $500]
|
||||
|
||||
# 30. Select from multiple named budgets.
|
||||
# 32. Select from multiple named budgets.
|
||||
<
|
||||
~ weekly weekly budget
|
||||
(aaa) 1
|
||||
|
Loading…
Reference in New Issue
Block a user