mirror of
https://github.com/plausible/analytics.git
synced 2024-12-25 02:24:55 +03:00
Wrap paddle actions with DB transactions (#2558)
* Wrap paddle actions with DB transactions * Bow to credo * Make the paddle transactions crash when applicable * s/changeset/details
This commit is contained in:
parent
1785653b1e
commit
44afbaa2f9
@ -12,93 +12,28 @@ defmodule Plausible.Billing do
|
||||
user_id |> active_subscription_query() |> Repo.exists?()
|
||||
end
|
||||
|
||||
defp active_subscription_query(user_id) do
|
||||
from s in Subscription,
|
||||
where: s.user_id == ^user_id and s.status == "active",
|
||||
order_by: [desc: s.inserted_at],
|
||||
limit: 1
|
||||
end
|
||||
|
||||
def subscription_created(params) do
|
||||
params =
|
||||
if present?(params["passthrough"]) do
|
||||
params
|
||||
else
|
||||
user = Repo.get_by(Plausible.Auth.User, email: params["email"])
|
||||
Map.put(params, "passthrough", user && user.id)
|
||||
end
|
||||
|
||||
changeset = Subscription.changeset(%Subscription{}, format_subscription(params))
|
||||
|
||||
Repo.insert(changeset) |> after_subscription_update
|
||||
Repo.transaction(fn ->
|
||||
handle_subscription_created(params)
|
||||
end)
|
||||
end
|
||||
|
||||
def subscription_updated(params) do
|
||||
subscription = Repo.get_by!(Subscription, paddle_subscription_id: params["subscription_id"])
|
||||
changeset = Subscription.changeset(subscription, format_subscription(params))
|
||||
|
||||
Repo.update(changeset) |> after_subscription_update
|
||||
Repo.transaction(fn ->
|
||||
handle_subscription_updated(params)
|
||||
end)
|
||||
end
|
||||
|
||||
defp after_subscription_update({:ok, subscription}) do
|
||||
user =
|
||||
Repo.get(Plausible.Auth.User, subscription.user_id)
|
||||
|> Map.put(:subscription, subscription)
|
||||
|
||||
user
|
||||
|> maybe_remove_grace_period
|
||||
|> check_lock_status
|
||||
|> maybe_adjust_api_key_limits
|
||||
end
|
||||
|
||||
defp after_subscription_update(err), do: err
|
||||
|
||||
def subscription_cancelled(params) do
|
||||
subscription =
|
||||
Repo.get_by(Subscription, paddle_subscription_id: params["subscription_id"])
|
||||
|> Repo.preload(:user)
|
||||
|
||||
if subscription do
|
||||
changeset =
|
||||
Subscription.changeset(subscription, %{
|
||||
status: params["status"]
|
||||
})
|
||||
|
||||
case Repo.update(changeset) do
|
||||
{:ok, updated} ->
|
||||
PlausibleWeb.Email.cancellation_email(subscription.user)
|
||||
|> Plausible.Mailer.send()
|
||||
|
||||
{:ok, updated}
|
||||
|
||||
err ->
|
||||
err
|
||||
end
|
||||
else
|
||||
{:ok, nil}
|
||||
end
|
||||
Repo.transaction(fn ->
|
||||
handle_subscription_cancelled(params)
|
||||
end)
|
||||
end
|
||||
|
||||
def subscription_payment_succeeded(params) do
|
||||
subscription = Repo.get_by(Subscription, paddle_subscription_id: params["subscription_id"])
|
||||
|
||||
if subscription do
|
||||
{:ok, api_subscription} = paddle_api().get_subscription(subscription.paddle_subscription_id)
|
||||
|
||||
amount =
|
||||
:erlang.float_to_binary(api_subscription["next_payment"]["amount"] / 1, decimals: 2)
|
||||
|
||||
changeset =
|
||||
Subscription.changeset(subscription, %{
|
||||
next_bill_amount: amount,
|
||||
next_bill_date: api_subscription["next_payment"]["date"],
|
||||
last_bill_date: api_subscription["last_payment"]["date"]
|
||||
})
|
||||
|
||||
Repo.update(changeset)
|
||||
else
|
||||
{:ok, nil}
|
||||
end
|
||||
Repo.transaction(fn ->
|
||||
handle_subscription_payment_succeeded(params)
|
||||
end)
|
||||
end
|
||||
|
||||
def change_plan(user, new_plan_id) do
|
||||
@ -247,6 +182,71 @@ defmodule Plausible.Billing do
|
||||
end
|
||||
end
|
||||
|
||||
defp handle_subscription_created(params) do
|
||||
params =
|
||||
if present?(params["passthrough"]) do
|
||||
params
|
||||
else
|
||||
user = Repo.get_by(Plausible.Auth.User, email: params["email"])
|
||||
Map.put(params, "passthrough", user && user.id)
|
||||
end
|
||||
|
||||
%Subscription{}
|
||||
|> Subscription.changeset(format_subscription(params))
|
||||
|> Repo.insert!()
|
||||
|> after_subscription_update()
|
||||
end
|
||||
|
||||
defp handle_subscription_updated(params) do
|
||||
Subscription
|
||||
|> Repo.get_by!(paddle_subscription_id: params["subscription_id"])
|
||||
|> Subscription.changeset(format_subscription(params))
|
||||
|> Repo.update!()
|
||||
|> after_subscription_update()
|
||||
end
|
||||
|
||||
defp handle_subscription_cancelled(params) do
|
||||
subscription =
|
||||
Subscription
|
||||
|> Repo.get_by(paddle_subscription_id: params["subscription_id"])
|
||||
|> Repo.preload(:user)
|
||||
|
||||
if subscription do
|
||||
changeset =
|
||||
Subscription.changeset(subscription, %{
|
||||
status: params["status"]
|
||||
})
|
||||
|
||||
updated = Repo.update!(changeset)
|
||||
|
||||
subscription
|
||||
|> Map.fetch!(:user)
|
||||
|> PlausibleWeb.Email.cancellation_email()
|
||||
|> Plausible.Mailer.send()
|
||||
|
||||
updated
|
||||
end
|
||||
end
|
||||
|
||||
defp handle_subscription_payment_succeeded(params) do
|
||||
subscription = Repo.get_by(Subscription, paddle_subscription_id: params["subscription_id"])
|
||||
|
||||
if subscription do
|
||||
{:ok, api_subscription} = paddle_api().get_subscription(subscription.paddle_subscription_id)
|
||||
|
||||
amount =
|
||||
:erlang.float_to_binary(api_subscription["next_payment"]["amount"] / 1, decimals: 2)
|
||||
|
||||
subscription
|
||||
|> Subscription.changeset(%{
|
||||
next_bill_amount: amount,
|
||||
next_bill_date: api_subscription["next_payment"]["date"],
|
||||
last_bill_date: api_subscription["last_payment"]["date"]
|
||||
})
|
||||
|> Repo.update!()
|
||||
end
|
||||
end
|
||||
|
||||
defp has_active_enterprise_subscription(user) do
|
||||
Plausible.Repo.exists?(
|
||||
from(s in Plausible.Billing.Subscription,
|
||||
@ -287,24 +287,22 @@ defmodule Plausible.Billing do
|
||||
if new_allowance > allowance_required do
|
||||
user
|
||||
|> Plausible.Auth.GracePeriod.remove_changeset()
|
||||
|> Repo.update()
|
||||
|> Repo.update!()
|
||||
else
|
||||
{:ok, user}
|
||||
user
|
||||
end
|
||||
|
||||
_ ->
|
||||
{:ok, user}
|
||||
user
|
||||
end
|
||||
end
|
||||
|
||||
defp check_lock_status({:ok, user}) do
|
||||
defp check_lock_status(user) do
|
||||
Plausible.Billing.SiteLocker.check_sites_for(user)
|
||||
{:ok, user}
|
||||
user
|
||||
end
|
||||
|
||||
defp check_lock_status(err), do: err
|
||||
|
||||
defp maybe_adjust_api_key_limits({:ok, user}) do
|
||||
defp maybe_adjust_api_key_limits(user) do
|
||||
plan =
|
||||
Repo.get_by(Plausible.Billing.EnterprisePlan,
|
||||
user_id: user.id,
|
||||
@ -317,10 +315,27 @@ defmodule Plausible.Billing do
|
||||
Repo.update_all(api_keys, set: [hourly_request_limit: plan.hourly_api_request_limit])
|
||||
end
|
||||
|
||||
{:ok, user}
|
||||
user
|
||||
end
|
||||
|
||||
defp maybe_adjust_api_key_limits(err), do: err
|
||||
|
||||
def paddle_api(), do: Application.fetch_env!(:plausible, :paddle_api)
|
||||
|
||||
defp active_subscription_query(user_id) do
|
||||
from s in Subscription,
|
||||
where: s.user_id == ^user_id and s.status == "active",
|
||||
order_by: [desc: s.inserted_at],
|
||||
limit: 1
|
||||
end
|
||||
|
||||
defp after_subscription_update(subscription) do
|
||||
user =
|
||||
Plausible.Auth.User
|
||||
|> Repo.get!(subscription.user_id)
|
||||
|> Map.put(:subscription, subscription)
|
||||
|
||||
user
|
||||
|> maybe_remove_grace_period()
|
||||
|> check_lock_status()
|
||||
|> maybe_adjust_api_key_limits()
|
||||
end
|
||||
end
|
||||
|
@ -68,8 +68,8 @@ defmodule PlausibleWeb.Api.PaddleController do
|
||||
json(conn, "")
|
||||
end
|
||||
|
||||
defp webhook_response({:error, changeset}, conn, _params) do
|
||||
Logger.error("Error processing Paddle webhook: #{inspect(changeset)}")
|
||||
defp webhook_response({:error, details}, conn, _params) do
|
||||
Logger.error("Error processing Paddle webhook: #{inspect(details)}")
|
||||
|
||||
conn |> send_resp(400, "") |> halt
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user