2019-09-02 14:29:19 +03:00
|
|
|
defmodule PlausibleWeb.BillingController do
|
|
|
|
use PlausibleWeb, :controller
|
|
|
|
use Plausible.Repo
|
|
|
|
alias Plausible.Billing
|
|
|
|
require Logger
|
|
|
|
|
|
|
|
plug PlausibleWeb.RequireAccountPlug
|
|
|
|
|
2022-10-04 15:54:54 +03:00
|
|
|
def ping_subscription(%Plug.Conn{} = conn, _params) do
|
|
|
|
subscribed? = Billing.has_active_subscription?(conn.assigns.current_user.id)
|
|
|
|
json(conn, %{is_subscribed: subscribed?})
|
|
|
|
end
|
|
|
|
|
2021-10-20 17:49:11 +03:00
|
|
|
def upgrade(conn, _params) do
|
|
|
|
user =
|
|
|
|
conn.assigns[:current_user]
|
|
|
|
|> Repo.preload(:enterprise_plan)
|
|
|
|
|
|
|
|
cond do
|
|
|
|
user.subscription && user.subscription.status == "active" ->
|
|
|
|
redirect(conn, to: Routes.billing_path(conn, :change_plan_form))
|
|
|
|
|
|
|
|
user.enterprise_plan ->
|
|
|
|
redirect(conn,
|
|
|
|
to: Routes.billing_path(conn, :upgrade_enterprise_plan, user.enterprise_plan.id)
|
|
|
|
)
|
|
|
|
|
|
|
|
true ->
|
|
|
|
render(conn, "upgrade.html",
|
2023-05-16 11:52:17 +03:00
|
|
|
skip_plausible_tracking: true,
|
2023-08-24 20:22:49 +03:00
|
|
|
usage: Plausible.Billing.Quota.monthly_pageview_usage(user),
|
2021-10-20 17:49:11 +03:00
|
|
|
user: user,
|
|
|
|
layout: {PlausibleWeb.LayoutView, "focus.html"}
|
|
|
|
)
|
|
|
|
end
|
2020-05-26 16:09:34 +03:00
|
|
|
end
|
|
|
|
|
2023-10-03 13:36:22 +03:00
|
|
|
def choose_plan(conn, _params) do
|
|
|
|
user = conn.assigns[:current_user]
|
|
|
|
|
|
|
|
if FunWithFlags.enabled?(:business_tier, for: user) do
|
|
|
|
render(conn, "choose_plan.html",
|
|
|
|
skip_plausible_tracking: true,
|
|
|
|
user: user,
|
|
|
|
layout: {PlausibleWeb.LayoutView, "focus.html"},
|
|
|
|
connect_live_socket: true
|
|
|
|
)
|
|
|
|
else
|
|
|
|
render_error(conn, 404)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2021-10-20 17:49:11 +03:00
|
|
|
def upgrade_enterprise_plan(conn, %{"plan_id" => plan_id}) do
|
2022-03-29 13:00:25 +03:00
|
|
|
user = conn.assigns[:current_user]
|
2022-03-30 10:10:44 +03:00
|
|
|
subscription = user.subscription
|
2022-03-29 13:00:25 +03:00
|
|
|
plan = Repo.get_by(Plausible.Billing.EnterprisePlan, user_id: user.id, id: plan_id)
|
2021-10-20 17:49:11 +03:00
|
|
|
|
2022-03-30 10:10:44 +03:00
|
|
|
cond do
|
|
|
|
plan && subscription && plan.paddle_plan_id == subscription.paddle_plan_id ->
|
|
|
|
redirect(conn, to: Routes.billing_path(conn, :change_plan_form))
|
|
|
|
|
|
|
|
plan ->
|
|
|
|
render(conn, "upgrade_to_plan.html",
|
2023-05-16 11:52:17 +03:00
|
|
|
skip_plausible_tracking: true,
|
2022-03-30 10:10:44 +03:00
|
|
|
user: user,
|
|
|
|
plan: plan,
|
|
|
|
layout: {PlausibleWeb.LayoutView, "focus.html"}
|
|
|
|
)
|
|
|
|
|
|
|
|
true ->
|
|
|
|
render_error(conn, 404)
|
2021-10-20 17:49:11 +03:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def upgrade_success(conn, _params) do
|
2023-05-17 16:13:41 +03:00
|
|
|
render(conn, "upgrade_success.html", layout: {PlausibleWeb.LayoutView, "focus.html"})
|
2021-10-20 17:49:11 +03:00
|
|
|
end
|
|
|
|
|
|
|
|
def change_plan_form(conn, _params) do
|
|
|
|
user =
|
|
|
|
conn.assigns[:current_user]
|
|
|
|
|> Repo.preload(:enterprise_plan)
|
|
|
|
|
|
|
|
subscription = Billing.active_subscription_for(user.id)
|
|
|
|
|
|
|
|
cond do
|
2022-04-18 14:17:30 +03:00
|
|
|
subscription && user.enterprise_plan &&
|
|
|
|
subscription.paddle_plan_id !== user.enterprise_plan.paddle_plan_id ->
|
|
|
|
redirect(conn,
|
|
|
|
to: Routes.billing_path(conn, :change_enterprise_plan, user.enterprise_plan.id)
|
|
|
|
)
|
|
|
|
|
|
|
|
subscription && user.enterprise_plan &&
|
|
|
|
subscription.paddle_plan_id == user.enterprise_plan.paddle_plan_id ->
|
2022-03-29 13:00:25 +03:00
|
|
|
render(conn, "change_enterprise_plan_contact_us.html",
|
2023-05-16 11:52:17 +03:00
|
|
|
skip_plausible_tracking: true,
|
2022-03-29 13:00:25 +03:00
|
|
|
user: user,
|
|
|
|
plan: user.enterprise_plan,
|
|
|
|
layout: {PlausibleWeb.LayoutView, "focus.html"}
|
2021-10-20 17:49:11 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
subscription ->
|
|
|
|
render(conn, "change_plan.html",
|
2023-05-16 11:52:17 +03:00
|
|
|
skip_plausible_tracking: true,
|
2021-10-20 17:49:11 +03:00
|
|
|
subscription: subscription,
|
|
|
|
layout: {PlausibleWeb.LayoutView, "focus.html"}
|
|
|
|
)
|
|
|
|
|
|
|
|
true ->
|
|
|
|
redirect(conn, to: Routes.billing_path(conn, :upgrade))
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def change_enterprise_plan(conn, %{"plan_id" => plan_id}) do
|
2022-03-29 13:00:25 +03:00
|
|
|
user = conn.assigns[:current_user]
|
|
|
|
|
|
|
|
new_plan = Repo.get_by(Plausible.Billing.EnterprisePlan, user_id: user.id, id: plan_id)
|
2021-10-20 17:49:11 +03:00
|
|
|
|
|
|
|
cond do
|
|
|
|
is_nil(user.subscription) ->
|
|
|
|
redirect(conn, to: "/billing/upgrade")
|
|
|
|
|
2022-03-29 13:00:25 +03:00
|
|
|
is_nil(new_plan) || new_plan.paddle_plan_id == user.subscription.paddle_plan_id ->
|
2021-10-20 17:49:11 +03:00
|
|
|
render_error(conn, 404)
|
|
|
|
|
|
|
|
true ->
|
|
|
|
render(conn, "change_enterprise_plan.html",
|
2023-05-16 11:52:17 +03:00
|
|
|
skip_plausible_tracking: true,
|
2021-10-20 17:49:11 +03:00
|
|
|
user: user,
|
2022-03-29 13:00:25 +03:00
|
|
|
plan: new_plan,
|
2021-10-20 17:49:11 +03:00
|
|
|
layout: {PlausibleWeb.LayoutView, "focus.html"}
|
|
|
|
)
|
2019-09-02 14:29:19 +03:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-04-21 14:11:38 +03:00
|
|
|
def change_plan_preview(conn, %{"plan_id" => new_plan_id}) do
|
2022-09-06 22:27:25 +03:00
|
|
|
with {:ok, {subscription, preview_info}} <-
|
|
|
|
preview_subscription(conn.assigns.current_user, new_plan_id) do
|
2020-06-08 10:35:13 +03:00
|
|
|
render(conn, "change_plan_preview.html",
|
2023-05-16 11:52:17 +03:00
|
|
|
skip_plausible_tracking: true,
|
2020-06-08 10:35:13 +03:00
|
|
|
subscription: subscription,
|
|
|
|
preview_info: preview_info,
|
|
|
|
layout: {PlausibleWeb.LayoutView, "focus.html"}
|
|
|
|
)
|
2020-04-21 14:11:38 +03:00
|
|
|
else
|
2022-09-06 22:27:25 +03:00
|
|
|
_ ->
|
|
|
|
redirect(conn, to: "/billing/upgrade")
|
2020-04-21 14:11:38 +03:00
|
|
|
end
|
|
|
|
end
|
2019-09-02 14:29:19 +03:00
|
|
|
|
2020-04-21 14:11:38 +03:00
|
|
|
def change_plan(conn, %{"new_plan_id" => new_plan_id}) do
|
|
|
|
case Billing.change_plan(conn.assigns[:current_user], new_plan_id) do
|
2019-09-02 14:29:19 +03:00
|
|
|
{:ok, _subscription} ->
|
|
|
|
conn
|
|
|
|
|> put_flash(:success, "Plan changed successfully")
|
|
|
|
|> redirect(to: "/settings")
|
2020-06-08 10:35:13 +03:00
|
|
|
|
2019-09-02 14:29:19 +03:00
|
|
|
{:error, e} ->
|
2021-04-19 14:44:17 +03:00
|
|
|
# https://developer.paddle.com/api-reference/intro/api-error-codes
|
|
|
|
msg =
|
|
|
|
case e do
|
|
|
|
%{"code" => 147} ->
|
2021-11-26 12:53:23 +03:00
|
|
|
"We were unable to charge your card. Click 'update billing info' to update your payment details and try again."
|
2021-04-19 14:44:17 +03:00
|
|
|
|
|
|
|
%{"message" => msg} when not is_nil(msg) ->
|
|
|
|
msg
|
|
|
|
|
|
|
|
_ ->
|
|
|
|
"Something went wrong. Please try again or contact support at support@plausible.io"
|
|
|
|
end
|
|
|
|
|
2020-06-08 10:35:13 +03:00
|
|
|
Sentry.capture_message("Error changing plans",
|
|
|
|
extra: %{
|
|
|
|
errors: inspect(e),
|
2021-04-19 14:44:17 +03:00
|
|
|
message: msg,
|
2020-06-08 10:35:13 +03:00
|
|
|
new_plan_id: new_plan_id,
|
|
|
|
user_id: conn.assigns[:current_user].id
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
2019-09-02 14:29:19 +03:00
|
|
|
conn
|
2021-11-26 12:53:23 +03:00
|
|
|
|> put_flash(:error, msg)
|
2019-09-02 14:29:19 +03:00
|
|
|
|> redirect(to: "/settings")
|
|
|
|
end
|
|
|
|
end
|
2022-09-06 22:27:25 +03:00
|
|
|
|
|
|
|
defp preview_subscription(%{id: user_id}, new_plan_id) do
|
|
|
|
subscription = Billing.active_subscription_for(user_id)
|
|
|
|
|
|
|
|
if subscription do
|
|
|
|
with {:ok, preview_info} <- Billing.change_plan_preview(subscription, new_plan_id) do
|
|
|
|
{:ok, {subscription, preview_info}}
|
|
|
|
end
|
|
|
|
else
|
|
|
|
{:error, :no_subscription}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def preview_susbcription(_, _) do
|
|
|
|
{:error, :no_user_id}
|
|
|
|
end
|
2019-09-02 14:29:19 +03:00
|
|
|
end
|