fix: bal: Make sure boring parent accounts in compound balance reports

include historical postings when account declarations have undeclared
parents. (#1698)
This commit is contained in:
Stephen Morgan 2021-09-16 22:18:27 +10:00 committed by Simon Michael
parent 3b5262e54a
commit 62351dd329
2 changed files with 56 additions and 15 deletions

View File

@ -25,7 +25,8 @@ module Hledger.Reports.MultiBalanceReport (
makeReportQuery, makeReportQuery,
getPostingsByColumn, getPostingsByColumn,
getPostings, getPostings,
startingBalances, startingPostings,
startingBalancesFromPostings,
generateMultiBalanceReport, generateMultiBalanceReport,
balanceReportTableAsText, balanceReportTableAsText,
@ -121,7 +122,8 @@ multiBalanceReportWith rspec' j priceoracle = report
-- The matched accounts with a starting balance. All of these should appear -- The matched accounts with a starting balance. All of these should appear
-- in the report, even if they have no postings during the report period. -- in the report, even if they have no postings during the report period.
startbals = dbg5 "startbals" $ startingBalances rspec j priceoracle reportspan startbals = dbg5 "startbals" . startingBalancesFromPostings rspec j priceoracle
$ startingPostings rspec j priceoracle reportspan
-- Generate and postprocess the report, negating balances and taking percentages if needed -- Generate and postprocess the report, negating balances and taking percentages if needed
report = dbg4 "multiBalanceReportWith" $ report = dbg4 "multiBalanceReportWith" $
@ -147,9 +149,9 @@ compoundBalanceReportWith rspec' j priceoracle subreportspecs = cbr
-- Group postings into their columns. -- Group postings into their columns.
colps = dbg5 "colps" $ getPostingsByColumn rspec j priceoracle reportspan colps = dbg5 "colps" $ getPostingsByColumn rspec j priceoracle reportspan
-- The matched accounts with a starting balance. All of these should appear -- The matched postings with a starting balance. All of these should appear
-- in the report, even if they have no postings during the report period. -- in the report, even if they have no postings during the report period.
startbals = dbg5 "startbals" $ startingBalances rspec j priceoracle reportspan startps = dbg5 "startps" $ startingPostings rspec j priceoracle reportspan
subreports = map generateSubreport subreportspecs subreports = map generateSubreport subreportspecs
where where
@ -163,7 +165,8 @@ compoundBalanceReportWith rspec' j priceoracle subreportspecs = cbr
where where
-- Filter the column postings according to each subreport -- Filter the column postings according to each subreport
colps' = filter (matchesPosting q) <$> colps colps' = filter (matchesPosting q) <$> colps
startbals' = HM.filterWithKey (\k _ -> matchesAccount q k) startbals -- We need to filter historical postings directly, rather than their accumulated balances. (#1698)
startbals' = startingBalancesFromPostings rspec j priceoracle $ filter (matchesPosting q) startps
ropts = cbcsubreportoptions $ _rsReportOpts rspec ropts = cbcsubreportoptions $ _rsReportOpts rspec
q = cbcsubreportquery j q = cbcsubreportquery j
@ -180,28 +183,31 @@ compoundBalanceReportWith rspec' j priceoracle subreportspecs = cbr
cbr = CompoundPeriodicReport "" (M.keys colps) subreports overalltotals cbr = CompoundPeriodicReport "" (M.keys colps) subreports overalltotals
-- | Calculate starting balances from postings, if needed for -H.
startingBalancesFromPostings :: ReportSpec -> Journal -> PriceOracle -> [Posting]
-> HashMap AccountName Account
startingBalancesFromPostings rspec j priceoracle =
fmap (M.findWithDefault nullacct emptydatespan)
. calculateReportMatrix rspec j priceoracle mempty
. M.singleton emptydatespan
-- | Calculate starting balances, if needed for -H -- | Postings needed to calculate starting balances.
-- --
-- Balances at report start date, from all earlier postings which otherwise match the query. -- Balances at report start date, from all earlier postings which otherwise match the query.
-- These balances are unvalued. -- These balances are unvalued.
-- TODO: Do we want to check whether to bother calculating these? isHistorical -- TODO: Do we want to check whether to bother calculating these? isHistorical
-- and startDate is not nothing, otherwise mempty? This currently gives a -- and startDate is not nothing, otherwise mempty? This currently gives a
-- failure with some totals which are supposed to be 0 being blank. -- failure with some totals which are supposed to be 0 being blank.
startingBalances :: ReportSpec -> Journal -> PriceOracle -> DateSpan -> HashMap AccountName Account startingPostings :: ReportSpec -> Journal -> PriceOracle -> DateSpan -> [Posting]
startingBalances rspec@ReportSpec{_rsQuery=query,_rsReportOpts=ropts} j priceoracle reportspan = startingPostings rspec@ReportSpec{_rsQuery=query,_rsReportOpts=ropts} j priceoracle reportspan =
fmap (M.findWithDefault nullacct precedingspan) acctmap map fst $ getPostings rspec' j priceoracle
where where
acctmap = calculateReportMatrix rspec' j priceoracle mempty
. M.singleton precedingspan . map fst $ getPostings rspec' j priceoracle
rspec' = rspec{_rsQuery=startbalq,_rsReportOpts=ropts'} rspec' = rspec{_rsQuery=startbalq,_rsReportOpts=ropts'}
-- If we're re-valuing every period, we need to have the unvalued start -- If we're re-valuing every period, we need to have the unvalued start
-- balance, so we can do it ourselves later. -- balance, so we can do it ourselves later.
ropts' = case value_ ropts of ropts' = case value_ ropts of
Just (AtEnd _) -> ropts''{value_=Nothing} Just (AtEnd _) -> ropts{period_=precedingperiod, value_=Nothing}
_ -> ropts'' _ -> ropts{period_=precedingperiod}
where ropts'' = ropts{period_=precedingperiod, no_elide_=accountlistmode_ ropts == ALTree}
-- q projected back before the report start date. -- q projected back before the report start date.
-- When there's no report start date, in case there are future txns (the hledger-ui case above), -- When there's no report start date, in case there are future txns (the hledger-ui case above),

View File

@ -327,3 +327,38 @@ $ hledger -f - balancesheet --tree --output-format=csv --drop 1
"Liabilities","" "Liabilities",""
"total" "total"
"Net:","$1" "Net:","$1"
# 14. When declaring account types, we want boring parents to include their
# interesting children, including their historical postings. (#1698)
<
account assets:foobar:reserve ; type: Cash
account assets:foobar:current ; type: Cash
account assets:receivable:anon ; type: Asset
2018-12-06
assets:foobar:current 1 A
expenses:example
2019-01-04
assets:foobar:current 1 A
expenses:example
$ hledger -f - balancesheet --tree --no-elide --begin 2019-01-01
Balance Sheet 2019-01-04
|| 2019-01-04
=============++============
Assets ||
-------------++------------
assets || 2 A
foobar || 2 A
current || 2 A
-------------++------------
|| 2 A
=============++============
Liabilities ||
-------------++------------
-------------++------------
||
=============++============
Net: || 2 A