lib/requests/payments/sources/bank_account.ex

defmodule Requests.Payments.Sources.BankAccount do
  alias Customers.AccountHolder

  @type t :: %__MODULE__{
          type: String.t(),
          payment_method: String.t(),
          account_type: String.t(),
          country: <<_::2>>,
          account_number: String.t(),
          bank_code: String.t(),
          account_holder: AccountHolder.t()
        }

  @enforce_keys [
    :type,
    :payment_method,
    :account_type,
    :country,
    :account_number,
    :bank_code,
    :account_holder
  ]
  defstruct [
    :type,
    :payment_method,
    :account_type,
    :country,
    :account_number,
    :bank_code,
    :account_holder
  ]

  def build(raw_params) when is_map(raw_params) do
    params = Enum.into(raw_params, %{}, fn {key, value} -> {convert(key), value} end)

    %{
      type: params[:type],
      payment_method: params[:payment_method],
      account_type: params[:account_type],
      country: params[:country],
      account_number: params[:account_number],
      bank_code: params[:bank_code],
      account_holder: AccountHolder.build(params[:account_holder])
    }
  end

  def build(_), do: nil

  defp convert(key) when is_binary(key), do: String.to_existing_atom(key)

  defp convert(key) when is_atom(key), do: key
end