File size: 4,710 Bytes
6778ee0 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 | defmodule Plausible.Billing.DevSubscriptions do
@moduledoc """
Module for conveniently handling subscriptions in the :dev environment.
"""
use Plausible
on_ee do
import Ecto.Query
alias Plausible.{Repo, Billing}
alias Plausible.Billing.{Plan, EnterprisePlan, DevPaddleApiMock}
alias PlausibleWeb.Router.Helpers, as: Routes
def create_after_1s(team_id, plan_id) do
Task.start(fn ->
Process.sleep(1000)
create(team_id, plan_id)
end)
end
def create(team_id, plan_id, opts \\ []) do
plan_or_enterprise_plan = get_plan_or_enterprise_plan(plan_id)
if plan_or_enterprise_plan do
if Keyword.get(opts, :clean_existing, true) do
delete(team_id)
end
%{
"event_time" => to_string(NaiveDateTime.utc_now(:second)),
"alert_name" => "subscription_created",
"passthrough" => "ee:true;user:0;team:#{team_id}",
"email" => "",
"subscription_id" => Ecto.UUID.generate(),
"subscription_plan_id" => plan_id,
"update_url" => Routes.dev_subscription_path(PlausibleWeb.Endpoint, :update_form),
"cancel_url" => Routes.dev_subscription_path(PlausibleWeb.Endpoint, :cancel_form),
"status" => "active",
"next_bill_date" => next_bill_date(plan_or_enterprise_plan, plan_id),
"unit_price" => "#{to_string(DevPaddleApiMock.all_prices()[plan_id])}.00",
"currency" => "EUR"
}
|> Plausible.Billing.subscription_created()
{:ok, Repo.reload(get_team_subscription(team_id))}
else
{:error, "Plan with id '#{plan_id}' not found."}
end
end
def update(team_id, new_status) do
if subscription = get_team_subscription(team_id) do
current_plan_id = subscription.paddle_plan_id
current_plan = get_plan_or_enterprise_plan(current_plan_id)
next_bill_date =
case new_status do
"active" -> next_bill_date(current_plan, current_plan_id)
"past_due" -> Date.utc_today() |> Date.shift(day: 5) |> Date.to_iso8601()
"paused" -> subscription.next_bill_date |> Date.to_iso8601()
end
%{
"subscription_id" => subscription.paddle_subscription_id,
"subscription_plan_id" => current_plan_id,
"update_url" => subscription.update_url,
"cancel_url" => subscription.cancel_url,
"old_status" => to_string(subscription.status),
"status" => new_status,
"next_bill_date" => next_bill_date,
"new_unit_price" => "#{to_string(DevPaddleApiMock.all_prices()[current_plan_id])}.00",
"currency" => "EUR"
}
|> Plausible.Billing.subscription_updated()
:ok
else
{:error, :no_subscription}
end
end
def delete(team_id, opts \\ []) do
delete_enterprise? = Keyword.get(opts, :delete_enterprise?, false)
if subscription = get_team_subscription(team_id) do
Repo.delete(subscription)
if delete_enterprise? do
Plausible.Repo.delete_all(from(e in EnterprisePlan, where: e.team_id == ^team_id))
end
:ok
else
{:error, :no_subscription}
end
end
def cancel(team_id, opts \\ []) do
set_expired? = Keyword.get(opts, :set_expired?, false)
if subscription = get_team_subscription(team_id) do
%{"subscription_id" => subscription.paddle_subscription_id, "status" => "deleted"}
|> Billing.subscription_cancelled()
subscription = Repo.reload!(subscription)
if set_expired? do
subscription
|> Ecto.Changeset.change(%{next_bill_date: Date.utc_today() |> Date.add(-1)})
|> Repo.update()
else
{:ok, subscription}
end
else
{:error, :no_subscription}
end
end
defp get_plan_or_enterprise_plan(plan_id) do
Billing.Plans.find(plan_id) || Repo.get_by(EnterprisePlan, paddle_plan_id: plan_id)
end
defp get_team_subscription(team_id) do
Plausible.Teams.Team
|> Plausible.Repo.get(team_id)
|> Plausible.Teams.with_subscription()
|> Map.get(:subscription)
end
defp next_bill_date(%EnterprisePlan{} = plan, _) do
if plan.billing_interval == :monthly, do: next_month(), else: next_year()
end
defp next_bill_date(%Plan{} = plan, plan_id) do
if plan_id == plan.monthly_product_id, do: next_month(), else: next_year()
end
defp next_month(), do: Date.utc_today() |> Date.shift(month: 1) |> Date.to_iso8601()
defp next_year(), do: Date.utc_today() |> Date.shift(year: 1) |> Date.to_iso8601()
end
end
|