Money.Subscription.change_plan
change_plan
, go back to Money.Subscription module for more information.
Specs
change_plan( subscription_or_plan :: t() | Money.Subscription.Plan.t(), new_plan :: Money.Subscription.Plan.t(), options :: Keyword.t() ) :: {:ok, Money.Subscription.Change.t() | t()} | {:error, {module(), String.t()}}
Change plan from the current plan to a new plan.
Arguments
subscription_or_plan
is either aMoney.Subscription.t
orMoney.Subscription.Plan.t
or a map with the same fieldsnew_plan
is aMoney.Subscription.Plan.t
or a map with at least the fieldsinterval
,interval_count
andprice
current_interval_started
is aDate.t
or other map with the fieldsyear
,month
,day
andcalendar
options
is a keyword list of options the define how the change is to be made
Options
:effective
defines when the new plan comes into effect. The values are:immediately
, aDate.t
or:next_period
. The default is:next_period
. Note that the date applied in the case of:immediately
is the date returned byDate.utc_today
.:prorate
which determines how to prorate the current plan into the new plan. The options are:price
which will reduce the price of the first period of the new plan by the credit amount left on the old plan (this is the default). Or:period
in which case the first period of the new plan is extended by theinterval
amount of the new plan that the credit on the old plan will fund.:round
determines whether when prorating the:period
it is truncated or rounded up to the next nearest fullinterval_count
. Valid values are:down
,:half_up
,:half_even
,:ceiling
,:floor
,:half_down
,:up
. The default is:up
.:first_interval_started
determines the anchor day for monthly billing. For example if a monthly plan starts on January 31st then the next period will start on February 28th (or 29th). The period following that should, however, be March 31st. Ifsubscription_or_plan
is aMoney.Subscription.t
then the:first_interval_started
is automatically populated from the subscription. If:first_interval_started
isnil
then the date defined by:effective
is used.
Returns
A Money.Subscription.Change.t
with the following elements:
:first_interval_starts
which is the start date of the first interval for the new plan:first_billing_amount
is the amount to be billed, net of any credit, at the:first_interval_starts
:next_interval_starts
is the start date of the next interval after thefirst interval
including anycredit_days_applied
:credit_amount
is the amount of unconsumed credit of the current plan:credit_amount_applied
is the amount of credit applied to the new plan. If the:prorate
option is:price
(the default) then:first_billing_amount
is the plan:price
reduced by the:credit_amount_applied
. If the:prorate
option is:period
then the:first_billing_amount
is the planprice
and the:next_interval_date
is extended by the:credit_days_applied
instead.:credit_days_applied
is the number of days credit applied to the first interval by adding days to the:first_interval_starts
date.:credit_period_ends
is the date on which any applied credit is consumed ornil
:carry_forward
is any amount of credit carried forward to a subsequent period. If non-zero, this amount is a negativeMoney.t
. It is non-zero when the credit amount for the current plan is greater than the:price
of the new plan. In this case the:first_billing_amount
is zero.
Returns
{:ok, updated_subscription}
or{:error, {exception, message}}
Examples
# Change at end of the current period so no proration
iex> current = Money.Subscription.Plan.new!(Money.new(:USD, 10), :month, 1)
iex> new = Money.Subscription.Plan.new!(Money.new(:USD, 10), :month, 3)
iex> Money.Subscription.change_plan current, new, current_interval_started: ~D[2018-01-01]
{:ok, %Money.Subscription.Change{
carry_forward: Money.zero(:USD),
credit_amount: Money.zero(:USD),
credit_amount_applied: Money.zero(:USD),
credit_days_applied: 0,
credit_period_ends: nil,
next_interval_starts: ~D[2018-05-01],
first_billing_amount: Money.new(:USD, 10),
first_interval_starts: ~D[2018-02-01]
}}
# Change during the current plan generates a credit amount
iex> current = Money.Subscription.Plan.new!(Money.new(:USD, 10), :month, 1)
iex> new = Money.Subscription.Plan.new!(Money.new(:USD, 10), :month, 3)
iex> Money.Subscription.change_plan current, new, current_interval_started: ~D[2018-01-01], effective: ~D[2018-01-15]
{:ok, %Money.Subscription.Change{
carry_forward: Money.zero(:USD),
credit_amount: Money.new(:USD, "5.49"),
credit_amount_applied: Money.new(:USD, "5.49"),
credit_days_applied: 0,
credit_period_ends: nil,
next_interval_starts: ~D[2018-04-15],
first_billing_amount: Money.new(:USD, "4.51"),
first_interval_starts: ~D[2018-01-15]
}}
# Change during the current plan generates a credit period
iex> current = Money.Subscription.Plan.new!(Money.new(:USD, 10), :month, 1)
iex> new = Money.Subscription.Plan.new!(Money.new(:USD, 10), :month, 3)
iex> Money.Subscription.change_plan current, new, current_interval_started: ~D[2018-01-01], effective: ~D[2018-01-15], prorate: :period
{:ok, %Money.Subscription.Change{
carry_forward: Money.zero(:USD),
credit_amount: Money.new(:USD, "5.49"),
credit_amount_applied: Money.zero(:USD),
credit_days_applied: 50,
credit_period_ends: ~D[2018-03-05],
next_interval_starts: ~D[2018-06-04],
first_billing_amount: Money.new(:USD, 10),
first_interval_starts: ~D[2018-01-15]
}}