analytics/lib/plausible/users.ex

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