@@ -197,6 +197,7 @@ defmodule Money do
197197 case validate_currency ( currency_code ) do
198198 { :error , { _exception , message } } ->
199199 { :error , { Money.UnknownCurrencyError , message } }
200+
200201 { :ok , code } ->
201202 format_options = extract_format_options ( options )
202203 % Money { amount: amount , currency: code , format_options: format_options }
@@ -326,6 +327,9 @@ defmodule Money do
326327
327328 * `amount` is a float
328329
330+ * `options` is a keyword list of options passed
331+ to `Money.new/3`. The default is `[]`.
332+
329333 ## Examples
330334
331335 iex> Money.from_float 1.23456, :USD
@@ -339,15 +343,17 @@ defmodule Money do
339343 "Reduce the precision or call Money.new/2 with a Decimal or String amount"}}
340344
341345 """
342- Cldr.Macros . doc_since "2.0.0"
346+ Cldr.Macros . doc_since ( "2.0.0" )
343347 @ max_precision_allowed 15
344- @ spec from_float ( float | currency_code , float | currency_code ) ::
348+ @ spec from_float ( float | currency_code , float | currency_code , Keyword . t ( ) ) ::
345349 Money . t ( ) | { :error , { module ( ) , String . t ( ) } }
346350
347- def from_float ( currency_code , amount )
351+ def from_float ( currency_code , amount , options \\ [ ] )
352+
353+ def from_float ( currency_code , amount , options )
348354 when ( is_binary ( currency_code ) or is_atom ( currency_code ) ) and is_float ( amount ) do
349355 if Cldr.Number . precision ( amount ) <= @ max_precision_allowed do
350- new ( currency_code , Decimal . from_float ( amount ) )
356+ new ( currency_code , Decimal . from_float ( amount ) , options )
351357 else
352358 { :error ,
353359 { Money.InvalidAmountError ,
@@ -358,9 +364,9 @@ defmodule Money do
358364 end
359365 end
360366
361- def from_float ( amount , currency_code )
367+ def from_float ( amount , currency_code , options )
362368 when ( is_binary ( currency_code ) or is_atom ( currency_code ) ) and is_float ( amount ) do
363- from_float ( currency_code , amount )
369+ from_float ( currency_code , amount , options )
364370 end
365371
366372 @ doc """
@@ -379,6 +385,9 @@ defmodule Money do
379385
380386 * `amount` is a float
381387
388+ * `options` is a keyword list of options passed
389+ to `Money.new/3`. The default is `[]`.
390+
382391 ## Examples
383392
384393 iex> Money.from_float!(:USD, 1.234)
@@ -389,16 +398,36 @@ defmodule Money do
389398 (ex_money) lib/money.ex:293: Money.from_float!/2
390399
391400 """
392- Cldr.Macros . doc_since "2.0.0"
393- @ spec from_float! ( currency_code , float ) :: Money . t ( ) | no_return ( )
401+ Cldr.Macros . doc_since ( "2.0.0" )
402+ @ spec from_float! ( currency_code , float , Keyword . t ( ) ) :: Money . t ( ) | no_return ( )
394403
395- def from_float! ( currency_code , amount ) do
396- case from_float ( currency_code , amount ) do
404+ def from_float! ( currency_code , amount , options \\ [ ] ) do
405+ case from_float ( currency_code , amount , options ) do
397406 { :error , { exception , reason } } -> raise exception , reason
398407 money -> money
399408 end
400409 end
401410
411+ @ doc """
412+ Add format options to a `t:Money`.
413+
414+ ## Arguments
415+
416+ * `money` is any valid `t:Money` type returned
417+ by `Money.new/2`
418+
419+ * `options` is a keyword list of options. These
420+ options are used when calling `Money.to_string/2`.
421+ The default is `[]`
422+
423+ """
424+
425+ Cldr.Macros . doc_since ( "5.5.0" )
426+ @ spec put_format_options ( Money . t ( ) , Keyword . t ( ) ) :: Money . t ( )
427+ def put_format_options ( % Money { } = money , options ) when is_list ( options ) do
428+ % { money | format_options: options }
429+ end
430+
402431 @ doc """
403432 Parse a string and return a `Money.t` or an error.
404433
@@ -516,7 +545,7 @@ defmodule Money do
516545 {:error, {Money.ParseError, "Could not parse \\ "USD 100 with trailing text\\ "."}}
517546
518547 """
519- Cldr.Macros . doc_since "3.2.0"
548+ Cldr.Macros . doc_since ( "3.2.0" )
520549 @ spec parse ( String . t ( ) , Keyword . t ( ) ) :: Money . t ( ) | { :error , { module ( ) , String . t ( ) } }
521550
522551 def parse ( string , options \\ [ ] ) do
@@ -672,6 +701,7 @@ defmodule Money do
672701
673702 def to_string ( % Money { } = money , options ) when is_list ( options ) do
674703 default_options = [ backend: Money . default_backend ( ) , currency: money . currency ]
704+
675705 options =
676706 default_options
677707 |> Keyword . merge ( money . format_options )
@@ -814,11 +844,12 @@ defmodule Money do
814844 """
815845 @ spec add ( money_1 :: Money . t ( ) , money_2 :: Money . t ( ) ) ::
816846 { :ok , Money . t ( ) } | { :error , { module ( ) , String . t ( ) } }
817- def add ( % Money { currency: same_currency , amount: amount_a } , % Money {
818- currency: same_currency ,
819- amount: amount_b
820- } ) do
821- { :ok , % Money { currency: same_currency , amount: Decimal . add ( amount_a , amount_b ) } }
847+
848+ def add (
849+ % Money { currency: same_currency , amount: amount_a } ,
850+ % Money { currency: same_currency , amount: amount_b } = money_b
851+ ) do
852+ { :ok , % { money_b | amount: Decimal . add ( amount_a , amount_b ) } }
822853 end
823854
824855 def add ( % Money { currency: code_a } , % Money { currency: code_b } ) do
@@ -885,11 +916,10 @@ defmodule Money do
885916 @ spec sub ( money_1 :: Money . t ( ) , money_2 :: Money . t ( ) ) ::
886917 { :ok , Money . t ( ) } | { :error , { module ( ) , String . t ( ) } }
887918
888- def sub ( % Money { currency: same_currency , amount: amount_a } , % Money {
889- currency: same_currency ,
890- amount: amount_b
891- } ) do
892- { :ok , % Money { currency: same_currency , amount: Decimal . sub ( amount_a , amount_b ) } }
919+ def sub ( % Money { currency: same_currency , amount: amount_a } ,
920+ % Money { currency: same_currency , amount: amount_b } = money_b
921+ ) do
922+ { :ok , % { money_b | amount: Decimal . sub ( amount_a , amount_b ) } }
893923 end
894924
895925 def sub ( % Money { currency: code_a } , % Money { currency: code_b } ) do
@@ -962,16 +992,17 @@ defmodule Money do
962992 """
963993 @ spec mult ( Money . t ( ) , Cldr.Math . number_or_decimal ( ) ) ::
964994 { :ok , Money . t ( ) } | { :error , { module ( ) , String . t ( ) } }
965- def mult ( % Money { currency: code , amount: amount } , number ) when is_integer ( number ) do
966- { :ok , % Money { currency: code , amount: Decimal . mult ( amount , Decimal . new ( number ) ) } }
995+
996+ def mult ( % Money { amount: amount } = money , number ) when is_integer ( number ) do
997+ { :ok , % { money | amount: Decimal . mult ( amount , Decimal . new ( number ) ) } }
967998 end
968999
969- def mult ( % Money { currency: code , amount: amount } , number ) when is_float ( number ) do
970- { :ok , % Money { currency: code , amount: Decimal . mult ( amount , Decimal . from_float ( number ) ) } }
1000+ def mult ( % Money { amount: amount } = money , number ) when is_float ( number ) do
1001+ { :ok , % { money | amount: Decimal . mult ( amount , Decimal . from_float ( number ) ) } }
9711002 end
9721003
973- def mult ( % Money { currency: code , amount: amount } , % Decimal { } = number ) do
974- { :ok , % Money { currency: code , amount: Decimal . mult ( amount , number ) } }
1004+ def mult ( % Money { amount: amount } = money , % Decimal { } = number ) do
1005+ { :ok , % { money | amount: Decimal . mult ( amount , number ) } }
9751006 end
9761007
9771008 def mult ( % Money { } , other ) do
@@ -1040,16 +1071,17 @@ defmodule Money do
10401071 """
10411072 @ spec div ( Money . t ( ) , Cldr.Math . number_or_decimal ( ) ) ::
10421073 { :ok , Money . t ( ) } | { :error , { module ( ) , String . t ( ) } }
1043- def div ( % Money { currency: code , amount: amount } , number ) when is_integer ( number ) do
1044- { :ok , % Money { currency: code , amount: Decimal . div ( amount , Decimal . new ( number ) ) } }
1074+
1075+ def div ( % Money { amount: amount } = money , number ) when is_integer ( number ) do
1076+ { :ok , % { money | amount: Decimal . div ( amount , Decimal . new ( number ) ) } }
10451077 end
10461078
1047- def div ( % Money { currency: code , amount: amount } , number ) when is_float ( number ) do
1048- { :ok , % Money { currency: code , amount: Decimal . div ( amount , Decimal . from_float ( number ) ) } }
1079+ def div ( % Money { amount: amount } = money , number ) when is_float ( number ) do
1080+ { :ok , % { money | amount: Decimal . div ( amount , Decimal . from_float ( number ) ) } }
10491081 end
10501082
1051- def div ( % Money { currency: code , amount: amount } , % Decimal { } = number ) do
1052- { :ok , % Money { currency: code , amount: Decimal . div ( amount , number ) } }
1083+ def div ( % Money { amount: amount } = money , % Decimal { } = number ) do
1084+ { :ok , % { money | amount: Decimal . div ( amount , number ) } }
10531085 end
10541086
10551087 def div ( % Money { } , other ) do
@@ -1161,6 +1193,7 @@ defmodule Money do
11611193 @ spec sum ( [ t ( ) , ... ] , ExchangeRates . t ( ) ) :: { :ok , t } | { :error , { module ( ) , String . t ( ) } }
11621194 def sum ( [ % Money { } = first | rest ] = money_list , rates \\ % { } ) when is_list ( money_list ) do
11631195 % Money { currency: target_currency } = first
1196+
11641197 Enum . reduce_while ( rest , { :ok , first } , fn money , { :ok , acc } ->
11651198 case to_currency ( money , target_currency , rates ) do
11661199 { :ok , increment } -> { :cont , Money . add ( acc , increment ) }
@@ -1533,23 +1566,23 @@ defmodule Money do
15331566 @ one Decimal . new ( 1 )
15341567 @ zero Decimal . new ( 0 )
15351568
1536- def put_fraction ( % Money { currency: code , amount: amount } , upto ) when is_integer ( upto ) do
1537- with { :ok , currency } <- Currency . currency_for_code ( code ) do
1569+ def put_fraction ( % Money { amount: amount } = money , upto ) when is_integer ( upto ) do
1570+ with { :ok , currency } <- Currency . currency_for_code ( money . currency ) do
15381571 digits = currency . digits
15391572 diff = Decimal . from_float ( ( 100 - upto ) * :math . pow ( 10 , - digits ) )
15401573
15411574 if Cldr.Decimal . compare ( diff , @ one ) in [ :lt , :eq ] &&
1542- Cldr.Decimal . compare ( @ zero , diff ) in [ :lt , :eq ] do
1575+ Cldr.Decimal . compare ( @ zero , diff ) in [ :lt , :eq ] do
15431576 new_amount =
15441577 Decimal . round ( amount , 0 )
15451578 |> Decimal . add ( @ one )
15461579 |> Decimal . sub ( diff )
15471580
1548- Money . new ( code , new_amount )
1581+ % { money | amount: new_amount }
15491582 else
15501583 { :error ,
15511584 { Money.InvalidAmountError ,
1552- "Rounding up to #{ inspect ( upto ) } is invalid for currency #{ inspect ( code ) } " } }
1585+ "Rounding up to #{ inspect ( upto ) } is invalid for currency #{ inspect ( money . currency ) } " } }
15531586 end
15541587 end
15551588 end
@@ -1621,12 +1654,12 @@ defmodule Money do
16211654 end
16221655 end
16231656
1624- def to_currency ( % Money { currency: from_currency , amount: amount } , to_currency , % { } = rates )
1625- when is_atom ( to_currency ) do
1657+ def to_currency ( % Money { currency: from_currency , amount: amount } = money , to_currency , rates )
1658+ when is_atom ( to_currency ) and is_map ( rates ) do
16261659 with { :ok , to_currency_code } <- validate_currency ( to_currency ) ,
16271660 { :ok , cross_rate } <- cross_rate ( from_currency , to_currency_code , rates ) do
16281661 converted_amount = Decimal . mult ( amount , cross_rate )
1629- { :ok , Money . new ( to_currency , converted_amount ) }
1662+ { :ok , % { money | currency: to_currency , amount: converted_amount } }
16301663 end
16311664 end
16321665
@@ -1793,14 +1826,15 @@ defmodule Money do
17931826
17941827 """
17951828 @ spec normalize ( Money . t ( ) ) :: Money . t ( )
1796- Cldr.Macros . doc_since "5.0.0"
1829+ Cldr.Macros . doc_since ( "5.0.0" )
1830+
17971831 if Code . ensure_loaded? ( Decimal ) and function_exported? ( Decimal , :normalize , 1 ) do
1798- def normalize ( % Money { currency: currency , amount: amount } ) do
1799- % Money { currency: currency , amount: Decimal . normalize ( amount ) }
1832+ def normalize ( % Money { amount: amount } = money ) do
1833+ % { money | amount: Decimal . normalize ( amount ) }
18001834 end
18011835 else
1802- def normalize ( % Money { currency: currency , amount: amount } ) do
1803- % Money { currency: currency , amount: Decimal . reduce ( amount ) }
1836+ def normalize ( % Money { amount: amount } = money ) do
1837+ % { money | amount: Decimal . reduce ( amount ) }
18041838 end
18051839 end
18061840
@@ -1876,9 +1910,11 @@ defmodule Money do
18761910 * `currency` is the currency code for the `integer`. The assumed
18771911 decimal places is derived from the currency code.
18781912
1913+ * `options` is a keyword list of options passed to `Money.new/3`
1914+
18791915 ## Returns
18801916
1881- * A `Money` struct or
1917+ * A `t: Money` struct or
18821918
18831919 * `{:error, {Cldr.UnknownCurrencyError, message}}`
18841920
@@ -1897,21 +1933,31 @@ defmodule Money do
18971933 #Money<:COP, 200.12>
18981934
18991935 """
1900- @ spec from_integer ( integer , currency_code ) :: Money . t ( ) | { :error , module ( ) , String . t ( ) }
1901- def from_integer ( amount , currency ) when is_integer ( amount ) do
1936+ @ spec from_integer ( integer , currency_code , Keyword . t ( ) ) ::
1937+ Money . t ( ) | { :error , module ( ) , String . t ( ) }
1938+
1939+ def from_integer ( amount , currency , options \\ [ ] ) when is_integer ( amount ) do
19021940 with { :ok , currency } <- validate_currency ( currency ) ,
19031941 { :ok , % { iso_digits: digits } } <- Currency . currency_for_code ( currency ) do
19041942 sign = if amount < 0 , do: - 1 , else: 1
19051943 digits = if digits == 0 , do: 0 , else: - digits
19061944
19071945 sign
19081946 |> Decimal . new ( Kernel . abs ( amount ) , digits )
1909- |> Money . new ( currency )
1947+ |> Money . new ( currency , options )
19101948 end
19111949 end
19121950
19131951 @ doc """
1914- Return a zero amount `Money.t` in the given currency
1952+ Return a zero amount `t:Money` in the given currency.
1953+
1954+ ## Arguments
1955+
1956+ * `money_or_currency` is either a `t:Money` or
1957+ a currency code
1958+
1959+ * `options` is a keyword list of options passed
1960+ to `Money.new/3`. The default is `[]`.
19151961
19161962 ## Example
19171963
@@ -1927,13 +1973,16 @@ defmodule Money do
19271973
19281974 """
19291975 @ spec zero ( currency_code | Money . t ( ) ) :: Money . t ( )
1930- def zero ( % { currency: currency , amount: _amount } ) do
1931- zero ( currency )
1976+
1977+ def zero ( money_or_currency , options \\ [ ] )
1978+
1979+ def zero ( % Money { currency: currency } , options ) do
1980+ zero ( currency , options )
19321981 end
19331982
1934- def zero ( currency ) do
1983+ def zero ( currency , options ) do
19351984 with { :ok , currency } <- validate_currency ( currency ) do
1936- Money . new ( currency , 0 )
1985+ Money . new ( currency , 0 , options )
19371986 end
19381987 end
19391988
0 commit comments