Refactor Plausible.Billing.Plans module (#3268)

This pull request introduces a series of improvements to Plausible.Billing.Plans, including:

* Tag the JSON file with the plan version
* Rename the JSON field limit to monthly_pageview_limit
* Move site_limit function to Billing.Plans
* Refactor subscription_interval, allowance and site_limit functions
* Remove unused AnalyzePlans task
This commit is contained in:
Vini Brasil 2023-08-16 13:38:38 -03:00 committed by GitHub
parent 3f9ca35d58
commit 34f1ddfc8c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 305 additions and 281 deletions

View File

@ -8,7 +8,6 @@ ENVIRONMENT=test
MAILER_ADAPTER=Bamboo.TestAdapter
ENABLE_EMAIL_VERIFICATION=true
SELFHOST=false
SITE_LIMIT=3
HCAPTCHA_SITEKEY=test
HCAPTCHA_SECRET=scottiger
IP_GEOLOCATION_DB=test/priv/GeoLite2-City-Test.mmdb

View File

@ -204,11 +204,6 @@ custom_script_name =
config_dir
|> get_var_from_path_or_env("CUSTOM_SCRIPT_NAME", "script")
{site_limit, ""} =
config_dir
|> get_var_from_path_or_env("SITE_LIMIT", "50")
|> Integer.parse()
site_limit_exempt =
config_dir
|> get_var_from_path_or_env("SITE_LIMIT_EXEMPT", "")
@ -241,7 +236,6 @@ config :plausible,
environment: env,
mailer_email: mailer_email,
super_admin_user_ids: super_admin_user_ids,
site_limit: site_limit,
site_limit_exempt: site_limit_exempt,
is_selfhost: is_selfhost,
custom_script_name: custom_script_name,

View File

@ -1,60 +0,0 @@
defmodule Mix.Tasks.AnalyzePlans do
use Mix.Task
use Plausible.Repo
# coveralls-ignore-start
def run(_) do
Mix.Task.run("app.start")
res =
Repo.all(
from s in Plausible.Billing.Subscription,
where: s.status == "active",
group_by: s.paddle_plan_id,
select: {s.paddle_plan_id, count(s)}
)
res =
Enum.map(res, fn {plan_id, count} ->
plan = Plausible.Billing.Plans.find(plan_id)
if plan do
is_monthly = plan_id == plan.monthly_product_id
monthly_revenue =
if is_monthly do
price(plan.monthly_cost)
else
price(plan.yearly_cost) / 12
end
{PlausibleWeb.StatsView.large_number_format(plan.limit), monthly_revenue, count}
end
end)
|> Enum.filter(& &1)
res =
Enum.reduce(res, %{}, fn {limit, revenue, count}, acc ->
total_revenue = revenue * count
Map.update(acc, limit, {total_revenue, count}, fn {ex_rev, ex_count} ->
{ex_rev + total_revenue, ex_count + count}
end)
end)
total_revenue = round(Enum.reduce(res, 0, fn {_, {revenue, _}}, sum -> sum + revenue end))
for {limit, {rev, _}} <- res do
percentage = round(rev / total_revenue * 100)
IO.puts(
"The #{limit} plan makes up #{percentage}% of total revenue ($#{round(rev)} / $#{total_revenue})"
)
end
end
defp price("$" <> nr) do
String.to_integer(nr)
end
end

View File

@ -156,37 +156,6 @@ defmodule Plausible.Billing do
Plausible.Stats.Clickhouse.usage_breakdown(site_ids)
end
@doc """
Returns the number of sites that an account is allowed to have. Accounts for
grandfathering old accounts to unlimited websites and ignores site limit on self-hosted
installations.
"""
@limit_accounts_since ~D[2021-05-05]
def sites_limit(user) do
user = Plausible.Repo.preload(user, :enterprise_plan)
cond do
Timex.before?(user.inserted_at, @limit_accounts_since) ->
nil
Application.get_env(:plausible, :is_selfhost) ->
nil
user.email in Application.get_env(:plausible, :site_limit_exempt) ->
nil
user.enterprise_plan ->
if has_active_enterprise_subscription(user) do
nil
else
Application.get_env(:plausible, :site_limit)
end
true ->
Application.get_env(:plausible, :site_limit)
end
end
defp handle_subscription_created(params) do
params =
if present?(params["passthrough"]) do
@ -255,18 +224,6 @@ defmodule Plausible.Billing do
end
end
defp has_active_enterprise_subscription(user) do
Plausible.Repo.exists?(
from(s in Plausible.Billing.Subscription,
join: e in Plausible.Billing.EnterprisePlan,
on: s.user_id == e.user_id and s.paddle_plan_id == e.paddle_plan_id,
where: s.user_id == ^user.id,
where: s.paddle_plan_id == ^user.enterprise_plan.paddle_plan_id,
where: s.status == "active"
)
)
end
defp format_subscription(params) do
%{
paddle_subscription_id: params["subscription_id"],

View File

@ -2,12 +2,14 @@ defmodule Plausible.Billing.Plan do
@moduledoc false
@derive Jason.Encoder
@enforce_keys ~w(limit volume monthly_cost yearly_cost monthly_product_id yearly_product_id)a
@enforce_keys ~w(kind site_limit monthly_pageview_limit volume monthly_cost yearly_cost monthly_product_id yearly_product_id)a
defstruct @enforce_keys
@type t() ::
%__MODULE__{
limit: non_neg_integer(),
kind: atom(),
monthly_pageview_limit: non_neg_integer(),
site_limit: non_neg_integer(),
volume: String.t(),
monthly_cost: String.t() | nil,
yearly_cost: String.t() | nil,
@ -34,7 +36,14 @@ defmodule Plausible.Billing.Plans do
path
|> File.read!()
|> Jason.decode!(keys: :atoms!)
|> Enum.map(&Map.put(&1, :volume, PlausibleWeb.StatsView.large_number_format(&1.limit)))
|> Enum.map(
&Map.put(
&1,
:volume,
PlausibleWeb.StatsView.large_number_format(&1.monthly_pageview_limit)
)
)
|> Enum.map(&Map.put(&1, :kind, String.to_atom(&1.kind)))
|> Enum.map(&struct!(Plausible.Billing.Plan, &1))
Module.put_attribute(__MODULE__, f, contents)
@ -48,7 +57,7 @@ defmodule Plausible.Billing.Plans do
As new versions of plans are introduced, users who were on old plans can
still choose from old plans.
"""
def for_user(user) do
def for_user(%Plausible.Auth.User{} = user) do
user = Plausible.Users.with_subscription(user)
cond do
@ -96,46 +105,81 @@ defmodule Plausible.Billing.Plans do
end)
end
def subscription_interval(%Plausible.Billing.Subscription{paddle_plan_id: "free_10k"}),
do: "N/A"
@limit_sites_since ~D[2021-05-05]
@spec site_limit(Plausible.Auth.User.t()) :: non_neg_integer() | :unlimited
@doc """
Returns the limit of sites a user can have.
For enterprise customers, returns :unlimited. The site limit is checked in a
background job so as to avoid service disruption.
"""
def site_limit(user) do
cond do
Application.get_env(:plausible, :is_selfhost) -> :unlimited
user.email in Application.get_env(:plausible, :site_limit_exempt) -> :unlimited
Timex.before?(user.inserted_at, @limit_sites_since) -> :unlimited
true -> get_site_limit_from_plan(user)
end
end
@site_limit_for_trials 50
@site_limit_for_free_10k 50
defp get_site_limit_from_plan(user) do
user = Plausible.Users.with_subscription(user)
case get_subscription_plan(user.subscription) do
%Plausible.Billing.EnterprisePlan{} -> :unlimited
%Plausible.Billing.Plan{site_limit: site_limit} -> site_limit
:free_10k -> @site_limit_for_free_10k
nil -> @site_limit_for_trials
end
end
defp get_subscription_plan(subscription) do
if subscription && subscription.paddle_plan_id == "free_10k" do
:free_10k
else
find(subscription) || get_enterprise_plan(subscription)
end
end
def subscription_interval(subscription) do
case find(subscription.paddle_plan_id) do
nil ->
enterprise_plan = get_enterprise_plan(subscription)
case get_subscription_plan(subscription) do
%Plausible.Billing.EnterprisePlan{billing_interval: interval} ->
interval
enterprise_plan && enterprise_plan.billing_interval
plan ->
if subscription.paddle_plan_id == plan.monthly_product_id do
%Plausible.Billing.Plan{} = plan ->
if plan.monthly_product_id == subscription.paddle_plan_id do
"monthly"
else
"yearly"
end
_any ->
"N/A"
end
end
def allowance(%Plausible.Billing.Subscription{paddle_plan_id: "free_10k"}), do: 10_000
@spec allowance(Plausible.Billing.Subscription.t()) :: non_neg_integer() | nil
def allowance(subscription) do
found = find(subscription.paddle_plan_id)
case get_subscription_plan(subscription) do
%Plausible.Billing.EnterprisePlan{monthly_pageview_limit: limit} ->
limit
if found do
Map.fetch!(found, :limit)
else
enterprise_plan = get_enterprise_plan(subscription)
%Plausible.Billing.Plan{monthly_pageview_limit: limit} ->
limit
if enterprise_plan do
enterprise_plan.monthly_pageview_limit
else
:free_10k ->
10_000
_any ->
Sentry.capture_message("Unknown allowance for plan",
extra: %{
paddle_plan_id: subscription.paddle_plan_id
}
extra: %{paddle_plan_id: subscription.paddle_plan_id}
)
end
end
end
defp get_enterprise_plan(nil), do: nil
defp get_enterprise_plan(%Plausible.Billing.Subscription{} = subscription) do
Repo.get_by(Plausible.Billing.EnterprisePlan,
@ -161,7 +205,7 @@ defmodule Plausible.Billing.Plans do
cond do
usage_during_cycle > @enterprise_level_usage -> :enterprise
Plausible.Auth.enterprise?(user) -> :enterprise
true -> Enum.find(for_user(user), &(usage_during_cycle < &1.limit))
true -> Enum.find(for_user(user), &(usage_during_cycle < &1.monthly_pageview_limit))
end
end

View File

@ -13,13 +13,10 @@ defmodule Plausible.Sites do
Ecto.Multi.new()
|> Ecto.Multi.run(:limit, fn _, _ ->
limit = Plausible.Billing.sites_limit(user)
count = owned_sites_count(user)
if count >= limit do
{:error, limit}
else
{:ok, count}
case {Plausible.Billing.Plans.site_limit(user), owned_sites_count(user)} do
{:unlimited, actual} -> {:ok, actual}
{limit, actual} when actual >= limit -> {:error, limit}
{_limit, actual} -> {:ok, actual}
end
end)
|> Ecto.Multi.insert(:site, site_changeset)

View File

@ -51,17 +51,17 @@ defmodule PlausibleWeb.SiteController do
def new(conn, _params) do
current_user = conn.assigns[:current_user]
owned_site_count = Plausible.Sites.owned_sites_count(current_user)
site_limit = Plausible.Billing.sites_limit(current_user)
is_at_limit = site_limit && owned_site_count >= site_limit
is_first_site = owned_site_count == 0
changeset = Plausible.Site.changeset(%Plausible.Site{})
{site_limit, is_at_limit} =
case Plausible.Billing.Plans.site_limit(current_user) do
:unlimited -> {:unlimited, false}
limit when is_integer(limit) -> {limit, owned_site_count >= limit}
end
render(conn, "new.html",
changeset: changeset,
is_first_site: is_first_site,
changeset: Plausible.Site.changeset(%Plausible.Site{}),
is_first_site: owned_site_count == 0,
is_at_limit: is_at_limit,
site_limit: site_limit,
layout: {PlausibleWeb.LayoutView, "focus.html"}

View File

@ -1,72 +1,92 @@
[
{
"limit":10000,
"kind":"growth",
"monthly_pageview_limit":10000,
"monthly_cost":"$6",
"monthly_product_id":"558018",
"yearly_cost":"$48",
"yearly_product_id":"572810"
"yearly_product_id":"572810",
"site_limit":50
},
{
"limit":100000,
"kind":"growth",
"monthly_pageview_limit":100000,
"monthly_cost":"$12",
"monthly_product_id":"558745",
"yearly_cost":"$96",
"yearly_product_id":"590752"
"yearly_product_id":"590752",
"site_limit":50
},
{
"limit":200000,
"kind":"growth",
"monthly_pageview_limit":200000,
"monthly_cost":"$18",
"monthly_product_id":"597485",
"yearly_cost":"$144",
"yearly_product_id":"597486"
"yearly_product_id":"597486",
"site_limit":50
},
{
"limit":500000,
"kind":"growth",
"monthly_pageview_limit":500000,
"monthly_cost":"$27",
"monthly_product_id":"597487",
"yearly_cost":"$216",
"yearly_product_id":"597488"
"yearly_product_id":"597488",
"site_limit":50
},
{
"limit":1000000,
"kind":"growth",
"monthly_pageview_limit":1000000,
"monthly_cost":"$48",
"monthly_product_id":"597642",
"yearly_cost":"$384",
"yearly_product_id":"597643"
"yearly_product_id":"597643",
"site_limit":50
},
{
"limit":2000000,
"kind":"growth",
"monthly_pageview_limit":2000000,
"monthly_cost":"$69",
"monthly_product_id":"597309",
"yearly_cost":"$552",
"yearly_product_id":"597310"
"yearly_product_id":"597310",
"site_limit":50
},
{
"limit":5000000,
"kind":"growth",
"monthly_pageview_limit":5000000,
"monthly_cost":"$99",
"monthly_product_id":"597311",
"yearly_cost":"$792",
"yearly_product_id":"597312"
"yearly_product_id":"597312",
"site_limit":50
},
{
"limit":10000000,
"kind":"growth",
"monthly_pageview_limit":10000000,
"monthly_cost":"$150",
"monthly_product_id":"642352",
"yearly_cost":"$1200",
"yearly_product_id":"642354"
"yearly_product_id":"642354",
"site_limit":50
},
{
"limit":20000000,
"kind":"growth",
"monthly_pageview_limit":20000000,
"monthly_cost":"$225",
"monthly_product_id":"642355",
"yearly_cost":"$1800",
"yearly_product_id":"642356"
"yearly_product_id":"642356",
"site_limit":50
},
{
"limit":50000000,
"kind":"growth",
"monthly_pageview_limit":50000000,
"monthly_cost":"$330",
"monthly_product_id":"650652",
"yearly_cost":"$2640",
"yearly_product_id":"650653"
"yearly_product_id":"650653",
"site_limit":50
}
]

View File

@ -1,72 +1,92 @@
[
{
"limit":10000,
"kind":"growth",
"monthly_pageview_limit":10000,
"monthly_cost":"$6",
"monthly_product_id":"654177",
"yearly_cost":"$60",
"yearly_product_id":"653232"
"yearly_product_id":"653232",
"site_limit":50
},
{
"limit":100000,
"kind":"growth",
"monthly_pageview_limit":100000,
"monthly_cost":"$12",
"monthly_product_id":"654178",
"yearly_cost":"$120",
"yearly_product_id":"653234"
"yearly_product_id":"653234",
"site_limit":50
},
{
"limit":200000,
"kind":"growth",
"monthly_pageview_limit":200000,
"monthly_cost":"$20",
"monthly_product_id":"653237",
"yearly_cost":"$200",
"yearly_product_id":"653236"
"yearly_product_id":"653236",
"site_limit":50
},
{
"limit":500000,
"kind":"growth",
"monthly_pageview_limit":500000,
"monthly_cost":"$30",
"monthly_product_id":"653238",
"yearly_cost":"$300",
"yearly_product_id":"653239"
"yearly_product_id":"653239",
"site_limit":50
},
{
"limit":1000000,
"kind":"growth",
"monthly_pageview_limit":1000000,
"monthly_cost":"$50",
"monthly_product_id":"653240",
"yearly_cost":"$500",
"yearly_product_id":"653242"
"yearly_product_id":"653242",
"site_limit":50
},
{
"limit":2000000,
"kind":"growth",
"monthly_pageview_limit":2000000,
"monthly_cost":"$70",
"monthly_product_id":"653253",
"yearly_cost":"$700",
"yearly_product_id":"653254"
"yearly_product_id":"653254",
"site_limit":50
},
{
"limit":5000000,
"kind":"growth",
"monthly_pageview_limit":5000000,
"monthly_cost":"$100",
"monthly_product_id":"653255",
"yearly_cost":"$1000",
"yearly_product_id":"653256"
"yearly_product_id":"653256",
"site_limit":50
},
{
"limit":10000000,
"kind":"growth",
"monthly_pageview_limit":10000000,
"monthly_cost":"$150",
"monthly_product_id":"654181",
"yearly_cost":"$1500",
"yearly_product_id":"653257"
"yearly_product_id":"653257",
"site_limit":50
},
{
"limit":20000000,
"kind":"growth",
"monthly_pageview_limit":20000000,
"monthly_cost":"$225",
"monthly_product_id":"654182",
"yearly_cost":"$2250",
"yearly_product_id":"653258"
"yearly_product_id":"653258",
"site_limit":50
},
{
"limit":50000000,
"kind":"growth",
"monthly_pageview_limit":50000000,
"monthly_cost":"$330",
"monthly_product_id":"654183",
"yearly_cost":"$3300",
"yearly_product_id":"653259"
"yearly_product_id":"653259",
"site_limit":50
}
]

View File

@ -1,59 +1,74 @@
[
{
"limit":10000,
"kind":"growth",
"monthly_pageview_limit":10000,
"monthly_cost":"$9",
"monthly_product_id":"749342",
"yearly_cost":"$90",
"yearly_product_id":"749343"
"yearly_product_id":"749343",
"site_limit":50
},
{
"limit":100000,
"kind":"growth",
"monthly_pageview_limit":100000,
"monthly_cost":"$19",
"monthly_product_id":"749344",
"yearly_cost":"$190",
"yearly_product_id":"749345"
"yearly_product_id":"749345",
"site_limit":50
},
{
"limit":200000,
"kind":"growth",
"monthly_pageview_limit":200000,
"monthly_cost":"$29",
"monthly_product_id":"749346",
"yearly_cost":"$290",
"yearly_product_id":"749347"
"yearly_product_id":"749347",
"site_limit":50
},
{
"limit":500000,
"kind":"growth",
"monthly_pageview_limit":500000,
"monthly_cost":"$49",
"monthly_product_id":"749348",
"yearly_cost":"$490",
"yearly_product_id":"749349"
"yearly_product_id":"749349",
"site_limit":50
},
{
"limit":1000000,
"kind":"growth",
"monthly_pageview_limit":1000000,
"monthly_cost":"$69",
"monthly_product_id":"749350",
"yearly_cost":"$690",
"yearly_product_id":"749352"
"yearly_product_id":"749352",
"site_limit":50
},
{
"limit":2000000,
"kind":"growth",
"monthly_pageview_limit":2000000,
"monthly_cost":"$89",
"monthly_product_id":"749353",
"yearly_cost":"$890",
"yearly_product_id":"749355"
"yearly_product_id":"749355",
"site_limit":50
},
{
"limit":5000000,
"kind":"growth",
"monthly_pageview_limit":5000000,
"monthly_cost":"$129",
"monthly_product_id":"749356",
"yearly_cost":"$1290",
"yearly_product_id":"749357"
"yearly_product_id":"749357",
"site_limit":50
},
{
"limit":10000000,
"kind":"growth",
"monthly_pageview_limit":10000000,
"monthly_cost":"$169",
"monthly_product_id":"749358",
"yearly_cost":"$1690",
"yearly_product_id":"749359"
"yearly_product_id":"749359",
"site_limit":50
}
]

View File

@ -1,16 +1,20 @@
[
{
"limit":10000,
"kind":"growth",
"monthly_pageview_limit":10000,
"monthly_product_id":"19878",
"yearly_product_id":"20127",
"monthly_cost":"$6",
"yearly_cost":"$60"
"yearly_cost":"$60",
"site_limit":50
},
{
"limit":100000,
"kind":"growth",
"monthly_pageview_limit":100000,
"monthly_product_id":"20657",
"yearly_product_id":"20658",
"monthly_cost":"$12.34",
"yearly_cost":"$120.34"
"yearly_cost":"$120.34",
"site_limit":50
}
]

View File

@ -1,9 +1,11 @@
[
{
"limit":150000000,
"kind":"growth",
"monthly_pageview_limit":150000000,
"yearly_product_id":"648089",
"yearly_cost":"$4800",
"monthly_product_id":null,
"monthly_cost":null
"monthly_cost":null,
"site_limit":50
}
]

View File

@ -1,9 +1,11 @@
[
{
"limit":10000000,
"kind":"growth",
"monthly_pageview_limit":10000000,
"monthly_product_id":"655350",
"monthly_cost":"$250",
"yearly_product_id":null,
"yearly_cost":null
"yearly_cost":null,
"site_limit":50
}
]

View File

@ -49,52 +49,6 @@ defmodule Plausible.BillingTest do
end
end
describe "sites_limit" do
test "is the globally configured site limit for regular accounts" do
user = insert(:user, subscription: build(:subscription))
assert Billing.sites_limit(user) == Application.get_env(:plausible, :site_limit)
end
test "is limited for enterprise customers who have not upgraded yet" do
enterprise_plan_paddle_id = "123321"
user =
insert(:user,
enterprise_plan: build(:enterprise_plan, paddle_plan_id: enterprise_plan_paddle_id),
subscription: build(:subscription, paddle_plan_id: "99999")
)
assert Billing.sites_limit(user) == Application.get_env(:plausible, :site_limit)
end
test "is unlimited for enterprise customers. Their site limit is checked in a background job so as to avoid service disruption" do
enterprise_plan_paddle_id = "123321"
user =
insert(:user,
enterprise_plan: build(:enterprise_plan, paddle_plan_id: enterprise_plan_paddle_id),
subscription: build(:subscription, paddle_plan_id: enterprise_plan_paddle_id)
)
assert Billing.sites_limit(user) == nil
end
test "is unlimited for enterprise customers who are due to change a plan" do
enterprise_plan_paddle_id = "123321"
user =
insert(:user,
enterprise_plan: build(:enterprise_plan, paddle_plan_id: enterprise_plan_paddle_id),
subscription: build(:subscription, paddle_plan_id: enterprise_plan_paddle_id)
)
insert(:enterprise_plan, user_id: user.id, paddle_plan_id: "new-paddle-plan-id")
assert Billing.sites_limit(user) == nil
end
end
describe "last_two_billing_cycles" do
test "billing on the 1st" do
last_bill_date = ~D[2021-01-01]

View File

@ -88,22 +88,22 @@ defmodule Plausible.Billing.PlansTest do
user = insert(:user, subscription: build(:subscription, paddle_plan_id: @v1_plan_id))
assert %Plausible.Billing.Plan{
limit: 100_000,
monthly_pageview_limit: 100_000,
monthly_cost: "$12",
monthly_product_id: "558745",
volume: "100k",
yearly_cost: "$96",
yearly_product_id: "590752"
} == Plans.suggest(user, 10_000)
} = Plans.suggest(user, 10_000)
assert %Plausible.Billing.Plan{
limit: 200_000,
monthly_pageview_limit: 200_000,
monthly_cost: "$18",
monthly_product_id: "597485",
volume: "200k",
yearly_cost: "$144",
yearly_product_id: "597486"
} == Plans.suggest(user, 100_000)
} = Plans.suggest(user, 100_000)
end
test "returns nil when user has enterprise-level usage" do
@ -153,4 +153,86 @@ defmodule Plausible.Billing.PlansTest do
] == Plans.yearly_product_ids()
end
end
describe "site_limit/1" do
test "returns 50 when user is on an old plan" do
user_on_v1 = insert(:user, subscription: build(:subscription, paddle_plan_id: @v1_plan_id))
user_on_v2 = insert(:user, subscription: build(:subscription, paddle_plan_id: @v2_plan_id))
user_on_v3 = insert(:user, subscription: build(:subscription, paddle_plan_id: @v3_plan_id))
assert 50 == Plans.site_limit(user_on_v1)
assert 50 == Plans.site_limit(user_on_v2)
assert 50 == Plans.site_limit(user_on_v3)
end
test "returns 50 when user is on free_10k plan" do
user = insert(:user, subscription: build(:subscription, paddle_plan_id: "free_10k"))
assert 50 == Plans.site_limit(user)
end
test "returns unlimited when user is on an enterprise plan" do
user = insert(:user)
enterprise_plan =
insert(:enterprise_plan,
user_id: user.id,
monthly_pageview_limit: 100_000,
site_limit: 500
)
_subscription =
insert(:subscription, user_id: user.id, paddle_plan_id: enterprise_plan.paddle_plan_id)
assert :unlimited == Plans.site_limit(user)
end
test "returns 50 when user in on trial" do
user = insert(:user, trial_expiry_date: Timex.shift(Timex.now(), days: 7))
assert 50 == Plans.site_limit(user)
user = insert(:user, trial_expiry_date: Timex.shift(Timex.now(), days: -7))
assert 50 == Plans.site_limit(user)
end
test "returns the subscription limit for enterprise users who have not paid yet" do
user =
insert(:user,
enterprise_plan: build(:enterprise_plan, paddle_plan_id: "123321"),
subscription: build(:subscription, paddle_plan_id: @v1_plan_id)
)
assert 50 == Plans.site_limit(user)
end
test "returns 50 for enterprise users who have not upgraded yet and are on trial" do
user =
insert(:user,
enterprise_plan: build(:enterprise_plan, paddle_plan_id: "123321"),
subscription: nil
)
assert 50 == Plans.site_limit(user)
end
test "is unlimited for enterprise customers" do
user =
insert(:user,
enterprise_plan: build(:enterprise_plan, paddle_plan_id: "123321"),
subscription: build(:subscription, paddle_plan_id: "123321")
)
assert :unlimited == Plans.site_limit(user)
end
test "is unlimited for enterprise customers who are due to change a plan" do
user =
insert(:user,
enterprise_plan: build(:enterprise_plan, paddle_plan_id: "old-paddle-plan-id"),
subscription: build(:subscription, paddle_plan_id: "old-paddle-plan-id")
)
insert(:enterprise_plan, user_id: user.id, paddle_plan_id: "new-paddle-plan-id")
assert :unlimited == Plans.site_limit(user)
end
end
end

View File

@ -62,10 +62,7 @@ defmodule PlausibleWeb.Api.ExternalSitesControllerTest do
end
test "does not allow creating more sites than the limit", %{conn: conn, user: user} do
patch_env(:site_limit, 3)
insert(:site, members: [user])
insert(:site, members: [user])
insert(:site, members: [user])
insert_list(50, :site, members: [user])
conn =
post(conn, "/api/v1/sites", %{
@ -75,7 +72,7 @@ defmodule PlausibleWeb.Api.ExternalSitesControllerTest do
assert json_response(conn, 403) == %{
"error" =>
"Your account has reached the limit of 3 sites per account. Please contact hello@plausible.io to unlock more sites."
"Your account has reached the limit of 50 sites per account. Please contact hello@plausible.io to unlock more sites."
}
end

View File

@ -170,10 +170,7 @@ defmodule PlausibleWeb.SiteControllerTest do
conn: conn,
user: user
} do
# default site limit defined in config/.test.env
insert(:site, members: [user])
insert(:site, members: [user])
insert(:site, members: [user])
insert_list(50, :site, members: [user])
conn =
post(conn, "/sites", %{
@ -185,7 +182,7 @@ defmodule PlausibleWeb.SiteControllerTest do
assert html = html_response(conn, 200)
assert html =~ "Upgrade required"
assert html =~ "Your account is limited to 3 sites"
assert html =~ "Your account is limited to 50 sites"
assert html =~ "Please contact support"
refute Repo.get_by(Plausible.Site, domain: "over-limit.example.com")
end