lib/requests/instruments/update_bank_account.ex

defmodule Requests.Instruments.UpdateBankAccount do
    @moduledoc false
  alias Customers.{
    AccountHolder,
    BillingAddress,
    Phone
  }

  alias Instruments.Bank

  @account_types ["savings", "current", "cash"]
  @derive Jason.Encoder

  @type account_holder :: %{
          first_name: String.t(),
          last_name: String.t(),
          billing_address: BillingAddress.t(),
          phone: Phone.t()
        }

  @type customer :: %{
          default: true | false,
          id: String.t()
        }

  @type t() :: %__MODULE__{
          id: String.t(),
          type: String.t(),
          account_type: String.t(),
          account_number: String.t(),
          bank_code: String.t(),
          branch_code: String.t(),
          iban: String.t(),
          bban: String.t(),
          swift_bic: String.t(),
          currency: <<_::3>>,
          country: <<_::2>>,
          processing_channel_id: String.t(),
          account_holder: AccountHolder.t(),
          bank: Bank.t(),
          customer: customer()
        }

  defstruct [
    :id,
    :type,
    :account_type,
    :account_number,
    :bank_code,
    :branch_code,
    :iban,
    :bban,
    :swift_bic,
    :currency,
    :country,
    :processing_channel_id,
    :account_holder,
    :bank,
    :customer
  ]

  def build(%{id: id} = params) when is_binary(id) and id != "" do
    case verify_account_type(params[:account_type]) do
      true ->
        %__MODULE__{
          id: id,
          type: params[:type],
          account_type: params[:account_type],
          account_number: params[:account_number],
          bank_code: params[:bank_code],
          branch_code: params[:branch_code],
          iban: params[:iban],
          bban: params[:bban],
          swift_bic: params[:swift_bic],
          currency: params[:currency],
          country: params[:country],
          processing_channel_id: params[:processing_channel_id],
          account_holder: AccountHolder.build(params[:account_holder]),
          bank: Bank.build(params[:bank]),
          customer: build_customer(params[:customer])
        }

      _ ->
        {:error, "Bank account type must be one of: #{Enum.join(@account_types, ", ")}"}
    end
  end

  def build(params) when is_map(params), do: {:error, "Bank account must have an id"}

  def build(_), do: {:error, "params must be a map"}

  defp build_customer(params) when is_map(params) do
    %{
      default: params[:default],
      id: params[:id]
    }
  end

  defp build_customer(_), do: nil

  defp verify_account_type(type) when type in @account_types, do: true

  defp verify_account_type(_), do: false
end