mirror of
https://github.com/simonmichael/hledger.git
synced 2024-09-19 18:29:36 +03:00
balance, register, register-csv: depth 0 shows summary items (#206)
Previously, a depth:0 query produced an empty report (since there are no level zero accounts). Now, it aggregates all data into one summary item with account name "...". This makes it easier to see the kind of data Gwern was looking for from register-csv (net worth over time). Eg this shows one line per month summarising the total of assets and liabilities: hledger register-csv -- -MHE ^assets ^liabilities depth:0 Single and multi-column balance reports behave similarly.
This commit is contained in:
parent
0620ec9840
commit
7f6cf1f849
@ -125,7 +125,7 @@ clipAccounts d a = a{asubs=subs}
|
||||
clipAccountsAndAggregate :: Int -> [Account] -> [Account]
|
||||
clipAccountsAndAggregate d as = combined
|
||||
where
|
||||
clipped = [a{aname=clipAccountName d $ aname a} | a <- as]
|
||||
clipped = [a{aname=clipOrEllipsifyAccountName d $ aname a} | a <- as]
|
||||
combined = [a{aebalance=sum (map aebalance same)}
|
||||
| same@(a:_) <- groupBy (\a1 a2 -> aname a1 == aname a2) clipped]
|
||||
{-
|
||||
|
@ -108,9 +108,17 @@ elideAccountName width s =
|
||||
| length ss > 1 = elideparts width (done++[take 2 $ head ss]) (tail ss)
|
||||
| otherwise = done++ss
|
||||
|
||||
-- | Keep only the first n components of an account name, where n
|
||||
-- is a positive integer. If n is 0, returns the empty string.
|
||||
clipAccountName :: Int -> AccountName -> AccountName
|
||||
clipAccountName n = accountNameFromComponents . take n . accountNameComponents
|
||||
|
||||
-- | Keep only the first n components of an account name, where n
|
||||
-- is a positive integer. If n is 0, returns "...".
|
||||
clipOrEllipsifyAccountName :: Int -> AccountName -> AccountName
|
||||
clipOrEllipsifyAccountName 0 = const "..."
|
||||
clipOrEllipsifyAccountName n = accountNameFromComponents . take n . accountNameComponents
|
||||
|
||||
-- | Convert an account name to a regular expression matching it and its subaccounts.
|
||||
accountNameToAccountRegex :: String -> String
|
||||
accountNameToAccountRegex "" = ""
|
||||
|
@ -67,6 +67,9 @@ balanceReport opts q j = (items, total)
|
||||
|
||||
accts = ledgerRootAccount $ ledgerFromJournal q $ journalSelectingAmountFromOpts opts j
|
||||
accts' :: [Account]
|
||||
| queryDepth q == 0 =
|
||||
dbg "accts" $
|
||||
take 1 $ clipAccountsAndAggregate (queryDepth q) $ flattenAccounts accts
|
||||
| flat_ opts = dbg "accts" $
|
||||
filterzeros $
|
||||
filterempty $
|
||||
@ -75,7 +78,8 @@ balanceReport opts q j = (items, total)
|
||||
filter (not.aboring) $
|
||||
drop 1 $ flattenAccounts $
|
||||
markboring $
|
||||
prunezeros $ clipAccounts (queryDepth q) accts
|
||||
prunezeros $
|
||||
clipAccounts (queryDepth q) accts
|
||||
where
|
||||
balance = if flat_ opts then aebalance else aibalance
|
||||
filterzeros = if empty_ opts then id else filter (not . isZeroMixedAmount . balance)
|
||||
@ -99,14 +103,18 @@ markBoringParentAccounts = tieAccountParents . mapAccounts mark
|
||||
| otherwise = a
|
||||
|
||||
balanceReportItem :: ReportOpts -> Query -> Account -> BalanceReportItem
|
||||
balanceReportItem opts _ a@Account{aname=name}
|
||||
balanceReportItem opts q a
|
||||
| flat_ opts = ((name, name, 0), (if flatShowsExclusiveBalance then aebalance else aibalance) a)
|
||||
| otherwise = ((name, elidedname, indent), aibalance a)
|
||||
where
|
||||
name | queryDepth q > 0 = aname a
|
||||
| otherwise = "..."
|
||||
elidedname = accountNameFromComponents (adjacentboringparentnames ++ [accountLeafName name])
|
||||
adjacentboringparentnames = reverse $ map (accountLeafName.aname) $ takeWhile aboring $ parents
|
||||
indent = length $ filter (not.aboring) parents
|
||||
parents = init $ parentAccounts a
|
||||
-- parents exclude the tree's root node
|
||||
parents = case parentAccounts a of [] -> []
|
||||
as -> init as
|
||||
|
||||
-- -- the above using the newer multi balance report code:
|
||||
-- balanceReport' opts q j = (items, total)
|
||||
|
@ -129,7 +129,7 @@ multiBalanceReport opts q j = MultiBalanceReport (displayspans, items, totals)
|
||||
displayedAccts :: [ClippedAccountName] =
|
||||
dbg "displayedAccts" $
|
||||
(if tree_ opts then expandAccountNames else id) $
|
||||
nub $ map (clipAccountName depth) $
|
||||
nub $ map (clipOrEllipsifyAccountName depth) $
|
||||
if empty_ opts then nub $ sort $ startAccts ++ postedAccts else postedAccts
|
||||
|
||||
acctBalChangesPerSpan :: [[(ClippedAccountName, MixedAmount)]] =
|
||||
@ -150,7 +150,7 @@ multiBalanceReport opts q j = MultiBalanceReport (displayspans, items, totals)
|
||||
HistoricalBalance -> drop 1 $ scanl (+) (startingBalanceFor a) changes
|
||||
CumulativeBalance -> drop 1 $ scanl (+) nullmixedamt changes
|
||||
_ -> changes
|
||||
, empty_ opts || any (not . isZeroMixedAmount) displayedBals
|
||||
, empty_ opts || depth == 0 || any (not . isZeroMixedAmount) displayedBals
|
||||
]
|
||||
|
||||
totals :: [MixedAmount] =
|
||||
@ -162,6 +162,6 @@ multiBalanceReport opts q j = MultiBalanceReport (displayspans, items, totals)
|
||||
dbg "highestlevelaccts" $
|
||||
[a | a <- displayedAccts, not $ any (`elem` displayedAccts) $ init $ expandAccountName a]
|
||||
|
||||
dbg s = let p = "multiBalanceReport" in Hledger.Utils.dbg (p++" "++s) -- add prefix in debug output
|
||||
-- dbg = const id -- exclude from debug output
|
||||
dbg s = let p = "multiBalanceReport" in Hledger.Utils.dbg (p++" "++s) -- add prefix in this function's debug output
|
||||
-- dbg = const id -- exclude this function from debug output
|
||||
|
||||
|
@ -85,7 +85,7 @@ postingsReport opts q j = (totallabel, items)
|
||||
whichdate = whichDateFromOpts opts
|
||||
itemps | interval == NoInterval = map (,Nothing) reportps
|
||||
| otherwise = summarisePostingsByInterval interval whichdate depth showempty reportspan reportps
|
||||
items = postingsReportItems itemps (nullposting,Nothing) whichdate depth startbal runningcalc 1
|
||||
items = dbg "items" $ postingsReportItems itemps (nullposting,Nothing) whichdate depth startbal runningcalc 1
|
||||
where
|
||||
startbal = if balancetype_ opts == HistoricalBalance then sumPostings precedingps else 0
|
||||
runningcalc | average_ opts = \i avg amt -> avg + (amt - avg) `divideMixedAmount` (fromIntegral i) -- running average
|
||||
@ -108,7 +108,7 @@ postingsReportItems ((p,menddate):ps) (pprev,menddateprev) wd d b runningcalcfn
|
||||
isfirstintxn = ptransaction p /= ptransaction pprev
|
||||
isdifferentdate = case wd of PrimaryDate -> postingDate p /= postingDate pprev
|
||||
SecondaryDate -> postingDate2 p /= postingDate2 pprev
|
||||
p' = p{paccount=clipAccountName d $ paccount p}
|
||||
p' = p{paccount= clipOrEllipsifyAccountName d $ paccount p}
|
||||
b' = runningcalcfn itemnum b (pamount p)
|
||||
|
||||
-- | Generate one postings report line item, containing the posting,
|
||||
@ -150,8 +150,10 @@ type SummaryPosting = (Posting, Maybe Day)
|
||||
-- postings within it, aggregate the postings into one summary posting per
|
||||
-- account.
|
||||
--
|
||||
-- When a depth argument is present, postings to accounts of greater depth are
|
||||
-- also aggregated where possible.
|
||||
-- When a depth argument is present, postings to accounts of greater
|
||||
-- depth are also aggregated where possible. If the depth is 0, all
|
||||
-- postings in the span are aggregated into a single posting with
|
||||
-- account name "...".
|
||||
--
|
||||
-- The showempty flag includes spans with no postings and also postings
|
||||
-- with 0 amount.
|
||||
@ -166,8 +168,10 @@ summarisePostingsInDateSpan (DateSpan b e) wd depth showempty ps
|
||||
b' = fromMaybe (maybe nulldate postingdate $ headMay ps) b
|
||||
e' = fromMaybe (maybe (addDays 1 nulldate) postingdate $ lastMay ps) e
|
||||
summaryp = nullposting{pdate=Just b'}
|
||||
clippedanames = nub $ map (clipAccountName depth) anames
|
||||
summaryps = [summaryp{paccount=a,pamount=balance a} | a <- clippedanames]
|
||||
clippedanames | depth > 0 = nub $ map (clipAccountName depth) anames
|
||||
| otherwise = ["..."]
|
||||
summaryps | depth > 0 = [summaryp{paccount=a,pamount=balance a} | a <- clippedanames]
|
||||
| otherwise = [summaryp{paccount="...",pamount=sum $ map pamount ps}]
|
||||
summarypes = map (, Just e') $ (if showempty then id else filter (not . isZeroMixedAmount . pamount)) summaryps
|
||||
anames = sort $ nub $ map paccount ps
|
||||
-- aggregate balances by account, like ledgerFromJournal, then do depth-clipping
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 1
|
||||
# 1.
|
||||
hledgerdev -f sample.journal balance --no-total --depth 1
|
||||
>>>
|
||||
$-1 assets
|
||||
@ -7,3 +7,22 @@ hledgerdev -f sample.journal balance --no-total --depth 1
|
||||
$1 liabilities
|
||||
>>>=0
|
||||
|
||||
# 2. Depth 0 aggregates everything into one line
|
||||
hledgerdev -f sample.journal balance --no-total --depth 0
|
||||
>>>
|
||||
0 ...
|
||||
>>>=0
|
||||
|
||||
# 3. Ditto in a multi-column balance report.
|
||||
hledgerdev -f sample.journal balance -M -e 2008/4 --depth 0
|
||||
>>>
|
||||
Balance changes in 2008/01:
|
||||
|
||||
|| 2008/01
|
||||
=====++==========
|
||||
... || 0
|
||||
-----++----------
|
||||
|| 0
|
||||
|
||||
>>>=0
|
||||
|
||||
|
@ -8,7 +8,7 @@ hledgerdev -f - register aa --depth 1
|
||||
2010/01/01 x a 1 1
|
||||
>>>=0
|
||||
|
||||
# 2. similar to above, postings with same clipped account name are not aggregated
|
||||
# 2. separate postings remain separate
|
||||
hledgerdev -f - register aa --depth 2
|
||||
<<<
|
||||
2010/1/1 x
|
||||
@ -28,7 +28,7 @@ hledgerdev -f - register aa --depth 2
|
||||
2010/01/02 z a:aa 1 3
|
||||
>>>=0
|
||||
|
||||
# 3. as above, but with a reporting interval causing postings to be aggregated
|
||||
# 3. with a reporting interval, all postings are aggregated under each (clipped) account
|
||||
hledgerdev -f - register aa --depth 1 --daily
|
||||
<<<
|
||||
2010/1/1 x
|
||||
@ -56,3 +56,26 @@ hledgerdev -f - register a --depth 1 --cleared
|
||||
2012/01/01 (a) 1 1
|
||||
>>>2
|
||||
>>>=0
|
||||
|
||||
# 5. depth 0 aggregates everything into a single line
|
||||
hledgerdev -f - register --depth 0 --daily a b
|
||||
<<<
|
||||
2010/1/1 x
|
||||
a:aa 1
|
||||
b:bb 2
|
||||
c:cc
|
||||
|
||||
2010/1/1 y
|
||||
a:aa 1
|
||||
b:bb 2
|
||||
c:cc
|
||||
|
||||
2010/1/2 z
|
||||
a:aa 1
|
||||
b:bb 2
|
||||
c:cc
|
||||
>>>
|
||||
2010/01/01d ... 6 6
|
||||
2010/01/02d ... 3 9
|
||||
>>>=0
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user