refactor, fix balance report
This commit is contained in:
		
							parent
							
								
									ba40fbf733
								
							
						
					
					
						commit
						1322bcb4a0
					
				
							
								
								
									
										89
									
								
								Account.hs
									
									
									
									
									
								
							
							
						
						
									
										89
									
								
								Account.hs
									
									
									
									
									
								
							| @ -1,17 +1,11 @@ | |||||||
| 
 | 
 | ||||||
| module Account | module Account | ||||||
| where | where | ||||||
| 
 |  | ||||||
| import Debug.Trace |  | ||||||
| import Text.Printf |  | ||||||
| import Text.Regex |  | ||||||
| import Data.List |  | ||||||
| 
 |  | ||||||
| import Utils | import Utils | ||||||
|  | import BasicTypes | ||||||
| 
 | 
 | ||||||
| -- AccountNames are strings like "assets:cash:petty"; from these we build | -- AccountNames are strings like "assets:cash:petty"; from these we build | ||||||
| -- the chart of accounts, which should be a simple hierarchy. We could | -- the chart of accounts, which should be a simple hierarchy.  | ||||||
| -- almost get by with just these, but see below. |  | ||||||
| type AccountName = String | type AccountName = String | ||||||
| 
 | 
 | ||||||
| accountNameComponents :: AccountName -> [String] | accountNameComponents :: AccountName -> [String] | ||||||
| @ -53,50 +47,43 @@ matchAccountName s a = | |||||||
|       Nothing -> False |       Nothing -> False | ||||||
|       otherwise -> True |       otherwise -> True | ||||||
| 
 | 
 | ||||||
| -- We need structures smart enough to eg display the account tree with |  | ||||||
| -- boring accounts elided. |  | ||||||
| 
 |  | ||||||
| -- simple polymorphic tree. each node is a tuple of the node type and a |  | ||||||
| -- list of subtrees |  | ||||||
| newtype Tree a = Tree { unTree :: (a, [Tree a]) } deriving (Show,Eq) |  | ||||||
| 
 |  | ||||||
| -- an Account has a name and a list of sub-accounts - ie a tree of |  | ||||||
| -- AccountNames. |  | ||||||
| type Account = Tree AccountName |  | ||||||
| atacct = fst . unTree |  | ||||||
| atsubs = snd . unTree |  | ||||||
| nullacct = Tree ("", []) |  | ||||||
| 
 |  | ||||||
| accountFrom :: [AccountName] -> Account |  | ||||||
| accountFrom_props = |  | ||||||
|     [ |  | ||||||
|      accountFrom [] == nullacct, |  | ||||||
|      accountFrom ["a"] == Tree ("", [Tree ("a",[])]), |  | ||||||
|      accountFrom ["a","b"] == Tree ("", [Tree ("a", []), Tree ("b", [])]), |  | ||||||
|      accountFrom ["a","a:b"] == Tree ("", [Tree ("a", [Tree ("a:b", [])])]), |  | ||||||
|      accountFrom ["a:b"] == Tree ("", [Tree ("a", [Tree ("a:b", [])])]) |  | ||||||
|     ] |  | ||||||
| accountFrom accts =  |  | ||||||
|     Tree ("top", accountsFrom (topAccountNames accts)) |  | ||||||
|         where |  | ||||||
|           accountsFrom :: [AccountName] -> [Account] |  | ||||||
|           accountsFrom [] = [] |  | ||||||
|           accountsFrom as = [Tree (a, accountsFrom $ subs a) | a <- as] |  | ||||||
|           subs = (subAccountNamesFrom accts) |  | ||||||
| 
 |  | ||||||
| showAccount :: Account -> String |  | ||||||
| showAccount at = showAccounts $ atsubs at |  | ||||||
| 
 |  | ||||||
| showAccounts :: [Account] -> String |  | ||||||
| showAccounts ats = |  | ||||||
|     concatMap showAccountBranch ats |  | ||||||
|         where |  | ||||||
|           showAccountBranch at = topacct ++ "\n" ++ subs |  | ||||||
|               where |  | ||||||
|                 topacct = indentAccountName $ atacct at |  | ||||||
|                 subs = showAccounts $ atsubs at |  | ||||||
| 
 |  | ||||||
| indentAccountName :: AccountName -> String | indentAccountName :: AccountName -> String | ||||||
| indentAccountName a = replicate (((accountNameLevel a) - 1) * 2) ' ' ++ (accountLeafName a) | indentAccountName a = replicate (((accountNameLevel a) - 1) * 2) ' ' ++ (accountLeafName a) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | -- We could almost get by with just the above, but we need smarter | ||||||
|  | -- structures to eg display the account tree with boring accounts elided. | ||||||
|  | -- first, here is a tree of AccountNames; Account and Account tree are | ||||||
|  | -- defined later. | ||||||
|  | 
 | ||||||
|  | antacctname = fst . node | ||||||
|  | antsubs = snd . node | ||||||
|  | 
 | ||||||
|  | accountNameTreeFrom_props = | ||||||
|  |     [ | ||||||
|  |      accountNameTreeFrom ["a"] == Tree ("top", [Tree ("a",[])]), | ||||||
|  |      accountNameTreeFrom ["a","b"] == Tree ("top", [Tree ("a", []), Tree ("b", [])]), | ||||||
|  |      accountNameTreeFrom ["a","a:b"] == Tree ("top", [Tree ("a", [Tree ("a:b", [])])]), | ||||||
|  |      accountNameTreeFrom ["a:b"] == Tree ("top", [Tree ("a", [Tree ("a:b", [])])]) | ||||||
|  |     ] | ||||||
|  | accountNameTreeFrom :: [AccountName] -> Tree AccountName | ||||||
|  | accountNameTreeFrom accts =  | ||||||
|  |     Tree ("top", accountsFrom (topAccountNames accts)) | ||||||
|  |         where | ||||||
|  |           accountsFrom :: [AccountName] -> [Tree AccountName] | ||||||
|  |           accountsFrom [] = [] | ||||||
|  |           accountsFrom as = [Tree (a, accountsFrom $ subs a) | a <- as] | ||||||
|  |           subs = (subAccountNamesFrom accts) | ||||||
|  | 
 | ||||||
|  | showAccountNameTree :: Tree AccountName -> String | ||||||
|  | showAccountNameTree at = showAccountNameTrees $ antsubs at | ||||||
|  | 
 | ||||||
|  | showAccountNameTrees :: [Tree AccountName] -> String | ||||||
|  | showAccountNameTrees ats = | ||||||
|  |     concatMap showAccountNameBranch ats | ||||||
|  |         where | ||||||
|  |           showAccountNameBranch at = topacct ++ "\n" ++ subs | ||||||
|  |               where | ||||||
|  |                 topacct = indentAccountName $ antacctname at | ||||||
|  |                 subs = showAccountNameTrees $ antsubs at | ||||||
|  | 
 | ||||||
|  | |||||||
| @ -1,12 +1,6 @@ | |||||||
| 
 | 
 | ||||||
| module BasicTypes | module BasicTypes | ||||||
| where | where | ||||||
| 
 |  | ||||||
| import Debug.Trace |  | ||||||
| import Text.Printf |  | ||||||
| import Text.Regex |  | ||||||
| import Data.List |  | ||||||
| 
 |  | ||||||
| import Utils | import Utils | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -42,3 +36,8 @@ amountRoundedOrZero (Amount cur qty) = | |||||||
|       "-0.00"   -> "0" |       "-0.00"   -> "0" | ||||||
|       otherwise -> cur ++ rounded |       otherwise -> cur ++ rounded | ||||||
| 
 | 
 | ||||||
|  | -- generic tree. each node is a tuple of the node type and a | ||||||
|  | -- list of subtrees | ||||||
|  | newtype Tree a = Tree { node :: (a, [Tree a]) } deriving (Show,Eq) | ||||||
|  | branches = snd . node | ||||||
|  | 
 | ||||||
|  | |||||||
							
								
								
									
										6
									
								
								Entry.hs
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								Entry.hs
									
									
									
									
									
								
							| @ -1,12 +1,6 @@ | |||||||
| 
 | 
 | ||||||
| module Entry | module Entry | ||||||
| where | where | ||||||
| 
 |  | ||||||
| import Debug.Trace |  | ||||||
| import Text.Printf |  | ||||||
| import Text.Regex |  | ||||||
| import Data.List |  | ||||||
| 
 |  | ||||||
| import Utils | import Utils | ||||||
| import BasicTypes | import BasicTypes | ||||||
| import Transaction | import Transaction | ||||||
|  | |||||||
| @ -1,15 +1,8 @@ | |||||||
| 
 | 
 | ||||||
| module EntryTransaction | module EntryTransaction | ||||||
| where | where | ||||||
| 
 |  | ||||||
| import Debug.Trace |  | ||||||
| import Text.Printf |  | ||||||
| import Text.Regex |  | ||||||
| import Data.List |  | ||||||
| 
 |  | ||||||
| import Utils | import Utils | ||||||
| import BasicTypes | import BasicTypes | ||||||
| import Account |  | ||||||
| import Entry | import Entry | ||||||
| import Transaction | import Transaction | ||||||
| 
 | 
 | ||||||
| @ -40,9 +33,6 @@ sumEntryTransactions :: [EntryTransaction] -> Amount | |||||||
| sumEntryTransactions ets =  | sumEntryTransactions ets =  | ||||||
|     sumTransactions $ map transaction ets |     sumTransactions $ map transaction ets | ||||||
| 
 | 
 | ||||||
| accountNamesFromTransactions :: [EntryTransaction] -> [AccountName] |  | ||||||
| accountNamesFromTransactions ts = nub $ map account ts |  | ||||||
| 
 |  | ||||||
| matchTransactionAccount :: String -> EntryTransaction -> Bool | matchTransactionAccount :: String -> EntryTransaction -> Bool | ||||||
| matchTransactionAccount s t = | matchTransactionAccount s t = | ||||||
|     case matchRegex (mkRegex s) (account t) of |     case matchRegex (mkRegex s) (account t) of | ||||||
|  | |||||||
							
								
								
									
										24
									
								
								Ledger.hs
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								Ledger.hs
									
									
									
									
									
								
							| @ -1,13 +1,8 @@ | |||||||
| module Ledger | module Ledger | ||||||
| where | where | ||||||
| 
 |  | ||||||
| import Debug.Trace |  | ||||||
| import Text.Printf |  | ||||||
| import Text.Regex |  | ||||||
| import Data.List |  | ||||||
| 
 |  | ||||||
| import Utils | import Utils | ||||||
| import Account | import Account | ||||||
|  | import BasicTypes | ||||||
| import Entry | import Entry | ||||||
| import EntryTransaction | import EntryTransaction | ||||||
| 
 | 
 | ||||||
| @ -37,6 +32,9 @@ ledgerTransactionsMatching (acctregexps,descregexps) l = | |||||||
|     (concat [filter (matchTransactionDescription r) ts | r <- descregexps]) |     (concat [filter (matchTransactionDescription r) ts | r <- descregexps]) | ||||||
|     where ts = ledgerTransactions l |     where ts = ledgerTransactions l | ||||||
| 
 | 
 | ||||||
|  | accountNamesFromTransactions :: [EntryTransaction] -> [AccountName] | ||||||
|  | accountNamesFromTransactions ts = nub $ map account ts | ||||||
|  | 
 | ||||||
| ledgerAccountNamesUsed :: Ledger -> [AccountName] | ledgerAccountNamesUsed :: Ledger -> [AccountName] | ||||||
| ledgerAccountNamesUsed l = accountNamesFromTransactions $ entryTransactionsFrom $ entries l | ledgerAccountNamesUsed l = accountNamesFromTransactions $ entryTransactionsFrom $ entries l | ||||||
| 
 | 
 | ||||||
| @ -52,18 +50,8 @@ ledgerAccountNamesMatching acctregexps l = | |||||||
|     concat [filter (matchAccountName r) accountNames | r <- acctregexps] |     concat [filter (matchAccountName r) accountNames | r <- acctregexps] | ||||||
|         where accountNames = ledgerTopAccountNames l |         where accountNames = ledgerTopAccountNames l | ||||||
| 
 | 
 | ||||||
| ledgerAccounts :: Ledger -> Tree AccountName | ledgerAccountNameTree :: Ledger -> Tree AccountName | ||||||
| ledgerAccounts l = accountFrom $ ledgerAccountNames l | ledgerAccountNameTree l = accountNameTreeFrom $ ledgerAccountNames l | ||||||
| 
 | 
 | ||||||
| showLedgerAccounts :: Ledger -> [String] -> Int -> String |  | ||||||
| showLedgerAccounts l acctpats depth =  |  | ||||||
|     showAccountsWithBalances l accounts depth |  | ||||||
|         where |  | ||||||
|           accounts = ledgerAccountsMatching l acctpats |  | ||||||
| 
 | 
 | ||||||
| showAccountsWithBalances :: Ledger -> [Account] -> Int -> String |  | ||||||
| showAccountsWithBalances l accts depth = |  | ||||||
|     "" |  | ||||||
| 
 | 
 | ||||||
| ledgerAccountsMatching :: Ledger -> [String] -> [Account] |  | ||||||
| ledgerAccountsMatching l acctpats = [] |  | ||||||
|  | |||||||
							
								
								
									
										135
									
								
								Models.hs
									
									
									
									
									
								
							
							
						
						
									
										135
									
								
								Models.hs
									
									
									
									
									
								
							| @ -9,12 +9,6 @@ module Models ( | |||||||
|                module BasicTypes, |                module BasicTypes, | ||||||
|               ) |               ) | ||||||
| where | where | ||||||
| 
 |  | ||||||
| import Debug.Trace |  | ||||||
| import Text.Printf |  | ||||||
| import Text.Regex |  | ||||||
| import Data.List |  | ||||||
| 
 |  | ||||||
| import Utils | import Utils | ||||||
| import BasicTypes | import BasicTypes | ||||||
| import Account | import Account | ||||||
| @ -24,9 +18,30 @@ import EntryTransaction | |||||||
| import Ledger | import Ledger | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| -- any top-level stuff that mixed up the other types | -- top-level stuff that mixes types | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | -- an Account caches an account's name, balance and transactions for convenience | ||||||
|  | type Account = (AccountName,[EntryTransaction],Amount) | ||||||
|  | aname (a,_,_) = a | ||||||
|  | atxns (_,ts,_) = ts | ||||||
|  | abal (_,_,b) = b | ||||||
|  | 
 | ||||||
|  | mkAccount :: Ledger -> AccountName -> Account | ||||||
|  | mkAccount l a = (a, accountNameTransactionsNoSubs l a, accountNameBalance l a) | ||||||
|  | 
 | ||||||
|  | accountNameBalance :: Ledger -> AccountName -> Amount | ||||||
|  | accountNameBalance l a = sumEntryTransactions (accountNameTransactions l a) | ||||||
|  | 
 | ||||||
|  | accountNameTransactions :: Ledger -> AccountName -> [EntryTransaction] | ||||||
|  | accountNameTransactions l a = ledgerTransactionsMatching (["^" ++ a ++ "(:.+)?$"], []) l | ||||||
|  | 
 | ||||||
|  | accountNameBalanceNoSubs :: Ledger -> AccountName -> Amount | ||||||
|  | accountNameBalanceNoSubs l a = sumEntryTransactions (accountNameTransactionsNoSubs l a) | ||||||
|  | 
 | ||||||
|  | accountNameTransactionsNoSubs :: Ledger -> AccountName -> [EntryTransaction] | ||||||
|  | accountNameTransactionsNoSubs l a = ledgerTransactionsMatching (["^" ++ a ++ "$"], []) l | ||||||
|  | 
 | ||||||
| -- showAccountNamesWithBalances :: [(AccountName,String)] -> Ledger -> String | -- showAccountNamesWithBalances :: [(AccountName,String)] -> Ledger -> String | ||||||
| -- showAccountNamesWithBalances as l = | -- showAccountNamesWithBalances as l = | ||||||
| --     unlines $ map (showAccountNameAndBalance l) as | --     unlines $ map (showAccountNameAndBalance l) as | ||||||
| @ -35,40 +50,42 @@ import Ledger | |||||||
| -- showAccountNameAndBalance l (a, adisplay) = | -- showAccountNameAndBalance l (a, adisplay) = | ||||||
| --     printf "%20s  %s" (showBalance $ accountBalance l a) adisplay | --     printf "%20s  %s" (showBalance $ accountBalance l a) adisplay | ||||||
| 
 | 
 | ||||||
| accountBalance :: Ledger -> AccountName -> Amount |  | ||||||
| accountBalance l a = |  | ||||||
|     sumEntryTransactions (accountTransactions l a) |  | ||||||
| 
 | 
 | ||||||
| accountTransactions :: Ledger -> AccountName -> [EntryTransaction] | -- a tree of Accounts | ||||||
| accountTransactions l a = ledgerTransactionsMatching (["^" ++ a ++ "(:.+)?$"], []) l |  | ||||||
| 
 | 
 | ||||||
| accountBalanceNoSubs :: Ledger -> AccountName -> Amount | atacct = fst . node | ||||||
| accountBalanceNoSubs l a = |  | ||||||
|     sumEntryTransactions (accountTransactionsNoSubs l a) |  | ||||||
| 
 | 
 | ||||||
| accountTransactionsNoSubs :: Ledger -> AccountName -> [EntryTransaction] | addDataToAccountNameTree :: Ledger -> Tree AccountName -> Tree Account | ||||||
| accountTransactionsNoSubs l a = ledgerTransactionsMatching (["^" ++ a ++ "$"], []) l | addDataToAccountNameTree l ant =  | ||||||
| 
 |     Tree (mkAccount l aname, map (addDataToAccountNameTree l) (antsubs ant)) | ||||||
| addDataToAccounts :: Ledger -> (Tree AccountName) -> (Tree AccountData) |  | ||||||
| addDataToAccounts l acct =  |  | ||||||
|     Tree (acctdata, map (addDataToAccounts l) (atsubs acct)) |  | ||||||
|         where  |         where  | ||||||
|           acctdata = (aname, atxns, abal) |           aname = antacctname ant | ||||||
|           aname = atacct acct |  | ||||||
|           atxns = accountTransactionsNoSubs l aname |  | ||||||
|           abal = accountBalance l aname |  | ||||||
| 
 | 
 | ||||||
| -- an AccountData tree adds some other things we want to cache for | showAccountTreeWithBalances :: Ledger -> Int -> Tree Account -> String | ||||||
| -- convenience, like the account's balance and transactions. | showAccountTreeWithBalances l depth at = (showAccountTreesWithBalances l depth) (branches at) | ||||||
| type AccountData = (AccountName,[EntryTransaction],Amount) |  | ||||||
| type AccountDataTree = Tree AccountData |  | ||||||
| adtdata = fst . unTree |  | ||||||
| adtsubs = snd . unTree |  | ||||||
| nullad = Tree (("", [], 0), []) |  | ||||||
| adname (a,_,_) = a |  | ||||||
| adtxns (_,ts,_) = ts |  | ||||||
| adamt (_,_,amt) = amt |  | ||||||
| 
 | 
 | ||||||
|  | showAccountTreesWithBalances :: Ledger -> Int -> [Tree Account] -> String | ||||||
|  | showAccountTreesWithBalances _ 0 _ = "" | ||||||
|  | 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 = atxns $ atacct at | ||||||
|  |                 bal = abal $ 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) | -- a (2 txns) | ||||||
| --   b (boring acct - 0 txns, exactly 1 sub) | --   b (boring acct - 0 txns, exactly 1 sub) | ||||||
| --     c (5 txns) | --     c (5 txns) | ||||||
| @ -78,46 +95,18 @@ adamt (_,_,amt) = amt | |||||||
| --   b:c (5 txns) | --   b:c (5 txns) | ||||||
| --     d | --     d | ||||||
| 
 | 
 | ||||||
| -- elideAccount adt = adt | -- elideAccountTree at = at | ||||||
| 
 | 
 | ||||||
| -- elideAccount :: Tree AccountData -> Tree AccountData | elideAccountTree :: Tree Account -> Tree Account | ||||||
| -- elideAccount adt = adt | elideAccountTree = id | ||||||
|      |  | ||||||
| 
 | 
 | ||||||
| -- a | ledgerAccountTree :: Ledger -> Tree Account | ||||||
| --   b | ledgerAccountTree l = elideAccountTree $ addDataToAccountNameTree l (ledgerAccountNameTree l) | ||||||
| --     c |  | ||||||
| -- d |  | ||||||
| -- to: |  | ||||||
| -- $7  a |  | ||||||
| -- $5    b |  | ||||||
| -- $5      c |  | ||||||
| -- $0  d |  | ||||||
| showAccountWithBalances :: Ledger -> Tree AccountData -> String |  | ||||||
| showAccountWithBalances l adt = (showAccountsWithBalance l) (adtsubs adt) |  | ||||||
| 
 | 
 | ||||||
| showAccountsWithBalance :: Ledger -> [Tree AccountData] -> String | ledgerAccountsMatching :: Ledger -> [String] -> [Account] | ||||||
| showAccountsWithBalance l adts = | ledgerAccountsMatching l acctpats = undefined | ||||||
|     concatMap showAccountDataBranch adts |  | ||||||
|         where |  | ||||||
|           showAccountDataBranch :: Tree AccountData -> String |  | ||||||
|           showAccountDataBranch adt =  |  | ||||||
|               topacct ++ "\n" ++ subs |  | ||||||
| --               case boring of |  | ||||||
| --                 True  ->  |  | ||||||
| --                 False ->  |  | ||||||
|               where |  | ||||||
|                 topacct = (showAmount abal) ++ "  " ++ (indentAccountName aname) |  | ||||||
|                 showAmount amt = printf "%11s" (show amt) |  | ||||||
|                 aname = adname $ adtdata adt |  | ||||||
|                 atxns = adtxns $ adtdata adt |  | ||||||
|                 abal = adamt $ adtdata adt |  | ||||||
|                 subs = (showAccountsWithBalance l) $ adtsubs adt |  | ||||||
|                 boring = (length atxns == 0) && ((length subs) == 1) |  | ||||||
| 
 | 
 | ||||||
| ledgerAccountsData :: Ledger -> Tree AccountData | showLedgerAccounts :: Ledger -> Int -> String | ||||||
| ledgerAccountsData l = addDataToAccounts l (ledgerAccounts l) | showLedgerAccounts l depth =  | ||||||
|  |     showAccountTreeWithBalances l depth (ledgerAccountTree l) | ||||||
| 
 | 
 | ||||||
| showLedgerAccountsWithBalances :: Ledger -> Tree AccountData -> String |  | ||||||
| showLedgerAccountsWithBalances l adt = |  | ||||||
|     showAccountWithBalances l adt |  | ||||||
|  | |||||||
							
								
								
									
										15
									
								
								Options.hs
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								Options.hs
									
									
									
									
									
								
							| @ -1,21 +1,21 @@ | |||||||
| 
 | 
 | ||||||
| module Options (module Options, usageInfo) | module Options (module Options, usageInfo) | ||||||
| where | where | ||||||
|      |  | ||||||
| import System.Console.GetOpt | import System.Console.GetOpt | ||||||
| import Data.Maybe ( fromMaybe ) |  | ||||||
| import System.Environment (getEnv) | import System.Environment (getEnv) | ||||||
|  | import Data.Maybe (fromMaybe) | ||||||
|      |      | ||||||
| import Utils | import Utils | ||||||
| 
 | 
 | ||||||
| data Flag = Version | File String | ShowSubs  | 
 | ||||||
|  | data Flag = Version | File String | ShowSubs | ||||||
|             deriving (Show,Eq) |             deriving (Show,Eq) | ||||||
|      |      | ||||||
| options :: [OptDescr Flag] | options :: [OptDescr Flag] | ||||||
| options = [ | options = [ | ||||||
|             Option ['v'] ["version"] (NoArg Version)     "show version number" |             Option ['v'] ["version"] (NoArg Version)     "show version number" | ||||||
|           , Option ['f'] ["file"]    (OptArg inp "FILE") "ledger file, or - to read stdin" |           , Option ['f'] ["file"]    (OptArg inp "FILE") "ledger file, or - to read stdin" | ||||||
| --          , Option ['s'] ["subtotal"] (NoArg ShowSubs)     "balance: show sub-accounts; register: show subtotals" |           , Option ['s'] ["subtotal"] (NoArg ShowSubs)     "balance: show sub-accounts" --; register: show subtotals" | ||||||
|           ] |           ] | ||||||
| 
 | 
 | ||||||
| inp :: Maybe String -> Flag | inp :: Maybe String -> Flag | ||||||
| @ -47,5 +47,8 @@ ledgerPatternArgs args = | |||||||
|       True -> ((takeWhile (/= "--") args), tail $ (dropWhile (/= "--") args)) |       True -> ((takeWhile (/= "--") args), tail $ (dropWhile (/= "--") args)) | ||||||
|       False -> (args,[]) |       False -> (args,[]) | ||||||
| 
 | 
 | ||||||
| depthOption :: [Flag] -> Int | getDepth :: [Flag] -> Int | ||||||
| depthOption opts = 1 | getDepth opts =  | ||||||
|  |     maximum $ [1] ++ map depthval opts where | ||||||
|  |         depthval (ShowSubs) = 9999 | ||||||
|  |         depthval _ = 1 | ||||||
|  | |||||||
							
								
								
									
										3
									
								
								Parse.hs
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								Parse.hs
									
									
									
									
									
								
							| @ -1,12 +1,11 @@ | |||||||
| 
 | 
 | ||||||
| module Parse | module Parse | ||||||
| where | where | ||||||
| 
 |  | ||||||
| import Text.ParserCombinators.Parsec | import Text.ParserCombinators.Parsec | ||||||
| import Text.ParserCombinators.Parsec.Language | import Text.ParserCombinators.Parsec.Language | ||||||
| import qualified Text.ParserCombinators.Parsec.Token as P | import qualified Text.ParserCombinators.Parsec.Token as P | ||||||
| import Text.Printf |  | ||||||
| 
 | 
 | ||||||
|  | import Utils | ||||||
| import Models | import Models | ||||||
| 
 | 
 | ||||||
| {- | {- | ||||||
|  | |||||||
							
								
								
									
										9
									
								
								TODO
									
									
									
									
									
								
							
							
						
						
									
										9
									
								
								TODO
									
									
									
									
									
								
							| @ -1,4 +1,6 @@ | |||||||
| cleanup/reorganize | cleanup/reorganize | ||||||
|  |  Entry/Transaction/EntryTransaction | ||||||
|  | 
 | ||||||
| hledger | hledger | ||||||
|  Options |  Options | ||||||
|  Tests |  Tests | ||||||
| @ -14,8 +16,8 @@ hledger | |||||||
| 
 | 
 | ||||||
| basic features | basic features | ||||||
|  balance |  balance | ||||||
|   show balances with new tree structures |   elide boring accounts | ||||||
|   elide empty accounts |  handle mixed amounts and currencies | ||||||
|  print |  print | ||||||
|  entry |  entry | ||||||
|  -j and -J graph data output |  -j and -J graph data output | ||||||
| @ -26,7 +28,7 @@ make it fast | |||||||
|  profile |  profile | ||||||
| 
 | 
 | ||||||
| more features | more features | ||||||
|  svn-style elision |  3.0-style elision | ||||||
|  -p period expressions |  -p period expressions | ||||||
|  -d display expressions |  -d display expressions | ||||||
|  read gnucash files |  read gnucash files | ||||||
| @ -37,6 +39,7 @@ new features | |||||||
|  smart data entry |  smart data entry | ||||||
|  incorporate timeclock features |  incorporate timeclock features | ||||||
|  timelog simple amount entries |  timelog simple amount entries | ||||||
|  |  better layout | ||||||
| 
 | 
 | ||||||
| tests | tests | ||||||
|  better use of quickcheck/smallcheck |  better use of quickcheck/smallcheck | ||||||
|  | |||||||
							
								
								
									
										10
									
								
								Tests.hs
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								Tests.hs
									
									
									
									
									
								
							| @ -1,7 +1,6 @@ | |||||||
| 
 | 
 | ||||||
| module Tests | module Tests | ||||||
| where | where | ||||||
| 
 |  | ||||||
| import Text.ParserCombinators.Parsec | import Text.ParserCombinators.Parsec | ||||||
| import Test.QuickCheck | import Test.QuickCheck | ||||||
| import Test.HUnit | import Test.HUnit | ||||||
| @ -273,7 +272,9 @@ test_expandAccountNames = | |||||||
| 
 | 
 | ||||||
| test_ledgerAccountNames = | test_ledgerAccountNames = | ||||||
|     assertEqual' |     assertEqual' | ||||||
|     ["assets","assets:cash","assets:checking","equity","equity:opening balances","expenses","expenses:vacation"] |     ["assets","assets:cash","assets:checking","assets:saving","equity","equity:opening balances", | ||||||
|  |     "expenses","expenses:food","expenses:food:dining","expenses:phone","expenses:vacation", | ||||||
|  |      "liabilities","liabilities:credit cards","liabilities:credit cards:discover"] | ||||||
|     (ledgerAccountNames ledger7) |     (ledgerAccountNames ledger7) | ||||||
| 
 | 
 | ||||||
| -- quickcheck properties | -- quickcheck properties | ||||||
| @ -284,7 +285,10 @@ props = | |||||||
|      (Transaction "expenses:food:dining" (Amount "$" 10)) |      (Transaction "expenses:food:dining" (Amount "$" 10)) | ||||||
|     , |     , | ||||||
|      ledgerAccountNames ledger7 ==  |      ledgerAccountNames ledger7 ==  | ||||||
|      ["assets","assets:cash","assets:checking","equity","equity:opening balances","expenses","expenses:vacation"] |      ["assets","assets:cash","assets:checking","assets:saving","equity", | ||||||
|  |       "equity:opening balances","expenses","expenses:food","expenses:food:dining", | ||||||
|  |       "expenses:phone","expenses:vacation","liabilities","liabilities:credit cards", | ||||||
|  |       "liabilities:credit cards:discover"] | ||||||
|     , |     , | ||||||
|      ledgerPatternArgs [] == ([],[]) |      ledgerPatternArgs [] == ([],[]) | ||||||
|     ,ledgerPatternArgs ["a"] == (["a"],[]) |     ,ledgerPatternArgs ["a"] == (["a"],[]) | ||||||
|  | |||||||
| @ -1,12 +1,6 @@ | |||||||
| 
 | 
 | ||||||
| module Transaction | module Transaction | ||||||
| where | where | ||||||
| 
 |  | ||||||
| import Debug.Trace |  | ||||||
| import Text.Printf |  | ||||||
| import Text.Regex |  | ||||||
| import Data.List |  | ||||||
| 
 |  | ||||||
| import Utils | import Utils | ||||||
| import BasicTypes | import BasicTypes | ||||||
| import Account | import Account | ||||||
|  | |||||||
							
								
								
									
										18
									
								
								Utils.hs
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								Utils.hs
									
									
									
									
									
								
							| @ -1,9 +1,19 @@ | |||||||
| 
 | module Utils ( | ||||||
| module Utils |               module Utils, | ||||||
|  |               module Data.List, | ||||||
|  |               module Debug.Trace, | ||||||
|  |               module Text.Printf, | ||||||
|  |               module Text.Regex, | ||||||
|  |               quickCheck, | ||||||
|  |              ) | ||||||
| where | where | ||||||
| 
 |  | ||||||
| import Data.List |  | ||||||
| import System.Directory | import System.Directory | ||||||
|  | import Data.List | ||||||
|  | import Debug.Trace | ||||||
|  | import Test.QuickCheck (quickCheck) | ||||||
|  | import Text.Printf | ||||||
|  | import Text.Regex | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| rhead = head . reverse  | rhead = head . reverse  | ||||||
| rtail = reverse . tail . reverse  | rtail = reverse . tail . reverse  | ||||||
|  | |||||||
							
								
								
									
										33
									
								
								hledger.hs
									
									
									
									
									
								
							
							
						
						
									
										33
									
								
								hledger.hs
									
									
									
									
									
								
							| @ -1,22 +1,22 @@ | |||||||
| #!/usr/bin/env runhaskell | #!/usr/bin/env runhaskell | ||||||
| -- hledger - ledger-compatible money management utilities (& haskell study) | -- 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 | ||||||
| 
 | 
 | ||||||
| module Main -- application logic & most IO | -- application logic & most IO | ||||||
|  | module Main | ||||||
| where | where | ||||||
| 
 |  | ||||||
| import System.Environment (withArgs) -- for testing in old hugs |  | ||||||
| import System | import System | ||||||
| import Data.List | import System.Environment (withArgs) -- for testing in old hugs | ||||||
| import Test.HUnit (runTestTT) | import Test.HUnit (runTestTT) | ||||||
| import Test.QuickCheck (quickCheck) | import Test.QuickCheck (quickCheck) | ||||||
| import Text.ParserCombinators.Parsec (parseFromFile, ParseError) | import Text.ParserCombinators.Parsec (ParseError) | ||||||
| 
 | 
 | ||||||
| import Options | import Options | ||||||
| import Models | import Models | ||||||
| import Parse | import Parse | ||||||
| import Tests | import Tests | ||||||
|  | import Utils | ||||||
| 
 | 
 | ||||||
| main :: IO () | main :: IO () | ||||||
| main = do | main = do | ||||||
| @ -67,13 +67,16 @@ printRegister opts args ledger = do | |||||||
| 
 | 
 | ||||||
| printBalance :: [Flag] -> [String] -> Ledger -> IO () | printBalance :: [Flag] -> [String] -> Ledger -> IO () | ||||||
| printBalance opts args ledger = do | printBalance opts args ledger = do | ||||||
| --   putStr $ showAccountWithBalances ledger (ledgerAccountsData l) | --   putStr $ showLedgerAccounts ledger acctpats depth | ||||||
|   putStr $ showLedgerAccounts ledger acctpats depth | --       where  | ||||||
|       where  | --         (acctpats,_) = ledgerPatternArgs args | ||||||
|         (acctpats,_) = ledgerPatternArgs args |  | ||||||
|         depth = depthOption opts |  | ||||||
| 
 |  | ||||||
| --         showsubs = (ShowSubs `elem` opts) | --         showsubs = (ShowSubs `elem` opts) | ||||||
| --         accounts = case showsubs of | --         depth = case showsubs of | ||||||
| --                      True -> expandAccountNamesMostly ledger (ledgerTopAccountNames ledger) | --                   True -> 999 | ||||||
| --                      False -> [(a,indentAccountName a) | a <- ledgerAccountNamesMatching acctpats ledger] | --                   False -> depthOption opts | ||||||
|  |   putStr $ case showsubs of | ||||||
|  |              True -> showLedgerAccounts ledger 999 | ||||||
|  |              False -> showLedgerAccounts ledger (getDepth opts) | ||||||
|  |       where  | ||||||
|  |         showsubs = (ShowSubs `elem` opts) | ||||||
|  |         (acctpats,_) = ledgerPatternArgs args | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user