parse virtual and balanced virtual transactions, refactor register and transaction output
This commit is contained in:
parent
014723497f
commit
dce8fd0dde
@ -250,7 +250,9 @@ ledgercode :: Parser String
|
|||||||
ledgercode = try (do { char '('; code <- anyChar `manyTill` char ')'; many1 spacenonewline; return code } ) <|> return ""
|
ledgercode = try (do { char '('; code <- anyChar `manyTill` char ')'; many1 spacenonewline; return code } ) <|> return ""
|
||||||
|
|
||||||
ledgertransactions :: Parser [RawTransaction]
|
ledgertransactions :: Parser [RawTransaction]
|
||||||
ledgertransactions = (ledgertransaction <?> "transaction") `manyTill` (do {newline <?> "blank line"; return ()} <|> eof)
|
ledgertransactions =
|
||||||
|
((try virtualtransaction <|> try balancedvirtualtransaction <|> ledgertransaction) <?> "transaction")
|
||||||
|
`manyTill` (do {newline <?> "blank line"; return ()} <|> eof)
|
||||||
|
|
||||||
ledgertransaction :: Parser RawTransaction
|
ledgertransaction :: Parser RawTransaction
|
||||||
ledgertransaction = do
|
ledgertransaction = do
|
||||||
@ -260,7 +262,31 @@ ledgertransaction = do
|
|||||||
many spacenonewline
|
many spacenonewline
|
||||||
comment <- ledgercomment
|
comment <- ledgercomment
|
||||||
restofline
|
restofline
|
||||||
return (RawTransaction account amount comment)
|
return (RawTransaction account amount comment RegularTransaction)
|
||||||
|
|
||||||
|
virtualtransaction :: Parser RawTransaction
|
||||||
|
virtualtransaction = do
|
||||||
|
many1 spacenonewline
|
||||||
|
char '('
|
||||||
|
account <- ledgeraccountname
|
||||||
|
char ')'
|
||||||
|
amount <- transactionamount
|
||||||
|
many spacenonewline
|
||||||
|
comment <- ledgercomment
|
||||||
|
restofline
|
||||||
|
return (RawTransaction account amount comment VirtualTransaction)
|
||||||
|
|
||||||
|
balancedvirtualtransaction :: Parser RawTransaction
|
||||||
|
balancedvirtualtransaction = do
|
||||||
|
many1 spacenonewline
|
||||||
|
char '['
|
||||||
|
account <- ledgeraccountname
|
||||||
|
char ']'
|
||||||
|
amount <- transactionamount
|
||||||
|
many spacenonewline
|
||||||
|
comment <- ledgercomment
|
||||||
|
restofline
|
||||||
|
return (RawTransaction account amount comment BalancedVirtualTransaction)
|
||||||
|
|
||||||
-- | account names may have single spaces inside them, and are terminated by two or more spaces
|
-- | account names may have single spaces inside them, and are terminated by two or more spaces
|
||||||
ledgeraccountname :: Parser String
|
ledgeraccountname :: Parser String
|
||||||
@ -268,11 +294,13 @@ ledgeraccountname = do
|
|||||||
accountname <- many1 (accountnamechar <|> singlespace)
|
accountname <- many1 (accountnamechar <|> singlespace)
|
||||||
return $ striptrailingspace accountname
|
return $ striptrailingspace accountname
|
||||||
where
|
where
|
||||||
accountnamechar = nonspace <?> "account name character"
|
|
||||||
singlespace = try (do {spacenonewline; do {notFollowedBy spacenonewline; return ' '}})
|
singlespace = try (do {spacenonewline; do {notFollowedBy spacenonewline; return ' '}})
|
||||||
-- couldn't avoid consuming a final space sometimes, harmless
|
-- couldn't avoid consuming a final space sometimes, harmless
|
||||||
striptrailingspace s = if last s == ' ' then init s else s
|
striptrailingspace s = if last s == ' ' then init s else s
|
||||||
|
|
||||||
|
accountnamechar = notFollowedBy (oneOf "()[]") >> nonspace
|
||||||
|
<?> "account name character (non-bracket, non-parenthesis, non-whitespace)"
|
||||||
|
|
||||||
transactionamount :: Parser Amount
|
transactionamount :: Parser Amount
|
||||||
transactionamount =
|
transactionamount =
|
||||||
try (do
|
try (do
|
||||||
|
|||||||
@ -103,7 +103,7 @@ normaliseRawLedgerAmounts l@(RawLedger ms ps es f) = RawLedger ms ps es' f
|
|||||||
es' = map normaliseEntryAmounts es
|
es' = map normaliseEntryAmounts es
|
||||||
normaliseEntryAmounts (Entry d s c desc comm ts pre) = Entry d s c desc comm ts' pre
|
normaliseEntryAmounts (Entry d s c desc comm ts pre) = Entry d s c desc comm ts' pre
|
||||||
where ts' = map normaliseRawTransactionAmounts ts
|
where ts' = map normaliseRawTransactionAmounts ts
|
||||||
normaliseRawTransactionAmounts (RawTransaction acct a c) = RawTransaction acct a' c
|
normaliseRawTransactionAmounts (RawTransaction acct a c t) = RawTransaction acct a' c t
|
||||||
where a' = normaliseAmount a
|
where a' = normaliseAmount a
|
||||||
normaliseAmount (Amount c q) = Amount (firstoccurrenceof c) q
|
normaliseAmount (Amount c q) = Amount (firstoccurrenceof c) q
|
||||||
firstcommodities = nubBy samesymbol $ allcommodities
|
firstcommodities = nubBy samesymbol $ allcommodities
|
||||||
|
|||||||
@ -13,10 +13,10 @@ import Ledger.Amount
|
|||||||
import Ledger.AccountName
|
import Ledger.AccountName
|
||||||
|
|
||||||
|
|
||||||
instance Show RawTransaction where show = showLedgerTransaction
|
instance Show RawTransaction where show = showRawTransaction
|
||||||
|
|
||||||
showLedgerTransaction :: RawTransaction -> String
|
showRawTransaction :: RawTransaction -> String
|
||||||
showLedgerTransaction t = (showaccountname $ taccount t) ++ " " ++ (showamount $ tamount t)
|
showRawTransaction t = (showaccountname $ taccount t) ++ " " ++ (showamount $ tamount t)
|
||||||
where
|
where
|
||||||
showaccountname = printf "%-22s" . elideAccountName 22
|
showaccountname = printf "%-22s" . elideAccountName 22
|
||||||
showamount = printf "%12s" . showAmountOrZero
|
showamount = printf "%12s" . showAmountOrZero
|
||||||
|
|||||||
@ -58,6 +58,6 @@ entryFromTimeLogInOut i o =
|
|||||||
intime = parsedatetime $ tldatetime i
|
intime = parsedatetime $ tldatetime i
|
||||||
outtime = parsedatetime $ tldatetime o
|
outtime = parsedatetime $ tldatetime o
|
||||||
amount = hours $ realToFrac (diffUTCTime outtime intime) / 3600
|
amount = hours $ realToFrac (diffUTCTime outtime intime) / 3600
|
||||||
txns = [RawTransaction acctname amount ""
|
txns = [RawTransaction acctname amount "" RegularTransaction
|
||||||
--,RawTransaction "assets:time" (-amount) ""
|
--,RawTransaction "assets:time" (-amount) "" RegularTransaction
|
||||||
]
|
]
|
||||||
|
|||||||
@ -14,15 +14,17 @@ import Ledger.RawTransaction
|
|||||||
import Ledger.Amount
|
import Ledger.Amount
|
||||||
|
|
||||||
|
|
||||||
instance Show Transaction where
|
instance Show Transaction where show=showTransaction
|
||||||
show (Transaction eno d desc a amt) = unwords [d,desc,a,show amt]
|
|
||||||
|
showTransaction :: Transaction -> String
|
||||||
|
showTransaction (Transaction eno d desc a amt ttype) = unwords [d,desc,a,show amt,show ttype]
|
||||||
|
|
||||||
-- | Convert a 'Entry' to two or more 'Transaction's. An id number
|
-- | Convert a 'Entry' to two or more 'Transaction's. An id number
|
||||||
-- is attached to the transactions to preserve their grouping - it should
|
-- is attached to the transactions to preserve their grouping - it should
|
||||||
-- be unique per entry.
|
-- be unique per entry.
|
||||||
flattenEntry :: (Entry, Int) -> [Transaction]
|
flattenEntry :: (Entry, Int) -> [Transaction]
|
||||||
flattenEntry (Entry d _ _ desc _ ts _, e) =
|
flattenEntry (Entry d _ _ desc _ ts _, e) =
|
||||||
[Transaction e d desc (taccount t) (tamount t) | t <- ts]
|
[Transaction e d desc (taccount t) (tamount t) (rttype t) | t <- ts]
|
||||||
|
|
||||||
accountNamesFromTransactions :: [Transaction] -> [AccountName]
|
accountNamesFromTransactions :: [Transaction] -> [AccountName]
|
||||||
accountNamesFromTransactions ts = nub $ map account ts
|
accountNamesFromTransactions ts = nub $ map account ts
|
||||||
@ -30,4 +32,4 @@ accountNamesFromTransactions ts = nub $ map account ts
|
|||||||
sumTransactions :: [Transaction] -> Amount
|
sumTransactions :: [Transaction] -> Amount
|
||||||
sumTransactions = sum . map amount
|
sumTransactions = sum . map amount
|
||||||
|
|
||||||
nulltxn = Transaction 0 "" "" "" nullamt
|
nulltxn = Transaction 0 "" "" "" nullamt RegularTransaction
|
||||||
|
|||||||
@ -36,10 +36,14 @@ data Amount = Amount {
|
|||||||
|
|
||||||
type AccountName = String
|
type AccountName = String
|
||||||
|
|
||||||
|
data TransactionType = RegularTransaction | VirtualTransaction | BalancedVirtualTransaction
|
||||||
|
deriving (Eq,Show)
|
||||||
|
|
||||||
data RawTransaction = RawTransaction {
|
data RawTransaction = RawTransaction {
|
||||||
taccount :: AccountName,
|
taccount :: AccountName,
|
||||||
tamount :: Amount,
|
tamount :: Amount,
|
||||||
tcomment :: String
|
tcomment :: String,
|
||||||
|
rttype :: TransactionType
|
||||||
} deriving (Eq)
|
} deriving (Eq)
|
||||||
|
|
||||||
-- | a ledger "modifier" entry. Currently ignored.
|
-- | a ledger "modifier" entry. Currently ignored.
|
||||||
@ -86,7 +90,8 @@ data Transaction = Transaction {
|
|||||||
date :: Date,
|
date :: Date,
|
||||||
description :: String,
|
description :: String,
|
||||||
account :: AccountName,
|
account :: AccountName,
|
||||||
amount :: Amount
|
amount :: Amount,
|
||||||
|
ttype :: TransactionType
|
||||||
} deriving (Eq)
|
} deriving (Eq)
|
||||||
|
|
||||||
data Account = Account {
|
data Account = Account {
|
||||||
|
|||||||
@ -19,28 +19,35 @@ showTransactionsWithBalances opts args l =
|
|||||||
unlines $ showTransactionsWithBalances' ts nulltxn startingbalance
|
unlines $ showTransactionsWithBalances' ts nulltxn startingbalance
|
||||||
where
|
where
|
||||||
ts = filter matchtxn $ ledgerTransactions l
|
ts = filter matchtxn $ ledgerTransactions l
|
||||||
matchtxn (Transaction _ _ desc acct _) = matchLedgerPatterns False apats acct
|
matchtxn (Transaction _ _ desc acct _ _) = matchLedgerPatterns False apats acct
|
||||||
apats = fst $ parseAccountDescriptionArgs args
|
apats = fst $ parseAccountDescriptionArgs args
|
||||||
startingbalance = nullamt
|
startingbalance = nullamt
|
||||||
showTransactionsWithBalances' :: [Transaction] -> Transaction -> Amount -> [String]
|
showTransactionsWithBalances' :: [Transaction] -> Transaction -> Amount -> [String]
|
||||||
showTransactionsWithBalances' [] _ _ = []
|
showTransactionsWithBalances' [] _ _ = []
|
||||||
showTransactionsWithBalances' (t:ts) tprev b =
|
showTransactionsWithBalances' (t:ts) tprev b = this ++ rest
|
||||||
(if sameentry t tprev
|
|
||||||
then [showTransactionAndBalance t b']
|
|
||||||
else [showTransactionDescriptionAndBalance t b'])
|
|
||||||
++ (showTransactionsWithBalances' ts t b')
|
|
||||||
where
|
where
|
||||||
b' = b + (amount t)
|
b' = b + (amount t)
|
||||||
sameentry (Transaction e1 _ _ _ _) (Transaction e2 _ _ _ _) = e1 == e2
|
sameentry (Transaction {entryno=e1}) (Transaction {entryno=e2}) = e1 == e2
|
||||||
|
this = if sameentry t tprev
|
||||||
|
then [showTransactionWithoutDescription t b']
|
||||||
|
else [showTransactionWithDescription t b']
|
||||||
|
rest = showTransactionsWithBalances' ts t b'
|
||||||
|
|
||||||
showTransactionDescriptionAndBalance :: Transaction -> Amount -> String
|
showTransactionWithDescription :: Transaction -> Amount -> String
|
||||||
showTransactionDescriptionAndBalance t b =
|
showTransactionWithDescription t b =
|
||||||
(showEntryDescription $ Entry (date t) False "" (description t) "" [] "")
|
(showEntryDescription $ Entry (date t) False "" (description t) "" [] "")
|
||||||
++ (showLedgerTransaction $ RawTransaction (account t) (amount t) "") ++ (showBalance b)
|
++ (showTransactionFormatted t)
|
||||||
|
++ (showBalance b)
|
||||||
|
|
||||||
showTransactionAndBalance :: Transaction -> Amount -> String
|
showTransactionWithoutDescription :: Transaction -> Amount -> String
|
||||||
showTransactionAndBalance t b =
|
showTransactionWithoutDescription t b =
|
||||||
(replicate 32 ' ') ++ (showLedgerTransaction $ RawTransaction (account t) (amount t) "") ++ (showBalance b)
|
(replicate 32 ' ')
|
||||||
|
++ (showTransactionFormatted t)
|
||||||
|
++ (showBalance b)
|
||||||
|
|
||||||
|
showTransactionFormatted :: Transaction -> String
|
||||||
|
showTransactionFormatted (Transaction eno d desc a amt ttype) =
|
||||||
|
showRawTransaction $ RawTransaction a amt "" ttype
|
||||||
|
|
||||||
showBalance :: Amount -> String
|
showBalance :: Amount -> String
|
||||||
showBalance b = printf " %12s" (showAmountOrZero b)
|
showBalance b = printf " %12s" (showAmountOrZero b)
|
||||||
|
|||||||
42
Tests.hs
42
Tests.hs
@ -230,7 +230,7 @@ assertparseequal expected parsed = either printParseError (assertequal expected)
|
|||||||
|
|
||||||
rawtransaction1_str = " expenses:food:dining $10.00\n"
|
rawtransaction1_str = " expenses:food:dining $10.00\n"
|
||||||
|
|
||||||
rawtransaction1 = RawTransaction "expenses:food:dining" (dollars 10) ""
|
rawtransaction1 = RawTransaction "expenses:food:dining" (dollars 10) "" RegularTransaction
|
||||||
|
|
||||||
entry1_str = "\
|
entry1_str = "\
|
||||||
\2007/01/28 coopportunity\n\
|
\2007/01/28 coopportunity\n\
|
||||||
@ -240,8 +240,8 @@ entry1_str = "\
|
|||||||
|
|
||||||
entry1 =
|
entry1 =
|
||||||
(Entry "2007/01/28" False "" "coopportunity" ""
|
(Entry "2007/01/28" False "" "coopportunity" ""
|
||||||
[RawTransaction "expenses:food:groceries" (dollars 47.18) "",
|
[RawTransaction "expenses:food:groceries" (dollars 47.18) "" RegularTransaction,
|
||||||
RawTransaction "assets:checking" (dollars (-47.18)) ""] "")
|
RawTransaction "assets:checking" (dollars (-47.18)) "" RegularTransaction] "")
|
||||||
|
|
||||||
|
|
||||||
entry2_str = "\
|
entry2_str = "\
|
||||||
@ -386,12 +386,14 @@ rawledger7 = RawLedger
|
|||||||
RawTransaction {
|
RawTransaction {
|
||||||
taccount="assets:cash",
|
taccount="assets:cash",
|
||||||
tamount=dollars 4.82,
|
tamount=dollars 4.82,
|
||||||
tcomment=""
|
tcomment="",
|
||||||
|
rttype=RegularTransaction
|
||||||
},
|
},
|
||||||
RawTransaction {
|
RawTransaction {
|
||||||
taccount="equity:opening balances",
|
taccount="equity:opening balances",
|
||||||
tamount=dollars (-4.82),
|
tamount=dollars (-4.82),
|
||||||
tcomment=""
|
tcomment="",
|
||||||
|
rttype=RegularTransaction
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
epreceding_comment_lines=""
|
epreceding_comment_lines=""
|
||||||
@ -407,12 +409,14 @@ rawledger7 = RawLedger
|
|||||||
RawTransaction {
|
RawTransaction {
|
||||||
taccount="expenses:vacation",
|
taccount="expenses:vacation",
|
||||||
tamount=dollars 179.92,
|
tamount=dollars 179.92,
|
||||||
tcomment=""
|
tcomment="",
|
||||||
|
rttype=RegularTransaction
|
||||||
},
|
},
|
||||||
RawTransaction {
|
RawTransaction {
|
||||||
taccount="assets:checking",
|
taccount="assets:checking",
|
||||||
tamount=dollars (-179.92),
|
tamount=dollars (-179.92),
|
||||||
tcomment=""
|
tcomment="",
|
||||||
|
rttype=RegularTransaction
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
epreceding_comment_lines=""
|
epreceding_comment_lines=""
|
||||||
@ -428,12 +432,14 @@ rawledger7 = RawLedger
|
|||||||
RawTransaction {
|
RawTransaction {
|
||||||
taccount="assets:saving",
|
taccount="assets:saving",
|
||||||
tamount=dollars 200,
|
tamount=dollars 200,
|
||||||
tcomment=""
|
tcomment="",
|
||||||
|
rttype=RegularTransaction
|
||||||
},
|
},
|
||||||
RawTransaction {
|
RawTransaction {
|
||||||
taccount="assets:checking",
|
taccount="assets:checking",
|
||||||
tamount=dollars (-200),
|
tamount=dollars (-200),
|
||||||
tcomment=""
|
tcomment="",
|
||||||
|
rttype=RegularTransaction
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
epreceding_comment_lines=""
|
epreceding_comment_lines=""
|
||||||
@ -449,12 +455,14 @@ rawledger7 = RawLedger
|
|||||||
RawTransaction {
|
RawTransaction {
|
||||||
taccount="expenses:food:dining",
|
taccount="expenses:food:dining",
|
||||||
tamount=dollars 4.82,
|
tamount=dollars 4.82,
|
||||||
tcomment=""
|
tcomment="",
|
||||||
|
rttype=RegularTransaction
|
||||||
},
|
},
|
||||||
RawTransaction {
|
RawTransaction {
|
||||||
taccount="assets:cash",
|
taccount="assets:cash",
|
||||||
tamount=dollars (-4.82),
|
tamount=dollars (-4.82),
|
||||||
tcomment=""
|
tcomment="",
|
||||||
|
rttype=RegularTransaction
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
epreceding_comment_lines=""
|
epreceding_comment_lines=""
|
||||||
@ -470,12 +478,14 @@ rawledger7 = RawLedger
|
|||||||
RawTransaction {
|
RawTransaction {
|
||||||
taccount="expenses:phone",
|
taccount="expenses:phone",
|
||||||
tamount=dollars 95.11,
|
tamount=dollars 95.11,
|
||||||
tcomment=""
|
tcomment="",
|
||||||
|
rttype=RegularTransaction
|
||||||
},
|
},
|
||||||
RawTransaction {
|
RawTransaction {
|
||||||
taccount="assets:checking",
|
taccount="assets:checking",
|
||||||
tamount=dollars (-95.11),
|
tamount=dollars (-95.11),
|
||||||
tcomment=""
|
tcomment="",
|
||||||
|
rttype=RegularTransaction
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
epreceding_comment_lines=""
|
epreceding_comment_lines=""
|
||||||
@ -491,12 +501,14 @@ rawledger7 = RawLedger
|
|||||||
RawTransaction {
|
RawTransaction {
|
||||||
taccount="liabilities:credit cards:discover",
|
taccount="liabilities:credit cards:discover",
|
||||||
tamount=dollars 80,
|
tamount=dollars 80,
|
||||||
tcomment=""
|
tcomment="",
|
||||||
|
rttype=RegularTransaction
|
||||||
},
|
},
|
||||||
RawTransaction {
|
RawTransaction {
|
||||||
taccount="assets:checking",
|
taccount="assets:checking",
|
||||||
tamount=dollars (-80),
|
tamount=dollars (-80),
|
||||||
tcomment=""
|
tcomment="",
|
||||||
|
rttype=RegularTransaction
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
epreceding_comment_lines=""
|
epreceding_comment_lines=""
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user