balance: --tree makes multicolumn reports show hierarchy

Multicolumn balance reports can now be switched to a hierarchical view
with --tree. This is similar to the single column balance report with
--no-elide, ie we do not elide boring parents into the following line.

The --flat and --tree flags are opposites; the last one to appear on
the command line is decisive (in future, if not already).
This commit is contained in:
Simon Michael 2014-04-06 21:56:47 -07:00
parent 349bb1db01
commit 7d99ae5033
3 changed files with 29 additions and 25 deletions

View File

@ -129,6 +129,7 @@ periodBalanceReport opts q j = MultiBalanceReport (spans, items, totals)
displayedAccts :: [ClippedAccountName] = displayedAccts :: [ClippedAccountName] =
dbg "displayedAccts" $ dbg "displayedAccts" $
(if tree_ opts then expandAccountNames else id) $
nub $ map (clipAccountName depth) postedAccts nub $ map (clipAccountName depth) postedAccts
-- [ "assets" ] -- [ "assets" ]
@ -142,14 +143,14 @@ periodBalanceReport opts q j = MultiBalanceReport (spans, items, totals)
[postingAcctBals ps | ps <- psBySpan] [postingAcctBals ps | ps <- psBySpan]
where where
postingAcctBals :: [Posting] -> [(ClippedAccountName, MixedAmount)] postingAcctBals :: [Posting] -> [(ClippedAccountName, MixedAmount)]
postingAcctBals ps = [(aname a, (if flatShowsExclusiveBalance then aebalance else aibalance) a) | a <- as] postingAcctBals ps = [(aname a, (if tree_ opts then aibalance else aebalance) a) | a <- as]
where where
as = depthLimit $ as = depthLimit $
filter ((>0).anumpostings) $ (if tree_ opts then id else filter ((>0).anumpostings)) $
drop 1 $ accountsFromPostings ps drop 1 $ accountsFromPostings ps
depthLimit depthLimit
| flatShowsExclusiveBalance = clipAccountsAndAggregate depth -- aggregate deeper balances at the depth limit | tree_ opts = filter ((depthq `matchesAccount`).aname) -- exclude deeper balances
| otherwise = filter ((depthq `matchesAccount`).aname) -- exclude deeper balances | otherwise = clipAccountsAndAggregate depth -- aggregate deeper balances at the depth limit
-- [ [ ( "assets" , 0 ) ] -- [ [ ( "assets" , 0 ) ]
-- , [ ( "assets" , 1 ) ] -- , [ ( "assets" , 1 ) ]
-- , [ ( "assets" , 1 ) ] -- , [ ( "assets" , 1 ) ]
@ -179,7 +180,7 @@ periodBalanceReport opts q j = MultiBalanceReport (spans, items, totals)
items :: [MultiBalanceReportRow] = items :: [MultiBalanceReportRow] =
dbg "items" $ dbg "items" $
[((a, a, accountNameLevel a), bs) | (a,bs) <- acctBalsAlist, empty_ opts || any (not . isZeroMixedAmount) bs] [((a, accountLeafName a, accountNameLevel a), bs) | (a,bs) <- acctBalsAlist, empty_ opts || any (not . isZeroMixedAmount) bs]
-- [ ( ( "assets" , "assets" , 1 ) , [ 0 , 1 , 1 ] ) ] -- [ ( ( "assets" , "assets" , 1 ) , [ 0 , 1 , 1 ] ) ]
-- highestLevelBalsBySpan :: [[MixedAmount]] = -- highestLevelBalsBySpan :: [[MixedAmount]] =
@ -188,9 +189,9 @@ periodBalanceReport opts q j = MultiBalanceReport (spans, items, totals)
totals :: [MixedAmount] = totals :: [MixedAmount] =
dbg "totals" $ dbg "totals" $
if flatShowsExclusiveBalance if tree_ opts
then map (sum . map snd) displayedBalsBySpan then map (sum . map pamount) psBySpan
else map (sum . map pamount) psBySpan else map (sum . map snd) displayedBalsBySpan
-- else map sum highestLevelBalsBySpan -- else map sum highestLevelBalsBySpan
-- [ 0 , 1 , 1 ] -- [ 0 , 1 , 1 ]
@ -211,7 +212,7 @@ cumulativeOrHistoricalBalanceReport opts q j = MultiBalanceReport (periodbalance
where where
dateless = filterQuery (not . queryIsDate) dateless = filterQuery (not . queryIsDate)
precedingq = dbg "precedingq" $ And [dateless q, Date $ DateSpan Nothing (spanStart reportspan)] precedingq = dbg "precedingq" $ And [dateless q, Date $ DateSpan Nothing (spanStart reportspan)]
(startbalanceitems,_) = dbg "starting balance report" $ balanceReport opts{flat_=True,empty_=True} precedingq j (startbalanceitems,_) = dbg "starting balance report" $ balanceReport opts{flat_=True,empty_=True} precedingq j -- XXX
-- acctsWithStartingBalance = map fst $ filter (not . isZeroMixedAmount . snd) startacctbals -- acctsWithStartingBalance = map fst $ filter (not . isZeroMixedAmount . snd) startacctbals
startingBalanceFor a startingBalanceFor a
| balancetype_ opts == HistoricalBalance = fromMaybe nullmixedamt $ lookup a startacctbals | balancetype_ opts == HistoricalBalance = fromMaybe nullmixedamt $ lookup a startacctbals
@ -237,9 +238,9 @@ cumulativeOrHistoricalBalanceReport opts q j = MultiBalanceReport (periodbalance
items = dbg "items" $ [((a,a,0), endingBalancesFor a) | a <- reportaccts] items = dbg "items" $ [((a,a,0), endingBalancesFor a) | a <- reportaccts]
totals = dbg "totals" $ totals = dbg "totals" $
if flatShowsExclusiveBalance if tree_ opts
then map sum balsbycol then map sum highestlevelbalsbycol
else map sum highestlevelbalsbycol else map sum balsbycol
where where
balsbycol = transpose $ map endingBalancesFor reportaccts balsbycol = transpose $ map endingBalancesFor reportaccts
highestlevelbalsbycol = transpose $ map endingBalancesFor highestlevelaccts highestlevelbalsbycol = transpose $ map endingBalancesFor highestlevelaccts

View File

@ -77,7 +77,8 @@ data ReportOpts = ReportOpts {
,related_ :: Bool ,related_ :: Bool
-- balance -- balance
,balancetype_ :: BalanceType ,balancetype_ :: BalanceType
,flat_ :: Bool ,flat_ :: Bool -- mutually
,tree_ :: Bool -- exclusive
,drop_ :: Int ,drop_ :: Int
,no_total_ :: Bool ,no_total_ :: Bool
} deriving (Show, Data, Typeable) } deriving (Show, Data, Typeable)
@ -111,6 +112,7 @@ defreportopts = ReportOpts
def def
def def
def def
def
rawOptsToReportOpts :: RawOpts -> IO ReportOpts rawOptsToReportOpts :: RawOpts -> IO ReportOpts
rawOptsToReportOpts rawopts = do rawOptsToReportOpts rawopts = do
@ -139,6 +141,7 @@ rawOptsToReportOpts rawopts = do
,related_ = boolopt "related" rawopts ,related_ = boolopt "related" rawopts
,balancetype_ = balancetypeopt rawopts ,balancetype_ = balancetypeopt rawopts
,flat_ = boolopt "flat" rawopts ,flat_ = boolopt "flat" rawopts
,tree_ = boolopt "tree" rawopts
,drop_ = intopt "drop" rawopts ,drop_ = intopt "drop" rawopts
,no_total_ = boolopt "no-total" rawopts ,no_total_ = boolopt "no-total" rawopts
} }

View File

@ -265,7 +265,8 @@ balancemode = (defCommandMode $ ["balance"] ++ aliases ++ ["bal"]) { -- also acc
groupUnnamed = [ groupUnnamed = [
flagNone ["cumulative"] (\opts -> setboolopt "cumulative" opts) "with a reporting interval, show accumulated totals starting from 0" flagNone ["cumulative"] (\opts -> setboolopt "cumulative" opts) "with a reporting interval, show accumulated totals starting from 0"
,flagNone ["historical","H"] (\opts -> setboolopt "historical" opts) "with a reporting interval, show accurate historical ending balances" ,flagNone ["historical","H"] (\opts -> setboolopt "historical" opts) "with a reporting interval, show accurate historical ending balances"
,flagNone ["flat"] (\opts -> setboolopt "flat" opts) "show full account names, unindented" ,flagNone ["flat"] (\opts -> setboolopt "flat" opts) "show full account names, as a list"
,flagNone ["tree"] (\opts -> setboolopt "tree" opts) "show short account names, as a tree"
,flagReq ["drop"] (\s opts -> Right $ setopt "drop" s opts) "N" "with --flat, omit this many leading account name components" ,flagReq ["drop"] (\s opts -> Right $ setopt "drop" s opts) "N" "with --flat, omit this many leading account name components"
,flagReq ["format"] (\s opts -> Right $ setopt "format" s opts) "FORMATSTR" "use this custom line format" ,flagReq ["format"] (\s opts -> Right $ setopt "format" s opts) "FORMATSTR" "use this custom line format"
,flagNone ["no-elide"] (\opts -> setboolopt "no-elide" opts) "no eliding at all, stronger than --empty" ,flagNone ["no-elide"] (\opts -> setboolopt "no-elide" opts) "no eliding at all, stronger than --empty"
@ -290,7 +291,6 @@ balance CliOpts{reportopts_=ropts} j = do
(_,PeriodBalance) -> periodBalanceReportAsText ropts $ periodBalanceReport ropts (queryFromOpts d ropts) j (_,PeriodBalance) -> periodBalanceReportAsText ropts $ periodBalanceReport ropts (queryFromOpts d ropts) j
(_,CumulativeBalance) -> cumulativeBalanceReportAsText ropts $ cumulativeOrHistoricalBalanceReport ropts (queryFromOpts d ropts) j (_,CumulativeBalance) -> cumulativeBalanceReportAsText ropts $ cumulativeOrHistoricalBalanceReport ropts (queryFromOpts d ropts) j
(_,HistoricalBalance) -> historicalBalanceReportAsText ropts $ cumulativeOrHistoricalBalanceReport ropts (queryFromOpts d ropts) j (_,HistoricalBalance) -> historicalBalanceReportAsText ropts $ cumulativeOrHistoricalBalanceReport ropts (queryFromOpts d ropts) j
putStr $ unlines output putStr $ unlines output
-- | Render an old-style single-column balance report as plain text. -- | Render an old-style single-column balance report as plain text.
@ -386,9 +386,9 @@ periodBalanceReportAsText opts (MultiBalanceReport (colspans, items, coltotals))
items' | empty_ opts = items items' | empty_ opts = items
| otherwise = items -- dbg "2" $ filter (any (not . isZeroMixedAmount) . snd) $ dbg "1" items | otherwise = items -- dbg "2" $ filter (any (not . isZeroMixedAmount) . snd) $ dbg "1" items
accts = map renderacct items' accts = map renderacct items'
renderacct ((a,a',_i),_) renderacct ((a,a',i),_)
| flat_ opts = a | tree_ opts = replicate (i*2) ' ' ++ a'
| otherwise = a' -- replicate i ' ' ++ | otherwise = a
acctswidth = maximum $ map length $ accts acctswidth = maximum $ map length $ accts
totalrow | no_total_ opts = row "" [] totalrow | no_total_ opts = row "" []
| otherwise = row "" coltotals | otherwise = row "" coltotals
@ -407,9 +407,9 @@ cumulativeBalanceReportAsText opts (MultiBalanceReport (colspans, items, coltota
where where
trimborder = ("":) . (++[""]) . drop 1 . init . map (drop 1 . init) trimborder = ("":) . (++[""]) . drop 1 . init . map (drop 1 . init)
accts = map renderacct items accts = map renderacct items
renderacct ((a,a',_),_) renderacct ((a,a',i),_)
| flat_ opts = a | tree_ opts = replicate (i*2) ' ' ++ a'
| otherwise = a' -- replicate i ' ' ++ | otherwise = a
acctswidth = maximum $ map length $ accts acctswidth = maximum $ map length $ accts
addtotalrow | no_total_ opts = id addtotalrow | no_total_ opts = id
| otherwise = (+----+ row "" coltotals) | otherwise = (+----+ row "" coltotals)
@ -428,9 +428,9 @@ historicalBalanceReportAsText opts (MultiBalanceReport (colspans, items, coltota
where where
trimborder = ("":) . (++[""]) . drop 1 . init . map (drop 1 . init) trimborder = ("":) . (++[""]) . drop 1 . init . map (drop 1 . init)
accts = map renderacct items accts = map renderacct items
renderacct ((a,a',_),_) renderacct ((a,a',i),_)
| flat_ opts = a | tree_ opts = replicate (i*2) ' ' ++ a'
| otherwise = a' -- replicate i ' ' ++ | otherwise = a
acctswidth = maximum $ map length $ accts acctswidth = maximum $ map length $ accts
addtotalrow | no_total_ opts = id addtotalrow | no_total_ opts = id
| otherwise = (+----+ row "" coltotals) | otherwise = (+----+ row "" coltotals)