lib/iso_20022/camt/053.ex

defmodule ISO20022.Camt053 do
  @moduledoc """
  Parse ISO 20022 **camt.053** (Bank to Customer Statement) messages.

  Supports schema versions 001.02 through 001.14. The output is always the same
  struct tree regardless of input version.

  ## Quick start

      xml = File.read!("statement.xml")

      case ISO20022.Camt053.parse(xml) do
        {:ok, doc} ->
          Enum.each(doc.statements, fn stmt ->
            IO.puts("Account: \#{stmt.account.iban}")
            closing = Enum.find(stmt.balances, &(&1.type == :closing_booked))
            IO.puts("Closing balance: \#{closing.amount} \#{closing.currency}")
          end)

        {:error, reason} ->
          IO.inspect(reason, label: "parse error")
      end

  ## Return values

  - `{:ok, %ISO20022.Camt053.Document{}}` on success
  - `{:error, {:parse_error, reason}}` — malformed XML
  - `{:error, {:unsupported_version, namespace}}` — namespace not recognised as camt.053
  - `{:error, {:missing_required_field, path}}` — mandatory element absent
  - `{:error, {:invalid_amount | :invalid_date | :invalid_datetime, value, path}}` — bad value

  ## Struct hierarchy

  ```
  Document
  ├── group_header: GroupHeader
  └── statements: [Statement]
      ├── account: Account
      ├── balances: [Balance]
      └── entries: [Entry]
          └── details: [EntryDetails]
              └── transaction_details: [TransactionDetails]
  ```
  """

  alias ISO20022.Camt053.{Document, Parser}

  @doc """
  Parses a camt.053 XML document from a binary string.

  Returns `{:ok, %Document{}}` on success, or `{:error, reason}` on failure.
  """
  @spec parse(binary()) :: {:ok, Document.t()} | {:error, term()}
  def parse(xml) when is_binary(xml) do
    Parser.parse(xml)
  end

  @doc """
  Like `parse/1` but raises `ISO20022.ParseError` on failure.
  """
  @spec parse!(binary()) :: Document.t()
  def parse!(xml) when is_binary(xml) do
    case Parser.parse(xml) do
      {:ok, doc} -> doc
      {:error, reason} -> raise ISO20022.ParseError, reason: reason
    end
  end
end