lib: Generalise CBCSubreportSpec to allow more subreport control.

This commit is contained in:
Stephen Morgan 2020-09-23 11:51:40 +10:00 committed by Simon Michael
parent 6e65d4e071
commit affc8d10f2
7 changed files with 39 additions and 36 deletions

View File

@ -16,7 +16,6 @@ module Hledger.Reports.MultiBalanceReport (
multiBalanceReport, multiBalanceReport,
multiBalanceReportWith, multiBalanceReportWith,
CompoundBalanceReport,
compoundBalanceReport, compoundBalanceReport,
compoundBalanceReportWith, compoundBalanceReportWith,
@ -86,7 +85,6 @@ import Hledger.Reports.ReportTypes
type MultiBalanceReport = PeriodicReport DisplayName MixedAmount type MultiBalanceReport = PeriodicReport DisplayName MixedAmount
type MultiBalanceReportRow = PeriodicReportRow DisplayName MixedAmount type MultiBalanceReportRow = PeriodicReportRow DisplayName MixedAmount
type CompoundBalanceReport = CompoundPeriodicReport DisplayName MixedAmount
-- type alias just to remind us which AccountNames might be depth-clipped, below. -- type alias just to remind us which AccountNames might be depth-clipped, below.
type ClippedAccountName = AccountName type ClippedAccountName = AccountName
@ -131,14 +129,15 @@ multiBalanceReportWith rspec' j priceoracle = report
-- | Generate a compound balance report from a list of CBCSubreportSpec. This -- | Generate a compound balance report from a list of CBCSubreportSpec. This
-- shares postings between the subreports. -- shares postings between the subreports.
compoundBalanceReport :: ReportSpec -> Journal -> [CBCSubreportSpec] compoundBalanceReport :: ReportSpec -> Journal -> [CBCSubreportSpec a]
-> CompoundBalanceReport -> CompoundPeriodicReport a MixedAmount
compoundBalanceReport rspec j = compoundBalanceReportWith rspec j (journalPriceOracle infer j) compoundBalanceReport rspec j = compoundBalanceReportWith rspec j (journalPriceOracle infer j)
where infer = infer_value_ $ rsOpts rspec where infer = infer_value_ $ rsOpts rspec
-- | A helper for compoundBalanceReport, similar to multiBalanceReportWith. -- | A helper for compoundBalanceReport, similar to multiBalanceReportWith.
compoundBalanceReportWith :: ReportSpec -> Journal -> PriceOracle compoundBalanceReportWith :: ReportSpec -> Journal -> PriceOracle
-> [CBCSubreportSpec] -> CompoundBalanceReport -> [CBCSubreportSpec a]
-> CompoundPeriodicReport a MixedAmount
compoundBalanceReportWith rspec' j priceoracle subreportspecs = cbr compoundBalanceReportWith rspec' j priceoracle subreportspecs = cbr
where where
-- Queries, report/column dates. -- Queries, report/column dates.
@ -160,16 +159,16 @@ compoundBalanceReportWith rspec' j priceoracle subreportspecs = cbr
generateSubreport CBCSubreportSpec{..} = generateSubreport CBCSubreportSpec{..} =
( cbcsubreporttitle ( cbcsubreporttitle
-- Postprocess the report, negating balances and taking percentages if needed -- Postprocess the report, negating balances and taking percentages if needed
, prNormaliseSign cbcsubreportnormalsign $ , cbcsubreporttransform $
generateMultiBalanceReport rspec' j valuation colspans colps' startbals' generateMultiBalanceReport rspec{rsOpts=ropts} j valuation colspans colps' startbals'
, cbcsubreportincreasestotal , cbcsubreportincreasestotal
) )
where where
rspec' = rspec{rsOpts=ropts}
ropts = (rsOpts rspec){normalbalance_=Just cbcsubreportnormalsign}
-- Filter the column postings according to each subreport -- Filter the column postings according to each subreport
colps' = filter (matchesPosting $ cbcsubreportquery j) <$> colps colps' = filter (matchesPosting q) <$> colps
startbals' = HM.filterWithKey (\k _ -> matchesAccount (cbcsubreportquery j) k) startbals startbals' = HM.filterWithKey (\k _ -> matchesAccount q k) startbals
ropts = cbcsubreportoptions $ rsOpts rspec
q = cbcsubreportquery j
-- Sum the subreport totals by column. Handle these cases: -- Sum the subreport totals by column. Handle these cases:
-- - no subreports -- - no subreports

View File

@ -17,7 +17,6 @@ module Hledger.Reports.ReportTypes
, Average , Average
, periodicReportSpan , periodicReportSpan
, prNormaliseSign
, prMapName , prMapName
, prMapMaybeName , prMapMaybeName
@ -40,8 +39,10 @@ import Data.Maybe (mapMaybe)
import Data.Semigroup (Semigroup(..)) import Data.Semigroup (Semigroup(..))
#endif #endif
import GHC.Generics (Generic) import GHC.Generics (Generic)
import Hledger.Data import Hledger.Data
import Hledger.Query (Query) import Hledger.Query (Query)
import Hledger.Reports.ReportOptions (ReportOpts)
type Percentage = Decimal type Percentage = Decimal
@ -109,12 +110,6 @@ periodicReportSpan :: PeriodicReport a b -> DateSpan
periodicReportSpan (PeriodicReport [] _ _) = DateSpan Nothing Nothing periodicReportSpan (PeriodicReport [] _ _) = DateSpan Nothing Nothing
periodicReportSpan (PeriodicReport colspans _ _) = DateSpan (spanStart $ head colspans) (spanEnd $ last colspans) periodicReportSpan (PeriodicReport colspans _ _) = DateSpan (spanStart $ head colspans) (spanEnd $ last colspans)
-- | Given a PeriodicReport and its normal balance sign,
-- if it is known to be normally negative, convert it to normally positive.
prNormaliseSign :: Num b => NormalSign -> PeriodicReport a b -> PeriodicReport a b
prNormaliseSign NormallyNegative = fmap negate
prNormaliseSign NormallyPositive = id
-- | Map a function over the row names. -- | Map a function over the row names.
prMapName :: (a -> b) -> PeriodicReport a c -> PeriodicReport b c prMapName :: (a -> b) -> PeriodicReport a c -> PeriodicReport b c
prMapName f report = report{prRows = map (prrMapName f) $ prRows report} prMapName f report = report{prRows = map (prrMapName f) $ prRows report}
@ -157,10 +152,11 @@ data CompoundPeriodicReport a b = CompoundPeriodicReport
-- | Description of one subreport within a compound balance report. -- | Description of one subreport within a compound balance report.
-- Part of a "CompoundBalanceCommandSpec", but also used in hledger-lib. -- Part of a "CompoundBalanceCommandSpec", but also used in hledger-lib.
data CBCSubreportSpec = CBCSubreportSpec data CBCSubreportSpec a = CBCSubreportSpec
{ cbcsubreporttitle :: String { cbcsubreporttitle :: String
, cbcsubreportquery :: Journal -> Query , cbcsubreportquery :: Journal -> Query
, cbcsubreportnormalsign :: NormalSign , cbcsubreportoptions :: ReportOpts -> ReportOpts
, cbcsubreporttransform :: PeriodicReport DisplayName MixedAmount -> PeriodicReport a MixedAmount
, cbcsubreportincreasestotal :: Bool , cbcsubreportincreasestotal :: Bool
} }

View File

@ -24,13 +24,15 @@ balancesheetSpec = CompoundBalanceCommandSpec {
CBCSubreportSpec{ CBCSubreportSpec{
cbcsubreporttitle="Assets" cbcsubreporttitle="Assets"
,cbcsubreportquery=journalAssetAccountQuery ,cbcsubreportquery=journalAssetAccountQuery
,cbcsubreportnormalsign=NormallyPositive ,cbcsubreportoptions=(\ropts -> ropts{normalbalance_=Just NormallyPositive})
,cbcsubreporttransform=id
,cbcsubreportincreasestotal=True ,cbcsubreportincreasestotal=True
} }
,CBCSubreportSpec{ ,CBCSubreportSpec{
cbcsubreporttitle="Liabilities" cbcsubreporttitle="Liabilities"
,cbcsubreportquery=journalLiabilityAccountQuery ,cbcsubreportquery=journalLiabilityAccountQuery
,cbcsubreportnormalsign=NormallyNegative ,cbcsubreportoptions=(\ropts -> ropts{normalbalance_=Just NormallyNegative})
,cbcsubreporttransform=fmap negate
,cbcsubreportincreasestotal=False ,cbcsubreportincreasestotal=False
} }
], ],

View File

@ -24,19 +24,22 @@ balancesheetequitySpec = CompoundBalanceCommandSpec {
CBCSubreportSpec{ CBCSubreportSpec{
cbcsubreporttitle="Assets" cbcsubreporttitle="Assets"
,cbcsubreportquery=journalAssetAccountQuery ,cbcsubreportquery=journalAssetAccountQuery
,cbcsubreportnormalsign=NormallyPositive ,cbcsubreportoptions=(\ropts -> ropts{normalbalance_=Just NormallyPositive})
,cbcsubreporttransform=id
,cbcsubreportincreasestotal=True ,cbcsubreportincreasestotal=True
} }
,CBCSubreportSpec{ ,CBCSubreportSpec{
cbcsubreporttitle="Liabilities" cbcsubreporttitle="Liabilities"
,cbcsubreportquery=journalLiabilityAccountQuery ,cbcsubreportquery=journalLiabilityAccountQuery
,cbcsubreportnormalsign=NormallyNegative ,cbcsubreportoptions=(\ropts -> ropts{normalbalance_=Just NormallyNegative})
,cbcsubreporttransform=fmap negate
,cbcsubreportincreasestotal=False ,cbcsubreportincreasestotal=False
} }
,CBCSubreportSpec{ ,CBCSubreportSpec{
cbcsubreporttitle="Equity" cbcsubreporttitle="Equity"
,cbcsubreportquery=journalEquityAccountQuery ,cbcsubreportquery=journalEquityAccountQuery
,cbcsubreportnormalsign=NormallyNegative ,cbcsubreportoptions=(\ropts -> ropts{normalbalance_=Just NormallyNegative})
,cbcsubreporttransform=fmap negate
,cbcsubreportincreasestotal=False ,cbcsubreportincreasestotal=False
} }
], ],

View File

@ -27,7 +27,8 @@ cashflowSpec = CompoundBalanceCommandSpec {
CBCSubreportSpec{ CBCSubreportSpec{
cbcsubreporttitle="Cash flows" cbcsubreporttitle="Cash flows"
,cbcsubreportquery=journalCashAccountQuery ,cbcsubreportquery=journalCashAccountQuery
,cbcsubreportnormalsign=NormallyPositive ,cbcsubreportoptions=(\ropts -> ropts{normalbalance_= Just NormallyPositive})
,cbcsubreporttransform=id
,cbcsubreportincreasestotal=True ,cbcsubreportincreasestotal=True
} }
], ],

View File

@ -23,13 +23,15 @@ incomestatementSpec = CompoundBalanceCommandSpec {
CBCSubreportSpec{ CBCSubreportSpec{
cbcsubreporttitle="Revenues" cbcsubreporttitle="Revenues"
,cbcsubreportquery=journalRevenueAccountQuery ,cbcsubreportquery=journalRevenueAccountQuery
,cbcsubreportnormalsign=NormallyNegative ,cbcsubreportoptions=(\ropts -> ropts{normalbalance_=Just NormallyNegative})
,cbcsubreporttransform=fmap negate
,cbcsubreportincreasestotal=True ,cbcsubreportincreasestotal=True
} }
,CBCSubreportSpec{ ,CBCSubreportSpec{
cbcsubreporttitle="Expenses" cbcsubreporttitle="Expenses"
,cbcsubreportquery=journalExpenseAccountQuery ,cbcsubreportquery=journalExpenseAccountQuery
,cbcsubreportnormalsign=NormallyPositive ,cbcsubreportoptions=(\ropts -> ropts{normalbalance_=Just NormallyPositive})
,cbcsubreporttransform=id
,cbcsubreportincreasestotal=False ,cbcsubreportincreasestotal=False
} }
], ],

View File

@ -43,7 +43,7 @@ import Hledger.Cli.Utils (unsupportedOutputFormatError, writeOutput)
data CompoundBalanceCommandSpec = CompoundBalanceCommandSpec { data CompoundBalanceCommandSpec = CompoundBalanceCommandSpec {
cbcdoc :: CommandDoc, -- ^ the command's name(s) and documentation cbcdoc :: CommandDoc, -- ^ the command's name(s) and documentation
cbctitle :: String, -- ^ overall report title cbctitle :: String, -- ^ overall report title
cbcqueries :: [CBCSubreportSpec], -- ^ subreport details cbcqueries :: [CBCSubreportSpec DisplayName], -- ^ subreport details
cbctype :: BalanceType -- ^ the "balance" type (change, cumulative, historical) cbctype :: BalanceType -- ^ the "balance" type (change, cumulative, historical)
-- this report shows (overrides command line flags) -- this report shows (overrides command line flags)
} }
@ -186,7 +186,7 @@ Balance Sheet
Total || 1 1 1 Total || 1 1 1
-} -}
compoundBalanceReportAsText :: ReportOpts -> CompoundBalanceReport -> String compoundBalanceReportAsText :: ReportOpts -> CompoundPeriodicReport DisplayName MixedAmount -> String
compoundBalanceReportAsText ropts compoundBalanceReportAsText ropts
(CompoundPeriodicReport title _colspans subreports (PeriodicReportRow _ coltotals grandtotal grandavg)) = (CompoundPeriodicReport title _colspans subreports (PeriodicReportRow _ coltotals grandtotal grandavg)) =
title ++ "\n\n" ++ title ++ "\n\n" ++
@ -225,7 +225,7 @@ concatTables (Table hLeft hTop dat) (Table hLeft' _ dat') =
-- Subreports' CSV is concatenated, with the headings rows replaced by a -- Subreports' CSV is concatenated, with the headings rows replaced by a
-- subreport title row, and an overall title row, one headings row, and an -- subreport title row, and an overall title row, one headings row, and an
-- optional overall totals row is added. -- optional overall totals row is added.
compoundBalanceReportAsCsv :: ReportOpts -> CompoundBalanceReport -> CSV compoundBalanceReportAsCsv :: ReportOpts -> CompoundPeriodicReport DisplayName MixedAmount -> CSV
compoundBalanceReportAsCsv ropts (CompoundPeriodicReport title colspans subreports (PeriodicReportRow _ coltotals grandtotal grandavg)) = compoundBalanceReportAsCsv ropts (CompoundPeriodicReport title colspans subreports (PeriodicReportRow _ coltotals grandtotal grandavg)) =
addtotals $ addtotals $
padRow title : padRow title :
@ -262,7 +262,7 @@ compoundBalanceReportAsCsv ropts (CompoundPeriodicReport title colspans subrepor
]) ])
-- | Render a compound balance report as HTML. -- | Render a compound balance report as HTML.
compoundBalanceReportAsHtml :: ReportOpts -> CompoundBalanceReport -> Html () compoundBalanceReportAsHtml :: ReportOpts -> CompoundPeriodicReport DisplayName MixedAmount -> Html ()
compoundBalanceReportAsHtml ropts cbr = compoundBalanceReportAsHtml ropts cbr =
let let
CompoundPeriodicReport title colspans subreports (PeriodicReportRow _ coltotals grandtotal grandavg) = cbr CompoundPeriodicReport title colspans subreports (PeriodicReportRow _ coltotals grandtotal grandavg) = cbr