Current section
Files
Jump to
Current section
Files
lib/plaid/utils.ex
defmodule Plaid.Utils do
@moduledoc """
Utility functions.
"""
@type response :: %{required(String.t()) => any}
@type endpoint :: atom
@doc """
Handles Plaid response and maps to the correct data structure.
"""
@spec handle_resp({:ok, HTTPoison.Response.t()} | {:error, HTTPoison.Error.t()}, endpoint) ::
{:ok, any} | {:error, Plaid.Error.t() | HTTPoison.Error.t()}
def handle_resp({:ok, %HTTPoison.Response{status_code: code} = resp}, endpoint)
when code in 200..201 do
{:ok, map_response(resp.body, endpoint)}
end
def handle_resp({:ok, %HTTPoison.Response{} = resp}, _endpoint) do
{:error, Poison.Decode.decode(resp.body, as: %Plaid.Error{})}
end
def handle_resp({:error, %HTTPoison.Error{} = error}, _endpoint) do
{:error, error}
end
@doc """
Maps an endpoint's response to the corresponding internal data structure.
"""
@spec map_response(response, endpoint) :: any
def map_response(response, :categories) do
Poison.Decode.decode(response,
as: %Plaid.Categories{
categories: [
%Plaid.Categories.Category{}
]
}
)
end
def map_response(response, :income) do
Poison.Decode.decode(response,
as: %Plaid.Income{
item: %Plaid.Item{},
income: %Plaid.Income.Income{
income_streams: [
%Plaid.Income.Income.IncomeStream{}
]
}
}
)
end
def map_response(response, :institutions) do
Poison.Decode.decode(response,
as: %Plaid.Institutions{
institutions: [
%Plaid.Institutions.Institution{
credentials: [%Plaid.Institutions.Institution.Credentials{}]
}
]
}
)
end
def map_response(%{"institution" => institution} = response, :institution) do
new_response = response |> Map.take(["request_id"]) |> Map.merge(institution)
Poison.Decode.decode(new_response,
as: %Plaid.Institutions.Institution{
credentials: [%Plaid.Institutions.Institution.Credentials{}]
}
)
end
def map_response(response, :transactions) do
Poison.Decode.decode(response,
as: %Plaid.Transactions{
accounts: [
%Plaid.Accounts.Account{
balances: %Plaid.Accounts.Account.Balance{}
}
],
transactions: [
%Plaid.Transactions.Transaction{
location: %Plaid.Transactions.Transaction.Location{},
payment_meta: %Plaid.Transactions.Transaction.PaymentMeta{}
}
],
item: %Plaid.Item{}
}
)
end
def map_response(response, :accounts) do
Poison.Decode.decode(response,
as: %Plaid.Accounts{
accounts: [
%Plaid.Accounts.Account{balances: %Plaid.Accounts.Account.Balance{}}
],
item: %Plaid.Item{}
}
)
end
def map_response(response, :auth) do
Poison.Decode.decode(response,
as: %Plaid.Auth{
numbers: %Plaid.Auth.Numbers{
ach: [%Plaid.Auth.Numbers.ACH{}]
},
item: %Plaid.Item{},
accounts: [
%Plaid.Accounts.Account{
balances: %Plaid.Accounts.Account.Balance{}
}
]
}
)
end
def map_response(%{"item" => item} = response, :item) do
new_response = response |> Map.take(["request_id"]) |> Map.merge(item)
Poison.Decode.decode(new_response, as: %Plaid.Item{})
end
def map_response(%{"new_access_token" => _} = response, :item) do
response
|> Map.take(["new_access_token", "request_id"])
|> Enum.reduce(%{}, fn {k, v}, acc ->
Map.put(acc, String.to_atom(k), v)
end)
end
def map_response(%{"access_token" => _} = response, :item) do
response
|> Map.take(["access_token", "item_id", "request_id"])
|> Enum.reduce(%{}, fn {k, v}, acc ->
Map.put(acc, String.to_atom(k), v)
end)
end
def map_response(%{"public_token" => _} = response, :item) do
response
|> Map.take(["public_token", "expiration", "request_id"])
|> Enum.reduce(%{}, fn {k, v}, acc ->
Map.put(acc, String.to_atom(k), v)
end)
end
def map_response(%{"deleted" => _} = response, :item) do
response
|> Map.take(["deleted", "request_id"])
|> Enum.reduce(%{}, fn {k, v}, acc ->
Map.put(acc, String.to_atom(k), v)
end)
end
def map_response(%{"processor_token" => _} = response, :item) do
response
|> Map.take(["processor_token", "request_id"])
|> Enum.reduce(%{}, fn {k, v}, acc ->
Map.put(acc, String.to_atom(k), v)
end)
end
end