speed, cleanup
This commit is contained in:
parent
b06fe57c00
commit
d760acc85e
160
Account.hs
160
Account.hs
@ -17,163 +17,3 @@ instance Show Account where
|
|||||||
|
|
||||||
nullacct = Account "" [] nullamt
|
nullacct = Account "" [] nullamt
|
||||||
|
|
||||||
-- XXX SLOW
|
|
||||||
rawLedgerAccount :: RawLedger -> AccountName -> Account
|
|
||||||
rawLedgerAccount l a =
|
|
||||||
Account
|
|
||||||
a
|
|
||||||
(transactionsInAccountNamed l a)
|
|
||||||
(aggregateBalanceInAccountNamed l a)
|
|
||||||
|
|
||||||
-- queries
|
|
||||||
|
|
||||||
balanceInAccountNamed :: RawLedger -> AccountName -> Amount
|
|
||||||
balanceInAccountNamed l a =
|
|
||||||
sumEntryTransactions (transactionsInAccountNamed l a)
|
|
||||||
|
|
||||||
aggregateBalanceInAccountNamed :: RawLedger -> AccountName -> Amount
|
|
||||||
aggregateBalanceInAccountNamed l a =
|
|
||||||
sumEntryTransactions (aggregateTransactionsInAccountNamed l a)
|
|
||||||
|
|
||||||
transactionsInAccountNamed :: RawLedger -> AccountName -> [EntryTransaction]
|
|
||||||
transactionsInAccountNamed l a =
|
|
||||||
rawLedgerTransactionsMatching (["^" ++ a ++ "$"], []) l
|
|
||||||
|
|
||||||
aggregateTransactionsInAccountNamed :: RawLedger -> AccountName -> [EntryTransaction]
|
|
||||||
aggregateTransactionsInAccountNamed l a =
|
|
||||||
rawLedgerTransactionsMatching (["^" ++ a ++ "(:.+)?$"], []) l
|
|
||||||
|
|
||||||
-- build a tree of Accounts
|
|
||||||
addDataToAccountNameTree :: RawLedger -> Tree AccountName -> Tree Account
|
|
||||||
addDataToAccountNameTree l ant =
|
|
||||||
Node
|
|
||||||
(rawLedgerAccount l $ root ant)
|
|
||||||
(map (addDataToAccountNameTree l) $ branches ant)
|
|
||||||
|
|
||||||
-- balance report support
|
|
||||||
--
|
|
||||||
-- examples, ignoring the issue of eliding boring accounts:
|
|
||||||
-- here is a sample account tree:
|
|
||||||
--
|
|
||||||
-- assets
|
|
||||||
-- cash
|
|
||||||
-- checking
|
|
||||||
-- saving
|
|
||||||
-- equity
|
|
||||||
-- expenses
|
|
||||||
-- food
|
|
||||||
-- shelter
|
|
||||||
-- income
|
|
||||||
-- salary
|
|
||||||
-- liabilities
|
|
||||||
-- debts
|
|
||||||
--
|
|
||||||
-- standard balance command shows all top-level accounts:
|
|
||||||
--
|
|
||||||
-- > ledger bal
|
|
||||||
-- $ assets
|
|
||||||
-- $ equity
|
|
||||||
-- $ expenses
|
|
||||||
-- $ income
|
|
||||||
-- $ liabilities
|
|
||||||
--
|
|
||||||
-- with an account pattern, show only the ones with matching names:
|
|
||||||
--
|
|
||||||
-- > ledger bal asset
|
|
||||||
-- $ assets
|
|
||||||
--
|
|
||||||
-- with -s, show all subaccounts of matched accounts:
|
|
||||||
--
|
|
||||||
-- > ledger -s bal asset
|
|
||||||
-- $ assets
|
|
||||||
-- $ cash
|
|
||||||
-- $ checking
|
|
||||||
-- $ saving
|
|
||||||
|
|
||||||
showRawLedgerAccounts :: RawLedger -> [String] -> Bool -> Int -> String
|
|
||||||
showRawLedgerAccounts l acctpats showsubs maxdepth =
|
|
||||||
concatMap
|
|
||||||
(showAccountTree l)
|
|
||||||
(branches (rawLedgerAccountTreeMatching l acctpats showsubs maxdepth))
|
|
||||||
|
|
||||||
rawLedgerAccountTreeMatching :: RawLedger -> [String] -> Bool -> Int -> Tree Account
|
|
||||||
rawLedgerAccountTreeMatching l [] showsubs maxdepth =
|
|
||||||
rawLedgerAccountTreeMatching l [".*"] showsubs maxdepth
|
|
||||||
rawLedgerAccountTreeMatching l acctpats showsubs maxdepth =
|
|
||||||
addDataToAccountNameTree l $
|
|
||||||
filterAccountNameTree acctpats showsubs maxdepth $
|
|
||||||
rawLedgerAccountNameTree l
|
|
||||||
|
|
||||||
-- when displaying an account tree, we elide boring accounts.
|
|
||||||
-- 1. leaf accounts and branches with 0 balance or 0 transactions are omitted
|
|
||||||
-- 2. inner accounts with 0 transactions and 1 subaccount are displayed as
|
|
||||||
-- a prefix of the sub
|
|
||||||
--
|
|
||||||
-- example:
|
|
||||||
--
|
|
||||||
-- a (0 txns)
|
|
||||||
-- b (0 txns)
|
|
||||||
-- c
|
|
||||||
-- d
|
|
||||||
-- e (0 txns)
|
|
||||||
-- f
|
|
||||||
-- g
|
|
||||||
-- h (0 txns)
|
|
||||||
-- i (0 balance)
|
|
||||||
--
|
|
||||||
-- displays as:
|
|
||||||
--
|
|
||||||
-- a:b:c
|
|
||||||
-- d
|
|
||||||
-- e
|
|
||||||
-- f
|
|
||||||
-- g
|
|
||||||
showAccountTree :: RawLedger -> Tree Account -> String
|
|
||||||
showAccountTree l = showAccountTree' l 0 . interestingAccountsFrom
|
|
||||||
|
|
||||||
showAccountTree' :: RawLedger -> Int -> Tree Account -> String
|
|
||||||
showAccountTree' l indentlevel t
|
|
||||||
-- if this acct is boring, don't show it
|
|
||||||
| isBoringInnerAccount l acct = subacctsindented 0
|
|
||||||
-- otherwise show normal indented account name with balance,
|
|
||||||
-- prefixing the names of any boring parents
|
|
||||||
| otherwise =
|
|
||||||
bal ++ " " ++ indent ++ prefix ++ leafname ++ "\n" ++ (subacctsindented 1)
|
|
||||||
where
|
|
||||||
acct = root t
|
|
||||||
subacctsindented i = concatMap (showAccountTree' l (indentlevel+i)) $ branches t
|
|
||||||
bal = printf "%20s" $ show $ abalance $ acct
|
|
||||||
indent = replicate (indentlevel * 2) ' '
|
|
||||||
prefix = concatMap (++ ":") $ map accountLeafName boringparents
|
|
||||||
boringparents = takeWhile (isBoringInnerAccountName l) $ parentAccountNames $ aname acct
|
|
||||||
leafname = accountLeafName $ aname acct
|
|
||||||
|
|
||||||
isBoringInnerAccount :: RawLedger -> Account -> Bool
|
|
||||||
isBoringInnerAccount l a
|
|
||||||
| name == "top" = False
|
|
||||||
| (length txns == 0) && ((length subs) == 1) = True
|
|
||||||
| otherwise = False
|
|
||||||
where
|
|
||||||
name = aname a
|
|
||||||
txns = atransactions a
|
|
||||||
subs = subAccountNamesFrom (rawLedgerAccountNames l) name
|
|
||||||
|
|
||||||
-- darnit, still need this
|
|
||||||
isBoringInnerAccountName :: RawLedger -> AccountName -> Bool
|
|
||||||
isBoringInnerAccountName l name
|
|
||||||
| name == "top" = False
|
|
||||||
| (length txns == 0) && ((length subs) == 1) = True
|
|
||||||
| otherwise = False
|
|
||||||
where
|
|
||||||
txns = transactionsInAccountNamed l name
|
|
||||||
subs = subAccountNamesFrom (rawLedgerAccountNames l) name
|
|
||||||
|
|
||||||
interestingAccountsFrom :: Tree Account -> Tree Account
|
|
||||||
interestingAccountsFrom =
|
|
||||||
treefilter hastxns . treefilter hasbalance
|
|
||||||
where
|
|
||||||
hasbalance = (/= 0) . abalance
|
|
||||||
hastxns = (> 0) . length . atransactions
|
|
||||||
|
|
||||||
rawLedgerAccountTree :: RawLedger -> Tree Account
|
|
||||||
rawLedgerAccountTree l = addDataToAccountNameTree l (rawLedgerAccountNameTree l)
|
|
||||||
|
|||||||
@ -3,17 +3,20 @@ where
|
|||||||
import Utils
|
import Utils
|
||||||
import Types
|
import Types
|
||||||
|
|
||||||
|
sepchar = ':'
|
||||||
|
|
||||||
accountNameComponents :: AccountName -> [String]
|
accountNameComponents :: AccountName -> [String]
|
||||||
accountNameComponents = splitAtElement ':'
|
accountNameComponents = splitAtElement sepchar
|
||||||
|
|
||||||
accountNameFromComponents :: [String] -> AccountName
|
accountNameFromComponents :: [String] -> AccountName
|
||||||
accountNameFromComponents = concat . intersperse ":"
|
accountNameFromComponents = concat . intersperse [sepchar]
|
||||||
|
|
||||||
accountLeafName :: AccountName -> String
|
accountLeafName :: AccountName -> String
|
||||||
accountLeafName = last . accountNameComponents
|
accountLeafName = last . accountNameComponents
|
||||||
|
|
||||||
accountNameLevel :: AccountName -> Int
|
accountNameLevel :: AccountName -> Int
|
||||||
accountNameLevel = length . accountNameComponents
|
accountNameLevel "" = 0
|
||||||
|
accountNameLevel a = (length $ filter (==sepchar) a) + 1
|
||||||
|
|
||||||
-- ["a:b:c","d:e"] -> ["a","a:b","a:b:c","d","d:e"]
|
-- ["a:b:c","d:e"] -> ["a","a:b","a:b:c","d","d:e"]
|
||||||
expandAccountNames :: [AccountName] -> [AccountName]
|
expandAccountNames :: [AccountName] -> [AccountName]
|
||||||
@ -33,17 +36,19 @@ parentAccountNames a = parentAccountNames' $ parentAccountName a
|
|||||||
parentAccountNames' "" = []
|
parentAccountNames' "" = []
|
||||||
parentAccountNames' a = [a] ++ (parentAccountNames' $ parentAccountName a)
|
parentAccountNames' a = [a] ++ (parentAccountNames' $ parentAccountName a)
|
||||||
|
|
||||||
p `isAccountNamePrefixOf` s = ((p ++ ":") `isPrefixOf` s)
|
isAccountNamePrefixOf :: AccountName -> AccountName -> Bool
|
||||||
|
p `isAccountNamePrefixOf` s = ((p ++ [sepchar]) `isPrefixOf` s)
|
||||||
|
|
||||||
|
isSubAccountNameOf :: AccountName -> AccountName -> Bool
|
||||||
s `isSubAccountNameOf` p =
|
s `isSubAccountNameOf` p =
|
||||||
(p `isAccountNamePrefixOf` s) && (accountNameLevel s == (accountNameLevel p + 1))
|
(p `isAccountNamePrefixOf` s) && (accountNameLevel s == (accountNameLevel p + 1))
|
||||||
|
|
||||||
subAccountNamesFrom :: [AccountName] -> AccountName -> [AccountName]
|
subAccountNamesFrom :: [AccountName] -> AccountName -> [AccountName]
|
||||||
subAccountNamesFrom accts a = filter (`isSubAccountNameOf` a) accts
|
subAccountNamesFrom accts a = filter (`isSubAccountNameOf` a) accts
|
||||||
|
|
||||||
matchAccountName :: String -> AccountName -> Bool
|
matchAccountName :: Regex -> AccountName -> Bool
|
||||||
matchAccountName s a =
|
matchAccountName r a =
|
||||||
case matchRegex (mkRegex s) a of
|
case matchRegex r a of
|
||||||
Nothing -> False
|
Nothing -> False
|
||||||
otherwise -> True
|
otherwise -> True
|
||||||
|
|
||||||
@ -76,10 +81,10 @@ accountNameTreeFrom accts =
|
|||||||
|
|
||||||
filterAccountNameTree :: [String] -> Bool -> Int -> Tree AccountName -> Tree AccountName
|
filterAccountNameTree :: [String] -> Bool -> Int -> Tree AccountName -> Tree AccountName
|
||||||
filterAccountNameTree pats keepsubs maxdepth =
|
filterAccountNameTree pats keepsubs maxdepth =
|
||||||
treefilter (\a -> matchpats a || (keepsubs && issubofmatch a)) .
|
treefilter (\a -> matchany a || (keepsubs && issubofmatch a)) . treeprune maxdepth
|
||||||
treeprune maxdepth
|
|
||||||
where
|
where
|
||||||
matchpats a = any (match a) pats
|
regexes = map mkRegex pats
|
||||||
match a pat = matchAccountName pat $ accountLeafName a
|
matchany a = any (match a) regexes
|
||||||
issubofmatch a = any matchpats $ parentAccountNames a
|
match a r = matchAccountName r $ accountLeafName a
|
||||||
|
issubofmatch a = any matchany $ parentAccountNames a
|
||||||
|
|
||||||
|
|||||||
@ -32,15 +32,15 @@ sumEntryTransactions :: [EntryTransaction] -> Amount
|
|||||||
sumEntryTransactions ets =
|
sumEntryTransactions ets =
|
||||||
sumTransactions $ map transaction ets
|
sumTransactions $ map transaction ets
|
||||||
|
|
||||||
matchTransactionAccount :: String -> EntryTransaction -> Bool
|
matchTransactionAccount :: Regex -> EntryTransaction -> Bool
|
||||||
matchTransactionAccount s t =
|
matchTransactionAccount r t =
|
||||||
case matchRegex (mkRegex s) (account t) of
|
case matchRegex r (account t) of
|
||||||
Nothing -> False
|
Nothing -> False
|
||||||
otherwise -> True
|
otherwise -> True
|
||||||
|
|
||||||
matchTransactionDescription :: String -> EntryTransaction -> Bool
|
matchTransactionDescription :: Regex -> EntryTransaction -> Bool
|
||||||
matchTransactionDescription s t =
|
matchTransactionDescription r t =
|
||||||
case matchRegex (mkRegex s) (description t) of
|
case matchRegex r (description t) of
|
||||||
Nothing -> False
|
Nothing -> False
|
||||||
otherwise -> True
|
otherwise -> True
|
||||||
|
|
||||||
@ -69,15 +69,6 @@ showTransactionAndBalance t b =
|
|||||||
showBalance :: Amount -> String
|
showBalance :: Amount -> String
|
||||||
showBalance b = printf " %12s" (showAmountRoundedOrZero b)
|
showBalance b = printf " %12s" (showAmountRoundedOrZero b)
|
||||||
|
|
||||||
transactionsMatching :: ([String],[String]) -> [EntryTransaction] -> [EntryTransaction]
|
|
||||||
transactionsMatching ([],[]) ts = transactionsMatching ([".*"],[".*"]) ts
|
|
||||||
transactionsMatching (rs,[]) ts = transactionsMatching (rs,[".*"]) ts
|
|
||||||
transactionsMatching ([],rs) ts = transactionsMatching ([".*"],rs) ts
|
|
||||||
transactionsMatching (acctregexps,descregexps) ts =
|
|
||||||
intersect
|
|
||||||
(concat [filter (matchTransactionAccount r) ts | r <- acctregexps])
|
|
||||||
(concat [filter (matchTransactionDescription r) ts | r <- descregexps])
|
|
||||||
|
|
||||||
transactionsWithAccountName :: AccountName -> [EntryTransaction] -> [EntryTransaction]
|
transactionsWithAccountName :: AccountName -> [EntryTransaction] -> [EntryTransaction]
|
||||||
transactionsWithAccountName a ts = [t | t <- ts, account t == a]
|
transactionsWithAccountName a ts = [t | t <- ts, account t == a]
|
||||||
|
|
||||||
|
|||||||
150
Ledger.hs
150
Ledger.hs
@ -34,44 +34,129 @@ cacheLedger l =
|
|||||||
in
|
in
|
||||||
Ledger l ant amap
|
Ledger l ant amap
|
||||||
|
|
||||||
|
accountnames :: Ledger -> [AccountName]
|
||||||
|
accountnames l = flatten $ accountnametree l
|
||||||
|
|
||||||
ledgerAccount :: Ledger -> AccountName -> Account
|
ledgerAccount :: Ledger -> AccountName -> Account
|
||||||
-- wtf ledgerAccount l = ((accounts l) (!))
|
ledgerAccount l a = (accounts l) ! a
|
||||||
ledgerAccount l aname = head [a | (n,a) <- Map.toList $ accounts l, n == aname]
|
|
||||||
|
|
||||||
ledgerTransactions :: Ledger -> [EntryTransaction]
|
ledgerTransactions :: Ledger -> [EntryTransaction]
|
||||||
ledgerTransactions l = concatMap atransactions $ Map.elems $ accounts l
|
ledgerTransactions l = concatMap atransactions $ Map.elems $ accounts l
|
||||||
|
|
||||||
ledgerTransactionsMatching :: ([String],[String]) -> Ledger -> [EntryTransaction]
|
ledgerTransactionsMatching :: ([String],[String]) -> Ledger -> [EntryTransaction]
|
||||||
ledgerTransactionsMatching pats l = rawLedgerTransactionsMatching pats $ rawledger l
|
ledgerTransactionsMatching ([],[]) l = ledgerTransactionsMatching ([".*"],[".*"]) l
|
||||||
|
ledgerTransactionsMatching (rs,[]) l = ledgerTransactionsMatching (rs,[".*"]) l
|
||||||
|
ledgerTransactionsMatching ([],rs) l = ledgerTransactionsMatching ([".*"],rs) l
|
||||||
|
ledgerTransactionsMatching (acctpats,descpats) l =
|
||||||
|
intersect
|
||||||
|
(concat [filter (matchTransactionAccount r) ts | r <- acctregexps])
|
||||||
|
(concat [filter (matchTransactionDescription r) ts | r <- descregexps])
|
||||||
|
where
|
||||||
|
ts = ledgerTransactions l
|
||||||
|
acctregexps = map mkRegex acctpats
|
||||||
|
descregexps = map mkRegex descpats
|
||||||
|
|
||||||
|
ledgerAccountTreeMatching :: Ledger -> [String] -> Bool -> Int -> Tree Account
|
||||||
|
ledgerAccountTreeMatching l [] showsubs maxdepth =
|
||||||
|
ledgerAccountTreeMatching l [".*"] showsubs maxdepth
|
||||||
|
ledgerAccountTreeMatching l acctpats showsubs maxdepth =
|
||||||
|
addDataToAccountNameTree l $
|
||||||
|
filterAccountNameTree acctpats showsubs maxdepth $
|
||||||
|
accountnametree l
|
||||||
|
|
||||||
|
addDataToAccountNameTree :: Ledger -> Tree AccountName -> Tree Account
|
||||||
|
addDataToAccountNameTree = treemap . ledgerAccount
|
||||||
|
|
||||||
|
-- balance report support
|
||||||
|
--
|
||||||
|
-- examples: here is a sample account tree:
|
||||||
|
--
|
||||||
|
-- assets
|
||||||
|
-- cash
|
||||||
|
-- checking
|
||||||
|
-- saving
|
||||||
|
-- equity
|
||||||
|
-- expenses
|
||||||
|
-- food
|
||||||
|
-- shelter
|
||||||
|
-- income
|
||||||
|
-- salary
|
||||||
|
-- liabilities
|
||||||
|
-- debts
|
||||||
|
--
|
||||||
|
-- standard balance command shows all top-level accounts:
|
||||||
|
--
|
||||||
|
-- > ledger bal
|
||||||
|
-- $ assets
|
||||||
|
-- $ equity
|
||||||
|
-- $ expenses
|
||||||
|
-- $ income
|
||||||
|
-- $ liabilities
|
||||||
|
--
|
||||||
|
-- with an account pattern, show only the ones with matching names:
|
||||||
|
--
|
||||||
|
-- > ledger bal asset
|
||||||
|
-- $ assets
|
||||||
|
--
|
||||||
|
-- with -s, show all subaccounts of matched accounts:
|
||||||
|
--
|
||||||
|
-- > ledger -s bal asset
|
||||||
|
-- $ assets
|
||||||
|
-- $ cash
|
||||||
|
-- $ checking
|
||||||
|
-- $ saving
|
||||||
|
--
|
||||||
|
-- we elide boring accounts in two ways:
|
||||||
|
-- - leaf accounts and branches with 0 balance or 0 transactions are omitted
|
||||||
|
-- - inner accounts with 0 transactions and 1 subaccount are displayed inline
|
||||||
|
-- so this:
|
||||||
|
--
|
||||||
|
-- a (0 txns)
|
||||||
|
-- b (0 txns)
|
||||||
|
-- c
|
||||||
|
-- d
|
||||||
|
-- e (0 txns)
|
||||||
|
-- f
|
||||||
|
-- g
|
||||||
|
-- h (0 txns)
|
||||||
|
-- i (0 balance)
|
||||||
|
--
|
||||||
|
-- is displayed like:
|
||||||
|
--
|
||||||
|
-- a:b:c
|
||||||
|
-- d
|
||||||
|
-- e
|
||||||
|
-- f
|
||||||
|
-- g
|
||||||
|
|
||||||
showLedgerAccounts :: Ledger -> [String] -> Bool -> Int -> String
|
showLedgerAccounts :: Ledger -> [String] -> Bool -> Int -> String
|
||||||
showLedgerAccounts l acctpats showsubs maxdepth =
|
showLedgerAccounts l acctpats showsubs maxdepth =
|
||||||
concatMap
|
concatMap
|
||||||
(showAccountTree2 l)
|
(showAccountTree l)
|
||||||
(branches (ledgerAccountTreeMatching l acctpats showsubs maxdepth))
|
(branches (ledgerAccountTreeMatching l acctpats showsubs maxdepth))
|
||||||
|
|
||||||
showAccountTree2 :: Ledger -> Tree Account -> String
|
showAccountTree :: Ledger -> Tree Account -> String
|
||||||
showAccountTree2 l = showAccountTree'2 l 0 . interestingAccountsFrom
|
showAccountTree l = showAccountTree' l 0 . interestingAccountsFrom
|
||||||
|
|
||||||
showAccountTree'2 :: Ledger -> Int -> Tree Account -> String
|
showAccountTree' :: Ledger -> Int -> Tree Account -> String
|
||||||
showAccountTree'2 l indentlevel t
|
showAccountTree' l indentlevel t
|
||||||
-- if this acct is boring, don't show it
|
-- if this acct is boring, don't show it
|
||||||
| isBoringInnerAccount2 l acct = subacctsindented 0
|
| isBoringAccount l acct = subacctsindented 0
|
||||||
-- otherwise show normal indented account name with balance,
|
-- otherwise show normal indented account name with balance,
|
||||||
-- prefixing the names of any boring parents
|
-- prefixing the names of any boring parents
|
||||||
| otherwise =
|
| otherwise =
|
||||||
bal ++ " " ++ indent ++ prefix ++ leafname ++ "\n" ++ (subacctsindented 1)
|
bal ++ " " ++ indent ++ prefix ++ leafname ++ "\n" ++ (subacctsindented 1)
|
||||||
where
|
where
|
||||||
acct = root t
|
acct = root t
|
||||||
subacctsindented i = concatMap (showAccountTree'2 l (indentlevel+i)) $ branches t
|
subacctsindented i = concatMap (showAccountTree' l (indentlevel+i)) $ branches t
|
||||||
bal = printf "%20s" $ show $ abalance $ acct
|
bal = printf "%20s" $ show $ abalance $ acct
|
||||||
indent = replicate (indentlevel * 2) ' '
|
indent = replicate (indentlevel * 2) ' '
|
||||||
prefix = concatMap (++ ":") $ map accountLeafName boringparents
|
prefix = concatMap (++ ":") $ map accountLeafName boringparents
|
||||||
boringparents = takeWhile (isBoringInnerAccountName2 l) $ parentAccountNames $ aname acct
|
boringparents = takeWhile (isBoringAccountName l) $ parentAccountNames $ aname acct
|
||||||
leafname = accountLeafName $ aname acct
|
leafname = accountLeafName $ aname acct
|
||||||
|
|
||||||
isBoringInnerAccount2 :: Ledger -> Account -> Bool
|
isBoringAccount :: Ledger -> Account -> Bool
|
||||||
isBoringInnerAccount2 l a
|
isBoringAccount l a
|
||||||
| name == "top" = False
|
| name == "top" = False
|
||||||
| (length txns == 0) && ((length subs) == 1) = True
|
| (length txns == 0) && ((length subs) == 1) = True
|
||||||
| otherwise = False
|
| otherwise = False
|
||||||
@ -80,37 +165,12 @@ isBoringInnerAccount2 l a
|
|||||||
txns = atransactions a
|
txns = atransactions a
|
||||||
subs = subAccountNamesFrom (accountnames l) name
|
subs = subAccountNamesFrom (accountnames l) name
|
||||||
|
|
||||||
accountnames :: Ledger -> [AccountName]
|
isBoringAccountName :: Ledger -> AccountName -> Bool
|
||||||
accountnames l = flatten $ accountnametree l
|
isBoringAccountName l = isBoringAccount l . ledgerAccount l
|
||||||
|
|
||||||
isBoringInnerAccountName2 :: Ledger -> AccountName -> Bool
|
interestingAccountsFrom :: Tree Account -> Tree Account
|
||||||
isBoringInnerAccountName2 l name
|
interestingAccountsFrom =
|
||||||
| name == "top" = False
|
treefilter hastxns . treefilter hasbalance
|
||||||
| (length txns == 0) && ((length subs) == 1) = True
|
|
||||||
| otherwise = False
|
|
||||||
where
|
where
|
||||||
txns = atransactions $ ledgerAccount l name
|
hasbalance = (/= 0) . abalance
|
||||||
subs = subAccountNamesFrom (accountnames l) name
|
hastxns = (> 0) . length . atransactions
|
||||||
|
|
||||||
transactionsInAccountNamed2 :: Ledger -> AccountName -> [EntryTransaction]
|
|
||||||
transactionsInAccountNamed2 l a = atransactions $ ledgerAccount l a
|
|
||||||
|
|
||||||
----
|
|
||||||
|
|
||||||
ledgerAccountTreeMatching :: Ledger -> [String] -> Bool -> Int -> Tree Account
|
|
||||||
ledgerAccountTreeMatching l [] showsubs maxdepth =
|
|
||||||
ledgerAccountTreeMatching l [".*"] showsubs maxdepth
|
|
||||||
ledgerAccountTreeMatching l acctpats showsubs maxdepth =
|
|
||||||
addDataToAccountNameTree2 l $
|
|
||||||
filterAccountNameTree acctpats showsubs maxdepth $
|
|
||||||
accountnametree l
|
|
||||||
|
|
||||||
addDataToAccountNameTree2 :: Ledger -> Tree AccountName -> Tree Account
|
|
||||||
addDataToAccountNameTree2 l ant =
|
|
||||||
Node
|
|
||||||
(ledgerAccount l $ root ant)
|
|
||||||
(map (addDataToAccountNameTree2 l) $ branches ant)
|
|
||||||
|
|
||||||
-- ledgerAccountNames :: Ledger -> [AccountName]
|
|
||||||
-- ledgerAccountNames = sort . expandAccountNames . rawLedgerAccountNamesUsed
|
|
||||||
|
|
||||||
|
|||||||
22
RawLedger.hs
22
RawLedger.hs
@ -18,34 +18,12 @@ instance Show RawLedger where
|
|||||||
rawLedgerTransactions :: RawLedger -> [EntryTransaction]
|
rawLedgerTransactions :: RawLedger -> [EntryTransaction]
|
||||||
rawLedgerTransactions l = entryTransactionsFrom $ entries l
|
rawLedgerTransactions l = entryTransactionsFrom $ entries l
|
||||||
|
|
||||||
rawLedgerTransactionsMatching :: ([String],[String]) -> RawLedger -> [EntryTransaction]
|
|
||||||
rawLedgerTransactionsMatching ([],[]) l = rawLedgerTransactionsMatching ([".*"],[".*"]) l
|
|
||||||
rawLedgerTransactionsMatching (rs,[]) l = rawLedgerTransactionsMatching (rs,[".*"]) l
|
|
||||||
rawLedgerTransactionsMatching ([],rs) l = rawLedgerTransactionsMatching ([".*"],rs) l
|
|
||||||
rawLedgerTransactionsMatching (acctregexps,descregexps) l =
|
|
||||||
intersect
|
|
||||||
(concat [filter (matchTransactionAccount r) ts | r <- acctregexps])
|
|
||||||
(concat [filter (matchTransactionDescription r) ts | r <- descregexps])
|
|
||||||
where ts = rawLedgerTransactions l
|
|
||||||
|
|
||||||
rawLedgerAccountTransactions :: RawLedger -> AccountName -> [EntryTransaction]
|
|
||||||
rawLedgerAccountTransactions l a = rawLedgerTransactionsMatching (["^" ++ a ++ "$"], []) l
|
|
||||||
|
|
||||||
rawLedgerAccountNamesUsed :: RawLedger -> [AccountName]
|
rawLedgerAccountNamesUsed :: RawLedger -> [AccountName]
|
||||||
rawLedgerAccountNamesUsed l = accountNamesFromTransactions $ entryTransactionsFrom $ entries l
|
rawLedgerAccountNamesUsed l = accountNamesFromTransactions $ entryTransactionsFrom $ entries l
|
||||||
|
|
||||||
rawLedgerAccountNames :: RawLedger -> [AccountName]
|
rawLedgerAccountNames :: RawLedger -> [AccountName]
|
||||||
rawLedgerAccountNames = sort . expandAccountNames . rawLedgerAccountNamesUsed
|
rawLedgerAccountNames = sort . expandAccountNames . rawLedgerAccountNamesUsed
|
||||||
|
|
||||||
rawLedgerTopAccountNames :: RawLedger -> [AccountName]
|
|
||||||
rawLedgerTopAccountNames l = filter (notElem ':') (rawLedgerAccountNames l)
|
|
||||||
|
|
||||||
rawLedgerAccountNamesMatching :: [String] -> RawLedger -> [AccountName]
|
|
||||||
rawLedgerAccountNamesMatching [] l = rawLedgerAccountNamesMatching [".*"] l
|
|
||||||
rawLedgerAccountNamesMatching acctregexps l =
|
|
||||||
concat [filter (matchAccountName r) accountNames | r <- acctregexps]
|
|
||||||
where accountNames = rawLedgerTopAccountNames l
|
|
||||||
|
|
||||||
rawLedgerAccountNameTree :: RawLedger -> Tree AccountName
|
rawLedgerAccountNameTree :: RawLedger -> Tree AccountName
|
||||||
rawLedgerAccountNameTree l = accountNameTreeFrom $ rawLedgerAccountNames l
|
rawLedgerAccountNameTree l = accountNameTreeFrom $ rawLedgerAccountNames l
|
||||||
|
|
||||||
|
|||||||
2
Tests.hs
2
Tests.hs
@ -291,7 +291,7 @@ test_ledgerAccountNames =
|
|||||||
(rawLedgerAccountNames ledger7)
|
(rawLedgerAccountNames ledger7)
|
||||||
|
|
||||||
test_cacheLedger =
|
test_cacheLedger =
|
||||||
assertEqual' 14 (length $ Map.keys $ accounts $ cacheLedger ledger7)
|
assertEqual' 15 (length $ Map.keys $ accounts $ cacheLedger ledger7)
|
||||||
|
|
||||||
|
|
||||||
-- quickcheck properties
|
-- quickcheck properties
|
||||||
|
|||||||
@ -29,5 +29,5 @@ autofillTransactions ts =
|
|||||||
otherwise -> error "too many blank transactions in this entry"
|
otherwise -> error "too many blank transactions in this entry"
|
||||||
|
|
||||||
sumTransactions :: [Transaction] -> Amount
|
sumTransactions :: [Transaction] -> Amount
|
||||||
sumTransactions ts = sum [tamount t | t <- ts]
|
sumTransactions = sum . map tamount
|
||||||
|
|
||||||
|
|||||||
@ -71,11 +71,3 @@ doWithParsed :: (Ledger -> IO ()) -> (Either ParseError RawLedger) -> IO ()
|
|||||||
doWithParsed cmd parsed = do
|
doWithParsed cmd parsed = do
|
||||||
case parsed of Left e -> parseError e
|
case parsed of Left e -> parseError e
|
||||||
Right l -> cmd $ cacheLedger l
|
Right l -> cmd $ cacheLedger l
|
||||||
|
|
||||||
-- interactive testing:
|
|
||||||
--
|
|
||||||
-- p <- ledgerFilePath [] >>= parseLedgerFile
|
|
||||||
-- let l = either (\_ -> RawLedger [] [] []) id p
|
|
||||||
-- let ant = rawLedgerAccountNameTree l
|
|
||||||
-- let at = rawLedgerAccountTreeMatching l [] True 999
|
|
||||||
-- putStr $ drawTree $ treemap show $ rawLedgerAccountTreeMatching l ["a"] False 999
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user