Metadata-Version: 2.4
Name: camt053-loader-mt940
Version: 0.0.8
Summary: Convert legacy SWIFT MT940 bank statements to camt.053 ParsedDocument.
Project-URL: Homepage, https://github.com/sebastienrousseau/camt053-loader-mt940
Project-URL: Documentation, https://github.com/sebastienrousseau/camt053-loader-mt940#readme
Project-URL: Repository, https://github.com/sebastienrousseau/camt053-loader-mt940
Project-URL: Issues, https://github.com/sebastienrousseau/camt053-loader-mt940/issues
Project-URL: Parent project, https://github.com/sebastienrousseau/camt053
Author-email: Sebastien Rousseau <sebastian.rousseau@gmail.com>
License-Expression: Apache-2.0
License-File: LICENSE
Keywords: bank-statements,camt053,fintech,iso20022,loader,mt940,swift
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Financial and Insurance Industry
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Office/Business :: Financial
Requires-Python: >=3.10
Requires-Dist: camt053<1,>=0.0.6
Provides-Extra: dev
Requires-Dist: interrogate>=1.7; extra == 'dev'
Requires-Dist: mypy>=1.11; extra == 'dev'
Requires-Dist: pytest-cov>=5; extra == 'dev'
Requires-Dist: pytest>=8; extra == 'dev'
Requires-Dist: ruff>=0.6; extra == 'dev'
Description-Content-Type: text/markdown

# camt053-loader-mt940: MT940 → camt.053 loader

<p align="center">
  <img src="https://cloudcdn.pro/camt053/v1/logos/camt053.svg" alt="camt053-loader-mt940 logo" width="128" />
</p>

[![PyPI Version][pypi-badge]][07]
[![Python Versions][python-versions-badge]][07]
[![License][license-badge]][01]
[![Tests][tests-badge]][tests-url]
[![Quality][quality-badge]][quality-url]

**Convert legacy SWIFT MT940 bank statements into the same
[`camt053`][core] data model as native camt.053 input.** A single
`parse_mt940(text)` call returns a `camt053.models.ParsedDocument`,
ready for every downstream consumer in the suite (writer, validator,
reversal builder, MCP and LSP servers).

> **Latest release: v0.0.1.** SWIFT MT940 is scheduled for retirement
> in **November 2028**. This loader bridges the 2-year window where
> banks still produce MT940 but downstream tooling expects camt.053.

## Contents

- [Overview](#overview)
- [Install](#install)
- [Quick Start](#quick-start)
- [Supported Fields](#supported-fields)
- [Examples](#examples)
- [The camt053 suite](#the-camt053-suite)
- [When not to use camt053-loader-mt940](#when-not-to-use-camt053-loader-mt940)
- [Development](#development)
- [Security](#security)
- [Documentation](#documentation)
- [License](#license)
- [Contributing](#contributing)
- [Acknowledgements](#acknowledgements)

## Overview

`camt053-loader-mt940` is a small, focused companion to the
[`camt053`][core] ISO 20022 cash-management library. It does one thing
well: parse the common-denominator MT940 grammar shipped by EU and UK
commercial banks, and hand back the same `ParsedDocument` shape that
the camt.053 XML parser produces. The rest of the suite then works
unchanged.

This package is part of the **camt053 suite**, a set of independently
installable packages that share the `camt053.services` layer:

- [`camt053`][core] - the core library (CLI + REST API)
- [`camt053-mcp`][mcp] - the **Model Context Protocol** server for AI agents
- [`camt053-lsp`][lsp] - the **Language Server Protocol** server for editors
- [`camt053-writer-xlsx`][writer] - Excel `.xlsx` writer for parsed statements
- `camt053-loader-mt940` - this package, the MT940 loader

## Install

`camt053-loader-mt940` runs on macOS, Linux, and Windows and requires
**Python 3.10+** and **pip**. It pulls in `camt053` automatically and
has no other runtime dependencies.

```bash
pip install camt053-loader-mt940
```

## Quick Start

```python
from camt053_loader_mt940 import parse_mt940

mt940 = """:20:STMT-REF-1
:25:COBADEFFXXX/DE89370400440532013000
:28C:42/1
:60F:C260620EUR1000,00
:61:2606210621CR500,00NMSCREF1//CREF1
:86:Customer payment for invoice 123
:62F:C260621EUR1500,00
"""

document = parse_mt940(mt940)

print(document.msg_id)
# STMT-REF-1
print(document.statements[0].account.iban)
# DE89370400440532013000
print(document.statements[0].balances[0].amount)
# 1000.00
```

That's a `camt053.models.ParsedDocument`, ready to feed to
[`camt053-writer-xlsx`][writer] (Excel output), the camt053 REST API,
or any other consumer in the suite.

## Supported Fields

| Tag | Meaning | Mapped to |
| :--- | :--- | :--- |
| `:20:` | Transaction reference number | `ParsedDocument.msg_id` |
| `:25:` | Account identification (`BIC/account` or `account`) | `Statement.account` (IBAN or proprietary `other_id` + optional `servicer_bic`) |
| `:28C:` | Statement / sequence number | `Statement.id` + `Statement.electronic_seq_nb` |
| `:60F:` / `:60M:` | Opening balance (Final / intermediary) | `Balance` with `type_code="OPBD"` |
| `:61:` | Statement line (booked entry) | `Entry` with `amount`, `credit_debit_indicator`, `value_date`, `booking_date`, `reference`, `account_servicer_ref` |
| `:86:` | Information to account owner | `TransactionDetails.additional_info` attached to the preceding entry |
| `:62F:` / `:62M:` | Closing balance | `Balance` with `type_code="CLBD"` |
| `:64:` | Closing available balance | `Balance` with `type_code="CLAV"` |
| `:65:` | Forward available balance | `Balance` with `type_code="FWAV"` |

### Reversal detection

A `:61:` line whose debit/credit indicator is **`RD`** (reversal of
debit) or **`RC`** (reversal of credit) becomes an `Entry` with
`reversal_indicator=True`. Direct support for SEPA / NACHA / CBPR+
return-reason mapping is on the v0.0.2 roadmap.

### Unknown fields

Unrecognised tags (e.g. `:13D:` creation timestamp, bank-specific
extensions) are **silently ignored**, so future SWIFT additions do
not break parsing. This follows Postel's law: be liberal in what you
accept.

## Examples

Two runnable examples live in `examples/`:

- [`01_minimal_parse.py`](examples/01_minimal_parse.py) - the
  smallest valid MT940 + parse + inspect.
- [`02_round_trip_to_xlsx.py`](examples/02_round_trip_to_xlsx.py) -
  MT940 in, Excel `.xlsx` out (requires `camt053-writer-xlsx`).

Both are exercised in CI on every commit.

## The camt053 suite

`camt053-loader-mt940` is part of a set of independently installable
packages built around the [`camt053`][core] library — pick whichever
ones your stack needs:

| Package | Role |
| :--- | :--- |
| [`camt053`](https://pypi.org/project/camt053/) | Core library + CLI + FastAPI REST API |
| [`camt053-mcp`](https://pypi.org/project/camt053-mcp/) | Model Context Protocol server (for AI agents) |
| [`camt053-lsp`](https://pypi.org/project/camt053-lsp/) | Language Server Protocol server (for editors) |
| [`camt053-writer-xlsx`](https://pypi.org/project/camt053-writer-xlsx/) | Excel `.xlsx` writer for parsed statements |
| [`camt053-loader-mt940`](https://pypi.org/project/camt053-loader-mt940/) | **SWIFT MT940 → camt.053 loader (this package)** |

```mermaid
flowchart LR
    A["MT940 text"] -->|parse_mt940| B["camt053-loader-mt940"]
    B -->|ParsedDocument| C["camt053"]
    C -->|writer / validator / reversal / MCP / LSP| D["Downstream consumers"]
```

## When not to use camt053-loader-mt940

- **You already have native camt.053 input.** Use the camt053 core
  parser directly — this loader is the bridge for legacy MT940-only
  data sources, not an alternative for native camt.05x.
- **You need MT941 / MT942** (intraday-balance / intermediate-statement
  messages). Out of scope today; the data model supports adding them
  if you'd like to contribute a separate loader.
- **You need bank-specific `:86:` sub-field parsing** (e.g. Deutsche
  Bank's `?20` / `?30` / `?32` GVC codes). The raw `:86:` value is
  preserved verbatim in `TransactionDetails.additional_info`;
  downstream tooling can parse it if needed.
- **You need direct ISO return-reason mapping for `RD` / `RC`** lines.
  Currently `reversal_indicator=True` is set; mapping to ISO
  `ExternalReturnReasonCode` is on the v0.0.2 roadmap.
- **Your MT940 is PGP / GPG encrypted.** Decrypt upstream and pass
  the plaintext to the loader.

## Development

```bash
git clone https://github.com/sebastienrousseau/camt053-loader-mt940
cd camt053-loader-mt940
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
pytest                          # 100% line + branch coverage gate
interrogate camt053_loader_mt940  # 100% docstring gate
mypy camt053_loader_mt940       # strict
```

## Security

`camt053-loader-mt940` parses a flat text format with no XML envelope
— the XXE / billion-laughs surface lives upstream in the `camt053`
core (defusedxml + xml_guard). Field regexes are anchored and
bounded, so catastrophic backtracking is not a concern. Reporting
practice, supported versions, and supply-chain posture (PyPI Trusted
Publishing, sigstore attestations, signed tags) are documented in
[`SECURITY.md`](SECURITY.md). Vulnerabilities go via GitHub Private
Vulnerability Reporting, not public issues.

## Documentation

- [`README.md`](README.md) — this file
- [`CHANGELOG.md`](CHANGELOG.md) — release notes
- [`SECURITY.md`](SECURITY.md) — disclosure + supported versions
- [`SUPPORT.md`](SUPPORT.md) — how to get help
- [`MAINTAINERS.md`](MAINTAINERS.md) — who can merge
- [`examples/`](examples/) — runnable scripts, exercised in CI

## License

Licensed under the [Apache License, Version 2.0][01]. Any contribution
submitted for inclusion shall be licensed as above, without additional
terms.

## Contributing

Contributions are welcome. Open an issue or PR on
[the repository](https://github.com/sebastienrousseau/camt053-loader-mt940).

## Acknowledgements

Built on the [`camt053`][core] ISO 20022 Bank Statement library. The
MT940 grammar follows the SWIFT User Handbook MT940 specification and
the common-denominator subset shipped by major EU and UK commercial
banks.

[01]: https://opensource.org/license/apache-2-0/
[07]: https://pypi.org/project/camt053-loader-mt940/
[core]: https://github.com/sebastienrousseau/camt053
[mcp]: https://github.com/sebastienrousseau/camt053-mcp
[lsp]: https://github.com/sebastienrousseau/camt053-lsp
[writer]: https://github.com/sebastienrousseau/camt053-writer-xlsx
[pypi-badge]: https://img.shields.io/pypi/v/camt053-loader-mt940.svg?style=for-the-badge
[python-versions-badge]: https://img.shields.io/pypi/pyversions/camt053-loader-mt940.svg?style=for-the-badge
[license-badge]: https://img.shields.io/badge/License-Apache%202.0-blue.svg?style=for-the-badge
[tests-badge]: https://img.shields.io/github/actions/workflow/status/sebastienrousseau/camt053-loader-mt940/ci.yml?branch=main&label=Tests&style=for-the-badge
[tests-url]: https://github.com/sebastienrousseau/camt053-loader-mt940/actions/workflows/ci.yml
[quality-badge]: https://img.shields.io/badge/Coverage-100%25-brightgreen?style=for-the-badge
[quality-url]: https://github.com/sebastienrousseau/camt053-loader-mt940/actions/workflows/ci.yml
