From 616cdf9a0bc0ecb9854492463d0f3e21ce5ecc76 Mon Sep 17 00:00:00 2001 From: Nikola Begedin Date: Wed, 30 Nov 2016 14:33:14 +0100 Subject: [PATCH] Add verification before enabling donations on project --- .../stripe_service/stripe_connect_plan.ex | 24 ++++++-------- .../project_can_enable_donations.ex | 32 +++++++++++++++++++ .../stripe_connect_plan_controller_test.exs | 6 ++-- .../stripe_connect_plan_controller.ex | 2 +- 4 files changed, 45 insertions(+), 19 deletions(-) create mode 100644 lib/code_corps/stripe_service/validators/project_can_enable_donations.ex diff --git a/lib/code_corps/stripe_service/stripe_connect_plan.ex b/lib/code_corps/stripe_service/stripe_connect_plan.ex index 1c70e7bee..3cf2efd32 100644 --- a/lib/code_corps/stripe_service/stripe_connect_plan.ex +++ b/lib/code_corps/stripe_service/stripe_connect_plan.ex @@ -1,28 +1,22 @@ defmodule CodeCorps.StripeService.StripeConnectPlanService do - alias CodeCorps.Organization - alias CodeCorps.Project - alias CodeCorps.Repo + alias CodeCorps.{Project, Repo, StripeConnectPlan} alias CodeCorps.StripeService.Adapters.StripeConnectPlanAdapter - alias CodeCorps.StripeConnectAccount - alias CodeCorps.StripeConnectPlan + alias CodeCorps.StripeService.Validators.ProjectCanEnableDonations @api Application.get_env(:code_corps, :stripe) def create(%{"project_id" => project_id} = attributes) do - with %Project{donation_goals: [_h | _t], organization: %Organization{stripe_connect_account: %StripeConnectAccount{id_from_stripe: connect_account_id}}} <- - get_records(project_id), - %{} = create_attributes <- - get_create_attributes(), - {:ok, plan} <- - @api.Plan.create(create_attributes, connect_account: connect_account_id), - {:ok, params} <- - StripeConnectPlanAdapter.to_params(plan, attributes) + with {:ok, %Project{} = project} <- get_project(project_id) |> ProjectCanEnableDonations.validate, + %{} = create_attributes <- get_create_attributes(), + connect_account_id <- project.organization.stripe_connect_account.id_from_stripe, + {:ok, plan} <- @api.Plan.create(create_attributes, connect_account: connect_account_id), + {:ok, params} <- StripeConnectPlanAdapter.to_params(plan, attributes) do %StripeConnectPlan{} |> StripeConnectPlan.create_changeset(params) |> Repo.insert else - %Project{donation_goals: []} -> {:error, :donation_goals_not_found} + {:error, :project_not_ready} -> {:error, :project_not_ready} {:error, error} -> {:error, error} nil -> {:error, :not_found} end @@ -39,7 +33,7 @@ defmodule CodeCorps.StripeService.StripeConnectPlanService do } end - defp get_records(project_id) do + defp get_project(project_id) do Project |> Repo.get(project_id) |> Repo.preload([:donation_goals, {:organization, :stripe_connect_account}]) diff --git a/lib/code_corps/stripe_service/validators/project_can_enable_donations.ex b/lib/code_corps/stripe_service/validators/project_can_enable_donations.ex new file mode 100644 index 000000000..2ba7e0523 --- /dev/null +++ b/lib/code_corps/stripe_service/validators/project_can_enable_donations.ex @@ -0,0 +1,32 @@ +defmodule CodeCorps.StripeService.Validators.ProjectCanEnableDonations do + @moduledoc """ + Ensures a `CodeCorps.Project` is able to receive subscriptions. + """ + + alias CodeCorps.{Organization, Project, StripeConnectAccount} + + @doc """ + Determines if the provided `CodeCorps.Project` can enable donations. + + For a project to be able to enable donations, + it needs to have proper associations set up. + + These are: + + * At least one `CodeCorps.DonationGoal` + * `Organization` with a `StripeConnectAccount`, which has `charges_enabled: true` + + If the project has these relationships set up, it returns `{:ok, project}` + + In any other case, it returns {:error, :project_not_ready} + """ + def validate(%Project{} = project), do: do_validate(project) + + @invalid {:error, :project_not_ready} + + defp do_validate(%Project{ + donation_goals: [_h | _t], + organization: %Organization{stripe_connect_account: %StripeConnectAccount{charges_enabled: true}} + } = project), do: {:ok, project} + defp do_validate(_), do: @invalid +end diff --git a/test/controllers/stripe_connect_plan_controller_test.exs b/test/controllers/stripe_connect_plan_controller_test.exs index 7a8fee276..61e8a7d76 100644 --- a/test/controllers/stripe_connect_plan_controller_test.exs +++ b/test/controllers/stripe_connect_plan_controller_test.exs @@ -36,10 +36,10 @@ defmodule CodeCorps.StripeConnectPlanControllerTest do describe "create" do @tag :authenticated - test "creates and renders resource user is authenticated and authorized", %{conn: conn, current_user: current_user} do + test "creates and renders resource when user is authenticated and authorized", %{conn: conn, current_user: current_user} do organization = insert(:organization) insert(:organization_membership, role: "owner", member: current_user, organization: organization) - insert(:stripe_connect_account, organization: organization) + insert(:stripe_connect_account, organization: organization, charges_enabled: true) project = insert(:project, organization: organization) insert(:donation_goal, project: project) @@ -65,7 +65,7 @@ defmodule CodeCorps.StripeConnectPlanControllerTest do insert(:organization_membership, role: "owner", member: current_user, organization: organization) insert(:stripe_connect_account, organization: organization) project = insert(:project, organization: organization) - + assert conn |> request_create(%{project: project}) |> json_response(422) end end diff --git a/web/controllers/stripe_connect_plan_controller.ex b/web/controllers/stripe_connect_plan_controller.ex index 4e8333960..7487bc852 100644 --- a/web/controllers/stripe_connect_plan_controller.ex +++ b/web/controllers/stripe_connect_plan_controller.ex @@ -18,7 +18,7 @@ defmodule CodeCorps.StripeConnectPlanController do defp handle_create_result({:ok, %StripeConnectPlan{}} = result, conn) do result |> CodeCorps.Analytics.Segment.track(:created, conn) end - defp handle_create_result({:error, :donation_goals_not_found}, conn) do + defp handle_create_result({:error, :project_not_ready}, conn) do conn |> put_status(422) |> render(CodeCorps.ErrorView, "422.json-api")