Switch billing controller action to teams schema behind FF (#4843)

* Switch upgrade to enterprise plan view to teams schema behind FF

* Switch change plan preview action to teams schema behind FF

* Switch remaining billing controller actions to teams schema behind FF
This commit is contained in:
Adrian Gruntkowski 2024-11-20 11:10:54 +01:00 committed by GitHub
parent 380dc00d1a
commit a29eb3d3ca
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 91 additions and 37 deletions

View File

@ -55,7 +55,8 @@ defmodule Plausible.Billing do
do: do_change_plan(subscription, new_plan_id) do: do_change_plan(subscription, new_plan_id)
end end
defp do_change_plan(subscription, new_plan_id) do @doc false
def do_change_plan(subscription, new_plan_id) do
res = res =
paddle_api().update_subscription(subscription.paddle_subscription_id, %{ paddle_api().update_subscription(subscription.paddle_subscription_id, %{
plan_id: new_plan_id plan_id: new_plan_id

View File

@ -4,6 +4,13 @@ defmodule Plausible.Teams.Adapter.Read.Billing do
""" """
use Plausible.Teams.Adapter use Plausible.Teams.Adapter
def change_plan(user, new_plan_id) do
switch(user,
team_fn: &Plausible.Teams.Billing.change_plan(&1, new_plan_id),
user_fn: &Plausible.Billing.change_plan(&1, new_plan_id)
)
end
def enterprise_configured?(nil), do: false def enterprise_configured?(nil), do: false
def enterprise_configured?(user) do def enterprise_configured?(user) do
@ -13,6 +20,13 @@ defmodule Plausible.Teams.Adapter.Read.Billing do
) )
end end
def latest_enterprise_plan_with_prices(user, customer_ip) do
switch(user,
team_fn: &Plausible.Teams.Billing.latest_enterprise_plan_with_price(&1, customer_ip),
user_fn: &Plausible.Billing.Plans.latest_enterprise_plan_with_price(&1, customer_ip)
)
end
def has_active_subscription?(user) do def has_active_subscription?(user) do
switch(user, switch(user,
team_fn: &Plausible.Teams.Billing.has_active_subscription?/1, team_fn: &Plausible.Teams.Billing.has_active_subscription?/1,
@ -20,6 +34,13 @@ defmodule Plausible.Teams.Adapter.Read.Billing do
) )
end end
def active_subscription_for(user) do
switch(user,
team_fn: &Plausible.Teams.Billing.active_subscription_for/1,
user_fn: &Plausible.Billing.active_subscription_for/1
)
end
def get_subscription(user) do def get_subscription(user) do
case user_or_team(user) do case user_or_team(user) do
%{subscription: subscription} -> subscription %{subscription: subscription} -> subscription

View File

@ -18,6 +18,24 @@ defmodule Plausible.Teams.Billing do
@limit_sites_since ~D[2021-05-05] @limit_sites_since ~D[2021-05-05]
@site_limit_for_trials 10 @site_limit_for_trials 10
def change_plan(team, new_plan_id) do
subscription = active_subscription_for(team)
plan = Plausible.Billing.Plans.find(new_plan_id)
limit_checking_opts =
if team.allow_next_upgrade_override do
[ignore_pageview_limit: true]
else
[]
end
usage = quota_usage(team)
with :ok <-
Plausible.Billing.Quota.ensure_within_plan_limits(usage, plan, limit_checking_opts),
do: Plausible.Billing.do_change_plan(subscription, new_plan_id)
end
def enterprise_configured?(nil), do: false def enterprise_configured?(nil), do: false
def enterprise_configured?(%Teams.Team{} = team) do def enterprise_configured?(%Teams.Team{} = team) do
@ -26,6 +44,19 @@ defmodule Plausible.Teams.Billing do
|> Repo.exists?() |> Repo.exists?()
end end
def latest_enterprise_plan_with_price(team, customer_ip) do
enterprise_plan =
Repo.one!(
from(e in EnterprisePlan,
where: e.team_id == ^team.id,
order_by: [desc: e.inserted_at],
limit: 1
)
)
{enterprise_plan, Plausible.Billing.Plans.get_price_for(enterprise_plan, customer_ip)}
end
def has_active_subscription?(nil), do: false def has_active_subscription?(nil), do: false
def has_active_subscription?(team) do def has_active_subscription?(team) do
@ -34,6 +65,12 @@ defmodule Plausible.Teams.Billing do
|> Repo.exists?() |> Repo.exists?()
end end
def active_subscription_for(team) do
team
|> active_subscription_query()
|> Repo.one()
end
def check_needs_to_upgrade(nil), do: {:needs_to_upgrade, :no_trial} def check_needs_to_upgrade(nil), do: {:needs_to_upgrade, :no_trial}
def check_needs_to_upgrade(team) do def check_needs_to_upgrade(team) do
@ -132,7 +169,7 @@ defmodule Plausible.Teams.Billing do
end end
end end
def quota_usage(team, opts) do def quota_usage(team, opts \\ []) do
team = Teams.with_subscription(team) team = Teams.with_subscription(team)
with_features? = Keyword.get(opts, :with_features, false) with_features? = Keyword.get(opts, :with_features, false)
pending_site_ids = Keyword.get(opts, :pending_ownership_site_ids, []) pending_site_ids = Keyword.get(opts, :pending_ownership_site_ids, [])

View File

@ -30,19 +30,20 @@ defmodule PlausibleWeb.BillingController do
def upgrade_to_enterprise_plan(conn, _params) do def upgrade_to_enterprise_plan(conn, _params) do
current_user = conn.assigns.current_user current_user = conn.assigns.current_user
subscription = Plausible.Teams.Adapter.Read.Billing.get_subscription(current_user)
{latest_enterprise_plan, price} = {latest_enterprise_plan, price} =
Plans.latest_enterprise_plan_with_price(current_user, PlausibleWeb.RemoteIP.get(conn)) Plans.latest_enterprise_plan_with_price(current_user, PlausibleWeb.RemoteIP.get(conn))
subscription_resumable? = subscription_resumable? =
Plausible.Billing.Subscriptions.resumable?(current_user.subscription) Plausible.Billing.Subscriptions.resumable?(subscription)
subscribed_to_latest? = subscribed_to_latest? =
subscription_resumable? && subscription_resumable? &&
current_user.subscription.paddle_plan_id == latest_enterprise_plan.paddle_plan_id subscription.paddle_plan_id == latest_enterprise_plan.paddle_plan_id
cond do cond do
Subscription.Status.in?(current_user.subscription, [ Subscription.Status.in?(subscription, [
Subscription.Status.past_due(), Subscription.Status.past_due(),
Subscription.Status.paused() Subscription.Status.paused()
]) -> ]) ->
@ -68,8 +69,9 @@ defmodule PlausibleWeb.BillingController do
def change_plan_preview(conn, %{"plan_id" => new_plan_id}) do def change_plan_preview(conn, %{"plan_id" => new_plan_id}) do
current_user = conn.assigns.current_user current_user = conn.assigns.current_user
subscription = Plausible.Teams.Adapter.Read.Billing.active_subscription_for(current_user)
case preview_subscription(current_user, new_plan_id) do case preview_subscription(subscription, new_plan_id) do
{:ok, {subscription, preview_info}} -> {:ok, {subscription, preview_info}} ->
render(conn, "change_plan_preview.html", render(conn, "change_plan_preview.html",
back_link: Routes.billing_path(conn, :choose_plan), back_link: Routes.billing_path(conn, :choose_plan),
@ -99,7 +101,7 @@ defmodule PlausibleWeb.BillingController do
def change_plan(conn, %{"new_plan_id" => new_plan_id}) do def change_plan(conn, %{"new_plan_id" => new_plan_id}) do
current_user = conn.assigns.current_user current_user = conn.assigns.current_user
case Billing.change_plan(current_user, new_plan_id) do case Plausible.Teams.Adapter.Read.Billing.change_plan(current_user, new_plan_id) do
{:ok, _subscription} -> {:ok, _subscription} ->
conn conn
|> put_flash(:success, "Plan changed successfully") |> put_flash(:success, "Plan changed successfully")
@ -137,15 +139,11 @@ defmodule PlausibleWeb.BillingController do
end end
end end
defp preview_subscription(user, new_plan_id) do defp preview_subscription(nil, _new_plan_id), do: {:error, :no_subscription}
subscription = Billing.active_subscription_for(user)
if subscription do defp preview_subscription(subscription, new_plan_id) do
with {:ok, preview_info} <- Billing.change_plan_preview(subscription, new_plan_id) do with {:ok, preview_info} <- Billing.change_plan_preview(subscription, new_plan_id) do
{:ok, {subscription, preview_info}} {:ok, {subscription, preview_info}}
end end
else
{:error, :no_subscription}
end
end end
end end

View File

@ -24,17 +24,13 @@ defmodule PlausibleWeb.BillingControllerTest do
setup [:create_user, :log_in] setup [:create_user, :log_in]
test "errors if usage exceeds team member limit on the new plan", %{conn: conn, user: user} do test "errors if usage exceeds team member limit on the new plan", %{conn: conn, user: user} do
insert(:subscription, user: user, paddle_plan_id: "123123") subscribe_to_plan(user, "123123")
insert(:site, site = new_site(owner: user)
memberships: [
build(:site_membership, user: user, role: :owner), for _ <- 1..4 do
build(:site_membership, user: build(:user)), add_guest(site, role: :viewer)
build(:site_membership, user: build(:user)), end
build(:site_membership, user: build(:user)),
build(:site_membership, user: build(:user))
]
)
conn = post(conn, Routes.billing_path(conn, :change_plan, @v4_growth_plan)) conn = post(conn, Routes.billing_path(conn, :change_plan, @v4_growth_plan))
@ -46,9 +42,9 @@ defmodule PlausibleWeb.BillingControllerTest do
conn: conn, conn: conn,
user: user user: user
} do } do
insert(:subscription, user: user, paddle_plan_id: "123123") subscribe_to_plan(user, "123123")
for _ <- 1..11, do: insert(:site, members: [user]) for _ <- 1..11, do: new_site(owner: user)
Plausible.Users.allow_next_upgrade_override(user) Plausible.Users.allow_next_upgrade_override(user)
@ -64,8 +60,8 @@ defmodule PlausibleWeb.BillingControllerTest do
conn: conn, conn: conn,
user: user user: user
} do } do
insert(:subscription, user: user, paddle_plan_id: "123123") subscribe_to_plan(user, "123123")
site = insert(:site, members: [user]) site = new_site(owner: user)
now = NaiveDateTime.utc_now() now = NaiveDateTime.utc_now()
generate_usage_for(site, 11_000, Timex.shift(now, days: -5)) generate_usage_for(site, 11_000, Timex.shift(now, days: -5))
@ -91,7 +87,7 @@ defmodule PlausibleWeb.BillingControllerTest do
end end
test "calls Paddle API to update subscription", %{conn: conn, user: user} do test "calls Paddle API to update subscription", %{conn: conn, user: user} do
insert(:subscription, user: user) subscribe_to_plan(user, "321321")
post(conn, Routes.billing_path(conn, :change_plan, "123123")) post(conn, Routes.billing_path(conn, :change_plan, "123123"))
@ -218,7 +214,7 @@ defmodule PlausibleWeb.BillingControllerTest do
setup [:create_user, :log_in] setup [:create_user, :log_in]
test "renders preview information about the plan change", %{conn: conn, user: user} do test "renders preview information about the plan change", %{conn: conn, user: user} do
insert(:subscription, user: user, paddle_plan_id: @v4_growth_plan) subscribe_to_plan(user, @v4_growth_plan)
html_response = html_response =
conn conn
@ -339,29 +335,30 @@ defmodule PlausibleWeb.BillingControllerTest do
end end
defp configure_enterprise_plan(%{user: user}) do defp configure_enterprise_plan(%{user: user}) do
insert(:enterprise_plan, subscribe_to_enterprise_plan(user,
user_id: user.id,
paddle_plan_id: "123", paddle_plan_id: "123",
billing_interval: :yearly, billing_interval: :yearly,
monthly_pageview_limit: 50_000_000, monthly_pageview_limit: 50_000_000,
site_limit: 20_000, site_limit: 20_000,
hourly_api_request_limit: 5000, hourly_api_request_limit: 5000,
inserted_at: Timex.now() |> Timex.shift(hours: 1) inserted_at: NaiveDateTime.utc_now() |> NaiveDateTime.shift(hour: 1),
subscription?: false
) )
:ok :ok
end end
defp subscribe_enterprise(%{user: user}, opts \\ []) do defp subscribe_enterprise(%{user: user}, opts \\ []) do
{paddle_plan_id, opts} = Keyword.pop(opts, :paddle_plan_id, "321")
opts = opts =
opts opts
|> Keyword.put(:user, user) |> Keyword.put(:user, user)
|> Keyword.put_new(:paddle_plan_id, "321")
|> Keyword.put_new(:status, Subscription.Status.active()) |> Keyword.put_new(:status, Subscription.Status.active())
insert(:subscription, opts) user = subscribe_to_plan(user, paddle_plan_id, opts)
{:ok, user: Plausible.Users.with_subscription(user)} {:ok, user: user}
end end
defp get_paddle_checkout_params(element) do defp get_paddle_checkout_params(element) do