defmodule Braintree.Customer do
@moduledoc """
You can create a customer by itself, with a payment method, or with a
credit card with a billing address.
For additional reference see:
https://developers.braintreepayments.com/reference/request/customer/create/ruby
"""
use Braintree.Construction
alias Braintree.{AndroidPayCard, ApplePayCard, CreditCard, HTTP, PaypalAccount, Search}
alias Braintree.ErrorResponse, as: Error
@type t :: %__MODULE__{
id: String.t(),
company: String.t(),
email: String.t(),
fax: String.t(),
first_name: String.t(),
last_name: String.t(),
phone: String.t(),
website: String.t(),
created_at: String.t(),
updated_at: String.t(),
custom_fields: map,
addresses: [map],
android_pay_cards: [AndroidPayCard.t()],
apple_pay_cards: [ApplePayCard.t()],
credit_cards: [CreditCard.t()],
paypal_accounts: [PaypalAccount.t()],
coinbase_accounts: [map]
}
defstruct id: nil,
company: nil,
email: nil,
fax: nil,
first_name: nil,
last_name: nil,
phone: nil,
website: nil,
created_at: nil,
updated_at: nil,
custom_fields: %{},
addresses: [],
android_pay_cards: [],
apple_pay_cards: [],
credit_cards: [],
coinbase_accounts: [],
paypal_accounts: []
@doc """
Create a customer record, or return an error response with after failed
validation.
## Example
{:ok, customer} = Braintree.Customer.create(%{
first_name: "Jen",
last_name: "Smith",
company: "Braintree",
email: "jen@example.com",
phone: "312.555.1234",
fax: "614.555.5678",
website: "www.example.com"
})
customer.company # Braintree
"""
@spec create(map, Keyword.t()) :: {:ok, t} | {:error, Error.t()}
def create(params \\ %{}, opts \\ []) do
with {:ok, payload} <- HTTP.post("customers", %{customer: params}, opts) do
{:ok, new(payload)}
end
end
@doc """
You can delete a customer using its ID. When a customer is deleted, all
associated payment methods are also deleted, and all associated recurring
billing subscriptions are canceled.
## Example
:ok = Braintree.Customer.delete("customer_id")
"""
@spec delete(binary, Keyword.t()) :: :ok | {:error, Error.t()}
def delete(id, opts \\ []) when is_binary(id) do
with {:ok, _response} <- HTTP.delete("customers/" <> id, opts) do
:ok
end
end
@doc """
If you want to look up a single customer using its ID, use the find method.
## Example
customer = Braintree.Customer.find("customer_id")
"""
@spec find(binary, Keyword.t()) :: {:ok, t} | {:error, Error.t()}
def find(id, opts \\ []) when is_binary(id) do
with {:ok, payload} <- HTTP.get("customers/" <> id, opts) do
{:ok, new(payload)}
end
end
@doc """
To update a customer, use its ID along with new attributes. The same
validations apply as when creating a customer. Any attribute not passed will
remain unchanged.
## Example
{:ok, customer} = Braintree.Customer.update("customer_id", %{
company: "New Company Name"
})
customer.company # "New Company Name"
"""
@spec update(binary, map, Keyword.t()) :: {:ok, t} | {:error, Error.t()}
def update(id, params, opts \\ []) when is_binary(id) and is_map(params) do
with {:ok, payload} <- HTTP.put("customers/" <> id, %{customer: params}, opts) do
{:ok, new(payload)}
end
end
@doc """
To search for customers, pass a map of search parameters.
## Example:
{:ok, customers} = Braintree.Customer.search(%{first_name: %{is: "Jenna"}})
"""
@spec search(map, Keyword.t()) :: {:ok, t} | {:error, Error.t()}
def search(params, opts \\ []) when is_map(params) do
Search.perform(params, "customers", &new/1, opts)
end
@doc """
Convert a map into a Company struct along with nested payment options. Credit
cards and paypal accounts are converted to a list of structs as well.
## Example
customer = Braintree.Customer.new(%{"company" => "Soren",
"email" => "parker@example.com"})
"""
def new(%{"customer" => map}) do
new(map)
end
def new(map) when is_map(map) do
customer = super(map)
%{
customer
| android_pay_cards: AndroidPayCard.new(customer.android_pay_cards),
apple_pay_cards: ApplePayCard.new(customer.apple_pay_cards),
credit_cards: CreditCard.new(customer.credit_cards),
paypal_accounts: PaypalAccount.new(customer.paypal_accounts)
}
end
def new(list) when is_list(list) do
Enum.map(list, &new/1)
end
end