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