mirror of
https://github.com/outbackdingo/firezone.git
synced 2026-01-27 10:18:54 +00:00
feat(portal): Add legal_name field to accounts and sync it with new stripe metadata key (#4771)
Closes #4761
This commit is contained in:
@@ -5,6 +5,8 @@ defmodule Domain.Accounts.Account do
|
||||
field :name, :string
|
||||
field :slug, :string
|
||||
|
||||
field :legal_name, :string
|
||||
|
||||
# Updated by the billing subscription metadata fields
|
||||
embeds_one :features, Domain.Accounts.Features, on_replace: :delete
|
||||
embeds_one :limits, Domain.Accounts.Limits, on_replace: :delete
|
||||
|
||||
@@ -16,14 +16,15 @@ defmodule Domain.Accounts.Account.Changeset do
|
||||
|
||||
def create(attrs) do
|
||||
%Account{}
|
||||
|> cast(attrs, [:name, :slug])
|
||||
|> cast(attrs, [:name, :legal_name, :slug])
|
||||
|> changeset()
|
||||
end
|
||||
|
||||
def update_profile_and_config(%Account{} = account, attrs) do
|
||||
account
|
||||
|> cast(attrs, [:name])
|
||||
|> cast(attrs, [:name, :legal_name])
|
||||
|> validate_name()
|
||||
|> validate_legal_name()
|
||||
|> cast_embed(:config, with: &Config.Changeset.changeset/2)
|
||||
end
|
||||
|
||||
@@ -32,6 +33,7 @@ defmodule Domain.Accounts.Account.Changeset do
|
||||
|> cast(attrs, [
|
||||
:slug,
|
||||
:name,
|
||||
:legal_name,
|
||||
:disabled_reason,
|
||||
:disabled_at,
|
||||
:warning,
|
||||
@@ -44,6 +46,7 @@ defmodule Domain.Accounts.Account.Changeset do
|
||||
defp changeset(changeset) do
|
||||
changeset
|
||||
|> validate_name()
|
||||
|> validate_legal_name()
|
||||
|> validate_slug()
|
||||
|> prepare_changes(&put_default_slug/1)
|
||||
|> cast_embed(:config, with: &Config.Changeset.changeset/2)
|
||||
@@ -59,6 +62,13 @@ defmodule Domain.Accounts.Account.Changeset do
|
||||
|> validate_length(:name, min: 3, max: 64)
|
||||
end
|
||||
|
||||
defp validate_legal_name(changeset) do
|
||||
changeset
|
||||
|> put_default_value(:legal_name, from: :name)
|
||||
|> trim_change(:legal_name)
|
||||
|> validate_length(:legal_name, min: 1, max: 255)
|
||||
end
|
||||
|
||||
defp validate_slug(changeset) do
|
||||
changeset
|
||||
|> validate_length(:slug, min: 3, max: 100)
|
||||
|
||||
@@ -111,9 +111,15 @@ defmodule Domain.Billing do
|
||||
email = get_customer_email(account)
|
||||
|
||||
with {:ok, %{"id" => customer_id, "email" => customer_email}} <-
|
||||
APIClient.create_customer(secret_key, account.id, account.name, account.slug, email) do
|
||||
APIClient.create_customer(secret_key, account.legal_name, email, %{
|
||||
account_id: account.id,
|
||||
account_name: account.name,
|
||||
account_slug: account.slug
|
||||
}) do
|
||||
Accounts.update_account(account, %{
|
||||
metadata: %{stripe: %{customer_id: customer_id, billing_email: customer_email}}
|
||||
metadata: %{
|
||||
stripe: %{customer_id: customer_id, billing_email: customer_email}
|
||||
}
|
||||
})
|
||||
else
|
||||
{:ok, {status, body}} ->
|
||||
@@ -146,9 +152,12 @@ defmodule Domain.Billing do
|
||||
APIClient.update_customer(
|
||||
secret_key,
|
||||
customer_id,
|
||||
account.id,
|
||||
account.name,
|
||||
account.slug
|
||||
account.legal_name,
|
||||
%{
|
||||
account_id: account.id,
|
||||
account_name: account.name,
|
||||
account_slug: account.slug
|
||||
}
|
||||
) do
|
||||
{:ok, account}
|
||||
else
|
||||
|
||||
@@ -31,7 +31,8 @@ defmodule Domain.Billing.EventHandler do
|
||||
}) do
|
||||
attrs =
|
||||
%{
|
||||
name: customer_name,
|
||||
name: customer_metadata["account_name"] || customer_name,
|
||||
legal_name: customer_name,
|
||||
metadata: %{stripe: %{billing_email: customer_email}}
|
||||
}
|
||||
|> put_if_not_nil(:slug, customer_metadata["account_slug"])
|
||||
@@ -239,7 +240,8 @@ defmodule Domain.Billing.EventHandler do
|
||||
end
|
||||
|
||||
attrs = %{
|
||||
name: customer_name,
|
||||
name: metadata["account_name"] || customer_name,
|
||||
legal_name: customer_name,
|
||||
slug: account_slug,
|
||||
metadata: %{
|
||||
stripe: %{
|
||||
@@ -340,6 +342,7 @@ defmodule Domain.Billing.EventHandler do
|
||||
subscription_metadata,
|
||||
stripe_metadata_overrides
|
||||
) do
|
||||
# feature_fields = Accounts.Features.__schema__(:fields) |> Enum.map(&to_string/1)
|
||||
limit_fields = Accounts.Limits.__schema__(:fields) |> Enum.map(&to_string/1)
|
||||
metadata_fields = ["support_type"]
|
||||
|
||||
|
||||
@@ -25,31 +25,31 @@ defmodule Domain.Billing.Stripe.APIClient do
|
||||
[conn_opts: [transport_opts: transport_opts]]
|
||||
end
|
||||
|
||||
def create_customer(api_token, id, name, slug, email) do
|
||||
def create_customer(api_token, name, email, metadata) do
|
||||
metadata_params =
|
||||
for {key, value} <- metadata, into: %{} do
|
||||
{"metadata[#{key}]", value}
|
||||
end
|
||||
|
||||
body =
|
||||
URI.encode_query(
|
||||
%{
|
||||
"name" => name,
|
||||
"metadata[account_id]" => id,
|
||||
"metadata[account_slug]" => slug
|
||||
}
|
||||
|> put_if_not_nil("email", email),
|
||||
:www_form
|
||||
)
|
||||
metadata_params
|
||||
|> Map.put("name", name)
|
||||
|> put_if_not_nil("email", email)
|
||||
|> URI.encode_query(:www_form)
|
||||
|
||||
request(api_token, :post, "customers", body)
|
||||
end
|
||||
|
||||
def update_customer(api_token, customer_id, id, name, slug) do
|
||||
def update_customer(api_token, customer_id, name, metadata) do
|
||||
metadata_params =
|
||||
for {key, value} <- metadata, into: %{} do
|
||||
{"metadata[#{key}]", value}
|
||||
end
|
||||
|
||||
body =
|
||||
URI.encode_query(
|
||||
%{
|
||||
"name" => name,
|
||||
"metadata[account_id]" => id,
|
||||
"metadata[account_slug]" => slug
|
||||
},
|
||||
:www_form
|
||||
)
|
||||
metadata_params
|
||||
|> Map.put("name", name)
|
||||
|> URI.encode_query(:www_form)
|
||||
|
||||
request(api_token, :post, "customers/#{customer_id}", body)
|
||||
end
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
defmodule Domain.Repo.Migrations.AddAccountsLegalName do
|
||||
use Ecto.Migration
|
||||
|
||||
def change do
|
||||
alter table(:accounts) do
|
||||
add(:legal_name, :string)
|
||||
end
|
||||
|
||||
execute("UPDATE accounts SET legal_name = name")
|
||||
|
||||
execute("ALTER TABLE accounts ALTER COLUMN legal_name SET NOT NULL")
|
||||
end
|
||||
end
|
||||
@@ -375,9 +375,10 @@ defmodule Domain.BillingTest do
|
||||
assert_receive {:bypass_request, %{request_path: "/v1/customers"} = conn}
|
||||
|
||||
assert conn.params == %{
|
||||
"name" => account.name,
|
||||
"name" => account.legal_name,
|
||||
"metadata" => %{
|
||||
"account_id" => account.id,
|
||||
"account_name" => account.name,
|
||||
"account_slug" => account.slug
|
||||
}
|
||||
}
|
||||
@@ -527,6 +528,8 @@ defmodule Domain.BillingTest do
|
||||
assert handle_events([event]) == :ok
|
||||
|
||||
assert account = Repo.get_by(Domain.Accounts.Account, slug: "bigcompany")
|
||||
assert account.name == "New Account Name"
|
||||
assert account.legal_name == "New Account Name"
|
||||
assert account.metadata.stripe.customer_id == customer_id
|
||||
assert account.metadata.stripe.billing_email == "iown@bigcompany.com"
|
||||
assert account.metadata.stripe.subscription_id
|
||||
@@ -545,8 +548,12 @@ defmodule Domain.BillingTest do
|
||||
%{request_path: "/v1/customers/" <> ^customer_id, params: params}}
|
||||
|
||||
assert params == %{
|
||||
"metadata" => %{"account_id" => account.id, "account_slug" => account.slug},
|
||||
"name" => "New Account Name"
|
||||
"metadata" => %{
|
||||
"account_id" => account.id,
|
||||
"account_name" => account.name,
|
||||
"account_slug" => account.slug
|
||||
},
|
||||
"name" => account.legal_name
|
||||
}
|
||||
|
||||
assert_receive {:bypass_request, %{request_path: "/v1/subscriptions", params: params}}
|
||||
@@ -647,6 +654,8 @@ defmodule Domain.BillingTest do
|
||||
assert handle_events([event]) == :ok
|
||||
|
||||
assert account = Repo.get_by(Domain.Accounts.Account, slug: "bigcompany")
|
||||
assert account.name == "New Account Name"
|
||||
assert account.legal_name == "New Account Name"
|
||||
assert account.metadata.stripe.customer_id == customer_id
|
||||
assert account.metadata.stripe.billing_email == "iown@bigcompany.com"
|
||||
assert account.metadata.stripe.subscription_id
|
||||
@@ -669,8 +678,12 @@ defmodule Domain.BillingTest do
|
||||
}}
|
||||
|
||||
assert params == %{
|
||||
"metadata" => %{"account_id" => account.id, "account_slug" => account.slug},
|
||||
"name" => "New Account Name"
|
||||
"metadata" => %{
|
||||
"account_id" => account.id,
|
||||
"account_name" => account.name,
|
||||
"account_slug" => account.slug
|
||||
},
|
||||
"name" => account.legal_name
|
||||
}
|
||||
|
||||
assert_receive {:bypass_request,
|
||||
@@ -686,38 +699,6 @@ defmodule Domain.BillingTest do
|
||||
}
|
||||
end
|
||||
|
||||
test "updates an account from stripe on customer.updated event", %{account: account} do
|
||||
customer_metadata = %{
|
||||
"account_id" => account.id,
|
||||
"account_slug" => "this_is_a_new_slug"
|
||||
}
|
||||
|
||||
Bypass.open()
|
||||
|> Stripe.mock_fetch_customer_endpoint(account, %{
|
||||
"metadata" => customer_metadata
|
||||
})
|
||||
|> Stripe.mock_update_customer_endpoint(account)
|
||||
|
||||
event =
|
||||
Stripe.build_event(
|
||||
"customer.updated",
|
||||
Stripe.customer_object(
|
||||
account.metadata.stripe.customer_id,
|
||||
"Updated Account Name",
|
||||
"iown@bigcompany.com",
|
||||
customer_metadata
|
||||
)
|
||||
)
|
||||
|
||||
assert handle_events([event]) == :ok
|
||||
|
||||
assert account = Repo.one(Domain.Accounts.Account)
|
||||
assert account.name == "Updated Account Name"
|
||||
assert account.slug == "this_is_a_new_slug"
|
||||
|
||||
assert account.metadata.stripe.billing_email == "iown@bigcompany.com"
|
||||
end
|
||||
|
||||
test "disables the account on when subscription is deleted", %{
|
||||
account: account,
|
||||
customer_id: customer_id
|
||||
@@ -788,6 +769,17 @@ defmodule Domain.BillingTest do
|
||||
account: account,
|
||||
customer_id: customer_id
|
||||
} do
|
||||
account =
|
||||
Fixtures.Accounts.update_account(account, %{
|
||||
limits: %{
|
||||
service_accounts_count: 10101
|
||||
},
|
||||
features: %{
|
||||
flow_activities: true,
|
||||
traffic_filters: true
|
||||
}
|
||||
})
|
||||
|
||||
Bypass.open()
|
||||
|> Stripe.mock_fetch_customer_endpoint(account)
|
||||
|> Stripe.mock_fetch_product_endpoint("prod_Na6dGcTsmU0I4R", %{
|
||||
|
||||
@@ -8,6 +8,7 @@ defmodule Domain.Fixtures.Accounts do
|
||||
|
||||
Enum.into(attrs, %{
|
||||
name: "acc-#{unique_num}",
|
||||
legal_name: "l-acc-#{unique_num}",
|
||||
slug: "acc_#{unique_num}",
|
||||
config: %{
|
||||
clients_upstream_dns: [
|
||||
|
||||
@@ -84,6 +84,13 @@ defmodule Web.Settings.Billing do
|
||||
<%= @account.metadata.stripe.billing_email %>
|
||||
</:value>
|
||||
</.vertical_table_row>
|
||||
|
||||
<.vertical_table_row>
|
||||
<:label>Billing Name</:label>
|
||||
<:value>
|
||||
<%= @account.legal_name %>
|
||||
</:value>
|
||||
</.vertical_table_row>
|
||||
</.vertical_table>
|
||||
</:content>
|
||||
</.section>
|
||||
|
||||
Reference in New Issue
Block a user