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] =
dbg "displayedAccts" $
(if tree_ opts then expandAccountNames else id) $
nub $ map (clipAccountName depth) postedAccts
-- [ "assets" ]
@ -142,14 +143,14 @@ periodBalanceReport opts q j = MultiBalanceReport (spans, items, totals)
[postingAcctBals ps | ps <- psBySpan]
where
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
as = depthLimit $
filter ((>0).anumpostings) $
(if tree_ opts then id else filter ((>0).anumpostings)) $
drop 1 $ accountsFromPostings ps
depthLimit
| flatShowsExclusiveBalance = clipAccountsAndAggregate depth -- aggregate deeper balances at the depth limit
| otherwise = filter ((depthq `matchesAccount`).aname) -- exclude deeper balances
| tree_ opts = filter ((depthq `matchesAccount`).aname) -- exclude deeper balances
| otherwise = clipAccountsAndAggregate depth -- aggregate deeper balances at the depth limit
-- [ [ ( "assets" , 0 ) ]
-- , [ ( "assets" , 1 ) ]
-- , [ ( "assets" , 1 ) ]
@ -179,7 +180,7 @@ periodBalanceReport opts q j = MultiBalanceReport (spans, items, totals)
items :: [MultiBalanceReportRow] =
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 ] ) ]
-- highestLevelBalsBySpan :: [[MixedAmount]] =
@ -188,9 +189,9 @@ periodBalanceReport opts q j = MultiBalanceReport (spans, items, totals)
totals :: [MixedAmount] =
dbg "totals" $
if flatShowsExclusiveBalance
then map (sum . map snd) displayedBalsBySpan
else map (sum . map pamount) psBySpan
if tree_ opts
then map (sum . map pamount) psBySpan
else map (sum . map snd) displayedBalsBySpan
-- else map sum highestLevelBalsBySpan
-- [ 0 , 1 , 1 ]
@ -211,7 +212,7 @@ cumulativeOrHistoricalBalanceReport opts q j = MultiBalanceReport (periodbalance
where
dateless = filterQuery (not . queryIsDate)
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
startingBalanceFor a
| 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]
totals = dbg "totals" $
if flatShowsExclusiveBalance
then map sum balsbycol
else map sum highestlevelbalsbycol
if tree_ opts
then map sum highestlevelbalsbycol
else map sum balsbycol
where
balsbycol = transpose $ map endingBalancesFor reportaccts
highestlevelbalsbycol = transpose $ map endingBalancesFor highestlevelaccts

View File

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

View File

@ -265,7 +265,8 @@ balancemode = (defCommandMode $ ["balance"] ++ aliases ++ ["bal"]) { -- also acc
groupUnnamed = [
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 ["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 ["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"
@ -286,11 +287,10 @@ balance CliOpts{reportopts_=ropts} j = do
Left err -> [err]
Right _ ->
case (intervalFromOpts ropts, balancetype_ ropts) of
(NoInterval,_) -> balanceReportAsText ropts $ balanceReport ropts (queryFromOpts d ropts) j
(NoInterval,_) -> balanceReportAsText ropts $ balanceReport ropts (queryFromOpts d ropts) j
(_,PeriodBalance) -> periodBalanceReportAsText ropts $ periodBalanceReport ropts (queryFromOpts d ropts) j
(_,CumulativeBalance) -> cumulativeBalanceReportAsText ropts $ cumulativeOrHistoricalBalanceReport ropts (queryFromOpts d ropts) j
(_,HistoricalBalance) -> historicalBalanceReportAsText ropts $ cumulativeOrHistoricalBalanceReport ropts (queryFromOpts d ropts) j
putStr $ unlines output
-- | 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
| otherwise = items -- dbg "2" $ filter (any (not . isZeroMixedAmount) . snd) $ dbg "1" items
accts = map renderacct items'
renderacct ((a,a',_i),_)
| flat_ opts = a
| otherwise = a' -- replicate i ' ' ++
renderacct ((a,a',i),_)
| tree_ opts = replicate (i*2) ' ' ++ a'
| otherwise = a
acctswidth = maximum $ map length $ accts
totalrow | no_total_ opts = row "" []
| otherwise = row "" coltotals
@ -407,9 +407,9 @@ cumulativeBalanceReportAsText opts (MultiBalanceReport (colspans, items, coltota
where
trimborder = ("":) . (++[""]) . drop 1 . init . map (drop 1 . init)
accts = map renderacct items
renderacct ((a,a',_),_)
| flat_ opts = a
| otherwise = a' -- replicate i ' ' ++
renderacct ((a,a',i),_)
| tree_ opts = replicate (i*2) ' ' ++ a'
| otherwise = a
acctswidth = maximum $ map length $ accts
addtotalrow | no_total_ opts = id
| otherwise = (+----+ row "" coltotals)
@ -428,9 +428,9 @@ historicalBalanceReportAsText opts (MultiBalanceReport (colspans, items, coltota
where
trimborder = ("":) . (++[""]) . drop 1 . init . map (drop 1 . init)
accts = map renderacct items
renderacct ((a,a',_),_)
| flat_ opts = a
| otherwise = a' -- replicate i ' ' ++
renderacct ((a,a',i),_)
| tree_ opts = replicate (i*2) ' ' ++ a'
| otherwise = a
acctswidth = maximum $ map length $ accts
addtotalrow | no_total_ opts = id
| otherwise = (+----+ row "" coltotals)