Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 95 additions & 0 deletions lib/code_corps/stripe_service/adapters/stripe_connect_account.ex
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ defmodule CodeCorps.StripeService.Adapters.StripeConnectAccountAdapter do
]

def to_params(%Stripe.Account{} = stripe_account, %{} = attributes) do

result =
stripe_account
|> Map.from_struct
Expand All @@ -18,6 +19,100 @@ defmodule CodeCorps.StripeService.Adapters.StripeConnectAccountAdapter do
{:ok, result}
end

def to_managed_params(%Stripe.Account{} = stripe_account, %{} = attributes) do
params = %{
email: stripe_account.email,
managed: stripe_account.managed,
# TODO: A stripe response will not return the business_ein. instead,
# it will return business_tax_id_provided, which is a boolean. we should probably store that,
# not this
business_ein: attributes |> Map.get("business_ein"),
business_name: stripe_account.legal_entity.business_name, # or stripe_account.business_name

# as far as I can tell, stripe does not store this. might wanna remove it from the whole process.
# added it due to looking at kickstarter form
business_type: attributes |> Map.get("business_type"),

first_name: stripe_account.legal_entity.first_name,
last_name: stripe_account.legal_entity.last_name,
# TODO: A stripe response will not return the ssn_last4. instead,
# it will return ssn_last4_provided, which is a boolean. we should probably store that,
# not this
ssn_last4: attributes |> Map.get("ssn_last4"),
recipient_type: stripe_account.legal_entity.type,

# TODO: decide on getting legal_entity.address or legal_entity.personal_address
address1: stripe_account.legal_entity.address.line1,
address2: stripe_account.legal_entity.address.line2,
city: stripe_account.legal_entity.address.city,
country: stripe_account.legal_entity.address.country,
state: stripe_account.legal_entity.address.state,
# we maybe wanna rename this one
zip: stripe_account.legal_entity.address.postal_code,

dob_day: stripe_account.legal_entity.dob.day,
dob_month: stripe_account.legal_entity.dob.month,
dob_year: stripe_account.legal_entity.dob.year,

id_from_stripe: stripe_account.id,
charges_enabled: stripe_account.charges_enabled,
transfers_enabled: stripe_account.transfers_enabled,

organization_id: attributes |> Map.get("organization_id"),
}

IO.inspect(params)
{:ok, params}
end

def to_stripe_params(%{
"country" => country,
"email" => email
} = attributes) do
with legal_entity <- build_legal_entity(attributes)
do
params = %{ country: country, email: email, managed: true, legal_entity: legal_entity}
{:ok, params}
end
end
def to_stripe_managed_params(attributes) do
{:error, :fields_missing}
end

defp build_legal_entity(%{
"business_ein" => business_ein, "business_name" => business_name, "business_type" => _,
"first_name" => first_name, "last_name" => last_name, "ssn_last4" => ssn_last4,
"recipient_type" => recipient_type
} = attributes) do
with address <- build_address(attributes),
dob <- build_dob(attributes)
do
%{
business_name: business_name,
business_tax_id: business_ein,
dob: dob,
first_name: first_name,
last_name: last_name,
ssn_last_4: ssn_last4,
type: recipient_type,
# TODO: Decide which address to set
address: address,
personal_address: address
}
end
end

defp build_dob(%{"dob_day" => dob_day, "dob_month" => dob_month, "dob_year" => dob_year}) do
%{day: dob_day, month: dob_month, year: dob_year}
end

defp build_address(%{
"address1" => address1, "address2" => address2, "city" => city,
"country" => country, "state" => state,"zip" => zip
}) do
%{city: city, country: country, line1: address1, line2: address2, postal_code: zip, state: state}
end

@non_stripe_attributes ["organization_id"]

defp add_non_stripe_attributes(%{} = params, %{} = attributes) do
Expand Down
10 changes: 5 additions & 5 deletions lib/code_corps/stripe_service/stripe_connect_account.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ defmodule CodeCorps.StripeService.StripeConnectAccountService do

@api Application.get_env(:code_corps, :stripe)

def create(%{"access_code" => code, "organization_id" => _organization_id} = attributes) do
with {:ok, %TokenResponse{stripe_user_id: account_id}} <- @api.Connect.OAuth.token(code),
{:ok, account} <- @api.Account.retrieve(account_id),
{:ok, params} <- StripeConnectAccountAdapter.to_params(account, attributes)
def create(%{} = attributes) do
with {:ok, stripe_params} <- StripeConnectAccountAdapter.to_stripe_params(attributes),
{:ok, %Stripe.Account{} = stripe_account} <- @api.Account.create(stripe_params),
{:ok, params} <- StripeConnectAccountAdapter.to_managed_params(stripe_account, attributes)
do
%CodeCorps.StripeConnectAccount{}
|> CodeCorps.StripeConnectAccount.create_changeset(params)
|> CodeCorps.StripeConnectAccount.managed_create_changeset(params)
|> CodeCorps.Repo.insert
end
end
Expand Down
1 change: 1 addition & 0 deletions mix.lock
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.1", "28a4d65b7f59893bc2c7de786dec1e1555bd742d336043fe644ae956c3497fbe", [:make, :rebar], []},
"stripe_eventex": {:hex, :stripe_eventex, "1.0.0", "782016598b751c0fdb5489038c92c30a5aab034636d0d9d3a486f75a01fbf0b6", [:mix], [{:cowboy, "~> 1.0.0", [hex: :cowboy, optional: false]}, {:plug, "~> 1.0", [hex: :plug, optional: false]}, {:poison, "~> 2.0", [hex: :poison, optional: false]}]},
"stripity_stripe": {:hex, :stripity_stripe, "2.0.0-alpha.5", "ba6d4ffc6251029135c76e9c6e2dd77580713f5c6833fb82da708336023bbfa2", [:mix], [{:hackney, "~> 1.6", [hex: :hackney, optional: false]}, {:poison, "~> 2.0 or ~> 3.0", [hex: :poison, optional: false]}]},
"timber": {:hex, :timber, "0.4.7", "df3fcd79bcb4eb4b53874d906ef5f3a212937b4bc7b7c5b244745202cc389443", [:mix], [{:ecto, "~> 2.0", [hex: :ecto, optional: true]}, {:phoenix, "~> 1.2", [hex: :phoenix, optional: true]}, {:plug, "~> 1.2", [hex: :plug, optional: true]}, {:poison, "~> 2.0 or ~> 3.0", [hex: :poison, optional: false]}]},
"timex": {:hex, :timex, "3.1.5", "413d6d8d6f0162a5d47080cb8ca520d790184ac43e097c95191c7563bf25b428", [:mix], [{:combine, "~> 0.7", [hex: :combine, optional: false]}, {:gettext, "~> 0.10", [hex: :gettext, optional: false]}, {:tzdata, "~> 0.1.8 or ~> 0.5", [hex: :tzdata, optional: false]}]},
"timex_ecto": {:hex, :timex_ecto, "3.0.5", "3ec6c25e10d2c0020958e5df64d2b5e690e441faa2c2259da8bc6bd3d7f39256", [:mix], [{:ecto, "~> 2.0", [hex: :ecto, optional: false]}, {:timex, "~> 3.0", [hex: :timex, optional: false]}]},
"tzdata": {:hex, :tzdata, "0.5.9", "575be217b039057a47e133b72838cbe104fb5329b19906ea4e66857001c37edb", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, optional: false]}]},
Expand Down
31 changes: 31 additions & 0 deletions priv/repo/managed_account_spike.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
alias CodeCorps.Repo
alias CodeCorps.Organization
alias CodeCorps.Project
alias CodeCorps.User
alias CodeCorps.OrganizationMembership

{:ok, owner } =
%User{}
|> User.registration_changeset(%{username: "owner", email: "owner@managed.org", password: "password"})
|> Repo.insert

{:ok, organization } =
%Organization{}
|> Organization.create_changeset(%{name: "Managed", description: "A managed organization"})
|> Repo.insert

{:ok, _} =
%OrganizationMembership{member_id: owner.id, organization_id: organization.id, role: "owner"}
|> Repo.insert

{:ok, _project} =
%Project{}
|> Project.create_changeset(%{title: "Managed project", description: "A project created for a managed organization", organization_id: organization.id})
|> Repo.insert

{:ok, _donor} =
%User{}
|> User.registration_changeset(%{username: "donor", email: "donor@test.org", password: "password"})
|> Repo.insert


53 changes: 46 additions & 7 deletions web/models/stripe_connect_account.ex
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,67 @@ defmodule CodeCorps.StripeConnectAccount do
use CodeCorps.Web, :model

schema "stripe_connect_accounts" do
field :business_name, :string
# these might not be needed by managed accounts,
# but we have them defined at DB level

field :business_url, :string
field :charges_enabled, :boolean
field :country, :string
field :default_currency, :string
field :details_submitted, :boolean
field :display_name, :string
field :email, :string
field :id_from_stripe, :string, null: false
field :managed, :boolean
field :support_email, :string
field :support_phone, :string
field :support_url, :string
field :transfers_enabled, :boolean

# this was needed for connect
field :access_code, :string, virtual: true

# these fields are filled out and sent by the client

field :address1, :string, virtual: true
field :address2, :string, virtual: true
field :business_ein, :string, virtual: true
field :business_name, :string
field :business_type, :string, virtual: true
field :city, :string, virtual: true
field :country, :string
field :dob_day, :integer, virtual: true
field :dob_month, :integer, virtual: true
field :dob_year, :integer, virtual: true
field :email, :string
field :first_name, :string, virtual: true
field :last_name, :string, virtual: true
field :recipient_type, :string, virtual: true
field :ssn_last4, :string, virtual: true
field :state, :string, virtual: true
field :zip, :string, virtual: true

belongs_to :organization, CodeCorps.Organization

# these fields are set automatically
field :managed, :boolean

# these fields are set from stripe
field :id_from_stripe, :string, null: false
field :charges_enabled, :boolean
field :transfers_enabled, :boolean
timestamps()
end

@managed_create_fields [
:address1, :address2, :business_ein, :business_name, :business_type,
:city, :country, :dob_day, :dob_month, :dob_year, :email,
:first_name, :last_name, :recipient_type, :ssn_last4,
:state, :zip, :organization_id,
:managed, :id_from_stripe, :charges_enabled, :transfers_enabled
]

def managed_create_changeset(struct, params) do
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't think we want distinction between create and managed_create. Also, create fields will be just country and managed, where the latter is always true.

struct
|> cast(params, @managed_create_fields)
|> validate_required(@managed_create_fields)
|> assoc_constraint(:organization)
end

@insert_params [
:business_name, :business_url, :charges_enabled, :country, :default_currency,
:details_submitted, :email, :id_from_stripe, :managed, :organization_id,
Expand Down