Skip to content

Commit

Permalink
feat: partner upgrade/downgrade tiers (#1891)
Browse files Browse the repository at this point in the history
* feat: partner upgrade/downgrade tiers

* Update lib/logflare/partners.ex

Co-authored-by: Łukasz Jan Niemier <[email protected]>

* chore: PR comments

* chore: version bump

* Update lib/logflare/billing.ex

Co-authored-by: Łukasz Jan Niemier <[email protected]>

---------

Co-authored-by: Łukasz Jan Niemier <[email protected]>
  • Loading branch information
Ziinc and hauleth authored Dec 20, 2023
1 parent 0bff49f commit f3277b5
Show file tree
Hide file tree
Showing 10 changed files with 116 additions and 1 deletion.
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.5.12
1.5.13
4 changes: 4 additions & 0 deletions lib/logflare/billing.ex
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ defmodule Logflare.Billing do
Billing.PaymentMethod
}

alias Logflare.Partners
alias Logflare.SingleTenant

require Protocol
Expand Down Expand Up @@ -329,6 +330,9 @@ defmodule Logflare.Billing do
SingleTenant.single_tenant?() ->
get_plan_by(name: "Enterprise")

Partners.user_upgraded?(user) ->
get_plan_by(name: "Enterprise")

user.billing_enabled == false ->
legacy_plan()

Expand Down
23 changes: 23 additions & 0 deletions lib/logflare/partners.ex
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,27 @@ defmodule Logflare.Partners do
|> Multi.delete_all(:delete, query)
|> Repo.transaction()
end

def user_upgraded?(%User{id: id}) do
query =
from(pu in PartnerUser, where: pu.user_id == ^id, select: pu.upgraded)

Repo.one(query) || false
end

def upgrade_user(p, u), do: do_upgrade_downgrade(p, u, true)
def downgrade_user(p, u), do: do_upgrade_downgrade(p, u, false)

def do_upgrade_downgrade(%Partner{id: partner_id}, %User{id: user_id}, value) do
query =
from(pu in PartnerUser,
where: pu.partner_id == ^partner_id and pu.user_id == ^user_id,
select: pu
)

case Repo.update_all(query, set: [upgraded: value]) do
{1, [partner_user]} -> {:ok, partner_user}
_ -> {:error, :not_found}
end
end
end
1 change: 1 addition & 0 deletions lib/logflare/partners/partner_user.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ defmodule Logflare.Partners.PartnerUser do
schema "partner_users" do
belongs_to :partner, Logflare.Partners.Partner
belongs_to :user, Logflare.User
field :upgraded, :boolean, default: false
end

def changeset(partner_user, params) do
Expand Down
14 changes: 14 additions & 0 deletions lib/logflare_web/controllers/api/partner/user_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,20 @@ defmodule LogflareWeb.Api.Partner.UserController do
end
end

def upgrade(%{assigns: %{partner: partner}} = conn, %{"user_token" => user_token}) do
with user when not is_nil(user) <- Partners.get_user_by_token(partner, user_token),
{:ok, %_{}} <- Partners.upgrade_user(partner, user) do
json(conn, %{tier: "metered"})
end
end

def downgrade(%{assigns: %{partner: partner}} = conn, %{"user_token" => user_token}) do
with user when not is_nil(user) <- Partners.get_user_by_token(partner, user_token),
{:ok, %_{}} <- Partners.downgrade_user(partner, user) do
json(conn, %{tier: "free"})
end
end

defp sanitize_response(user) do
Enum.reduce(@allowed_fields, %{}, fn key, acc -> Map.put(acc, key, Map.get(user, key)) end)
end
Expand Down
2 changes: 2 additions & 0 deletions lib/logflare_web/router.ex
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,8 @@ defmodule LogflareWeb.Router do

get("/users", Api.Partner.UserController, :index)
post("/users", Api.Partner.UserController, :create)
put("/users/:user_token/upgrade", Api.Partner.UserController, :upgrade)
put("/users/:user_token/downgrade", Api.Partner.UserController, :downgrade)

get("/users/:user_token", Api.Partner.UserController, :get_user)
get("/users/:user_token/usage", Api.Partner.UserController, :get_user_usage)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
defmodule Logflare.Repo.Migrations.AddUpgradedColumnToPartnerUsersTable do
use Ecto.Migration

def up do

alter table(:partner_users) do
add :upgraded, :boolean, default: false, null: false
end
end

def down do

alter table(:partner_users) do
remove :upgraded
end
end
end
15 changes: 15 additions & 0 deletions test/logflare/billing_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ defmodule Logflare.BillingTest do
use Logflare.DataCase
alias Logflare.{User, Billing, Billing.BillingAccount, Billing.PaymentMethod, Billing.Plan}

alias Logflare.Partners

describe "billing accounts" do
@valid_attrs %{stripe_customer: "some stripe id"}
@update_attrs %{stripe_customer: "some stripe other id"}
Expand Down Expand Up @@ -216,6 +218,19 @@ defmodule Logflare.BillingTest do
assert %Plan{name: "Custom"} = Billing.get_plan_by_user(ba.user)
end

test "get_plan_by_user/1 with partner upgrade/downgrade" do
insert(:plan, name: "Free")
insert(:plan, name: "Enterprise")
user = insert(:user)
partner = insert(:partner, users: [user])
assert %Plan{name: "Free"} = Billing.get_plan_by_user(user)
# upgrade user
Partners.upgrade_user(partner,user )
assert %Plan{name: "Enterprise"} = Billing.get_plan_by_user(user)


end

test "change_plan/1 returns changeset" do
plan = insert(:plan)
assert %Ecto.Changeset{} = Billing.change_plan(plan)
Expand Down
16 changes: 16 additions & 0 deletions test/logflare/partners_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ defmodule Logflare.PartnerTest do
use Logflare.DataCase

alias Logflare.Partners
alias Logflare.Partners.PartnerUser
alias Logflare.Repo
alias Logflare.User

Expand Down Expand Up @@ -102,4 +103,19 @@ defmodule Logflare.PartnerTest do
assert {:error, :not_found} = Partners.delete_user(partner, user)
end
end

test "upgrade_user/2, downgrade_user/2, user_upgraded?/1" do
user = insert(:user)
partner = insert(:partner, users: [user])
assert Partners.user_upgraded?(user) == false
assert {:ok, %PartnerUser{upgraded: true}} = Partners.upgrade_user(partner, user)
assert Partners.user_upgraded?(user)
assert {:ok, %PartnerUser{upgraded: false}} = Partners.downgrade_user(partner, user)
assert Partners.user_upgraded?(user) == false

assert Partners.user_upgraded?(insert(:user)) == false

assert {:error, :not_found} = Partners.upgrade_user(partner, insert(:user))
end

end
23 changes: 23 additions & 0 deletions test/logflare_web/controllers/api/partner/user_controller_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,29 @@ defmodule LogflareWeb.Api.Partner.UserControllerTest do
end
end

describe "PUT user tiers" do
test "upgrade/downgrade", %{conn: conn} do
user = insert(:user)
partner = insert(:partner, users: [user])

# upgrade
assert %{"tier"=> "metered"} =
conn
|> add_partner_access_token(partner)
|> put(~p"/api/partner/users/#{user.token}/upgrade")
|> json_response(200)

# downgrade
assert %{"tier"=> "free"} =
conn
|> recycle()
|> add_partner_access_token(partner)
|> put(~p"/api/partner/users/#{user.token}/downgrade")
|> json_response(200)

end
end

describe "GET user usage" do
test "returns 200 and the usage for a given user", %{
conn: conn,
Expand Down

0 comments on commit f3277b5

Please sign in to comment.