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