diff --git a/Ledger.hs b/Ledger.hs index 21fec8322..5c4838d26 100644 --- a/Ledger.hs +++ b/Ledger.hs @@ -12,10 +12,13 @@ import LedgerFile rawLedgerTransactions :: LedgerFile -> [Transaction] -rawLedgerTransactions l = entryTransactionsFrom $ entries l +rawLedgerTransactions = txns . entries + where + txns :: [LedgerEntry] -> [Transaction] + txns es = concat $ map flattenEntry es rawLedgerAccountNamesUsed :: LedgerFile -> [AccountName] -rawLedgerAccountNamesUsed l = accountNamesFromTransactions $ entryTransactionsFrom $ entries l +rawLedgerAccountNamesUsed = accountNamesFromTransactions . rawLedgerTransactions rawLedgerAccountNames :: LedgerFile -> [AccountName] rawLedgerAccountNames = sort . expandAccountNames . rawLedgerAccountNamesUsed @@ -44,12 +47,12 @@ cacheLedger l = tmap = Map.union (Map.fromList [(account $ head g, g) | g <- groupedts]) (Map.fromList [(a,[]) | a <- ans]) - txns a = tmap ! a + txns = (tmap !) subaccts a = filter (isAccountNamePrefixOf a) ans subtxns a = concat [txns a | a <- [a] ++ subaccts a] - lprecision = maximum $ map (precision . tamount . transaction) ts + lprecision = maximum $ map (precision . amount) ts bmap = Map.union - (Map.fromList [(a, (sumEntryTransactions $ subtxns a){precision=lprecision}) | a <- ans]) + (Map.fromList [(a, (sumTransactions $ subtxns a){precision=lprecision}) | a <- ans]) (Map.fromList [(a,nullamt) | a <- ans]) amap = Map.fromList [(a, Account a (tmap ! a) (bmap ! a)) | a <- ans] in @@ -69,7 +72,7 @@ ledgerTransactions :: Ledger -> [Transaction] ledgerTransactions l = setprecisions $ rawLedgerTransactions $ rawledger l where - setprecisions = map (entryTransactionSetPrecision (lprecision l)) + setprecisions = map (transactionSetPrecision (lprecision l)) ledgerTransactionsMatching :: ([String],[String]) -> Ledger -> [Transaction] ledgerTransactionsMatching ([],[]) l = ledgerTransactionsMatching ([".*"],[".*"]) l diff --git a/LedgerEntry.hs b/LedgerEntry.hs index fb8df53b8..f32dcdc8a 100644 --- a/LedgerEntry.hs +++ b/LedgerEntry.hs @@ -1,4 +1,3 @@ - module LedgerEntry where import Utils @@ -27,7 +26,7 @@ showDate d = printf "%-10s" d showDescription s = printf "%-20s" (elideRight 20 s) isEntryBalanced :: LedgerEntry -> Bool -isEntryBalanced e = (sumTransactions . etransactions) e == 0 +isEntryBalanced e = (sumLedgerTransactions . etransactions) e == 0 autofillEntry :: LedgerEntry -> LedgerEntry autofillEntry e = @@ -68,7 +67,7 @@ showEntries = concatMap showEntry entrySetPrecision :: Int -> LedgerEntry -> LedgerEntry entrySetPrecision p (LedgerEntry d s c desc ts) = - LedgerEntry d s c desc $ map (transactionSetPrecision p) ts + LedgerEntry d s c desc $ map (ledgerTransactionSetPrecision p) ts -- modifier & periodic entries diff --git a/LedgerTransaction.hs b/LedgerTransaction.hs index 54f3a7d12..de5e08a31 100644 --- a/LedgerTransaction.hs +++ b/LedgerTransaction.hs @@ -1,4 +1,3 @@ - module LedgerTransaction where import Utils @@ -7,10 +6,10 @@ import AccountName import Amount -instance Show LedgerTransaction where show = showTransaction +instance Show LedgerTransaction where show = showLedgerTransaction -showTransaction :: LedgerTransaction -> String -showTransaction t = (showaccountname $ taccount t) ++ " " ++ (showamount $ tamount t) +showLedgerTransaction :: LedgerTransaction -> String +showLedgerTransaction t = (showaccountname $ taccount t) ++ " " ++ (showamount $ tamount t) where showaccountname = printf "%-22s" . elideRight 22 showamount = printf "%11s" . showAmountRoundedOrZero @@ -27,11 +26,11 @@ autofillTransactions ts = case (length as) of 0 -> ns 1 -> ns ++ [balanceTransaction $ head as] - where balanceTransaction t = t{tamount = -(sumTransactions ns)} + where balanceTransaction t = t{tamount = -(sumLedgerTransactions ns)} otherwise -> error "too many blank transactions in this entry" -sumTransactions :: [LedgerTransaction] -> Amount -sumTransactions = sum . map tamount +sumLedgerTransactions :: [LedgerTransaction] -> Amount +sumLedgerTransactions = sum . map tamount -transactionSetPrecision :: Int -> LedgerTransaction -> LedgerTransaction -transactionSetPrecision p (LedgerTransaction a amt) = LedgerTransaction a amt{precision=p} +ledgerTransactionSetPrecision :: Int -> LedgerTransaction -> LedgerTransaction +ledgerTransactionSetPrecision p (LedgerTransaction a amt) = LedgerTransaction a amt{precision=p} diff --git a/NOTES b/NOTES index 684fce6e6..14815adc2 100644 --- a/NOTES +++ b/NOTES @@ -2,7 +2,6 @@ hledger project notes * TO DO ** bugs/cleanup -*** rename EntryTransaction/Transaction ** ledger features *** print command **** need to save & print comments diff --git a/Transaction.hs b/Transaction.hs index 65a136a04..886775c39 100644 --- a/Transaction.hs +++ b/Transaction.hs @@ -9,30 +9,17 @@ import Amount import Currency -entry (e,t) = e -transaction (e,t) = t -date (e,t) = edate e -status (e,t) = estatus e -code (e,t) = ecode e -description (e,t) = edescription e -account (e,t) = taccount t -amount (e,t) = tamount t - flattenEntry :: LedgerEntry -> [Transaction] -flattenEntry e = [(e,t) | t <- etransactions e] +flattenEntry (LedgerEntry d _ _ desc ts) = [Transaction d desc (taccount t) (tamount t) | t <- ts] -entryTransactionSetPrecision :: Int -> Transaction -> Transaction -entryTransactionSetPrecision p (e, LedgerTransaction a amt) = (e, LedgerTransaction a amt{precision=p}) +transactionSetPrecision :: Int -> Transaction -> Transaction +transactionSetPrecision p (Transaction d desc a amt) = Transaction d desc a amt{precision=p} accountNamesFromTransactions :: [Transaction] -> [AccountName] accountNamesFromTransactions ts = nub $ map account ts -entryTransactionsFrom :: [LedgerEntry] -> [Transaction] -entryTransactionsFrom es = concat $ map flattenEntry es - -sumEntryTransactions :: [Transaction] -> Amount -sumEntryTransactions ets = - sumTransactions $ map transaction ets +sumTransactions :: [Transaction] -> Amount +sumTransactions = sum . map amount matchTransactionAccount :: Regex -> Transaction -> Bool matchTransactionAccount r t = @@ -53,22 +40,27 @@ showTransactionsWithBalances [] _ = [] showTransactionsWithBalances ts b = unlines $ showTransactionsWithBalances' ts dummyt b where - dummyt = (LedgerEntry "" False "" "" [], LedgerTransaction "" (dollars 0)) + dummyt = Transaction "" "" "" (dollars 0) showTransactionsWithBalances' [] _ _ = [] showTransactionsWithBalances' (t:ts) tprev b = - (if (entry t /= (entry tprev)) + (if sameentry t tprev then [showTransactionDescriptionAndBalance t b'] else [showTransactionAndBalance t b']) ++ (showTransactionsWithBalances' ts t b') - where b' = b + (amount t) + where + b' = b + (amount t) + sameentry (Transaction d1 desc1 _ _) (Transaction d2 desc2 _ _) = + d1 == d2 && desc1 == desc2 + -- we forgot the entry-txn relationships.. good enough ? showTransactionDescriptionAndBalance :: Transaction -> Amount -> String showTransactionDescriptionAndBalance t b = - (showEntryDescription $ entry t) ++ (showTransaction $ transaction t) ++ (showBalance b) + (showEntryDescription $ LedgerEntry (date t) False "" (description t) []) + ++ (showLedgerTransaction $ LedgerTransaction (account t) (amount t)) ++ (showBalance b) showTransactionAndBalance :: Transaction -> Amount -> String showTransactionAndBalance t b = - (replicate 32 ' ') ++ (showTransaction $ transaction t) ++ (showBalance b) + (replicate 32 ' ') ++ (showLedgerTransaction $ LedgerTransaction (account t) (amount t)) ++ (showBalance b) showBalance :: Amount -> String showBalance b = printf " %12s" (showAmountRoundedOrZero b) diff --git a/Types.hs b/Types.hs index 62f09c948..d4fd2adab 100644 --- a/Types.hs +++ b/Types.hs @@ -46,11 +46,11 @@ data Amount = Amount { precision :: Int -- number of significant decimal places } deriving (Eq) --- AccountNames are strings like "assets:cash:petty"; from these we figure --- out the chart of accounts +-- AccountNames are strings like "assets:cash:petty", from which we derive +-- the chart of accounts type AccountName = String --- a flow of some amount to some account (see also Transaction) +-- a line item in a ledger entry data LedgerTransaction = LedgerTransaction { taccount :: AccountName, tamount :: Amount @@ -59,21 +59,19 @@ data LedgerTransaction = LedgerTransaction { -- a ledger entry, with two or more balanced transactions data LedgerEntry = LedgerEntry { edate :: Date, - estatus :: EntryStatus, + estatus :: Bool, ecode :: String, edescription :: String, etransactions :: [LedgerTransaction] } deriving (Eq) -type EntryStatus = Bool - --- an "=" automated entry (ignored) +-- an automated ledger entry data ModifierEntry = ModifierEntry { valueexpr :: String, m_transactions :: [LedgerTransaction] } deriving (Eq) --- a "~" periodic entry (ignored) +-- a periodic ledger entry data PeriodicEntry = PeriodicEntry { periodexpr :: String, p_transactions :: [LedgerTransaction] @@ -97,20 +95,23 @@ data LedgerFile = LedgerFile { entries :: [LedgerEntry] } deriving (Eq) --- We convert Transactions into EntryTransactions, which are (entry, --- transaction) pairs, since I couldn't see how to have transactions --- reference their entry like in OO. These are referred to as just --- "transactions" in modules above Transaction. -type Transaction = (LedgerEntry,LedgerTransaction) +-- we flatten LedgerEntries and LedgerTransactions into Transactions, +-- which are simpler to query at the cost of some data duplication +data Transaction = Transaction { + date :: Date, + description :: String, + account :: AccountName, + amount :: Amount + } deriving (Eq) --- all information for a particular account, derived from a LedgerFile +-- cached information for a particular account data Account = Account { aname :: AccountName, atransactions :: [Transaction], -- excludes sub-accounts - abalance :: Amount -- includes sub-accounts + abalance :: Amount -- includes sub-accounts } --- a ledger with account info cached for faster queries +-- a ledger with account information cached for faster queries data Ledger = Ledger { rawledger :: LedgerFile, accountnametree :: Tree AccountName,