Money.Subscription.change_plan

You're seeing just the function change_plan, go back to Money.Subscription module for more information.
Link to this function

change_plan(subscription_or_plan, new_plan, options \\ [])

View Source

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 a Money.Subscription.t or Money.Subscription.Plan.t or a map with the same fields

  • new_plan is a Money.Subscription.Plan.t or a map with at least the fields interval, interval_count and price

  • current_interval_started is a Date.t or other map with the fields year, month, day and calendar

  • 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, a Date.t or :next_period. The default is :next_period. Note that the date applied in the case of :immediately is the date returned by Date.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 the interval 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 full interval_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. If subscription_or_plan is a Money.Subscription.t then the :first_interval_started is automatically populated from the subscription. If :first_interval_started is nil 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 the first intervalincluding any credit_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 plan price 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 or nil

  • :carry_forward is any amount of credit carried forward to a subsequent period. If non-zero, this amount is a negative Money.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]
}}