lib/iso_20022/camt/053/balance.ex

defmodule ISO20022.Camt053.Balance do
  @moduledoc """
  A balance entry from `<Bal>`.

  ## Balance types

  | Atom | ISO code | Description |
  |------|----------|-------------|
  | `:opening_booked` | `OPBD` | Opening booked balance (mandatory) |
  | `:closing_booked` | `CLBD` | Closing booked balance (mandatory) |
  | `:closing_available` | `CLAV` | Closing available balance |
  | `:interim_booked` | `ITBD` | Interim booked balance |
  | `:interim_available` | `ITAV` | Interim available balance |
  | `:forward_available` | `FWAV` | Forward available balance |
  | `{:other, code}` | any | Unrecognised type code |

  `amount` is always a positive `Decimal`. The sign of the balance is expressed via
  `credit_debit`: `:credit` for a positive/credit balance, `:debit` for an
  overdraft/negative balance.
  """

  @type balance_type ::
          :opening_booked
          | :closing_booked
          | :closing_available
          | :interim_booked
          | :interim_available
          | :forward_available
          | {:other, String.t()}

  @type credit_debit :: :credit | :debit

  @type t :: %__MODULE__{
          type: balance_type(),
          amount: Decimal.t(),
          currency: String.t(),
          credit_debit: credit_debit(),
          date: Date.t()
        }

  defstruct [:type, :amount, :currency, :credit_debit, :date]

  @doc """
  Parses an ISO 20022 balance type code string into an atom.
  """
  @spec parse_type(String.t()) :: balance_type()
  def parse_type("OPBD"), do: :opening_booked
  def parse_type("CLBD"), do: :closing_booked
  def parse_type("CLAV"), do: :closing_available
  def parse_type("ITBD"), do: :interim_booked
  def parse_type("ITAV"), do: :interim_available
  def parse_type("FWAV"), do: :forward_available
  def parse_type(code), do: {:other, code}
end