113 lines
3.1 KiB
Elixir
113 lines
3.1 KiB
Elixir
defmodule Plausible.Users do
|
|
@moduledoc """
|
|
User context
|
|
"""
|
|
use Plausible
|
|
@accept_traffic_until_free ~D[2135-01-01]
|
|
|
|
import Ecto.Query
|
|
|
|
alias Plausible.Auth
|
|
alias Plausible.Billing.Subscription
|
|
alias Plausible.Repo
|
|
|
|
@spec on_trial?(Auth.User.t()) :: boolean()
|
|
on_ee do
|
|
def on_trial?(%Auth.User{trial_expiry_date: nil}), do: false
|
|
|
|
def on_trial?(user) do
|
|
user = with_subscription(user)
|
|
not Plausible.Billing.Subscriptions.active?(user.subscription) && trial_days_left(user) >= 0
|
|
end
|
|
else
|
|
def on_trial?(_), do: true
|
|
end
|
|
|
|
@spec trial_days_left(Auth.User.t()) :: integer()
|
|
def trial_days_left(user) do
|
|
Timex.diff(user.trial_expiry_date, Timex.today(), :days)
|
|
end
|
|
|
|
@spec update_accept_traffic_until(Auth.User.t()) :: Auth.User.t()
|
|
def update_accept_traffic_until(user) do
|
|
user
|
|
|> Auth.User.changeset(%{accept_traffic_until: accept_traffic_until(user)})
|
|
|> Repo.update!()
|
|
end
|
|
|
|
@spec accept_traffic_until(Auth.User.t()) :: Date.t()
|
|
on_ee do
|
|
def accept_traffic_until(user) do
|
|
user = with_subscription(user)
|
|
|
|
cond do
|
|
Plausible.Users.on_trial?(user) ->
|
|
Timex.shift(user.trial_expiry_date,
|
|
days: Auth.User.trial_accept_traffic_until_offset_days()
|
|
)
|
|
|
|
user.subscription && user.subscription.paddle_plan_id == "free_10k" ->
|
|
@accept_traffic_until_free
|
|
|
|
user.subscription && user.subscription.next_bill_date ->
|
|
Timex.shift(user.subscription.next_bill_date,
|
|
days: Auth.User.subscription_accept_traffic_until_offset_days()
|
|
)
|
|
|
|
true ->
|
|
raise "This user is neither on trial or has a valid subscription. Manual intervention required."
|
|
end
|
|
end
|
|
else
|
|
def accept_traffic_until(_user) do
|
|
@accept_traffic_until_free
|
|
end
|
|
end
|
|
|
|
def with_subscription(%Auth.User{id: user_id} = user) do
|
|
Repo.preload(user, subscription: last_subscription_query(user_id))
|
|
end
|
|
|
|
def with_subscription(user_id) when is_integer(user_id) do
|
|
Repo.one(
|
|
from(user in Auth.User,
|
|
left_join: last_subscription in subquery(last_subscription_query(user_id)),
|
|
on: last_subscription.user_id == user.id,
|
|
left_join: subscription in Subscription,
|
|
on: subscription.id == last_subscription.id,
|
|
where: user.id == ^user_id,
|
|
preload: [subscription: subscription]
|
|
)
|
|
)
|
|
end
|
|
|
|
@spec has_email_code?(Auth.User.t()) :: boolean()
|
|
def has_email_code?(user) do
|
|
Auth.EmailVerification.any?(user)
|
|
end
|
|
|
|
def allow_next_upgrade_override(%Auth.User{} = user) do
|
|
user
|
|
|> Auth.User.changeset(%{allow_next_upgrade_override: true})
|
|
|> Repo.update!()
|
|
end
|
|
|
|
def maybe_reset_next_upgrade_override(%Auth.User{} = user) do
|
|
if user.allow_next_upgrade_override do
|
|
user
|
|
|> Auth.User.changeset(%{allow_next_upgrade_override: false})
|
|
|> Repo.update!()
|
|
else
|
|
user
|
|
end
|
|
end
|
|
|
|
defp last_subscription_query(user_id) do
|
|
from(subscription in Subscription,
|
|
where: subscription.user_id == ^user_id,
|
|
order_by: [desc: subscription.inserted_at],
|
|
limit: 1
|
|
)
|
|
end
|
|
end
|