Refactor current plan data format to make changing it easier

This commit is contained in:
Uku Taht 2021-05-06 11:46:22 +03:00
parent 09df65d5ec
commit 885b1d271a
16 changed files with 185 additions and 130 deletions

View File

@ -7,6 +7,8 @@
@import "tooltip.css";
@import "flatpickr.css";
[x-cloak] { display: none; }
.button {
@apply inline-flex justify-center px-4 py-2 text-sm font-medium text-white bg-indigo-600 border border-transparent rounded-md leading-5 transition hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500;
}

View File

@ -1,80 +1,93 @@
defmodule Plausible.Billing.Plans do
@monthly_plans [
%{product_id: "558018", cost: "$6", limit: 10_000, cycle: "monthly"},
%{product_id: "558745", cost: "$12", limit: 100_000, cycle: "monthly"},
%{product_id: "597485", cost: "$18", limit: 200_000, cycle: "monthly"},
%{product_id: "597487", cost: "$27", limit: 500_000, cycle: "monthly"},
%{product_id: "597642", cost: "$48", limit: 1_000_000, cycle: "monthly"},
%{product_id: "597309", cost: "$69", limit: 2_000_000, cycle: "monthly"},
%{product_id: "597311", cost: "$99", limit: 5_000_000, cycle: "monthly"},
%{product_id: "642352", cost: "$150", limit: 10_000_000, cycle: "monthly"},
%{product_id: "642355", cost: "$225", limit: 20_000_000, cycle: "monthly"},
%{product_id: "650652", cost: "$330", limit: 50_000_000, cycle: "monthly"}
]
@yearly_plans [
%{product_id: "572810", cost: "$48", monthly_cost: "$4", limit: 10_000, cycle: "yearly"},
%{product_id: "590752", cost: "$96", monthly_cost: "$8", limit: 100_000, cycle: "yearly"},
%{product_id: "597486", cost: "$144", monthly_cost: "$12", limit: 200_000, cycle: "yearly"},
%{product_id: "597488", cost: "$216", monthly_cost: "$18", limit: 500_000, cycle: "yearly"},
%{product_id: "597643", cost: "$384", monthly_cost: "$32", limit: 1_000_000, cycle: "yearly"},
%{product_id: "597310", cost: "$552", monthly_cost: "$46", limit: 2_000_000, cycle: "yearly"},
%{product_id: "597312", cost: "$792", monthly_cost: "$66", limit: 5_000_000, cycle: "yearly"},
@plans_v1 [
%{
limit: 10_000,
monthly_product_id: "558018",
monthly_cost: "$6",
yearly_product_id: "572810",
yearly_cost: "$48"
},
%{
limit: 100_000,
monthly_product_id: "558745",
monthly_cost: "$12",
yearly_product_id: "590752",
yearly_cost: "$96"
},
%{
limit: 200_000,
monthly_product_id: "597485",
monthly_cost: "$18",
yearly_product_id: "597486",
yearly_cost: "$144"
},
%{
limit: 500_000,
monthly_product_id: "597487",
monthly_cost: "$27",
yearly_product_id: "597488",
yearly_cost: "$216"
},
%{
limit: 1_000_000,
monthly_product_id: "597642",
monthly_cost: "$48",
yearly_product_id: "597643",
yearly_cost: "$384"
},
%{
limit: 2_000_000,
monthly_product_id: "597309",
monthly_cost: "$69",
yearly_product_id: "597310",
yearly_cost: "$552"
},
%{
limit: 5_000_000,
monthly_product_id: "597311",
monthly_cost: "$99",
yearly_product_id: "597312",
yearly_cost: "$792"
},
%{
product_id: "642354",
cost: "$1200",
monthly_cost: "$100",
limit: 10_000_000,
cycle: "yearly"
},
%{
product_id: "642356",
cost: "$1800",
monthly_product_id: "642352",
monthly_cost: "$150",
yearly_product_id: "642354",
yearly_cost: "$1200"
},
%{
limit: 20_000_000,
cycle: "yearly"
monthly_product_id: "642355",
monthly_cost: "$225",
yearly_product_id: "642356",
yearly_cost: "$1800"
},
%{
product_id: "650653",
cost: "$2640",
monthly_cost: "$220",
limit: 50_000_000,
cycle: "yearly"
},
%{
product_id: "648089",
cost: "$4800",
monthly_cost: "$400",
limit: 150_000_000,
cycle: "yearly"
monthly_product_id: "650652",
monthly_cost: "$330",
yearly_product_id: "650653",
yearly_cost: "$2640"
}
]
@all_plans @monthly_plans ++ @yearly_plans
@yearly_plans_v1 [
%{limit: 150_000_000, yearly_product_id: "648089", yearly_cost: "$4800"}
]
def plans do
monthly =
@monthly_plans
|> Enum.map(fn plan -> {String.to_atom(number_format(plan[:limit])), plan} end)
|> Enum.into(%{})
yearly =
@yearly_plans
|> Enum.map(fn plan -> {String.to_atom(number_format(plan[:limit])), plan} end)
|> Enum.into(%{})
%{
monthly: monthly,
yearly: yearly
}
def plans_for(user) do
@plans_v1 |> Enum.map(fn plan -> Map.put(plan, :volume, number_format(plan[:limit])) end)
end
def yearly_plan_ids do
Enum.map(@yearly_plans, fn plan -> plan[:product_id] end)
def all_yearly_plan_ids do
Enum.map(@plans_v1, fn plan -> plan[:yearly_product_id] end)
end
def for_product_id(product_id) do
Enum.find(@all_plans, fn plan -> plan[:product_id] == product_id end)
Enum.find(@plans_v1, fn plan ->
product_id in [plan[:monthly_product_id], plan[:yearly_product_id]]
end)
end
def subscription_quota("free_10k"), do: "10k"
@ -90,38 +103,32 @@ defmodule Plausible.Billing.Plans do
def subscription_interval(product_id) do
case for_product_id(product_id) do
nil -> raise "Unknown interval for subscription #{product_id}"
product -> product[:cycle]
nil ->
raise "Unknown interval for subscription #{product_id}"
plan ->
if product_id == plan[:monthly_product_id] do
"monthly"
else
"yearly"
end
end
end
def suggested_plan_name(usage) do
plan = suggested_plan(usage)
number_format(plan[:limit]) <> "/mo"
end
def suggested_plan_cost(usage) do
plan = suggested_plan(usage)
plan[:cost] <> "/mo"
end
def suggested_plan_cost_yearly(usage) do
plan = Enum.find(@yearly_plans, fn plan -> usage < plan[:limit] end)
plan[:monthly_cost] <> "/mo"
end
defp suggested_plan(usage) do
Enum.find(@monthly_plans, fn plan -> usage < plan[:limit] end)
end
def allowance(%Plausible.Billing.Subscription{paddle_plan_id: "free_10k"}), do: 10_000
def allowance(subscription) do
found = Enum.find(@all_plans, fn plan -> plan[:product_id] == subscription.paddle_plan_id end)
found = for_product_id(subscription.paddle_plan_id)
if found do
Map.fetch!(found, :limit)
end
end
def suggested_plan(user, usage) do
Enum.find(plans_for(user), fn plan -> usage < plan[:limit] end)
end
defp number_format(num) do
PlausibleWeb.StatsView.large_number_format(num)
end

View File

@ -71,6 +71,8 @@ defmodule PlausibleWeb.Email do
end
def trial_upgrade_email(user, day, {pageviews, custom_events}) do
suggested_plan = Plausible.Billing.Plans.suggested_plan(user, pageviews + custom_events)
base_email()
|> to(user)
|> tag("trial-upgrade-email")
@ -79,7 +81,8 @@ defmodule PlausibleWeb.Email do
user: user,
day: day,
custom_events: custom_events,
usage: pageviews + custom_events
usage: pageviews + custom_events,
suggested_plan: suggested_plan
)
end
@ -112,7 +115,7 @@ defmodule PlausibleWeb.Email do
})
end
def over_limit_email(user, usage, last_cycle) do
def over_limit_email(user, usage, last_cycle, suggested_plan) do
base_email()
|> to(user)
|> tag("over-limit")
@ -120,7 +123,8 @@ defmodule PlausibleWeb.Email do
|> render("over_limit.html", %{
user: user,
usage: usage,
last_cycle: last_cycle
last_cycle: last_cycle,
suggested_plan: suggested_plan
})
end

View File

@ -1,7 +1,7 @@
<tr @click="volume = '<%= @volume %>'" :class="{'border-2 border-green-300 bg-opacity-20 bg-green-300': volume === '<%= @volume %>', 'border-b border-gray-200 cursor-pointer': volume !== '<%= @volume %>'}">
<td class="px-6 py-4 text-sm leading-5 dark:text-gray-100" :class="{'font-bold': volume === '<%= @volume %>'}"><%= @volume %></td>
<td class="px-6 py-4 text-sm leading-5 dark:text-gray-100" :class="{'font-bold': volume === '<%= @volume %>'}">
<span x-show="billingCycle === 'monthly'"><%= @monthly_price %></span>
<span x-show="billingCycle === 'yearly'"><%= @yearly_price %></span>
<span x-show="billingCycle === 'monthly'"><%= @monthly_price %> / mo</span>
<span x-show="billingCycle === 'yearly'"><%= @yearly_price %> / yr</span>
</td>
</tr>

View File

@ -1,5 +1,27 @@
<script>
window.plans = <%= raw Jason.encode!(Plausible.Billing.Plans.plans()) %>
window.plans = function() {
return {
rawPlans: <%= raw Jason.encode!(Plausible.Billing.Plans.plans_for(@conn.assigns[:current_user])) %>,
volume: '10k',
billingCycle: 'monthly',
selectedPlanPrice() {
var selectedPlan = this.rawPlans.find((plan) => plan.volume === this.volume)
if (this.billingCycle === 'monthly'){
return selectedPlan.monthly_cost
} else {
return selectedPlan.yearly_cost
}
},
selectedPlanProductId() {
var selectedPlan = this.rawPlans.find((plan) => plan.volume === this.volume)
if (this.billingCycle === 'monthly'){
return selectedPlan.monthly_product_id
} else {
return selectedPlan.yearly_product_id
}
}
}
}
</script>
<div class="mx-auto mt-6 text-center">
@ -7,7 +29,7 @@
</div>
<div class="w-full max-w-lg px-4 mx-auto mt-4">
<div x-data="{volume: '10k', billingCycle: 'monthly'}" class="flex-1 px-8 py-4 mt-8 mb-4 bg-white rounded shadow-md dark:bg-gray-800">
<div x-data="window.plans()" class="flex-1 px-8 py-4 mt-8 mb-4 bg-white rounded shadow-md dark:bg-gray-800">
<div class="w-full pt-2 text-xl font-bold dark:text-gray-100">
Select your new plan
</div>
@ -48,15 +70,9 @@
</tr>
</thead>
<tbody class="bg-white dark:bg-gray-800">
<%= render("_plan_option.html", volume: "10k", monthly_price: "$6", yearly_price: "$4") %>
<%= render("_plan_option.html", volume: "100k", monthly_price: "$12", yearly_price: "$8") %>
<%= render("_plan_option.html", volume: "200k", monthly_price: "$18", yearly_price: "$12") %>
<%= render("_plan_option.html", volume: "500k", monthly_price: "$27", yearly_price: "$18") %>
<%= render("_plan_option.html", volume: "1M", monthly_price: "$48", yearly_price: "$32") %>
<%= render("_plan_option.html", volume: "2M", monthly_price: "$69", yearly_price: "$46") %>
<%= render("_plan_option.html", volume: "5M", monthly_price: "$99", yearly_price: "$69") %>
<%= render("_plan_option.html", volume: "10M", monthly_price: "$150", yearly_price: "$100") %>
<%= render("_plan_option.html", volume: "20M", monthly_price: "$225", yearly_price: "$150") %>
<%= for plan <- Plausible.Billing.Plans.plans_for(@conn.assigns[:current_user]) do %>
<%= render("_plan_option.html", volume: PlausibleWeb.StatsView.large_number_format(plan[:limit]), monthly_price: plan[:monthly_cost], yearly_price: plan[:yearly_cost]) %>
<% end %>
</tbody>
</table>
</div>
@ -65,12 +81,12 @@
<div class="mt-6 text-right">
<span class="inline-flex rounded-md shadow-sm">
<a x-show="window.plans[billingCycle][volume].product_id !== '<%= @subscription.paddle_plan_id %>'" style="display: none;" :href="'/billing/change-plan/preview/' + window.plans[billingCycle][volume].product_id" class="inline-flex items-center px-4 py-2 text-sm font-medium text-white bg-indigo-600 border border-transparent leading-5 rounded-md hover:bg-indigo-500 focus:outline-none focus:border-indigo-700 focus:ring active:bg-indigo-700 transition ease-in-out duration-150">
<a x-show="selectedPlanProductId() !== '<%= @subscription.paddle_plan_id %>'" style="display: none;" :href="'/billing/change-plan/preview/' + selectedPlanProductId()" class="inline-flex items-center px-4 py-2 text-sm font-medium text-white bg-indigo-600 border border-transparent leading-5 rounded-md hover:bg-indigo-500 focus:outline-none focus:border-indigo-700 focus:ring active:bg-indigo-700 transition ease-in-out duration-150">
<svg fill="currentColor" viewBox="0 0 20 20" class="inline w-4 h-4 mr-2"><path d="M10 12a2 2 0 100-4 2 2 0 000 4z"></path><path fill-rule="evenodd" d="M.458 10C1.732 5.943 5.522 3 10 3s8.268 2.943 9.542 7c-1.274 4.057-5.064 7-9.542 7S1.732 14.057.458 10zM14 10a4 4 0 11-8 0 4 4 0 018 0z" clip-rule="evenodd"></path></svg>
Preview changes
</a>
<a x-show="window.plans[billingCycle][volume].product_id === '<%= @subscription.paddle_plan_id %>'" style="display: none;" tooltip="Select a different plan to continue" class="inline-flex items-center px-4 py-2 text-sm font-medium text-white bg-gray-400 border border-transparent leading-5 rounded-md">
<a x-show="selectedPlanProductId() === '<%= @subscription.paddle_plan_id %>'" style="display: none;" tooltip="Select a different plan to continue" class="inline-flex items-center px-4 py-2 text-sm font-medium text-white bg-gray-400 border border-transparent leading-5 rounded-md">
<svg fill="currentColor" viewBox="0 0 20 20" class="inline w-4 h-4 mr-2"><path d="M10 12a2 2 0 100-4 2 2 0 000 4z"></path><path fill-rule="evenodd" d="M.458 10C1.732 5.943 5.522 3 10 3s8.268 2.943 9.542 7c-1.274 4.057-5.064 7-9.542 7S1.732 14.057.458 10zM14 10a4 4 0 11-8 0 4 4 0 018 0z" clip-rule="evenodd"></path></svg>
Preview changes
</a>

View File

@ -1,5 +1,27 @@
<script>
window.plans = <%= raw Jason.encode!(Plausible.Billing.Plans.plans()) %>
window.plans = function() {
return {
rawPlans: <%= raw Jason.encode!(Plausible.Billing.Plans.plans_for(@user)) %>,
volume: '10k',
billingCycle: 'monthly',
selectedPlanPrice() {
var selectedPlan = this.rawPlans.find((plan) => plan.volume === this.volume)
if (this.billingCycle === 'monthly'){
return selectedPlan.monthly_cost
} else {
return selectedPlan.yearly_cost
}
},
selectedPlanProductId() {
var selectedPlan = this.rawPlans.find((plan) => plan.volume === this.volume)
if (this.billingCycle === 'monthly'){
return selectedPlan.monthly_product_id
} else {
return selectedPlan.yearly_product_id
}
}
}
}
</script>
<div class="mx-auto mt-6 text-center">
@ -8,7 +30,7 @@
<div>
<div class="flex flex-col w-full max-w-4xl px-4 mx-auto mt-4 md:flex-row">
<div x-data="{volume: '10k', billingCycle: 'monthly'}" class="flex-1 px-8 py-4 mt-8 mb-4 bg-white rounded shadow-md dark:bg-gray-800">
<div x-data="window.plans()" class="flex-1 px-8 py-4 mt-8 mb-4 bg-white rounded shadow-md dark:bg-gray-800">
<div class="w-full py-4 dark:text-gray-100">
<span>You've used <b><%= PlausibleWeb.AuthView.delimit_integer(@usage) %></b> billable pageviews in the last 30 days</span>
</div>
@ -39,20 +61,14 @@
Monthly pageviews
</th>
<th class="px-6 py-3 text-xs font-medium tracking-wider text-left text-gray-500 uppercase bg-gray-100 border-b border-gray-200 dark:bg-gray-900 leading-4 dark:text-gray-200">
Price per month
Price
</th>
</tr>
</thead>
<tbody class="bg-white dark:bg-gray-800">
<%= render("_plan_option.html", volume: "10k", monthly_price: "$6", yearly_price: "$4") %>
<%= render("_plan_option.html", volume: "100k", monthly_price: "$12", yearly_price: "$8") %>
<%= render("_plan_option.html", volume: "200k", monthly_price: "$18", yearly_price: "$12") %>
<%= render("_plan_option.html", volume: "500k", monthly_price: "$27", yearly_price: "$18") %>
<%= render("_plan_option.html", volume: "1M", monthly_price: "$48", yearly_price: "$32") %>
<%= render("_plan_option.html", volume: "2M", monthly_price: "$69", yearly_price: "$46") %>
<%= render("_plan_option.html", volume: "5M", monthly_price: "$99", yearly_price: "$69") %>
<%= render("_plan_option.html", volume: "10M", monthly_price: "$150", yearly_price: "$100") %>
<%= render("_plan_option.html", volume: "20M", monthly_price: "$225", yearly_price: "$150") %>
<%= for plan <- Plausible.Billing.Plans.plans_for(@user) do %>
<%= render("_plan_option.html", volume: PlausibleWeb.StatsView.large_number_format(plan[:limit]), monthly_price: plan[:monthly_cost], yearly_price: plan[:yearly_cost]) %>
<% end %>
</tbody>
</table>
</div>
@ -60,9 +76,9 @@
</div>
<div class="mt-6 text-right">
<div class="mb-4 text-sm font-medium dark:text-gray-100">Due today: <b x-text="window.plans[billingCycle][volume].cost">$6</b></div>
<div class="mb-4 text-sm font-medium dark:text-gray-100">Due today: <b x-text="selectedPlanPrice()">$6</b></div>
<span class="inline-flex rounded-md shadow-sm">
<button type="button" data-theme="none" :data-product="window.plans[billingCycle][volume].product_id" data-email="<%= @conn.assigns[:current_user].email %>" data-disable-logout="true" data-passthrough="<%= @conn.assigns[:current_user].id %>" data-success="/billing/upgrade-success" class="inline-flex items-center px-4 py-2 text-sm font-medium text-white bg-indigo-600 border border-transparent paddle_button leading-5 rounded-md hover:bg-indigo-500 focus:outline-none focus:border-indigo-700 focus:ring active:bg-indigo-700 transition ease-in-out duration-150">
<button type="button" data-theme="none" :data-product="selectedPlanProductId()" data-email="<%= @conn.assigns[:current_user].email %>" data-disable-logout="true" data-passthrough="<%= @conn.assigns[:current_user].id %>" data-success="/billing/upgrade-success" class="inline-flex items-center px-4 py-2 text-sm font-medium text-white bg-indigo-600 border border-transparent paddle_button leading-5 rounded-md hover:bg-indigo-500 focus:outline-none focus:border-indigo-700 focus:ring active:bg-indigo-700 transition ease-in-out duration-150">
<svg fill="currentColor" viewBox="0 0 20 20" class="inline w-4 h-4 mr-2"><path fill-rule="evenodd" d="M5 9V7a5 5 0 0110 0v2a2 2 0 012 2v5a2 2 0 01-2 2H5a2 2 0 01-2-2v-5a2 2 0 012-2zm8-2v2H7V7a3 3 0 016 0z" clip-rule="evenodd"></path></svg>
Pay securely via Paddle
</button>

View File

@ -8,7 +8,7 @@ We don't enforce any hard limits at the moment, we're still counting your stats
<br /><br />
In the last billing cycle (<%= date_format(@last_cycle.first) %> to <%= date_format(@last_cycle.last) %>), your account has used <%= PlausibleWeb.StatsView.large_number_format(@usage) %> billable pageviews.
<%= if @usage <= 20_000_000 do %>
Based on that we recommend you select the <%= Plausible.Billing.Plans.suggested_plan_name(@usage) %> plan which runs at <%= Plausible.Billing.Plans.suggested_plan_cost(@usage) %> or <%= Plausible.Billing.Plans.suggested_plan_cost_yearly(@usage) %> when billed yearly.
Based on that we recommend you select the <%= @suggested_plan[:volume] %>/mo plan which runs at <%= @suggested_plan[:monthly_cost] %>/mo or <%= @suggested_plan[:yearly_cost] %>/yr when billed yearly.
<br /><br />
You can upgrade your subscription using our self-serve platform. The new charge will be prorated to reflect the amount you have already paid and the time until your current subscription is supposed to expire.
<br /><br />

View File

@ -4,7 +4,7 @@ Thanks for exploring Plausible, a simple and privacy-friendly alternative to Goo
<br /><br />
In the last month, your account has used <%= PlausibleWeb.AuthView.delimit_integer(@usage) %> billable pageviews<%= if @custom_events > 0, do: " and custom events in total", else: "" %>.
<%= if @usage <= 20_000_000 do %>
Based on that we recommend you select the <%= Plausible.Billing.Plans.suggested_plan_name(@usage) %> plan which runs at <%= Plausible.Billing.Plans.suggested_plan_cost(@usage) %>.
Based on that we recommend you select the <%= @suggested_plan[:volume] %>/mo plan which runs at <%= @suggested_plan[:monthly_cost] %>/mo.
You can also go with yearly billing to get 33% off on your plan.
<br /><br />

View File

@ -15,7 +15,7 @@ defmodule PlausibleWeb.AuthView do
end
def subscription_quota(subscription) do
Plans.subscription_quota(subscription.paddle_plan_id)
Plans.allowance(subscription) |> PlausibleWeb.StatsView.large_number_format()
end
def subscription_interval(subscription) do

View File

@ -53,7 +53,9 @@ defmodule Plausible.Workers.CheckUsage do
if last_last_month > allowance && last_month > allowance do
{_, last_cycle} = billing_mod.last_two_billing_cycles(subscriber)
template = PlausibleWeb.Email.over_limit_email(subscriber, last_month, last_cycle)
suggested_plan = Plausible.Billing.Plans.suggested_plan(subscriber, last_month)
template =
PlausibleWeb.Email.over_limit_email(subscriber, last_month, last_cycle, suggested_plan)
try do
Plausible.Mailer.send_email(template)

View File

@ -2,7 +2,7 @@ defmodule Plausible.Workers.NotifyAnnualRenewal do
use Plausible.Repo
use Oban.Worker, queue: :notify_annual_renewal
@yearly_plans Plausible.Billing.Plans.yearly_plan_ids()
@yearly_plans Plausible.Billing.Plans.all_yearly_plan_ids()
@impl Oban.Worker
@doc """

0
priv/plans_v1.json Normal file
View File

View File

@ -2,12 +2,4 @@ defmodule Plausible.Billing.PlansTest do
use Plausible.DataCase
use Bamboo.Test, shared: true
alias Plausible.Billing.Plans
test "suggested plan name" do
assert Plans.suggested_plan_name(110_000) == "200k/mo"
end
test "suggested plan cost" do
assert Plans.suggested_plan_cost(110_000) == "$18/mo"
end
end

View File

@ -270,6 +270,20 @@ defmodule PlausibleWeb.AuthControllerTest do
assert html_response(conn, 200) =~ "10k pageviews"
assert html_response(conn, 200) =~ "monthly billing"
end
test "shows yearly subscription", %{conn: conn, user: user} do
insert(:subscription, paddle_plan_id: "590752", user: user)
conn = get(conn, "/settings")
assert html_response(conn, 200) =~ "100k pageviews"
assert html_response(conn, 200) =~ "yearly billing"
end
test "shows free subscription", %{conn: conn, user: user} do
insert(:subscription, paddle_plan_id: "free_10k", user: user)
conn = get(conn, "/settings")
assert html_response(conn, 200) =~ "10k pageviews"
assert html_response(conn, 200) =~ "N/A billing"
end
end
describe "PUT /settings" do

View File

@ -7,7 +7,7 @@ defmodule Plausible.Workers.CheckUsageTest do
alias Plausible.Billing.Plans
setup [:create_user, :create_site]
@paddle_id_10k Plans.plans()[:monthly][:"10k"][:product_id]
@paddle_id_10k Plans.plans_for(nil) |> List.first() |> Map.get(:monthly_product_id)
test "ignores user without subscription" do
CheckUsage.perform(nil)
@ -89,7 +89,8 @@ defmodule Plausible.Workers.CheckUsageTest do
assert_email_delivered_with(
to: [user],
html_body: ~r/select the 100k\/mo plan which runs at \$12\/mo or \$8\/mo when billed yearly/
html_body:
~r/select the 100k\/mo plan which runs at \$12\/mo or \$96\/yr when billed yearly/
)
end

View File

@ -6,8 +6,9 @@ defmodule Plausible.Workers.NotifyAnnualRenewalTest do
alias Plausible.Billing.Plans
setup [:create_user, :create_site]
@monthly_plan Plans.plans()[:monthly][:"10k"][:product_id]
@yearly_plan Plans.plans()[:yearly][:"10k"][:product_id]
@plan_10k Plans.plans_for(nil) |> List.first()
@monthly_plan @plan_10k[:monthly_product_id]
@yearly_plan @plan_10k[:yearly_product_id]
test "ignores user without subscription" do
NotifyAnnualRenewal.perform(nil)