Skip to content

Commit b697c95

Browse files
committed
Add Money.Subscription.Plan.to_string/2. Addresses #186
1 parent 6ca90ca commit b697c95

8 files changed

Lines changed: 99 additions & 21 deletions

File tree

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,14 @@
44

55
## Money v5.21.0
66

7+
This is the changelog for Money v5.22.0 released on ______, 2025. For older changelogs please consult the release tag on [GitHub](https://github.com/kipcole9/money/tags)
8+
9+
### Enhancements
10+
11+
* Adds `Money.Subscription.Plan.to_string/2` to return a localized string representation of a subscription plan. The implementation is conditional on [ex_cldr_units](https://hex.pm/packages/ex_cldr_units) being configured as a dependency in `mix.exs` and `Cldr.Unit` being added as a provider in the CLDR backend module. Thanks to @peaceful-james for the suggestion. Closes #186.
12+
13+
## Money v5.21.0
14+
715
This is the changelog for Money v5.21.0 released on March 30th, 2025. For older changelogs please consult the release tag on [GitHub](https://github.com/kipcole9/money/tags)
816

917
### Enhancements

lib/money/subscription/plan.ex

Lines changed: 68 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ defmodule Money.Subscription.Plan do
2929
Returns `{:ok, Money.Subscription.Plan.t}` or an `{:error, reason}`
3030
tuple.
3131
32-
## Arguments
32+
### Arguments
3333
3434
* `:price` is any `Money.t`
3535
@@ -39,11 +39,11 @@ defmodule Money.Subscription.Plan do
3939
* `:interval_count` is an integer count of the number of `:interval`s
4040
of the plan. The default is `1`
4141
42-
## Returns
42+
### Returns
4343
4444
A `Money.Subscription.Plan.t`
4545
46-
## Examples
46+
### Examples
4747
4848
iex> Money.Subscription.Plan.new Money.new(:USD, 100), :month, 1
4949
{:ok,
@@ -93,7 +93,7 @@ defmodule Money.Subscription.Plan do
9393
9494
Takes the same arguments as `Money.Subscription.Plan.new/3`.
9595
96-
## Example
96+
##@ Example
9797
9898
iex> Money.Subscription.Plan.new! Money.new(:USD, 100), :day, 30
9999
%Money.Subscription.Plan{
@@ -112,4 +112,68 @@ defmodule Money.Subscription.Plan do
112112
{:error, {exception, reason}} -> raise exception, reason
113113
end
114114
end
115+
116+
if Code.ensure_loaded?(Cldr.Unit) do
117+
import Kernel, except: [to_string: 1]
118+
119+
@doc """
120+
Return a localised string representation of a subscription
121+
plan.
122+
123+
### Arguments
124+
125+
* Any `Money.Subscription.Plan.t/1` as returned from
126+
`Money.Subscription.Plan.new/3`.
127+
128+
* `options` is a keyword list of options.
129+
130+
### Options
131+
132+
* See `Cldr.Unit.to_string/1` for available options.
133+
134+
### Returns
135+
136+
* `{:ok, localized_string}` or
137+
138+
* `{:error, reason}`
139+
140+
### Examples
141+
142+
iex> {:ok, plan} = Money.Subscription.Plan.new(Money.new(:USD, 10), :year)
143+
iex> Money.Subscription.Plan.to_string(plan)
144+
{:ok, "$10.00 per year"}
145+
iex> Money.Subscription.Plan.to_string(plan, locale: :ja)
146+
{:ok, "$10.00毎年"}
147+
iex> Money.Subscription.Plan.to_string(plan, locale: :de, style: :narrow)
148+
{:ok, "10,00\u00A0$/J"}
149+
150+
iex> {:ok, plan} = Money.Subscription.Plan.new(Money.new(:USD, 10), :day, 30)
151+
iex> Money.Subscription.Plan.to_string(plan)
152+
{:ok, "$10.00 per 30 days"}
153+
iex> Money.Subscription.Plan.to_string(plan, locale: :de)
154+
{:ok, "10,00\u00A0$ pro 30 Tage"}
155+
iex> Money.Subscription.Plan.to_string(plan, locale: :de, style: :short)
156+
{:ok, "10,00\u00A0$/30 Tg."}
157+
158+
"""
159+
@doc since: "5.22.0"
160+
def to_string(%__MODULE__{} = plan, options \\ []) do
161+
backend = Keyword.get_lazy(options, :backend, &Money.default_backend/0)
162+
163+
plan
164+
|> unit_from_plan()
165+
|> Cldr.Unit.new!(plan.price.amount)
166+
|> Cldr.Unit.to_string(backend, options)
167+
end
168+
169+
defp unit_from_plan(%__MODULE__{interval_count: 1} = plan) do
170+
%{price: amount, interval: interval} = plan
171+
"curr-#{amount.currency}-per-#{interval}"
172+
end
173+
174+
defp unit_from_plan(%__MODULE__{interval_count: interval_count} = plan) do
175+
%{price: amount, interval: interval} = plan
176+
"curr-#{amount.currency}-per-#{interval_count}-#{interval}"
177+
end
178+
end
115179
end

mix.exs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
defmodule Money.Mixfile do
22
use Mix.Project
33

4-
@version "5.21.0"
4+
@version "5.22.0"
55

66
def project do
77
[
@@ -93,6 +93,9 @@ defmodule Money.Mixfile do
9393
[
9494
{:ex_cldr_numbers, "~> 2.34"},
9595

96+
# Used for Money.Subscription.Plan.to_string/1
97+
{:ex_cldr_units, "~> 3.19", optional: true},
98+
9699
{:nimble_parsec, "~> 0.5 or ~> 1.0"},
97100
{:decimal, "~> 1.6 or ~> 2.0"},
98101
{:poison, "~> 3.0 or ~> 4.0 or ~> 5.0 or ~> 6.0", optional: true},

mix.lock

Lines changed: 15 additions & 13 deletions
Large diffs are not rendered by default.

mix/test_cldr.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,5 @@ defmodule Money.Cldr do
2525
"ar-MA"
2626
],
2727
default_locale: "en",
28-
providers: [Cldr.Number, Money]
28+
providers: [Cldr.Number, Cldr.Unit, Money]
2929
end

test/money_test.exs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ defmodule MoneyTest do
1414
doctest Money.ExchangeRates.Retriever
1515
doctest Money.Financial
1616
doctest Money.Sigil
17+
doctest Money.Subscription.Plan
1718

1819
test "create a new money struct with a binary currency code" do
1920
money = Money.new(1234, "USD")

test/money_token_test.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,6 @@ defmodule Money.DigitalToken.Test do
99
end
1010

1111
test "Formatting digital token" do
12-
assert {:ok, "₿ 100.234235"} = Money.to_string(Money.new("BTC", "100.234235"))
12+
assert {:ok, "₿100.234235"} = Money.to_string(Money.new("BTC", "100.234235"))
1313
end
1414
end

test/support/test_cldr.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,6 @@ defmodule Test.Cldr do
1919
"bn",
2020
"ar-MA"
2121
],
22-
providers: [Cldr.Number, Money],
22+
providers: [Cldr.Number, Cldr.Unit, Money],
2323
suppress_warnings: true
2424
end

0 commit comments

Comments
 (0)