elide boring accounts in balance report, like ledger
This commit is contained in:
parent
6a55237836
commit
c370d34de6
92
Account.hs
92
Account.hs
@ -47,52 +47,66 @@ addDataToAccountNameTree l ant =
|
|||||||
where
|
where
|
||||||
aname = antacctname ant
|
aname = antacctname ant
|
||||||
|
|
||||||
showAccountTreeWithBalances :: Ledger -> Int -> Tree Account -> String
|
-- would be straightforward except we want to elide boring accounts when
|
||||||
showAccountTreeWithBalances l depth at = (showAccountTreesWithBalances l depth) (branches at)
|
-- displaying account trees:
|
||||||
|
-- a (0 txns, only 1 subacct)
|
||||||
showAccountTreesWithBalances :: Ledger -> Int -> [Tree Account] -> String
|
-- b (another boring acct.)
|
||||||
showAccountTreesWithBalances _ 0 _ = ""
|
-- c
|
||||||
showAccountTreesWithBalances l depth ats =
|
|
||||||
concatMap showAccountBranch ats
|
|
||||||
where
|
|
||||||
showAccountBranch :: Tree Account -> String
|
|
||||||
showAccountBranch at =
|
|
||||||
topacct ++ "\n" ++ subaccts
|
|
||||||
-- case boring of
|
|
||||||
-- True ->
|
|
||||||
-- False ->
|
|
||||||
where
|
|
||||||
topacct = (showAmount bal) ++ " " ++ (indentAccountName name)
|
|
||||||
showAmount amt = printf "%20s" (show amt)
|
|
||||||
name = aname $ atacct at
|
|
||||||
txns = atransactions $ atacct at
|
|
||||||
bal = abalance $ atacct at
|
|
||||||
subaccts = (showAccountTreesWithBalances l (depth - 1)) $ branches at
|
|
||||||
boring = (length txns == 0) && ((length subaccts) == 1)
|
|
||||||
|
|
||||||
-- we want to elide boring accounts in the account tree
|
|
||||||
--
|
|
||||||
-- a (2 txns)
|
|
||||||
-- b (boring acct - 0 txns, exactly 1 sub)
|
|
||||||
-- c (5 txns)
|
|
||||||
-- d
|
-- d
|
||||||
-- to:
|
-- becomes:
|
||||||
-- a (2 txns)
|
-- a:b:c
|
||||||
-- b:c (5 txns)
|
-- d
|
||||||
-- d
|
showAccountTree :: Ledger -> Int -> Int -> Tree Account -> String
|
||||||
|
showAccountTree _ 0 _ _ = ""
|
||||||
|
showAccountTree l maxdepth indentlevel t
|
||||||
|
-- if this acct is boring, don't show it (unless this is as deep as we're going)
|
||||||
|
| (boringacct && (maxdepth > 1)) = subacctsindented 0
|
||||||
|
|
||||||
-- elideAccountTree at = at
|
-- otherwise show normal indented account name with balance
|
||||||
|
-- if this acct has one or more boring parents, prepend their names
|
||||||
|
| otherwise =
|
||||||
|
bal ++ " " ++ indent ++ parentnames ++ leafname ++ "\n" ++ (subacctsindented 1)
|
||||||
|
|
||||||
elideAccountTree :: Tree Account -> Tree Account
|
where
|
||||||
elideAccountTree = id
|
boringacct = isBoringAccount2 l name
|
||||||
|
boringparents = takeWhile (isBoringAccount2 l) $ parentAccountNames name
|
||||||
|
bal = printf "%20s" $ show $ abalance $ atacct t
|
||||||
|
indent = replicate (indentlevel * 2) ' '
|
||||||
|
parentnames = concatMap (++ ":") $ map accountLeafName boringparents
|
||||||
|
leafname = accountLeafName name
|
||||||
|
name = aname $ atacct t
|
||||||
|
subacctsindented i =
|
||||||
|
case maxdepth > 1 of
|
||||||
|
True -> concatMap (showAccountTree l (maxdepth-1) (indentlevel+i)) $ branches t
|
||||||
|
False -> ""
|
||||||
|
|
||||||
|
isBoringAccount :: Tree Account -> Bool
|
||||||
|
isBoringAccount at =
|
||||||
|
(length txns == 0) && ((length subaccts) == 1) && (not $ name == "top")
|
||||||
|
where
|
||||||
|
a = atacct at
|
||||||
|
name = aname a
|
||||||
|
txns = atransactions a
|
||||||
|
subaccts = branches at
|
||||||
|
|
||||||
|
isBoringAccount2 :: Ledger -> AccountName -> Bool
|
||||||
|
isBoringAccount2 l a
|
||||||
|
| a == "top" = False
|
||||||
|
| (length txns == 0) && ((length subs) == 1) = True
|
||||||
|
| otherwise = False
|
||||||
|
where
|
||||||
|
txns = transactionsInAccountNamed l a
|
||||||
|
subs = subAccountNamesFrom (ledgerAccountNames l) a
|
||||||
|
|
||||||
ledgerAccountTree :: Ledger -> Tree Account
|
ledgerAccountTree :: Ledger -> Tree Account
|
||||||
ledgerAccountTree l = elideAccountTree $ addDataToAccountNameTree l (ledgerAccountNameTree l)
|
ledgerAccountTree l = addDataToAccountNameTree l (ledgerAccountNameTree l)
|
||||||
|
|
||||||
|
-- ledgerAccountTreeForAccount :: Ledger -> AccountName -> Tree Account
|
||||||
|
-- ledgerAccountTreeForAccount l a = addDataToAccountNameTree l (ledgerAccountNameTree l)
|
||||||
|
|
||||||
ledgerAccountsMatching :: Ledger -> [String] -> [Account]
|
ledgerAccountsMatching :: Ledger -> [String] -> [Account]
|
||||||
ledgerAccountsMatching l acctpats = undefined
|
ledgerAccountsMatching l acctpats = undefined
|
||||||
|
|
||||||
showLedgerAccounts :: Ledger -> Int -> String
|
showLedgerAccounts :: Ledger -> Int -> String
|
||||||
showLedgerAccounts l depth =
|
showLedgerAccounts l maxdepth =
|
||||||
showAccountTreeWithBalances l depth (ledgerAccountTree l)
|
concatMap (showAccountTree l maxdepth 0) (branches (ledgerAccountTree l))
|
||||||
|
|
||||||
|
|||||||
@ -29,11 +29,15 @@ expandAccountNames as = nub $ concat $ map expand as
|
|||||||
topAccountNames :: [AccountName] -> [AccountName]
|
topAccountNames :: [AccountName] -> [AccountName]
|
||||||
topAccountNames as = [a | a <- expandAccountNames as, accountNameLevel a == 1]
|
topAccountNames as = [a | a <- expandAccountNames as, accountNameLevel a == 1]
|
||||||
|
|
||||||
parentAccountName :: AccountName -> Maybe AccountName
|
parentAccountName :: AccountName -> AccountName
|
||||||
parentAccountName a =
|
parentAccountName a =
|
||||||
case accountNameLevel a > 1 of
|
accountNameFromComponents $ rtail $ accountNameComponents a
|
||||||
True -> Just $ accountNameFromComponents $ rtail $ accountNameComponents a
|
|
||||||
False -> Nothing
|
parentAccountNames :: AccountName -> [AccountName]
|
||||||
|
parentAccountNames a = parentAccountNames' $ parentAccountName a
|
||||||
|
where
|
||||||
|
parentAccountNames' "" = []
|
||||||
|
parentAccountNames' a = [a] ++ (parentAccountNames' $ parentAccountName a)
|
||||||
|
|
||||||
s `isSubAccountNameOf` p =
|
s `isSubAccountNameOf` p =
|
||||||
((p ++ ":") `isPrefixOf` s) && (accountNameLevel s == (accountNameLevel p + 1))
|
((p ++ ":") `isPrefixOf` s) && (accountNameLevel s == (accountNameLevel p + 1))
|
||||||
@ -47,8 +51,10 @@ matchAccountName s a =
|
|||||||
Nothing -> False
|
Nothing -> False
|
||||||
otherwise -> True
|
otherwise -> True
|
||||||
|
|
||||||
indentAccountName :: AccountName -> String
|
indentAccountName :: Int -> AccountName -> String
|
||||||
indentAccountName a = replicate (((accountNameLevel a) - 1) * 2) ' ' ++ (accountLeafName a)
|
indentAccountName indentcorrection a =
|
||||||
|
replicate (indentlevel * 2) ' ' ++ (accountLeafName a)
|
||||||
|
where indentlevel = ((accountNameLevel a) - 1) + indentcorrection
|
||||||
|
|
||||||
|
|
||||||
-- We could almost get by with just the above, but we need smarter
|
-- We could almost get by with just the above, but we need smarter
|
||||||
@ -75,14 +81,8 @@ accountNameTreeFrom accts =
|
|||||||
subs = (subAccountNamesFrom accts)
|
subs = (subAccountNamesFrom accts)
|
||||||
|
|
||||||
showAccountNameTree :: Tree AccountName -> String
|
showAccountNameTree :: Tree AccountName -> String
|
||||||
showAccountNameTree at = showAccountNameTrees $ branches at
|
showAccountNameTree t =
|
||||||
|
topacct ++ "\n" ++ concatMap showAccountNameTree (branches t)
|
||||||
showAccountNameTrees :: [Tree AccountName] -> String
|
|
||||||
showAccountNameTrees ats =
|
|
||||||
concatMap showAccountNameBranch ats
|
|
||||||
where
|
where
|
||||||
showAccountNameBranch at = topacct ++ "\n" ++ subaccts
|
topacct = indentAccountName 0 $ antacctname t
|
||||||
where
|
|
||||||
topacct = indentAccountName $ antacctname at
|
|
||||||
subaccts = showAccountNameTrees $ branches at
|
|
||||||
|
|
||||||
|
|||||||
@ -15,9 +15,9 @@ data Ledger = Ledger {
|
|||||||
|
|
||||||
instance Show Ledger where
|
instance Show Ledger where
|
||||||
show l = printf "Ledger with %d normal, %d modifier, %d periodic entries"
|
show l = printf "Ledger with %d normal, %d modifier, %d periodic entries"
|
||||||
(show $ length $ modifier_entries l)
|
(length $ modifier_entries l)
|
||||||
(show $ length $ periodic_entries l)
|
(length $ periodic_entries l)
|
||||||
(show $ length $ entries l)
|
(length $ entries l)
|
||||||
|
|
||||||
ledgerTransactions :: Ledger -> [EntryTransaction]
|
ledgerTransactions :: Ledger -> [EntryTransaction]
|
||||||
ledgerTransactions l = entryTransactionsFrom $ entries l
|
ledgerTransactions l = entryTransactionsFrom $ entries l
|
||||||
|
|||||||
2
TODO
2
TODO
@ -1,6 +1,4 @@
|
|||||||
basic features
|
basic features
|
||||||
balance
|
|
||||||
elide boring accounts
|
|
||||||
handle mixed amounts and currencies
|
handle mixed amounts and currencies
|
||||||
print
|
print
|
||||||
entry
|
entry
|
||||||
|
|||||||
@ -4,7 +4,7 @@ hledger - ledger-compatible money management utilities (& haskell study)
|
|||||||
GPLv3, (c) Simon Michael & contributors,
|
GPLv3, (c) Simon Michael & contributors,
|
||||||
John Wiegley's ledger is at http://newartisans.com/ledger.html
|
John Wiegley's ledger is at http://newartisans.com/ledger.html
|
||||||
|
|
||||||
The model/type/class hierarchy is roughly like this:
|
modules/models are organized roughly like this:
|
||||||
|
|
||||||
hledger
|
hledger
|
||||||
Options
|
Options
|
||||||
@ -95,7 +95,7 @@ printBalance opts args ledger = do
|
|||||||
-- False -> depthOption opts
|
-- False -> depthOption opts
|
||||||
putStr $ case showsubs of
|
putStr $ case showsubs of
|
||||||
True -> showLedgerAccounts ledger 999
|
True -> showLedgerAccounts ledger 999
|
||||||
False -> showLedgerAccounts ledger (getDepth opts)
|
False -> showLedgerAccounts ledger 1
|
||||||
where
|
where
|
||||||
showsubs = (ShowSubs `elem` opts)
|
showsubs = (ShowSubs `elem` opts)
|
||||||
(acctpats,_) = ledgerPatternArgs args
|
(acctpats,_) = ledgerPatternArgs args
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user