1 {-| 2 3 A 'Commodity' is a symbol representing a currency or some other kind of 4 thing we are tracking, and some display preferences that tell how to 5 display 'Amount's of the commodity - is the symbol on the left or right, 6 are thousands separated by comma, significant decimal places and so on. 7 8 -} 9 module Hledger.Data.Commodity 10 where 11 import Data.List 12 import Data.Map ((!)) 13 import Data.Maybe 14 import Test.HUnit 15 import qualified Data.Map as Map 16 17 import Hledger.Data.Types 18 import Hledger.Utils 19 20 21 nonsimplecommoditychars = "0123456789-.@;\n \"" 22 23 quoteCommoditySymbolIfNeeded s | any (`elem` nonsimplecommoditychars) s = "\"" ++ s ++ "\"" 24 | otherwise = s 25 26 -- convenient amount and commodity constructors, for tests etc. 27 28 unknown = Commodity {symbol="", side=L,spaced=False,decimalpoint='.',precision=0,separator=',',separatorpositions=[]} 29 dollar = Commodity {symbol="$",side=L,spaced=False,decimalpoint='.',precision=2,separator=',',separatorpositions=[]} 30 euro = Commodity {symbol="€",side=L,spaced=False,decimalpoint='.',precision=2,separator=',',separatorpositions=[]} 31 pound = Commodity {symbol="£",side=L,spaced=False,decimalpoint='.',precision=2,separator=',',separatorpositions=[]} 32 hour = Commodity {symbol="h",side=R,spaced=False,decimalpoint='.',precision=1,separator=',',separatorpositions=[]} 33 34 dollars n = Amount dollar n Nothing 35 euros n = Amount euro n Nothing 36 pounds n = Amount pound n Nothing 37 hours n = Amount hour n Nothing 38 39 defaultcommodities = [dollar, euro, pound, hour, unknown] 40 41 -- | Look up one of the hard-coded default commodities. For use in tests. 42 comm :: String -> Commodity 43 comm sym = fromMaybe 44 (error' "commodity lookup failed") 45 $ find (\(Commodity{symbol=s}) -> s==sym) defaultcommodities 46 47 -- | Find the conversion rate between two commodities. Currently returns 1. 48 conversionRate :: Commodity -> Commodity -> Double 49 conversionRate _ _ = 1 50 51 -- | Convert a list of commodities to a map from commodity symbols to 52 -- unique, display-preference-canonicalised commodities. 53 canonicaliseCommodities :: [Commodity] -> Map.Map String Commodity 54 canonicaliseCommodities cs = 55 Map.fromList [(s,firstc{precision=maxp}) | s <- symbols, 56 let cs = commoditymap ! s, 57 let firstc = head cs, 58 let maxp = maximum $ map precision cs 59 ] 60 where 61 commoditymap = Map.fromList [(s, commoditieswithsymbol s) | s <- symbols] 62 commoditieswithsymbol s = filter ((s==) . symbol) cs 63 symbols = nub $ map symbol cs 64 65 tests_Hledger_Data_Commodity = TestList [ 66 ] 67