From 3beb43a1a0629884ee2344ba9477ee825e89457f Mon Sep 17 00:00:00 2001 From: Nikola Begedin Date: Mon, 5 Dec 2016 11:38:01 +0100 Subject: [PATCH] Add connect customer updates --- lib/code_corps/services/user_service.ex | 46 +++++++++++++++++-- .../stripe_service/stripe_connect_customer.ex | 4 ++ .../code_corps/services/user_service_test.exs | 43 ++++++++++++++--- test/support/factories.ex | 3 +- web/controllers/user_controller.ex | 32 ++++++------- web/models/stripe_platform_customer.ex | 2 + 6 files changed, 102 insertions(+), 28 deletions(-) diff --git a/lib/code_corps/services/user_service.ex b/lib/code_corps/services/user_service.ex index 6d208a981..ff09f58ac 100644 --- a/lib/code_corps/services/user_service.ex +++ b/lib/code_corps/services/user_service.ex @@ -7,8 +7,8 @@ defmodule CodeCorps.Services.UserService do """ - alias CodeCorps.{Repo, StripePlatformCustomer, User} - alias CodeCorps.StripeService.StripePlatformCustomerService + alias CodeCorps.{Repo, StripeConnectCustomer, StripePlatformCustomer, User} + alias CodeCorps.StripeService.{StripeConnectCustomerService,StripePlatformCustomerService} alias Ecto.Changeset alias Ecto.Multi @@ -30,17 +30,32 @@ defmodule CodeCorps.Services.UserService do Multi.new |> Multi.update(:update_user, changeset) |> Multi.run(:update_platform_customer, &update_platform_customer/1) + |> Multi.run(:update_connect_customers, &update_connect_customers/1) case Repo.transaction(multi) do - {:ok, %{update_user: user, update_platform_customer: _}} -> - {:ok, user} + {:ok, %{ + update_user: user, + update_platform_customer: update_platform_customer_result, + update_connect_customers: update_connect_customers_results + }} -> + {:ok, user, update_platform_customer_result, update_connect_customers_results} {:error, :update_user, %Ecto.Changeset{} = changeset, %{}} -> {:error, changeset} {:error, _failed_operation, _failed_value, _changes_so_far} -> {:error, :unhandled} + other -> + IO.inspect(other, pretty: true) + end + end + + defp do_update(%Changeset{} = changeset) do + with {:ok, user} <- Repo.update(changeset) do + {:ok, user, :nothing_to_update, :nothing_to_update} + else + {:error, changeset} -> {:error, changeset} + _ -> {:error, :unhandled} end end - defp do_update(%Changeset{} = changeset), do: Repo.update(changeset) defp update_platform_customer(%{update_user: %User{id: user_id, email: email}}) do StripePlatformCustomer @@ -52,4 +67,25 @@ defmodule CodeCorps.Services.UserService do defp do_update_platform_customer(%StripePlatformCustomer{} = stripe_platform_customer, attributes) do StripePlatformCustomerService.update(stripe_platform_customer, attributes) end + + defp update_connect_customers(%{update_platform_customer: :nothing_to_update}), do: {:ok, :nothing_to_update} + + defp update_connect_customers(%{update_platform_customer: %StripePlatformCustomer{email: email} = stripe_platform_customer}) do + case do_update_connect_customers(stripe_platform_customer, %{email: email}) do + [_h | _t] = results -> {:ok, results} + [] -> {:ok, :nothing_to_update} + end + end + + defp do_update_connect_customers(stripe_platform_customer, attributes) do + stripe_platform_customer + |> Repo.preload([stripe_connect_customers: :stripe_connect_account]) + |> Map.get(:stripe_connect_customers) + |> Enum.map(&do_update_connect_customer(&1, attributes)) + end + + defp do_update_connect_customer(%StripeConnectCustomer{} = stripe_connect_customer, attributes) do + stripe_connect_customer + |> StripeConnectCustomerService.update(attributes) + end end diff --git a/lib/code_corps/stripe_service/stripe_connect_customer.ex b/lib/code_corps/stripe_service/stripe_connect_customer.ex index 93555ec31..e35e0cc9e 100644 --- a/lib/code_corps/stripe_service/stripe_connect_customer.ex +++ b/lib/code_corps/stripe_service/stripe_connect_customer.ex @@ -19,6 +19,10 @@ defmodule CodeCorps.StripeService.StripeConnectCustomerService do end end + def update(%StripeConnectCustomer{stripe_connect_account: connect_account} = connect_customer, attributes) do + @api.Customer.update(connect_customer.id_from_stripe, attributes, connect_account: connect_account.id_from_stripe) + end + defp create(%StripePlatformCustomer{} = platform_customer, %StripeConnectAccount{} = connect_account) do attributes = platform_customer |> create_non_stripe_attributes(connect_account) stripe_attributes = create_stripe_attributes(platform_customer) diff --git a/test/lib/code_corps/services/user_service_test.exs b/test/lib/code_corps/services/user_service_test.exs index 8bb3b366d..66059c115 100644 --- a/test/lib/code_corps/services/user_service_test.exs +++ b/test/lib/code_corps/services/user_service_test.exs @@ -9,7 +9,9 @@ defmodule CodeCorps.Services.UserServiceTest do describe "update/1" do test "it just updates the user if there is nothing associated to update" do user = insert(:user, email: "mail@mail.com", first_name: "Joe") - {:ok, user} = UserService.update(user, %{email: "changed@mail.com"}) + + {:ok, user, :nothing_to_update, :nothing_to_update} + = UserService.update(user, %{email: "changed@mail.com"}) assert user.email == "changed@mail.com" assert user.first_name == "Joe" @@ -26,7 +28,8 @@ defmodule CodeCorps.Services.UserServiceTest do user = insert(:user, email: "mail@mail.com") stripe_platform_customer = insert(:stripe_platform_customer, email: "mail@mail.com", user: user) - {:ok, user} = UserService.update(user, %{first_name: "Mark"}) + {:ok, user, :nothing_to_update, :nothing_to_update} + = UserService.update(user, %{first_name: "Mark"}) assert user.first_name == "Mark" assert user.email == "mail@mail.com" @@ -38,15 +41,43 @@ defmodule CodeCorps.Services.UserServiceTest do test "it also updates the associated platform customer if there is one" do user = insert(:user, email: "mail@mail.com") - stripe_platform_customer = insert(:stripe_platform_customer, user: user) + platform_customer = insert(:stripe_platform_customer, user: user) - {:ok, user} = UserService.update(user, %{email: "changed@mail.com"}) + {:ok, user, %StripePlatformCustomer{}, :nothing_to_update} + = UserService.update(user, %{email: "changed@mail.com"}) assert user.email == "changed@mail.com" - stripe_platform_customer = Repo.get(StripePlatformCustomer, stripe_platform_customer.id) + platform_customer = Repo.get(StripePlatformCustomer, platform_customer.id) + + assert platform_customer.email == "changed@mail.com" + end + + test "it also updates the associated connect customers if there are any" do + user = insert(:user, email: "mail@mail.com") + + platform_customer = %{id_from_stripe: platform_customer_id} + = insert(:stripe_platform_customer, user: user) + + [connect_customer_1, connect_customer_2] = + insert_pair(:stripe_connect_customer, stripe_platform_customer: platform_customer) + + {:ok, user, %StripePlatformCustomer{}, connect_updates} = UserService.update(user, %{email: "changed@mail.com"}) + + assert user.email == "changed@mail.com" + + platform_customer = Repo.get_by(StripePlatformCustomer, id_from_stripe: platform_customer_id) + assert platform_customer.email == "changed@mail.com" + + [ + {:ok, %Stripe.Customer{} = stripe_record_1}, + {:ok, %Stripe.Customer{} = stripe_record_2} + ] = connect_updates - assert stripe_platform_customer.email == "changed@mail.com" + assert stripe_record_1.id == connect_customer_1.id_from_stripe + assert stripe_record_1.email == "changed@mail.com" + assert stripe_record_2.id == connect_customer_2.id_from_stripe + assert stripe_record_2.email == "changed@mail.com" end end end diff --git a/test/support/factories.ex b/test/support/factories.ex index 39b465c5e..61ffb3a6c 100644 --- a/test/support/factories.ex +++ b/test/support/factories.ex @@ -113,7 +113,8 @@ defmodule CodeCorps.Factories do def stripe_connect_customer_factory do %CodeCorps.StripeConnectCustomer{ - id_from_stripe: sequence(:id_from_stripe, &"stripe_id_#{&1}") + id_from_stripe: sequence(:id_from_stripe, &"stripe_id_#{&1}"), + stripe_connect_account: build(:stripe_connect_account) } end diff --git a/web/controllers/user_controller.ex b/web/controllers/user_controller.ex index 60dda8b8f..c4137cf0e 100644 --- a/web/controllers/user_controller.ex +++ b/web/controllers/user_controller.ex @@ -15,26 +15,26 @@ defmodule CodeCorps.UserController do end def handle_create(conn, attributes) do - %User{} - |> User.registration_changeset(attributes) - |> Repo.insert - |> login(conn) - |> track_signup + with {:ok, user} <- %User{} |> User.registration_changeset(attributes) |> Repo.insert, + conn <- login(user, conn) + do + CodeCorps.Analytics.Segment.track({:ok, user}, :signed_up, conn) + else + {:error, changeset} -> changeset + _ -> conn + end end - defp login({:error, changeset}, conn), do: {:error, changeset, conn} - defp login({:ok, model}, conn) do - {:ok, model, conn |> Plug.Conn.assign(:current_user, model)} - end - - defp track_signup({status, model_or_changeset, conn}) do - CodeCorps.Analytics.Segment.track({status, model_or_changeset}, :signed_up, conn) - end + defp login(user, conn), do: Plug.Conn.assign(conn, :current_user, user) def handle_update(conn, record, attributes) do - record - |>UserService.update(attributes) - |> CodeCorps.Analytics.Segment.track(:updated_profile, conn) + with {:ok, user, _platform_customer_updates, _connect_customer_updates} <- UserService.update(record, attributes) + do + {:ok, user} |> CodeCorps.Analytics.Segment.track(:updated_profile, conn) + else + {:error, changeset} -> changeset + {:error, :unhandled} -> conn + end end def email_available(conn, %{"email" => email}) do diff --git a/web/models/stripe_platform_customer.ex b/web/models/stripe_platform_customer.ex index 1ef603bd8..50252670e 100644 --- a/web/models/stripe_platform_customer.ex +++ b/web/models/stripe_platform_customer.ex @@ -10,6 +10,8 @@ defmodule CodeCorps.StripePlatformCustomer do belongs_to :user, CodeCorps.User + has_many :stripe_connect_customers, CodeCorps.StripeConnectCustomer + timestamps() end