use MixedAmount everywhere. seems to work.
This commit is contained in:
parent
4f83326f14
commit
648887b36f
@ -47,6 +47,22 @@ import Ledger.Commodity
|
||||
instance Show Amount where show = showAmount
|
||||
-- instance Show MixedAmount where show = showMixedAmount
|
||||
|
||||
instance Num Amount where
|
||||
abs (Amount c q) = Amount c (abs q)
|
||||
signum (Amount c q) = Amount c (signum q)
|
||||
fromInteger i = Amount (comm "") (fromInteger i)
|
||||
(+) = amountop (+)
|
||||
(-) = amountop (-)
|
||||
(*) = amountop (*)
|
||||
|
||||
instance Num MixedAmount where
|
||||
abs = error "programming error, mixed amounts do not support abs"
|
||||
signum = error "programming error, mixed amounts do not support signum"
|
||||
fromInteger i = [Amount (comm "") (fromInteger i)]
|
||||
negate = map negate
|
||||
(+) = (++)
|
||||
(*) = error "programming error, mixed amounts do not support multiplication"
|
||||
|
||||
showMixedAmount :: MixedAmount -> String
|
||||
showMixedAmount as = concat $ intersperse ", " $ map show $ normaliseMixedAmount as
|
||||
|
||||
@ -60,9 +76,6 @@ groupAmountsByCommodity as = grouped
|
||||
hassymbol s a = s == (symbol $ commodity a)
|
||||
symbols = sort $ nub $ map (symbol . commodity) as
|
||||
|
||||
-- samecommoditysymbol Amount{commodity=c1} Amount{commodity=c2} = samesymbol c1 c2
|
||||
-- samesymbol Commodity{symbol=s1} Commodity{symbol=s2} = s1==s2
|
||||
|
||||
-- | Get the string representation of an amount, based on its commodity's
|
||||
-- display settings.
|
||||
showAmount :: Amount -> String
|
||||
@ -91,6 +104,12 @@ showAmountOrZero a
|
||||
| isZeroAmount a = "0"
|
||||
| otherwise = showAmount a
|
||||
|
||||
-- | Get the string representation of an amount, rounded, or showing just "0" if it's zero.
|
||||
showMixedAmountOrZero :: MixedAmount -> String
|
||||
showMixedAmountOrZero a
|
||||
| isZeroMixedAmount a = "0"
|
||||
| otherwise = showMixedAmount a
|
||||
|
||||
-- | is this amount zero, when displayed with its given precision ?
|
||||
isZeroAmount :: Amount -> Bool
|
||||
isZeroAmount a@(Amount c _ ) = nonzerodigits == ""
|
||||
@ -99,14 +118,6 @@ isZeroAmount a@(Amount c _ ) = nonzerodigits == ""
|
||||
isZeroMixedAmount :: MixedAmount -> Bool
|
||||
isZeroMixedAmount = all isZeroAmount . normaliseMixedAmount
|
||||
|
||||
instance Num Amount where
|
||||
abs (Amount c q) = Amount c (abs q)
|
||||
signum (Amount c q) = Amount c (signum q)
|
||||
fromInteger i = Amount (comm "") (fromInteger i)
|
||||
(+) = amountop (+)
|
||||
(-) = amountop (-)
|
||||
(*) = amountop (*)
|
||||
|
||||
-- | Apply a binary arithmetic operator to two amounts, converting to the
|
||||
-- second one's commodity and adopting the lowest precision. (Using the
|
||||
-- second commodity means that folds (like sum [Amount]) will preserve the
|
||||
@ -128,7 +139,7 @@ sumAmounts = sum . filter (not . isZeroAmount)
|
||||
sumMixedAmounts :: [MixedAmount] -> MixedAmount
|
||||
sumMixedAmounts = concat
|
||||
|
||||
nullamt = Amount (comm "") 0
|
||||
nullamt = []
|
||||
|
||||
-- temporary value for partial entries
|
||||
autoamt = Amount (Commodity {symbol="AUTO",side=L,spaced=False,comma=False,precision=0,rate=1}) 0
|
||||
autoamt = [Amount (Commodity {symbol="AUTO",side=L,spaced=False,comma=False,precision=0,rate=1}) 0]
|
||||
|
||||
@ -53,7 +53,7 @@ showEntry e =
|
||||
showtxn t = showacct t ++ " " ++ (showamount $ tamount t) ++ (showcomment $ tcomment t)
|
||||
showtxnnoamt t = showacct t ++ " " ++ (showcomment $ tcomment t)
|
||||
showacct t = " " ++ (showaccountname $ taccount t)
|
||||
showamount = printf "%12s" . showAmount
|
||||
showamount = printf "%12s" . showMixedAmount
|
||||
showaccountname s = printf "%-34s" s
|
||||
showcomment s = if (length s) > 0 then " ; "++s else ""
|
||||
|
||||
@ -77,9 +77,9 @@ balanceEntry e@(Entry{etransactions=ts}) = e{etransactions=ts'}
|
||||
1 -> map balance ts
|
||||
otherwise -> error $ "could not balance this entry, too many missing amounts:\n" ++ show e
|
||||
otherstotal = sumRawTransactions withamounts
|
||||
simpleotherstotal
|
||||
| length otherstotal == 1 = head otherstotal
|
||||
| otherwise = error $ "sorry, can't balance a mixed-commodity entry yet:\n" ++ show e
|
||||
-- simpleotherstotal
|
||||
-- | length otherstotal == 1 = head otherstotal
|
||||
-- | otherwise = error $ "sorry, can't balance a mixed-commodity entry yet:\n" ++ show e
|
||||
balance t
|
||||
| isReal t && not (hasAmount t) = t{tamount = -simpleotherstotal}
|
||||
| isReal t && not (hasAmount t) = t{tamount = -otherstotal}
|
||||
| otherwise = t
|
||||
|
||||
@ -301,7 +301,7 @@ ledgeraccountname = do
|
||||
accountnamechar = notFollowedBy (oneOf "()[]") >> nonspace
|
||||
<?> "account name character (non-bracket, non-parenthesis, non-whitespace)"
|
||||
|
||||
transactionamount :: Parser Amount
|
||||
transactionamount :: Parser MixedAmount
|
||||
transactionamount =
|
||||
try (do
|
||||
many1 spacenonewline
|
||||
@ -309,29 +309,29 @@ transactionamount =
|
||||
return a
|
||||
) <|> return autoamt
|
||||
|
||||
leftsymbolamount :: Parser Amount
|
||||
leftsymbolamount :: Parser MixedAmount
|
||||
leftsymbolamount = do
|
||||
sym <- commoditysymbol
|
||||
sp <- many spacenonewline
|
||||
(q,p,comma) <- amountquantity
|
||||
let c = Commodity {symbol=sym,side=L,spaced=not $ null sp,comma=comma,precision=p,rate=1}
|
||||
return $ Amount c q
|
||||
return [Amount c q]
|
||||
<?> "left-symbol amount"
|
||||
|
||||
rightsymbolamount :: Parser Amount
|
||||
rightsymbolamount :: Parser MixedAmount
|
||||
rightsymbolamount = do
|
||||
(q,p,comma) <- amountquantity
|
||||
sp <- many spacenonewline
|
||||
sym <- commoditysymbol
|
||||
let c = Commodity {symbol=sym,side=R,spaced=not $ null sp,comma=comma,precision=p,rate=1}
|
||||
return $ Amount c q
|
||||
return [Amount c q]
|
||||
<?> "right-symbol amount"
|
||||
|
||||
nosymbolamount :: Parser Amount
|
||||
nosymbolamount :: Parser MixedAmount
|
||||
nosymbolamount = do
|
||||
(q,p,comma) <- amountquantity
|
||||
let c = Commodity {symbol="",side=L,spaced=False,comma=comma,precision=p,rate=1}
|
||||
return $ Amount c q
|
||||
return [Amount c q]
|
||||
<?> "no-symbol amount"
|
||||
|
||||
commoditysymbol :: Parser String
|
||||
|
||||
@ -11,6 +11,7 @@ import qualified Data.Map as Map
|
||||
import Ledger.Utils
|
||||
import Ledger.Types
|
||||
import Ledger.AccountName
|
||||
import Ledger.Amount
|
||||
import Ledger.Entry
|
||||
import Ledger.Transaction
|
||||
|
||||
@ -104,10 +105,9 @@ normaliseRawLedgerAmounts l@(RawLedger ms ps es f) = RawLedger ms ps es' f
|
||||
normaliseEntryAmounts (Entry d s c desc comm ts pre) = Entry d s c desc comm ts' pre
|
||||
where ts' = map normaliseRawTransactionAmounts ts
|
||||
normaliseRawTransactionAmounts (RawTransaction acct a c t) = RawTransaction acct a' c t
|
||||
where a' = normaliseAmount a
|
||||
normaliseAmount (Amount c q) = Amount (firstoccurrenceof c) q
|
||||
where a' = normaliseMixedAmount a
|
||||
firstcommodities = nubBy samesymbol $ allcommodities
|
||||
allcommodities = map (commodity . amount) $ rawLedgerTransactions l
|
||||
allcommodities = map commodity $ concat $ map amount $ rawLedgerTransactions l
|
||||
samesymbol (Commodity {symbol=s1}) (Commodity {symbol=s2}) = s1==s2
|
||||
firstoccurrenceof c@(Commodity {symbol=s}) =
|
||||
fromMaybe
|
||||
|
||||
@ -20,7 +20,7 @@ showRawTransaction (RawTransaction a amt _ ttype) =
|
||||
showaccountname a ++ " " ++ (showamount amt)
|
||||
where
|
||||
showaccountname = printf "%-22s" . bracket . elideAccountName width
|
||||
showamount = printf "%12s" . showAmountOrZero
|
||||
showamount = printf "%12s" . showMixedAmountOrZero
|
||||
(bracket,width) = case ttype of
|
||||
BalancedVirtualTransaction -> (\s -> "["++s++"]", 20)
|
||||
VirtualTransaction -> (\s -> "("++s++")", 20)
|
||||
@ -30,7 +30,7 @@ isReal :: RawTransaction -> Bool
|
||||
isReal t = rttype t == RegularTransaction
|
||||
|
||||
hasAmount :: RawTransaction -> Bool
|
||||
hasAmount = ("AUTO" /=) . symbol . commodity . tamount
|
||||
hasAmount = (/= autoamt) . tamount
|
||||
|
||||
sumRawTransactions :: [RawTransaction] -> MixedAmount
|
||||
sumRawTransactions = normaliseMixedAmount . map tamount
|
||||
sumRawTransactions = normaliseMixedAmount . sumMixedAmounts . map tamount
|
||||
|
||||
@ -57,7 +57,7 @@ entryFromTimeLogInOut i o =
|
||||
showdate = formatTime defaultTimeLocale "%Y/%m/%d"
|
||||
intime = parsedatetime $ tldatetime i
|
||||
outtime = parsedatetime $ tldatetime o
|
||||
amount = hours $ realToFrac (diffUTCTime outtime intime) / 3600
|
||||
amount = [hours $ realToFrac (diffUTCTime outtime intime) / 3600]
|
||||
txns = [RawTransaction acctname amount "" RegularTransaction
|
||||
--,RawTransaction "assets:time" (-amount) "" RegularTransaction
|
||||
]
|
||||
|
||||
@ -30,7 +30,6 @@ accountNamesFromTransactions :: [Transaction] -> [AccountName]
|
||||
accountNamesFromTransactions ts = nub $ map account ts
|
||||
|
||||
sumTransactions :: [Transaction] -> MixedAmount
|
||||
-- sumTransactions = sum . map amount
|
||||
sumTransactions = map amount
|
||||
sumTransactions = sumMixedAmounts . map amount
|
||||
|
||||
nulltxn = Transaction 0 "" "" "" nullamt RegularTransaction
|
||||
|
||||
@ -41,7 +41,7 @@ data TransactionType = RegularTransaction | VirtualTransaction | BalancedVirtual
|
||||
|
||||
data RawTransaction = RawTransaction {
|
||||
taccount :: AccountName,
|
||||
tamount :: Amount,
|
||||
tamount :: MixedAmount,
|
||||
tcomment :: String,
|
||||
rttype :: TransactionType
|
||||
} deriving (Eq)
|
||||
@ -90,7 +90,7 @@ data Transaction = Transaction {
|
||||
date :: Date,
|
||||
description :: String,
|
||||
account :: AccountName,
|
||||
amount :: Amount,
|
||||
amount :: MixedAmount,
|
||||
ttype :: TransactionType
|
||||
} deriving (Eq)
|
||||
|
||||
|
||||
@ -35,19 +35,19 @@ showRegisterReport opts args l = showtxns ts nulltxn nullamt
|
||||
-- show transactions, one per line, with a running balance
|
||||
showtxns [] _ _ = ""
|
||||
showtxns (t@Transaction{amount=a}:ts) tprev bal =
|
||||
(if isZeroAmount a then "" else this) ++ showtxns ts t bal'
|
||||
(if isZeroMixedAmount a then "" else this) ++ showtxns ts t bal'
|
||||
where
|
||||
this = showtxn (t `issame` tprev) t bal'
|
||||
issame t1 t2 = entryno t1 == entryno t2
|
||||
bal' = bal + amount t
|
||||
|
||||
-- show one transaction line, with or without the entry details
|
||||
showtxn :: Bool -> Transaction -> Amount -> String
|
||||
showtxn :: Bool -> Transaction -> MixedAmount -> String
|
||||
showtxn omitdesc t b = entrydesc ++ txn ++ bal ++ "\n"
|
||||
where
|
||||
entrydesc = if omitdesc then replicate 32 ' ' else printf "%s %s " date desc
|
||||
date = showDate $ da
|
||||
desc = printf "%-20s" $ elideRight 20 de :: String
|
||||
txn = showRawTransaction $ RawTransaction a amt "" tt
|
||||
bal = printf " %12s" (showAmountOrZero b)
|
||||
bal = printf " %12s" (showMixedAmountOrZero b)
|
||||
Transaction{date=da,description=de,account=a,amount=amt,ttype=tt} = t
|
||||
|
||||
38
Tests.hs
38
Tests.hs
@ -78,7 +78,7 @@ unittests = TestList [
|
||||
,
|
||||
"balanceEntry" ~: do
|
||||
assertequal
|
||||
(dollars (-47.18))
|
||||
[dollars (-47.18)]
|
||||
(tamount $ last $ etransactions $ balanceEntry entry1)
|
||||
,
|
||||
"punctuatethousands" ~: punctuatethousands "" @?= ""
|
||||
@ -103,8 +103,8 @@ unittests = TestList [
|
||||
assertequal 15 (length $ Map.keys $ accountmap $ cacheLedger rawledger7)
|
||||
,
|
||||
"transactionamount" ~: do
|
||||
assertparseequal (dollars 47.18) (parsewith transactionamount " $47.18")
|
||||
assertparseequal (Amount (Commodity {symbol="$",side=L,spaced=False,comma=False,precision=0,rate=1}) 1) (parsewith transactionamount " $1.")
|
||||
assertparseequal [dollars 47.18] (parsewith transactionamount " $47.18")
|
||||
assertparseequal [Amount (Commodity {symbol="$",side=L,spaced=False,comma=False,precision=0,rate=1}) 1] (parsewith transactionamount " $1.")
|
||||
]
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
@ -215,7 +215,7 @@ balancecommandtests = TestList [
|
||||
]
|
||||
|
||||
registercommandtests = TestList [
|
||||
"register does something" ~:
|
||||
"register report" ~:
|
||||
do
|
||||
l <- ledgerfromfile "sample.ledger"
|
||||
assertequal (
|
||||
@ -243,7 +243,7 @@ assertparseequal expected parsed = either printParseError (assertequal expected)
|
||||
|
||||
rawtransaction1_str = " expenses:food:dining $10.00\n"
|
||||
|
||||
rawtransaction1 = RawTransaction "expenses:food:dining" (dollars 10) "" RegularTransaction
|
||||
rawtransaction1 = RawTransaction "expenses:food:dining" [dollars 10] "" RegularTransaction
|
||||
|
||||
entry1_str = "\
|
||||
\2007/01/28 coopportunity\n\
|
||||
@ -253,8 +253,8 @@ entry1_str = "\
|
||||
|
||||
entry1 =
|
||||
(Entry "2007/01/28" False "" "coopportunity" ""
|
||||
[RawTransaction "expenses:food:groceries" (dollars 47.18) "" RegularTransaction,
|
||||
RawTransaction "assets:checking" (dollars (-47.18)) "" RegularTransaction] "")
|
||||
[RawTransaction "expenses:food:groceries" [dollars 47.18] "" RegularTransaction,
|
||||
RawTransaction "assets:checking" [dollars (-47.18)] "" RegularTransaction] "")
|
||||
|
||||
|
||||
entry2_str = "\
|
||||
@ -398,13 +398,13 @@ rawledger7 = RawLedger
|
||||
etransactions=[
|
||||
RawTransaction {
|
||||
taccount="assets:cash",
|
||||
tamount=dollars 4.82,
|
||||
tamount=[dollars 4.82],
|
||||
tcomment="",
|
||||
rttype=RegularTransaction
|
||||
},
|
||||
RawTransaction {
|
||||
taccount="equity:opening balances",
|
||||
tamount=dollars (-4.82),
|
||||
tamount=[dollars (-4.82)],
|
||||
tcomment="",
|
||||
rttype=RegularTransaction
|
||||
}
|
||||
@ -421,13 +421,13 @@ rawledger7 = RawLedger
|
||||
etransactions=[
|
||||
RawTransaction {
|
||||
taccount="expenses:vacation",
|
||||
tamount=dollars 179.92,
|
||||
tamount=[dollars 179.92],
|
||||
tcomment="",
|
||||
rttype=RegularTransaction
|
||||
},
|
||||
RawTransaction {
|
||||
taccount="assets:checking",
|
||||
tamount=dollars (-179.92),
|
||||
tamount=[dollars (-179.92)],
|
||||
tcomment="",
|
||||
rttype=RegularTransaction
|
||||
}
|
||||
@ -444,13 +444,13 @@ rawledger7 = RawLedger
|
||||
etransactions=[
|
||||
RawTransaction {
|
||||
taccount="assets:saving",
|
||||
tamount=dollars 200,
|
||||
tamount=[dollars 200],
|
||||
tcomment="",
|
||||
rttype=RegularTransaction
|
||||
},
|
||||
RawTransaction {
|
||||
taccount="assets:checking",
|
||||
tamount=dollars (-200),
|
||||
tamount=[dollars (-200)],
|
||||
tcomment="",
|
||||
rttype=RegularTransaction
|
||||
}
|
||||
@ -467,13 +467,13 @@ rawledger7 = RawLedger
|
||||
etransactions=[
|
||||
RawTransaction {
|
||||
taccount="expenses:food:dining",
|
||||
tamount=dollars 4.82,
|
||||
tamount=[dollars 4.82],
|
||||
tcomment="",
|
||||
rttype=RegularTransaction
|
||||
},
|
||||
RawTransaction {
|
||||
taccount="assets:cash",
|
||||
tamount=dollars (-4.82),
|
||||
tamount=[dollars (-4.82)],
|
||||
tcomment="",
|
||||
rttype=RegularTransaction
|
||||
}
|
||||
@ -490,13 +490,13 @@ rawledger7 = RawLedger
|
||||
etransactions=[
|
||||
RawTransaction {
|
||||
taccount="expenses:phone",
|
||||
tamount=dollars 95.11,
|
||||
tamount=[dollars 95.11],
|
||||
tcomment="",
|
||||
rttype=RegularTransaction
|
||||
},
|
||||
RawTransaction {
|
||||
taccount="assets:checking",
|
||||
tamount=dollars (-95.11),
|
||||
tamount=[dollars (-95.11)],
|
||||
tcomment="",
|
||||
rttype=RegularTransaction
|
||||
}
|
||||
@ -513,13 +513,13 @@ rawledger7 = RawLedger
|
||||
etransactions=[
|
||||
RawTransaction {
|
||||
taccount="liabilities:credit cards:discover",
|
||||
tamount=dollars 80,
|
||||
tamount=[dollars 80],
|
||||
tcomment="",
|
||||
rttype=RegularTransaction
|
||||
},
|
||||
RawTransaction {
|
||||
taccount="assets:checking",
|
||||
tamount=dollars (-80),
|
||||
tamount=[dollars (-80)],
|
||||
tcomment="",
|
||||
rttype=RegularTransaction
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user