Switch on teams schema in choose plan view behind FF (#4838)

* Switch on teams schema in choose plan view behind FF

* Proxy via Read adapter where applicable for billing context

* Proxy remaining plan-related functions

* Switch enterprise_configured?/1 tests to use the adapter

* Format

* Update SiteLocker tests

* Actually use `has_active_subscription?/1` billing adapter

---------

Co-authored-by: Adam Rutkowski <hq@mtod.org>
This commit is contained in:
Adrian Gruntkowski 2024-11-20 09:35:18 +01:00 committed by GitHub
parent 7b49dd33c7
commit 380dc00d1a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
18 changed files with 251 additions and 229 deletions

View File

@ -6,14 +6,14 @@ defmodule Plausible.Billing do
alias Plausible.Billing.{Subscription, Plans, Quota}
alias Plausible.Auth.User
@spec active_subscription_for(integer()) :: Subscription.t() | nil
def active_subscription_for(user_id) do
user_id |> active_subscription_query() |> Repo.one()
@spec active_subscription_for(User.t()) :: Subscription.t() | nil
def active_subscription_for(user) do
user |> active_subscription_query() |> Repo.one()
end
@spec has_active_subscription?(integer()) :: boolean()
def has_active_subscription?(user_id) do
user_id |> active_subscription_query() |> Repo.exists?()
@spec has_active_subscription?(User.t()) :: boolean()
def has_active_subscription?(user) do
user |> active_subscription_query() |> Repo.exists?()
end
def subscription_created(params) do
@ -41,7 +41,7 @@ defmodule Plausible.Billing do
end
def change_plan(user, new_plan_id) do
subscription = active_subscription_for(user.id)
subscription = active_subscription_for(user)
plan = Plans.find(new_plan_id)
limit_checking_opts =
@ -283,9 +283,9 @@ defmodule Plausible.Billing do
"subscription_cancelled__#{user.id}"
end
defp active_subscription_query(user_id) do
defp active_subscription_query(user) do
from(s in Subscription,
where: s.user_id == ^user_id and s.status == ^Subscription.Status.active(),
where: s.user_id == ^user.id and s.status == ^Subscription.Status.active(),
order_by: [desc: s.inserted_at],
limit: 1
)

View File

@ -28,21 +28,20 @@ defmodule Plausible.Billing.Plans do
@business_tier_launch ~N[2023-11-08 12:00:00]
def business_tier_launch, do: @business_tier_launch
@spec growth_plans_for(User.t()) :: [Plan.t()]
@spec growth_plans_for(Subscription.t()) :: [Plan.t()]
@doc """
Returns a list of growth plans available for the user to choose.
Returns a list of growth plans available for the subscription to choose.
As new versions of plans are introduced, users who were on old plans can
As new versions of plans are introduced, subscriptions which were on old plans can
still choose from old plans.
"""
def growth_plans_for(%User{} = user) do
user = Plausible.Users.with_subscription(user)
owned_plan = get_regular_plan(user.subscription)
def growth_plans_for(subscription) do
owned_plan = get_regular_plan(subscription)
cond do
Application.get_env(:plausible, :environment) in ["dev", "staging"] -> @sandbox_plans
is_nil(owned_plan) -> @plans_v4
user.subscription && Subscriptions.expired?(user.subscription) -> @plans_v4
subscription && Subscriptions.expired?(subscription) -> @plans_v4
owned_plan.kind == :business -> @plans_v4
owned_plan.generation == 1 -> @plans_v1 |> drop_high_plans(owned_plan)
owned_plan.generation == 2 -> @plans_v2 |> drop_high_plans(owned_plan)
@ -52,21 +51,20 @@ defmodule Plausible.Billing.Plans do
|> Enum.filter(&(&1.kind == :growth))
end
def business_plans_for(%User{} = user) do
user = Plausible.Users.with_subscription(user)
owned_plan = get_regular_plan(user.subscription)
def business_plans_for(subscription) do
owned_plan = get_regular_plan(subscription)
cond do
Application.get_env(:plausible, :environment) in ["dev", "staging"] -> @sandbox_plans
user.subscription && Subscriptions.expired?(user.subscription) -> @plans_v4
subscription && Subscriptions.expired?(subscription) -> @plans_v4
owned_plan && owned_plan.generation < 4 -> @plans_v3
true -> @plans_v4
end
|> Enum.filter(&(&1.kind == :business))
end
def available_plans_for(%User{} = user, opts \\ []) do
plans = growth_plans_for(user) ++ business_plans_for(user)
def available_plans_for(subscription, opts \\ []) do
plans = growth_plans_for(subscription) ++ business_plans_for(subscription)
plans =
if Keyword.get(opts, :with_prices) do
@ -220,18 +218,16 @@ defmodule Plausible.Billing.Plans do
def suggest(user, usage_during_cycle) do
cond do
usage_during_cycle > @enterprise_level_usage -> :enterprise
Plausible.Auth.enterprise_configured?(user) -> :enterprise
true -> suggest_by_usage(user, usage_during_cycle)
Plausible.Teams.Adapter.Read.Billing.enterprise_configured?(user) -> :enterprise
true -> Plausible.Teams.Adapter.Read.Billing.suggest_by_usage(user, usage_during_cycle)
end
end
defp suggest_by_usage(user, usage_during_cycle) do
user = Plausible.Users.with_subscription(user)
def suggest_by_usage(subscription, usage_during_cycle) do
available_plans =
if business_tier?(user.subscription),
do: business_plans_for(user),
else: growth_plans_for(user)
if business_tier?(subscription),
do: business_plans_for(subscription),
else: growth_plans_for(subscription)
Enum.find(available_plans, &(usage_during_cycle < &1.monthly_pageview_limit))
end

View File

@ -67,10 +67,11 @@ defmodule Plausible.Billing.SiteLocker do
@spec send_grace_period_end_email(Plausible.Auth.User.t()) :: Plausible.Mailer.result()
def send_grace_period_end_email(user) do
usage = Plausible.Billing.Quota.Usage.monthly_pageview_usage(user)
usage = Plausible.Teams.Adapter.Read.Billing.monthly_pageview_usage(user)
suggested_plan = Plausible.Billing.Plans.suggest(user, usage.last_cycle.total)
PlausibleWeb.Email.dashboard_locked(user, usage, suggested_plan)
user
|> PlausibleWeb.Email.dashboard_locked(usage, suggested_plan)
|> Plausible.Mailer.send()
end
end

View File

@ -4,6 +4,22 @@ defmodule Plausible.Teams.Adapter.Read.Billing do
"""
use Plausible.Teams.Adapter
def enterprise_configured?(nil), do: false
def enterprise_configured?(user) do
switch(user,
team_fn: &Plausible.Teams.Billing.enterprise_configured?/1,
user_fn: &Plausible.Auth.enterprise_configured?/1
)
end
def has_active_subscription?(user) do
switch(user,
team_fn: &Plausible.Teams.Billing.has_active_subscription?/1,
user_fn: &Plausible.Billing.has_active_subscription?/1
)
end
def get_subscription(user) do
case user_or_team(user) do
%{subscription: subscription} -> subscription
@ -131,4 +147,9 @@ defmodule Plausible.Teams.Adapter.Read.Billing do
end
)
end
def suggest_by_usage(user, usage_during_cycle) do
subscription = get_subscription(user)
Plausible.Billing.Plans.suggest_by_usage(subscription, usage_during_cycle)
end
end

View File

@ -8,6 +8,13 @@ defmodule Plausible.Teams.Adapter.Read.Ownership do
alias Plausible.Auth
alias Plausible.Site.Memberships.Invitations
def all_pending_site_transfers(email, user) do
switch(user,
team_fn: fn _ -> Plausible.Teams.Memberships.all_pending_site_transfers(email) end,
user_fn: fn _ -> Plausible.Site.Memberships.all_pending_ownerships(email) end
)
end
def get_owner(site, user) do
switch(user,
team_fn: fn team ->

View File

@ -12,10 +12,28 @@ defmodule Plausible.Teams.Billing do
alias Plausible.Billing.{Plan, Plans, EnterprisePlan, Feature}
alias Plausible.Billing.Feature.{Goals, Props, StatsAPI}
require Plausible.Billing.Subscription.Status
@team_member_limit_for_trials 3
@limit_sites_since ~D[2021-05-05]
@site_limit_for_trials 10
def enterprise_configured?(nil), do: false
def enterprise_configured?(%Teams.Team{} = team) do
team
|> Ecto.assoc(:enterprise_plan)
|> Repo.exists?()
end
def has_active_subscription?(nil), do: false
def has_active_subscription?(team) do
team
|> active_subscription_query()
|> Repo.exists?()
end
def check_needs_to_upgrade(nil), do: {:needs_to_upgrade, :no_trial}
def check_needs_to_upgrade(team) do
@ -350,4 +368,13 @@ defmodule Plausible.Teams.Billing do
end
end
end
defp active_subscription_query(team) do
from(s in Plausible.Billing.Subscription,
where:
s.team_id == ^team.id and s.status == ^Plausible.Billing.Subscription.Status.active(),
order_by: [desc: s.inserted_at],
limit: 1
)
end
end

View File

@ -7,6 +7,26 @@ defmodule Plausible.Teams.Memberships do
alias Plausible.Repo
alias Plausible.Teams
def all_pending_site_transfers(email) do
email
|> pending_site_transfers_query()
|> Repo.all()
|> Enum.map(fn transfer ->
%Plausible.Auth.Invitation{
site_id: transfer.site_id,
email: transfer.email,
invitation_id: transfer.transfer_id,
role: :owner
}
end)
end
def any_pending_site_transfers?(email) do
email
|> pending_site_transfers_query()
|> Repo.exists?()
end
def get(team, user) do
result =
from(tm in Teams.Membership,
@ -127,4 +147,8 @@ defmodule Plausible.Teams.Memberships do
membership -> {:ok, membership}
end
end
defp pending_site_transfers_query(email) do
from st in Teams.SiteTransfer, where: st.email == ^email
end
end

View File

@ -189,7 +189,7 @@ defmodule PlausibleWeb.Components.Billing do
</div>
<.styled_link
:if={
not (Plausible.Auth.enterprise_configured?(@user) &&
not (Plausible.Teams.Adapter.Read.Billing.enterprise_configured?(@user) &&
Subscriptions.halted?(@subscription))
}
id="#upgrade-or-change-plan-link"

View File

@ -9,14 +9,16 @@ defmodule PlausibleWeb.BillingController do
plug PlausibleWeb.RequireAccountPlug
def ping_subscription(%Plug.Conn{} = conn, _params) do
subscribed? = Billing.has_active_subscription?(conn.assigns.current_user.id)
subscribed? =
Plausible.Teams.Adapter.Read.Billing.has_active_subscription?(conn.assigns.current_user)
json(conn, %{is_subscribed: subscribed?})
end
def choose_plan(conn, _params) do
current_user = conn.assigns.current_user
if Plausible.Auth.enterprise_configured?(current_user) do
if Plausible.Teams.Adapter.Read.Billing.enterprise_configured?(current_user) do
redirect(conn, to: Routes.billing_path(conn, :upgrade_to_enterprise_plan))
else
render(conn, "choose_plan.html",
@ -135,8 +137,8 @@ defmodule PlausibleWeb.BillingController do
end
end
defp preview_subscription(%{id: user_id}, new_plan_id) do
subscription = Billing.active_subscription_for(user_id)
defp preview_subscription(user, new_plan_id) do
subscription = Billing.active_subscription_for(user)
if subscription do
with {:ok, preview_info} <- Billing.change_plan_preview(subscription, new_plan_id) do

View File

@ -8,7 +8,6 @@ defmodule PlausibleWeb.Live.ChoosePlan do
require Plausible.Billing.Subscription.Status
alias PlausibleWeb.Components.Billing.{PlanBox, PlanBenefits, Notice, PageviewSlider}
alias Plausible.Site
alias Plausible.Billing.{Plans, Quota}
@contact_link "https://plausible.io/contact"
@ -19,7 +18,7 @@ defmodule PlausibleWeb.Live.ChoosePlan do
socket
|> assign_new(:pending_ownership_site_ids, fn %{current_user: current_user} ->
current_user.email
|> Site.Memberships.all_pending_ownerships()
|> Plausible.Teams.Adapter.Read.Ownership.all_pending_site_transfers(current_user)
|> Enum.map(& &1.site_id)
end)
|> assign_new(:usage, fn %{
@ -31,17 +30,20 @@ defmodule PlausibleWeb.Live.ChoosePlan do
pending_ownership_site_ids: pending_ownership_site_ids
)
end)
|> assign_new(:owned_plan, fn %{current_user: %{subscription: subscription}} ->
|> assign_new(:subscription, fn %{current_user: current_user} ->
Plausible.Teams.Adapter.Read.Billing.get_subscription(current_user)
end)
|> assign_new(:owned_plan, fn %{subscription: subscription} ->
Plans.get_regular_plan(subscription, only_non_expired: true)
end)
|> assign_new(:owned_tier, fn %{owned_plan: owned_plan} ->
if owned_plan, do: Map.get(owned_plan, :kind), else: nil
end)
|> assign_new(:current_interval, fn %{current_user: current_user} ->
current_user_subscription_interval(current_user.subscription)
|> assign_new(:current_interval, fn %{subscription: subscription} ->
current_user_subscription_interval(subscription)
end)
|> assign_new(:available_plans, fn %{current_user: current_user} ->
Plans.available_plans_for(current_user, with_prices: true, customer_ip: remote_ip)
|> assign_new(:available_plans, fn %{subscription: subscription} ->
Plans.available_plans_for(subscription, with_prices: true, customer_ip: remote_ip)
end)
|> assign_new(:recommended_tier, fn %{usage: usage, available_plans: available_plans} ->
highest_growth_plan = List.last(available_plans.growth)
@ -102,8 +104,8 @@ defmodule PlausibleWeb.Live.ChoosePlan do
class="pb-6"
pending_ownership_count={length(@pending_ownership_site_ids)}
/>
<Notice.subscription_past_due class="pb-6" subscription={@current_user.subscription} />
<Notice.subscription_paused class="pb-6" subscription={@current_user.subscription} />
<Notice.subscription_past_due class="pb-6" subscription={@subscription} />
<Notice.subscription_paused class="pb-6" subscription={@subscription} />
<Notice.upgrade_ineligible :if={not Quota.eligible_for_upgrade?(@usage)} />
<div class="mx-auto max-w-4xl text-center">
<p class="text-4xl font-bold tracking-tight lg:text-5xl">

View File

@ -6,7 +6,9 @@
<div class="flex flex-col gap-y-2">
<Notice.active_grace_period
:if={Plausible.Auth.GracePeriod.active?(@conn.assigns.current_user)}
enterprise?={Plausible.Auth.enterprise_configured?(@conn.assigns.current_user)}
enterprise?={
Plausible.Teams.Adapter.Read.Billing.enterprise_configured?(@conn.assigns.current_user)
}
grace_period_end={grace_period_end(@conn.assigns.current_user)}
/>

View File

@ -43,12 +43,20 @@ defmodule Plausible.AuthTest do
end
test "enterprise_configured?/1 returns whether the user has an enterprise plan" do
user_without_plan = insert(:user)
user_with_plan = insert(:user, enterprise_plan: build(:enterprise_plan))
user_without_plan = new_user()
user_with_plan = new_user() |> subscribe_to_enterprise_plan()
assert Auth.enterprise_configured?(user_with_plan)
refute Auth.enterprise_configured?(user_without_plan)
refute Auth.enterprise_configured?(nil)
user_with_plan_no_subscription =
new_user() |> subscribe_to_enterprise_plan(subscription?: false)
assert Plausible.Teams.Adapter.Read.Billing.enterprise_configured?(user_with_plan)
assert Plausible.Teams.Adapter.Read.Billing.enterprise_configured?(
user_with_plan_no_subscription
)
refute Plausible.Teams.Adapter.Read.Billing.enterprise_configured?(user_without_plan)
refute Plausible.Teams.Adapter.Read.Billing.enterprise_configured?(nil)
end
describe "create_api_key/3" do

View File

@ -531,9 +531,9 @@ defmodule Plausible.BillingTest do
paused = insert(:subscription, user: insert(:user), status: Subscription.Status.paused())
user_without_subscription = insert(:user)
assert Billing.active_subscription_for(active.user_id).id == active.id
assert Billing.active_subscription_for(paused.user_id) == nil
assert Billing.active_subscription_for(user_without_subscription.id) == nil
assert Billing.active_subscription_for(active.user).id == active.id
assert Billing.active_subscription_for(paused.user) == nil
assert Billing.active_subscription_for(user_without_subscription) == nil
end
test "has_active_subscription?/1 returns whether the user has an active subscription" do
@ -541,8 +541,8 @@ defmodule Plausible.BillingTest do
paused = insert(:subscription, user: insert(:user), status: Subscription.Status.paused())
user_without_subscription = insert(:user)
assert Billing.has_active_subscription?(active.user_id)
refute Billing.has_active_subscription?(paused.user_id)
refute Billing.has_active_subscription?(user_without_subscription.id)
assert Billing.has_active_subscription?(active.user)
refute Billing.has_active_subscription?(paused.user)
refute Billing.has_active_subscription?(user_without_subscription)
end
end

View File

@ -1,5 +1,6 @@
defmodule Plausible.Billing.PlansTest do
use Plausible.DataCase, async: true
use Plausible.Teams.Test
alias Plausible.Billing.Plans
@legacy_plan_id "558746"
@ -9,56 +10,49 @@ defmodule Plausible.Billing.PlansTest do
describe "getting subscription plans for user" do
test "growth_plans_for/1 returns v1 plans for a user on a legacy plan" do
insert(:user, subscription: build(:subscription, paddle_plan_id: @legacy_plan_id))
new_user()
|> subscribe_to_plan(@legacy_plan_id)
|> Map.fetch!(:subscription)
|> Plans.growth_plans_for()
|> assert_generation(1)
end
test "growth_plans_for/1 returns v1 plans for users who are already on v1 pricing" do
insert(:user, subscription: build(:subscription, paddle_plan_id: @v1_plan_id))
new_user()
|> subscribe_to_plan(@v1_plan_id)
|> Map.fetch!(:subscription)
|> Plans.growth_plans_for()
|> assert_generation(1)
end
test "growth_plans_for/1 returns v2 plans for users who are already on v2 pricing" do
insert(:user, subscription: build(:subscription, paddle_plan_id: @v2_plan_id))
new_user()
|> subscribe_to_plan(@v2_plan_id)
|> Map.fetch!(:subscription)
|> Plans.growth_plans_for()
|> assert_generation(2)
end
test "growth_plans_for/1 returns v4 plans for invited users with trial_expiry = nil" do
insert(:user, trial_expiry_date: nil)
|> Plans.growth_plans_for()
|> assert_generation(4)
end
test "growth_plans_for/1 returns v4 plans for users whose trial started after the business tiers release" do
insert(:user, trial_expiry_date: ~D[2023-12-24])
|> Plans.growth_plans_for()
|> assert_generation(4)
end
test "growth_plans_for/1 returns v4 plans for expired legacy subscriptions" do
subscription =
build(:subscription,
paddle_plan_id: @v1_plan_id,
status: :deleted,
next_bill_date: ~D[2023-11-10]
)
insert(:user, subscription: subscription)
new_user()
|> subscribe_to_plan(@v1_plan_id, status: :deleted, next_bill_date: ~D[2023-11-10])
|> Map.fetch!(:subscription)
|> Plans.growth_plans_for()
|> assert_generation(4)
end
test "growth_plans_for/1 shows v4 plans for everyone else" do
insert(:user)
new_user()
|> Repo.preload(:subscription)
|> Map.fetch!(:subscription)
|> Plans.growth_plans_for()
|> assert_generation(4)
end
test "growth_plans_for/1 does not return business plans" do
insert(:user)
new_user()
|> Repo.preload(:subscription)
|> Map.fetch!(:subscription)
|> Plans.growth_plans_for()
|> Enum.each(fn plan ->
assert plan.kind != :business
@ -66,64 +60,61 @@ defmodule Plausible.Billing.PlansTest do
end
test "growth_plans_for/1 returns the latest generation of growth plans for a user with a business subscription" do
insert(:user, subscription: build(:subscription, paddle_plan_id: @v3_business_plan_id))
new_user()
|> subscribe_to_plan(@v3_business_plan_id)
|> Map.fetch!(:subscription)
|> Plans.growth_plans_for()
|> assert_generation(4)
end
test "business_plans_for/1 returns v3 business plans for a user on a legacy plan" do
insert(:user, subscription: build(:subscription, paddle_plan_id: @legacy_plan_id))
new_user()
|> subscribe_to_plan(@legacy_plan_id)
|> Map.fetch!(:subscription)
|> Plans.business_plans_for()
|> assert_generation(3)
end
test "business_plans_for/1 returns v3 business plans for a v2 subscriber" do
user = insert(:user, subscription: build(:subscription, paddle_plan_id: @v2_plan_id))
user = new_user() |> subscribe_to_plan(@v2_plan_id)
business_plans = Plans.business_plans_for(user)
business_plans = Plans.business_plans_for(user.subscription)
assert Enum.all?(business_plans, &(&1.kind == :business))
assert_generation(business_plans, 3)
end
test "business_plans_for/1 returns v4 plans for invited users with trial_expiry = nil" do
insert(:user, trial_expiry_date: nil)
|> Plans.business_plans_for()
|> assert_generation(4)
end
test "business_plans_for/1 returns v4 plans for users whose trial started after the business tiers release" do
insert(:user, trial_expiry_date: ~D[2023-12-24])
new_user(trial_expiry_date: nil)
|> Repo.preload(:subscription)
|> Map.fetch!(:subscription)
|> Plans.business_plans_for()
|> assert_generation(4)
end
test "business_plans_for/1 returns v4 plans for expired legacy subscriptions" do
subscription =
build(:subscription,
paddle_plan_id: @v2_plan_id,
status: :deleted,
next_bill_date: ~D[2023-11-10]
)
user =
new_user()
|> subscribe_to_plan(@v2_plan_id, status: :deleted, next_bill_date: ~D[2023-11-10])
insert(:user, subscription: subscription)
user.subscription
|> Plans.business_plans_for()
|> assert_generation(4)
end
test "business_plans_for/1 returns v4 business plans for everyone else" do
user = insert(:user)
business_plans = Plans.business_plans_for(user)
user = new_user() |> Repo.preload(:subscription)
business_plans = Plans.business_plans_for(user.subscription)
assert Enum.all?(business_plans, &(&1.kind == :business))
assert_generation(business_plans, 4)
end
test "available_plans returns all plans for user with prices when asked for" do
user = insert(:user, subscription: build(:subscription, paddle_plan_id: @v2_plan_id))
user = new_user() |> subscribe_to_plan(@v2_plan_id)
%{growth: growth_plans, business: business_plans} =
Plans.available_plans_for(user, with_prices: true, customer_ip: "127.0.0.1")
Plans.available_plans_for(user.subscription, with_prices: true, customer_ip: "127.0.0.1")
assert Enum.find(growth_plans, fn plan ->
(%Money{} = plan.monthly_cost) && plan.monthly_product_id == @v2_plan_id
@ -135,9 +126,9 @@ defmodule Plausible.Billing.PlansTest do
end
test "available_plans returns all plans without prices by default" do
user = insert(:user, subscription: build(:subscription, paddle_plan_id: @v2_plan_id))
user = new_user() |> subscribe_to_plan(@v2_plan_id)
assert %{growth: [_ | _], business: [_ | _]} = Plans.available_plans_for(user)
assert %{growth: [_ | _], business: [_ | _]} = Plans.available_plans_for(user.subscription)
end
test "latest_enterprise_plan_with_price/1" do
@ -190,7 +181,7 @@ defmodule Plausible.Billing.PlansTest do
describe "suggested_plan/2" do
test "returns suggested plan based on usage" do
user = insert(:user, subscription: build(:subscription, paddle_plan_id: @v1_plan_id))
user = new_user() |> subscribe_to_plan(@v1_plan_id)
assert %Plausible.Billing.Plan{
monthly_pageview_limit: 100_000,
@ -212,13 +203,16 @@ defmodule Plausible.Billing.PlansTest do
end
test "returns nil when user has enterprise-level usage" do
user = insert(:user, subscription: build(:subscription, paddle_plan_id: @v1_plan_id))
user = new_user() |> subscribe_to_plan(@v1_plan_id)
assert :enterprise == Plans.suggest(user, 100_000_000)
end
test "returns nil when user is on an enterprise plan" do
user = insert(:user, subscription: build(:subscription, paddle_plan_id: @v1_plan_id))
_enterprise_plan = insert(:enterprise_plan, user_id: user.id, billing_interval: :yearly)
user =
new_user()
|> subscribe_to_plan(@v1_plan_id)
|> subscribe_to_enterprise_plan(billing_interval: :yearly, subscription?: false)
assert :enterprise == Plans.suggest(user, 10_000)
end
end

View File

@ -112,16 +112,9 @@ defmodule Plausible.Billing.SiteLockerTest do
test "locks all sites if user has active subscription but grace period has ended" do
grace_period = %Plausible.Auth.GracePeriod{end_date: Timex.shift(Timex.today(), days: -1)}
user = insert(:user, grace_period: grace_period)
insert(:subscription, status: Subscription.Status.active(), user: user)
site =
insert(:site,
memberships: [
build(:site_membership, user: user, role: :owner)
]
)
user = new_user(grace_period: grace_period)
subscribe_to_plan(user, "123")
site = new_site(owner: user)
assert SiteLocker.update_sites_for(user) == {:locked, :grace_period_ended_now}
@ -131,15 +124,9 @@ defmodule Plausible.Billing.SiteLockerTest do
@tag :teams
test "syncs grace period end with teams" do
grace_period = %Plausible.Auth.GracePeriod{end_date: Timex.shift(Timex.today(), days: -1)}
user = insert(:user, grace_period: grace_period)
insert(:subscription, status: Subscription.Status.active(), user: user)
insert(:site,
memberships: [
build(:site_membership, user: user, role: :owner)
]
)
user = new_user(grace_period: grace_period)
subscribe_to_plan(user, "123")
new_site(owner: user)
assert SiteLocker.update_sites_for(user) == {:locked, :grace_period_ended_now}
@ -151,15 +138,9 @@ defmodule Plausible.Billing.SiteLockerTest do
test "sends email if grace period has ended" do
grace_period = %Plausible.Auth.GracePeriod{end_date: Timex.shift(Timex.today(), days: -1)}
user = insert(:user, grace_period: grace_period)
insert(:subscription, status: Subscription.Status.active(), user: user)
insert(:site,
memberships: [
build(:site_membership, user: user, role: :owner)
]
)
user = new_user(grace_period: grace_period)
subscribe_to_plan(user, "123")
new_site(owner: user)
assert SiteLocker.update_sites_for(user) == {:locked, :grace_period_ended_now}
@ -170,21 +151,14 @@ defmodule Plausible.Billing.SiteLockerTest do
end
test "does not send grace period email if site is already locked" do
user =
insert(:user,
grace_period: %Plausible.Auth.GracePeriod{
end_date: Timex.shift(Timex.today(), days: -1),
is_over: false
}
)
grace_period = %Plausible.Auth.GracePeriod{
end_date: Timex.shift(Timex.today(), days: -1),
is_over: false
}
insert(:subscription, status: Subscription.Status.active(), user: user)
insert(:site,
memberships: [
build(:site_membership, user: user, role: :owner)
]
)
user = new_user(grace_period: grace_period)
subscribe_to_plan(user, "123")
new_site(owner: user)
assert SiteLocker.update_sites_for(user) == {:locked, :grace_period_ended_now}

View File

@ -1,5 +1,6 @@
defmodule PlausibleWeb.BillingControllerTest do
use PlausibleWeb.ConnCase, async: true
use Plausible.Teams.Test
import Plausible.Test.Support.HTML
require Plausible.Billing.Subscription.Status
alias Plausible.Billing.Subscription
@ -12,7 +13,8 @@ defmodule PlausibleWeb.BillingControllerTest do
test "redirects to enterprise upgrade page if user has an enterprise plan configured",
%{conn: conn, user: user} do
insert(:enterprise_plan, user: user, paddle_plan_id: "123")
subscribe_to_enterprise_plan(user, paddle_plan_id: "123")
conn = get(conn, Routes.billing_path(conn, :choose_plan))
assert redirected_to(conn) == Routes.billing_path(conn, :upgrade_to_enterprise_plan)
end

View File

@ -245,11 +245,11 @@ defmodule PlausibleWeb.Live.ChoosePlanTest do
user: user
} do
previous_owner = insert(:user)
site = insert(:site, members: [previous_owner])
site = new_site(owner: previous_owner)
insert(:goal, site: site, currency: :USD, event_name: "Purchase")
insert(:invitation, email: user.email, inviter: previous_owner, role: :owner, site: site)
invite_transfer(site, user, inviter: previous_owner)
{:ok, _lv, doc} = get_liveview(conn)
@ -259,31 +259,16 @@ defmodule PlausibleWeb.Live.ChoosePlanTest do
test "recommends Business when team member limit for Growth exceeded due to pending ownerships",
%{conn: conn, user: user} do
_owned_site =
insert(:site,
memberships: [
build(:site_membership, role: :owner, user: user),
build(:site_membership, role: :admin, user: insert(:user)),
build(:site_membership, role: :admin, user: insert(:user))
]
)
owned_site = new_site(owner: user)
add_guest(owned_site, role: :editor)
add_guest(owned_site, role: :editor)
previous_owner = insert(:user)
previous_owner = new_user()
pending_ownership_site =
insert(:site,
memberships: [
build(:site_membership, role: :owner, user: previous_owner),
build(:site_membership, role: :viewer, user: insert(:user))
]
)
pending_ownership_site = new_site(owner: previous_owner)
add_guest(pending_ownership_site, role: :viewer)
insert(:invitation,
email: user.email,
inviter: previous_owner,
role: :owner,
site: pending_ownership_site
)
invite_transfer(pending_ownership_site, user, inviter: previous_owner)
{:ok, _lv, doc} = get_liveview(conn)
@ -298,15 +283,10 @@ defmodule PlausibleWeb.Live.ChoosePlanTest do
insert_list(9, :site, members: [user])
assert 10 = Plausible.Billing.Quota.Usage.site_usage(user)
another_user = insert(:user)
pending_ownership_site = insert(:site, members: [another_user])
another_user = new_user()
pending_ownership_site = new_site(owner: another_user)
insert(:invitation,
email: user.email,
site: pending_ownership_site,
role: :owner,
inviter: another_user
)
invite_transfer(pending_ownership_site, user, inviter: another_user)
{:ok, _lv, doc} = get_liveview(conn)
@ -463,28 +443,18 @@ defmodule PlausibleWeb.Live.ChoosePlanTest do
build(:pageview, timestamp: yesterday)
])
another_user = insert(:user)
another_user = new_user()
pending_site =
insert(:site,
memberships: [
build(:site_membership, role: :owner, user: another_user),
build(:site_membership, role: :admin, user: build(:user)),
build(:site_membership, role: :viewer, user: build(:user)),
build(:site_membership, role: :viewer, user: build(:user))
]
)
pending_site = new_site(owner: another_user)
add_guest(pending_site, role: :editor)
add_guest(pending_site, role: :viewer)
add_guest(pending_site, role: :viewer)
populate_stats(pending_site, [
build(:pageview, timestamp: yesterday)
])
insert(:invitation,
site: pending_site,
inviter: another_user,
email: user.email,
role: :owner
)
invite_transfer(pending_site, user, inviter: another_user)
{:ok, _lv, doc} = get_liveview(conn)
@ -507,12 +477,7 @@ defmodule PlausibleWeb.Live.ChoosePlanTest do
Plausible.Props.allow(pending_site, ["author"])
insert(:invitation,
site: pending_site,
inviter: another_user,
email: user.email,
role: :owner
)
invite_transfer(pending_site, user, inviter: another_user)
{:ok, _lv, doc} = get_liveview(conn)
@ -644,18 +609,16 @@ defmodule PlausibleWeb.Live.ChoosePlanTest do
conn: conn,
user: user
} do
insert_list(49, :site, members: [user])
for _ <- 1..49 do
new_site(owner: user)
end
assert 50 = Plausible.Billing.Quota.Usage.site_usage(user)
another_user = insert(:user)
pending_ownership_site = insert(:site, members: [another_user])
another_user = new_user()
pending_ownership_site = new_site(owner: another_user)
insert(:invitation,
email: user.email,
site: pending_ownership_site,
role: :owner,
inviter: another_user
)
invite_transfer(pending_ownership_site, user, inviter: another_user)
{:ok, _lv, doc} = get_liveview(conn)
@ -1102,9 +1065,9 @@ defmodule PlausibleWeb.Live.ChoosePlanTest do
conn: conn,
user: user
} do
old_owner = insert(:user)
site = insert(:site, members: [old_owner])
insert(:invitation, site_id: site.id, inviter: old_owner, email: user.email, role: :owner)
old_owner = new_user()
site = new_site(owner: old_owner)
invite_transfer(site, user, inviter: old_owner)
{:ok, _lv, doc} = get_liveview(conn)
@ -1146,15 +1109,14 @@ defmodule PlausibleWeb.Live.ChoosePlanTest do
)
end
defp create_subscription_for(user, subscription_options) do
insert(:subscription, Keyword.put(subscription_options, :user, user))
{:ok, user: Plausible.Users.with_subscription(user)}
defp create_subscription_for(user, subscription_opts) do
{paddle_plan_id, subscription_opts} = Keyword.pop(subscription_opts, :paddle_plan_id)
user = subscribe_to_plan(user, paddle_plan_id, subscription_opts)
{:ok, user: user}
end
defp subscribe_free_10k(%{user: user}) do
Plausible.Billing.Subscription.free(%{user_id: user.id})
|> Repo.insert!()
user = subscribe_to_plan(user, "free_10k")
{:ok, user: user}
end

View File

@ -2,6 +2,7 @@ defmodule Plausible.Workers.SendTrialNotificationsTest do
use Plausible.DataCase
use Bamboo.Test
use Oban.Testing, repo: Plausible.Repo
use Plausible.Teams.Test
alias Plausible.Workers.SendTrialNotifications
test "does not send a notification if user didn't create a site" do
@ -220,10 +221,9 @@ defmodule Plausible.Workers.SendTrialNotificationsTest do
end
test "does not suggest a plan when user is switching to an enterprise plan" do
user = insert(:user)
user = new_user()
usage = %{total: 10_000, custom_events: 0}
insert(:enterprise_plan, user: user, paddle_plan_id: "enterprise-plan-id")
subscribe_to_enterprise_plan(user, paddle_plan_id: "enterprise-plan-id")
email = PlausibleWeb.Email.trial_upgrade_email(user, "today", usage)
assert email.html_body =~ "please reply back to this email to get a quote for your volume"