simple currency handling

This commit is contained in:
Simon Michael 2007-02-20 00:21:57 +00:00
parent c370d34de6
commit 3de3e861ee
5 changed files with 70 additions and 33 deletions

View File

@ -4,40 +4,80 @@ where
import Utils import Utils
type Date = String type Date = String
type Status = Bool
-- 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
-- amounts -- amounts
-- amount arithmetic currently ignores currency conversion {- a simple amount is a currency, quantity pair:
0
$1
£-50
EUR 3.44
HRS 1.5
DAYS 3
GOOG 500
a mixed amount is one or more simple amounts:
$50, EUR 3, APPL 500
HRS 16, $13.55, oranges 6
arithmetic:
$1 - $5 = $-4
$1 + EUR 0.76 = $2
EUR0.76 + $1 = EUR 1.52
EUR0.76 - $1 = 0
($5, HRS 2) + $1 = ($6, HRS 2)
($50, EUR 3, APPL 500) + ($13.55, oranges 6) = $67.51, APPL 500, oranges 6
($50, EUR 3) * $-1 = $-53.96
($50, APPL 500) * $-1 = error
-}
type Currency = String
data Amount = Amount { data Amount = Amount {
currency :: String, currency :: Currency,
quantity :: Double quantity :: Double
} deriving (Eq,Ord) } deriving (Eq,Ord)
instance Show Amount where show = showAmountRoundedOrZero
showAmountRoundedOrZero :: Amount -> String
showAmountRoundedOrZero (Amount cur qty) =
let rounded = printf "%.2f" qty in
case rounded of
"0.00" -> "0"
"-0.00" -> "0"
otherwise -> cur ++ rounded
instance Num Amount where instance Num Amount where
abs (Amount c q) = Amount c (abs q) abs (Amount c q) = Amount c (abs q)
signum (Amount c q) = Amount c (signum q) signum (Amount c q) = Amount c (signum q)
fromInteger i = Amount "$" (fromInteger i) fromInteger i = Amount "$" (fromInteger i)
(+) = amountAdd (+) = amountAdd
(-) = amountSub (-) = amountSub
(*) = amountMult (*) = amountMul
Amount ca qa `amountAdd` Amount cb qb = Amount ca (qa + qb) Amount ac aq `amountAdd` b = Amount ac (aq + (quantity $ toCurrency ac b))
Amount ca qa `amountSub` Amount cb qb = Amount ca (qa - qb) Amount ac aq `amountSub` b = Amount ac (aq - (quantity $ toCurrency ac b))
Amount ca qa `amountMult` Amount cb qb = Amount ca (qa * qb) Amount ac aq `amountMul` b = Amount ac (aq * (quantity $ toCurrency ac b))
instance Show Amount where show = amountRoundedOrZero toCurrency :: Currency -> Amount -> Amount
toCurrency newc (Amount oldc q) =
Amount newc (q * (conversionRate oldc newc))
amountRoundedOrZero :: Amount -> String conversionRate :: Currency -> Currency -> Double
amountRoundedOrZero (Amount cur qty) = conversionRate oldc newc = (rate newc) / (rate oldc)
let rounded = printf "%.2f" qty in
case rounded of
"0.00" -> "0"
"-0.00" -> "0"
otherwise -> cur ++ rounded
-- generic tree. each node is a tuple of the node type and a rate :: Currency -> Double
-- list of subtrees rate "$" = 1.0
newtype Tree a = Tree { node :: (a, [Tree a]) } deriving (Show,Eq) rate "EUR" = 0.760383
branches = snd . node rate "£" = 0.512527
rate _ = 1
data MixedAmount = MixedAmount [Amount] deriving (Eq,Ord)

View File

@ -6,6 +6,8 @@ import BasicTypes
import Transaction import Transaction
type EntryStatus = Bool
-- a register entry is displayed as two or more lines like this: -- a register entry is displayed as two or more lines like this:
-- date description account amount balance -- date description account amount balance
-- DDDDDDDDDD dddddddddddddddddddd aaaaaaaaaaaaaaaaaaaaaa AAAAAAAAAAA AAAAAAAAAAAA -- DDDDDDDDDD dddddddddddddddddddd aaaaaaaaaaaaaaaaaaaaaa AAAAAAAAAAA AAAAAAAAAAAA
@ -19,7 +21,7 @@ import Transaction
data Entry = Entry { data Entry = Entry {
edate :: Date, edate :: Date,
estatus :: Status, estatus :: EntryStatus,
ecode :: String, ecode :: String,
edescription :: String, edescription :: String,
etransactions :: [Transaction] etransactions :: [Transaction]

View File

@ -68,5 +68,5 @@ showTransactionAndBalance t b =
(replicate 32 ' ') ++ (showTransaction $ transaction t) ++ (showBalance b) (replicate 32 ' ') ++ (showTransaction $ transaction t) ++ (showBalance b)
showBalance :: Amount -> String showBalance :: Amount -> String
showBalance b = printf " %12s" (amountRoundedOrZero b) showBalance b = printf " %12s" (showAmountRoundedOrZero b)

10
TODO
View File

@ -1,15 +1,17 @@
make it fast
profile
basic features basic features
handle mixed amounts and currencies balance report account matching
-f -
print print
entry entry
-j and -J graph data output -j and -J graph data output
!include !include
read timelog files read timelog files
make it fast
profile
more features more features
handle mixed amounts
3.0-style elision 3.0-style elision
-p period expressions -p period expressions
-d display expressions -d display expressions

View File

@ -86,13 +86,6 @@ 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 $ showLedgerAccounts ledger acctpats depth
-- where
-- (acctpats,_) = ledgerPatternArgs args
-- showsubs = (ShowSubs `elem` opts)
-- depth = case showsubs of
-- True -> 999
-- False -> depthOption opts
putStr $ case showsubs of putStr $ case showsubs of
True -> showLedgerAccounts ledger 999 True -> showLedgerAccounts ledger 999
False -> showLedgerAccounts ledger 1 False -> showLedgerAccounts ledger 1