Metadata-Version: 2.4
Name: okane
Version: 0.3.0
Summary: Parser for bank statements in camt.053 XML format (Czech Banking Association dialect)
Project-URL: Homepage, https://github.com/tkarabela/okane
Project-URL: Repository, https://github.com/tkarabela/okane
Project-URL: Bug Tracker, https://github.com/tkarabela/okane/issues
Author-email: Tomas Karabela <tkarabela@seznam.cz>
License: Copyright (c) 2023-2026 Tomas Karabela
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in
        all copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
        THE SOFTWARE.
License-File: LICENSE.txt
Keywords: banking,camt053,czech,expenses,finance,sepa
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Financial and Insurance Industry
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: File Formats
Classifier: Topic :: Office/Business :: Financial :: Accounting
Classifier: Typing :: Typed
Requires-Python: >=3.12
Requires-Dist: lxml>=5.0
Requires-Dist: pydantic~=2.5
Provides-Extra: pandas
Requires-Dist: openpyxl~=3.1; extra == 'pandas'
Requires-Dist: pandas>=2.1; extra == 'pandas'
Description-Content-Type: text/markdown

[![CI - build](https://img.shields.io/github/actions/workflow/status/tkarabela/okane/main.yml?branch=master)](https://github.com/tkarabela/okane/actions)
[![CI - coverage](https://img.shields.io/codecov/c/github/tkarabela/okane)](https://app.codecov.io/github/tkarabela/okane)
![MyPy checked](http://www.mypy-lang.org/static/mypy_badge.svg)
![PyPI - Version](https://img.shields.io/pypi/v/okane.svg?style=flat-square)
![PyPI - Status](https://img.shields.io/pypi/status/okane.svg?style=flat-square)
![PyPI - Python Version](https://img.shields.io/pypi/pyversions/okane.svg?style=flat-square)
![License](https://img.shields.io/pypi/l/okane.svg?style=flat-square)

# お<ruby>金<rt>かね</rt></ruby> 【okane】

_okane_ is a pure Python parser for bank statements in camt.053 XML format [[1]], in dialect
used by the Czech Banking Association (ČBA) [[2]].

It parses `BkToCstmrStmt` XML element into `okane.models.BankToCustomerStatement` which is
a Pydantic model. It can also work as a CLI tool, converting camt.053 XML files to JSON or CSV.

## Installation

```shell
pip install okane

# or, if you'd like to use the CSV, XLSX export features and access the data as `pd.DataFrame`
pip install okane[pandas]
```

## Example

### Python API

    >>> import okane
    >>> statement = okane.BankToCustomerStatement.from_file("./tests/data/test2.xml")
    >>> statement.opening_balance
    Balance(amount=Decimal('1000.00'), currency='CZK', date=datetime.date(2023, 3, 1))
    >>> statement.transactions[5].amount
    Decimal('1000.00')
    >>> statement.transactions[5].currency
    'CZK'
    >>> statement.transactions[5].related_account_id
    AccountId(iban='LT6632xxxxxx', id=None)
    >>> statement.transactions[5].related_account_bank_id
    BankId(bic='REVOLT21', id=None)
    >>> statement.transactions[3].ref
    TransactionRef(message_id='XXX', end_to_end_id='XXX', account_servicer_ref=None, payment_invocation_id=None, instruction_id=None, mandate_id=None, cheque_number=None, clearing_system_ref=None)
    >>> df = statement.as_dataframe()

### Command-line interface

```shell
head ./tests/data/test2.xml
```

```xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:camt.053.001.02">
    <BkToCstmrStmt>
        <GrpHdr>
            <MsgId>camt.053-2023-04-01-001</MsgId>
            <CreDtTm>2023-04-01T12:00:00.000+02:00</CreDtTm>
            <MsgRcpt>
                <Nm>John Doe</Nm>
```

```shell
# okane ./tests/data/test*.xml -f json --no-indent -o output.jsonl
# okane ./tests/data/test*.xml -f csv -o output.csv
# okane ./tests/data/test*.xml -f xlsx -o output.xlsx

okane ./tests/data/test2.xml
```

```json
{
    "statement_id": "XXX-STATEMENT-ID",
    "created_time": "2023-04-01T12:00:00+02:00",
    "from_time": "2023-03-01T00:00:00+01:00",
    "to_time": "2023-03-31T23:59:59.999000+02:00",
    "account_id": {
        "iban": "XXX-IBAN",
        "id": null
    },
    "opening_balance": {
        "amount": "1000.00",
        "currency": "CZK",
        "date": "2023-03-01"
    },
    "closing_balance": {
        "amount": "2000.00",
        "currency": "CZK",
        "date": "2023-03-31"
    },
    "transactions": [
        {
            "ref": {
                "message_id": "XXX",
                "end_to_end_id": "XXX",
                "account_servicer_ref": null,
                "payment_invocation_id": null,
                "instruction_id": null,
                "mandate_id": null,
                "cheque_number": null,
                "clearing_system_ref": null
            },
            "entry_ref": "XXX-REF-1",
            "amount": "-100.00",
            "currency": "CZK",
            "val_date": "2023-03-01",
            "remote_info": "Nákup dne 27.2.2023, částka 100.00 CZK",
            "additional_transaction_info": "Nákup dne 27.2.2023, částka 100.00 CZK",
            "related_account_id": null,
            "related_account_bank_id": null
        },
        {
            "ref": {
                "message_id": "XXX",
                "end_to_end_id": "XXX",
                "account_servicer_ref": null,
                "payment_invocation_id": null,
                "instruction_id": null,
                "mandate_id": null,
                "cheque_number": null,
                "clearing_system_ref": null
            },
            "entry_ref": "XXX-REF-2",
            "amount": "-200.00",
            "currency": "CZK",
            "val_date": "2023-03-02",
            "remote_info": null,
            "additional_transaction_info": "transaction note",
            "related_account_id": {
                "iban": null,
                "id": "XXX-OTHER-ACC"
            },
            "related_account_bank_id": {
                "bic": null,
                "id": "XXX-OTHER-BANK"
            }
        },
        {
            "ref": {
                "message_id": "XXX",
                "end_to_end_id": null,
                "account_servicer_ref": null,
                "payment_invocation_id": null,
                "instruction_id": null,
                "mandate_id": null,
                "cheque_number": null,
                "clearing_system_ref": null
            },
            "entry_ref": "XXX-REF-3",
            "amount": "1000.00",
            "currency": "CZK",
            "val_date": "2023-03-07",
            "remote_info": null,
            "additional_transaction_info": null,
            "related_account_id": {
                "iban": null,
                "id": "XXX-OTHER-ACC"
            },
            "related_account_bank_id": {
                "bic": null,
                "id": "XXX-OTHER-BANK"
            }
        },
        {
            "ref": {
                "message_id": "XXX",
                "end_to_end_id": "XXX",
                "account_servicer_ref": null,
                "payment_invocation_id": null,
                "instruction_id": null,
                "mandate_id": null,
                "cheque_number": null,
                "clearing_system_ref": null
            },
            "entry_ref": "XXX-REF-4",
            "amount": "400.00",
            "currency": "CZK",
            "val_date": "2023-03-08",
            "remote_info": "description",
            "additional_transaction_info": "RECIPIENT NAME",
            "related_account_id": {
                "iban": null,
                "id": "XXX-OTHER-ACC"
            },
            "related_account_bank_id": {
                "bic": null,
                "id": "XXX-OTHER-BANK"
            }
        },
        {
            "ref": {
                "message_id": "XXX",
                "end_to_end_id": "XXX",
                "account_servicer_ref": null,
                "payment_invocation_id": null,
                "instruction_id": null,
                "mandate_id": null,
                "cheque_number": null,
                "clearing_system_ref": null
            },
            "entry_ref": "XXX-REF-5",
            "amount": "-100.00",
            "currency": "CZK",
            "val_date": "2023-03-31",
            "remote_info": "transaction description",
            "additional_transaction_info": null,
            "related_account_id": null,
            "related_account_bank_id": null
        },
        {
            "ref": {
                "message_id": "XXX",
                "end_to_end_id": null,
                "account_servicer_ref": null,
                "payment_invocation_id": null,
                "instruction_id": null,
                "mandate_id": null,
                "cheque_number": null,
                "clearing_system_ref": null
            },
            "entry_ref": "XXX-REF-6",
            "amount": "1000.00",
            "currency": "CZK",
            "val_date": "2023-03-07",
            "remote_info": null,
            "additional_transaction_info": null,
            "related_account_id": {
                "iban": "LT6632xxxxxx",
                "id": null
            },
            "related_account_bank_id": {
                "bic": "REVOLT21",
                "id": null
            }
        }
    ]
}
```


## License

MIT – see [LICENSE.txt](./LICENSE.txt).

[1]: https://www.iso20022.org/iso-20022-message-definitions?search=camt.053
[2]: https://cbaonline.cz/formaty-xml-pro-vzajemnou-komunikaci-bank-s-klienty

## Changelog

### 0.3.0

- Refactored code into a package (it should not break most callers)
- Upgraded dependencies (works with Pandas 2.x or 3.x, lxml 5.x or 6.x)
- Added support for Python 3.13, 3.14; removed support for Python 3.10, 3.11
- Switched project management from Poetry to uv

### 0.2.0

- Added `AccountId`, `BankId` models to handle IBAN/BIC codes
- Added `TransactionRef` model to store transaction references, eg. end-to-end reference
- Pandas integration: `BankToCustomerStatement.as_dataframe()`
- Pandas integration: `okane` CLI tool can merge multiple input XMLs into one CSV/XLSX
- Upgraded Pydantic version from 1.10 to 2.5

### 0.1.0

- Initial release
