changed CHANGELOG.md
 
@@ -2,6 2,20 @@
2
2
3
3
**Note** `ex_money` 5.17.0 and later is supported on Elixir 1.12 and later versions only.
4
4
5
## Money v5.17.1
6
7
This is the changelog for Money v5.17.1 released on September 6th, 2024. For older changelogs please consult the release tag on [GitHub](https://github.com/kipcole9/money/tags)
8
9
### Bug Fixes
10
11
* Update `poison` optional dependency to allow `~> 6.0`.
12
13
* Update `stream_data` test dependency to `~> 1.0`.
14
15
### Enhancements
16
17
* Improve specs and broaden dialyzer configuration.
18
5
19
## Money v5.17.0
6
20
7
21
This is the changelog for Money v5.17.0 released on May 28th, 2024. For older changelogs please consult the release tag on [GitHub](https://github.com/kipcole9/money/tags)
 
@@ -24,9 38,9 @@ This is the changelog for Money v5.16.0 released on April 21st, 2024. For older
24
38
25
39
### Bug Fixes
26
40
27
- * WHen parsing numbers, use the localized number system separators where they exist. Thanks to @pshoukry for the report. Closes #167.
41
* When parsing numbers, use the localized number system separators where they exist. Thanks to @pshoukry for the report. Closes #167.
28
42
29
- * Surface errors when starting the exchange rates retrieveer. Thanks to @danschultzer for the PR. Closes #165.
43
* Surface errors when starting the exchange rates retriever. Thanks to @danschultzer for the PR. Closes #165.
30
44
31
45
### Enhancements
32
46
 
@@ -84,7 98,7 @@ This is the changelog for Money v5.14.1 released on July 23rd, 2023. For older
84
98
85
99
### Bug Fixes
86
100
87
- * Fix `Looger.warn/1` warnings by moving to `Logger.warning/1`.
101
* Fix `Logger.warn/1` warnings by moving to `Logger.warning/1`.
88
102
89
103
* Fix failing test case.
changed hex_metadata.config
 
@@ -1,11 1,11 @@
1
1
{<<"links">>,
2
2
[{<<"Changelog">>,
3
- <<"https://github.com/kipcole9/money/blob/v5.17.0/CHANGELOG.md">>},
3
<<"https://github.com/kipcole9/money/blob/v5.17.1/CHANGELOG.md">>},
4
4
{<<"GitHub">>,<<"https://github.com/kipcole9/money">>},
5
5
{<<"Readme">>,
6
- <<"https://github.com/kipcole9/money/blob/v5.17.0/README.md">>}]}.
6
<<"https://github.com/kipcole9/money/blob/v5.17.1/README.md">>}]}.
7
7
{<<"name">>,<<"ex_money">>}.
8
- {<<"version">>,<<"5.17.0">>}.
8
{<<"version">>,<<"5.17.1">>}.
9
9
{<<"description">>,
10
10
<<"Money functions for operations on and localization of a money data type with support\nfor ISO 4217 currencies and ISO 24165 digial tokens (crypto currencies).">>}.
11
11
{<<"elixir">>,<<"~> 1.12">>}.
 
@@ -54,7 54,7 @@
54
54
[{<<"name">>,<<"poison">>},
55
55
{<<"app">>,<<"poison">>},
56
56
{<<"optional">>,true},
57
- {<<"requirement">>,<<"~> 3.0 or ~> 4.0 or ~> 5.0">>},
57
{<<"requirement">>,<<"~> 3.0 or ~> 4.0 or ~> 5.0 or ~> 6.0">>},
58
58
{<<"repository">>,<<"hexpm">>}],
59
59
[{<<"name">>,<<"phoenix_html">>},
60
60
{<<"app">>,<<"phoenix_html">>},
changed lib/money.ex
 
@@ -760,7 760,7 @@ defmodule Money do
760
760
761
761
"""
762
762
@spec to_string(Money.t(), Keyword.t() | Cldr.Number.Format.Options.t()) ::
763
- {:ok, String.t()} | {:error, {atom, String.t()}}
763
{:ok, String.t()} | {:error, {module, String.t()}}
764
764
765
765
def to_string(money, options \\ [])
766
766
 
@@ -1595,7 1595,7 @@ defmodule Money do
1595
1595
Money.new(:JPY, "124")
1596
1596
1597
1597
"""
1598
- @spec round(Money.t(), Keyword.t()) :: Money.t()
1598
@spec round(Money.t(), Keyword.t()) :: Money.t() | {:error, {module(), binary()}}
1599
1599
def round(money, opts \\ [])
1600
1600
1601
1601
# Digital tokens don't have rounding
 
@@ -2164,24 2164,28 @@ defmodule Money do
2164
2164
defp digits_from_options(currency_data, options) when is_list(options) do
2165
2165
{fractional_digits, options} = Keyword.pop(options, :fractional_digits)
2166
2166
2167
- with {:ok, digits} <- digits_from_options(currency_data, fractional_digits) do
2167
with {:ok, digits} <- do_digits_from_options(currency_data, fractional_digits) do
2168
2168
{:ok, -digits, options}
2169
else
2170
:error -> {:error, invalid_digits_error(fractional_digits)}
2171
other -> other
2169
2172
end
2170
2173
end
2171
2174
2172
- defp digits_from_options(currency_data, :iso), do: Map.fetch(currency_data, :iso_digits)
2173
- defp digits_from_options(currency_data, nil), do: Map.fetch(currency_data, :iso_digits)
2174
- defp digits_from_options(currency_data, :cash), do: Map.fetch(currency_data, :cash_digits)
2175
- defp digits_from_options(currency_data, :accounting), do: Map.fetch(currency_data, :digits)
2175
defp do_digits_from_options(currency_data, :iso), do: Map.fetch(currency_data, :iso_digits)
2176
defp do_digits_from_options(currency_data, nil), do: Map.fetch(currency_data, :iso_digits)
2177
defp do_digits_from_options(currency_data, :cash), do: Map.fetch(currency_data, :cash_digits)
2178
defp do_digits_from_options(currency_data, :accounting), do: Map.fetch(currency_data, :digits)
2176
2179
2177
- defp digits_from_options(_currency_data, integer) when is_integer(integer) and integer >= 0,
2180
defp do_digits_from_options(_currency_data, integer) when is_integer(integer) and integer >= 0,
2178
2181
do: {:ok, integer}
2179
2182
2180
- defp digits_from_options(_currency_data, other),
2181
- do:
2182
- {:error,
2183
- {Money.InvalidDigitsError,
2184
- "Unknown or invalid :fractional_digits option found: #{inspect(other)}"}}
2183
defp do_digits_from_options(_currency_data, other),
2184
do: {:error, invalid_digits_error(other)}
2185
2186
defp invalid_digits_error(other), do:
2187
{Money.InvalidDigitsError,
2188
"Unknown or invalid :fractional_digits option found: #{inspect(other)}"}
2185
2189
2186
2190
@doc """
2187
2191
Return a zero amount `t:Money.t/0` in the given currency.
 
@@ -2189,7 2193,7 @@ defmodule Money do
2189
2193
## Arguments
2190
2194
2191
2195
* `money_or_currency` is either a `t:Money.t/0` or
2192
- a currency code
2196
a currency code.
2193
2197
2194
2198
* `options` is a keyword list of options passed
2195
2199
to `Money.new/3`. The default is `[]`.
 
@@ -2207,7 2211,7 @@ defmodule Money do
2207
2211
{:error, {Cldr.UnknownCurrencyError, "The currency :ZZZ is invalid"}}
2208
2212
2209
2213
"""
2210
- @spec zero(currency_code | Money.t()) :: Money.t()
2214
@spec zero(currency_code | Money.t()) :: Money.t() | {:error, {module(), binary()}}
2211
2215
2212
2216
def zero(money_or_currency, options \\ [])
changed lib/money/backend.ex
 
@@ -539,13 539,13 @@ defmodule Money.Backend do
539
539
## Options
540
540
541
541
* `money_1` and `money_2` are any valid `t:Money.t/0` types returned
542
- by `Money.new/2`
542
by `Money.new/2`.
543
543
544
544
## Returns
545
545
546
546
* `{:ok, money}` or
547
547
548
- * `{:error, reason}`
548
* `{:error, reason}`.
549
549
550
550
## Example
551
551
 
@@ -568,7 568,7 @@ defmodule Money.Backend do
568
568
## Arguments
569
569
570
570
* `money_1` and `money_2` are any valid `t:Money.t/0` types returned
571
- by `Money.new/2`
571
by `Money.new/2`.
572
572
573
573
## Returns
574
574
 
@@ -598,9 598,9 @@ defmodule Money.Backend do
598
598
## Arguments
599
599
600
600
* `money` is any valid `t:Money.t/0` type returned
601
- by `Money.new/2`
601
by `Money.new/2`.
602
602
603
- * `number` is an integer, float or `t:Decimal.t/0`
603
* `number` is an integer, float or `t:Decimal.t/0`.
604
604
605
605
> Note that multipling one `t:Money.t/0` by another is not supported.
606
606
 
@@ -632,7 632,7 @@ defmodule Money.Backend do
632
632
## Arguments
633
633
634
634
* `money` is any valid `t:Money.t/0` types returned
635
- by `Money.new/2`
635
by `Money.new/2`.
636
636
637
637
* `number` is an integer, float or `Decimal.t`
638
638
 
@@ -662,10 662,10 @@ defmodule Money.Backend do
662
662
663
663
## Arguments
664
664
665
- * `money` is any valid `t:Money.t/0` types returned
665
* `money` is any valid `t:Money.t/0` types returned.
666
666
by `Money.new/2`
667
667
668
- * `number` is an integer, float or `t:Decimal.t/0`
668
* `number` is an integer, float or `t:Decimal.t/0`.
669
669
670
670
> Note that dividing one `t:Money.t/0` by another is not supported.
671
671
 
@@ -699,7 699,7 @@ defmodule Money.Backend do
699
699
* `money` is any valid `t:Money.t/0` types returned
700
700
by `Money.new/2`
701
701
702
- * `number` is an integer, float or `Decimal.t`
702
* `number` is an integer, float or `t:Decimal.t/0`
703
703
704
704
## Returns
705
705
 
@@ -754,13 754,13 @@ defmodule Money.Backend do
754
754
## Arguments
755
755
756
756
* `money_1` and `money_2` are any valid `t:Money.t/0` types returned
757
- by `Money.new/2`
757
by `Money.new/2`.
758
758
759
759
## Returns
760
760
761
761
* `:gt` | `:eq` | `:lt` or
762
762
763
- * `{:error, {module(), String.t}}`
763
* `{:error, {module(), String.t}}`.
764
764
765
765
## Examples
766
766
 
@@ -791,13 791,13 @@ defmodule Money.Backend do
791
791
## Arguments
792
792
793
793
* `money_1` and `money_2` are any valid `t:Money.t/0` types returned
794
- by `Money.new/2`
794
by `Money.new/2`.
795
795
796
796
## Returns
797
797
798
798
* `:gt` | `:eq` | `:lt` or
799
799
800
- * raises an exception
800
* raises an exception.
801
801
802
802
## Examples
803
803
 
@@ -817,7 817,7 @@ defmodule Money.Backend do
817
817
## Arguments
818
818
819
819
* `money_1` and `money_2` are any valid `t:Money.t/0` types returned
820
- by `Money.new/2`
820
by `Money.new/2`.
821
821
822
822
## Returns
823
823
 
@@ -854,13 854,13 @@ defmodule Money.Backend do
854
854
## Arguments
855
855
856
856
* `money_1` and `money_2` are any valid `t:Money.t/0` types returned
857
- by `Money.new/2`
857
by `Money.new/2`.
858
858
859
859
## Returns
860
860
861
861
* `-1` | `0` | `1` or
862
862
863
- * raises an exception
863
* raises an exception.
864
864
865
865
## Examples
866
866
 
@@ -887,12 887,12 @@ defmodule Money.Backend do
887
887
derived as follows:
888
888
889
889
1. Round the money amount to the required currency precision using
890
- `Money.round/1`
890
`Money.round/1`.
891
891
892
- 2. Divide the result of step 1 by the integer divisor
892
2. Divide the result of step 1 by the integer divisor.
893
893
894
894
3. Round the result of the division to the precision of the currency
895
- using `Money.round/1`
895
using `Money.round/1`.
896
896
897
897
4. Return two numbers: the result of the division and any remainder
898
898
that could not be applied given the precision of the currency.
 
@@ -921,15 921,15 @@ defmodule Money.Backend do
921
921
922
922
## Arguments
923
923
924
- * `money` is a ``t:Money.t/0`` struct
924
* `money` is a `t:Money.t/0` struct.
925
925
926
- * `opts` is a keyword list of options
926
* `options` is a keyword list of options.
927
927
928
928
## Options
929
929
930
930
* `:rounding_mode` that defines how the number will be rounded. See
931
931
`Decimal.Context`. The default is `:half_even` which is also known
932
- as "banker's rounding"
932
as "banker's rounding".
933
933
934
934
* `:currency_digits` which determines the rounding increment.
935
935
The valid options are `:cash`, `:accounting` and `:iso` or
 
@@ -940,13 940,13 @@ defmodule Money.Backend do
940
940
941
941
There are two kinds of rounding applied:
942
942
943
- 1. Round to the appropriate number of fractional digits
943
1. Round to the appropriate number of fractional digits.
944
944
945
945
3. Apply an appropriate rounding increment. Most currencies
946
946
round to the same precision as the number of decimal digits, but some
947
947
such as `:CHF` round to a minimum such as `0.05` when its a cash
948
948
amount. The rounding increment is applied when the option
949
- `:currency_digits` is set to `:cash`
949
`:currency_digits` is set to `:cash`.
950
950
951
951
## Examples
952
952
 
@@ -963,7 963,9 @@ defmodule Money.Backend do
963
963
Money.new(:JPY, "124")
964
964
965
965
"""
966
- @spec round(Elixir.Money.t(), Keyword.t()) :: Elixir.Money.t()
966
@spec round(Elixir.Money.t(), Keyword.t()) ::
967
Elixir.Money.t() | {:error, {module(), binary()}}
968
967
969
def round(%Elixir.Money{} = money, options \\ []) do
968
970
Elixir.Money.round(money, options)
969
971
end
 
@@ -1266,7 1268,7 @@ defmodule Money.Backend do
1266
1268
1267
1269
"""
1268
1270
@spec from_integer(integer, Elixir.Money.currency_code(), Keyword.t()) ::
1269
- Elixir.Money.t() | {:error, module(), String.t()}
1271
Elixir.Money.t() | {:error, {module(), String.t()}}
1270
1272
1271
1273
def from_integer(amount, currency, options \\ []) when is_integer(amount) do
1272
1274
Elixir.Money.from_integer(amount, currency, options)
 
@@ -1297,7 1299,7 @@ defmodule Money.Backend do
1297
1299
1298
1300
"""
1299
1301
@spec zero(Elixir.Money.currency_code() | Elixir.Money.t(), Keyword.t()) ::
1300
- Elixir.Money.t()
1302
Elixir.Money.t() | {:error, {module(), binary()}}
1301
1303
1302
1304
def zero(money, options \\ [])
changed lib/money/financial.ex
 
@@ -209,13 209,12 @@ defmodule Money.Financial do
209
209
Money.new(:USD, "7731.466833737959119743127888")
210
210
211
211
"""
212
- @spec net_present_value(Money.t(), number, number) :: Money.t()
213
-
212
@spec net_present_value(Money.t(), float, number) :: Money.t()
214
213
def net_present_value(%Money{currency: currency} = future_value, interest_rate, periods) do
215
214
net_present_value(future_value, interest_rate, periods, Money.new(currency, 0))
216
215
end
217
216
218
- @spec net_present_value(Money.t(), number, number, Money.t()) :: Money.t()
217
@spec net_present_value(Money.t(), float, number, Money.t()) :: Money.t()
219
218
def net_present_value(%Money{} = future_value, interest_rate, periods, %Money{} = investment) do
220
219
present_value(future_value, interest_rate, periods)
221
220
|> Money.sub!(investment)
 
@@ -228,7 227,7 @@ defmodule Money.Financial do
228
227
represented as a tuple of the form `{period, %Money{}}`
229
228
230
229
"""
231
- @spec internal_rate_of_return(list({integer, Money.t()})) :: number()
230
@spec internal_rate_of_return(list({integer, Money.t()})) :: float()
232
231
def internal_rate_of_return([{_period, %Money{}} | _other_flows] = flows) do
233
232
# estimate_m = sum_of_inflows(flows)
234
233
# |> Kernel./(abs(Math.to_float(amount)))
changed lib/money/sigil.ex
 
@@ -14,7 14,7 @@ defmodule Money.Sigil do
14
14
Money.new(:USD, "1000.34")
15
15
16
16
"""
17
- @spec sigil_M(binary, list) :: Money.t() | {:error, {Exception.t(), String.t()}}
17
@spec sigil_M(binary, list(char)) :: Money.t() | {:error, {module(), String.t()}}
18
18
def sigil_M(amount, [_, _, _] = currency) do
19
19
Money.new(to_decimal(amount), atomize(currency))
20
20
end
changed lib/money/subscription.ex
 
@@ -263,7 263,8 @@ defmodule Money.Subscription do
263
263
264
264
"""
265
265
# @doc since: "2.3.0"
266
- @spec current_plan(Subscription.t() | map, Keyword.t()) :: Plan.t() | nil
266
@spec current_plan(Subscription.t() | map, Keyword.t()) ::
267
Plan.t() | {Change.t(), Plan.t()} | nil
267
268
268
269
def current_plan(subscription, options \\ [])
269
270
 
@@ -988,6 989,7 @@ defmodule Money.Subscription do
988
989
end
989
990
end
990
991
992
@dialyzer {:nowarn_function, raise_change_plan_options_error: 1}
991
993
defp raise_change_plan_options_error(opt) do
992
994
raise ArgumentError, "change_plan requires the the option #{inspect(opt)}"
993
995
end
changed mix.exs
 
@@ -1,7 1,7 @@
1
1
defmodule Money.Mixfile do
2
2
use Mix.Project
3
3
4
- @version "5.17.0"
4
@version "5.17.1"
5
5
6
6
def project do
7
7
[
 
@@ -21,7 21,14 @@ defmodule Money.Mixfile do
21
21
elixirc_paths: elixirc_paths(Mix.env()),
22
22
dialyzer: [
23
23
ignore_warnings: ".dialyzer_ignore_warnings",
24
- plt_add_apps: ~w(inets jason mix phoenix_html gringotts)a
24
plt_add_apps: ~w(inets jason mix phoenix_html gringotts)a,
25
flags: [
26
:error_handling,
27
:unknown,
28
:underspecs,
29
:extra_return,
30
:missing_return
31
]
25
32
],
26
33
compilers: Mix.compilers()
27
34
]
 
@@ -88,14 95,14 @@ defmodule Money.Mixfile do
88
95
{:ex_cldr_numbers, "~> 2.33"},
89
96
{:nimble_parsec, "~> 0.5 or ~> 1.0"},
90
97
{:decimal, "~> 1.6 or ~> 2.0"},
91
- {:poison, "~> 3.0 or ~> 4.0 or ~> 5.0", optional: true},
98
{:poison, "~> 3.0 or ~> 4.0 or ~> 5.0 or ~> 6.0", optional: true},
92
99
{:phoenix_html, "~> 2.0 or ~> 3.0 or ~> 4.0", optional: true},
93
100
{:dialyxir, "~> 1.0", only: [:dev, :test], runtime: false},
94
101
{:jason, "~> 1.0", optional: true},
95
- {:stream_data, "~> 0.4", only: [:dev, :test]},
102
{:stream_data, "~> 1.0", only: [:dev, :test]},
96
103
{:benchee, "~> 1.0", optional: true, only: :dev},
97
104
{:exprof, "~> 0.2", only: :dev, runtime: false},
98
- {:ex_doc, "0.30.9", only: [:dev, :release]},
105
{:ex_doc, "~> 0.31", only: [:dev, :release]},
99
106
100
107
{:gringotts, "~> 1.1", optional: true}
101
108
]