Metadata-Version: 2.4
Name: accounting-bridge
Version: 0.6.0
Summary: Deterministic multi-ERP financial consolidation, POS-to-journal, and GL audit engine for SMEs
Author: Wietze Suijker
License: MIT
Project-URL: Homepage, https://github.com/wietzesuijker/accounting-bridge
Project-URL: Repository, https://github.com/wietzesuijker/accounting-bridge
Project-URL: Issues, https://github.com/wietzesuijker/accounting-bridge/issues
Project-URL: Changelog, https://github.com/wietzesuijker/accounting-bridge/blob/main/CHANGELOG.md
Keywords: accounting,consolidation,trial-balance,finance,audit,ERP
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Financial and Insurance Industry
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Office/Business :: Financial :: Accounting
Classifier: Typing :: Typed
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pandas>=2.0
Requires-Dist: polars>=1.0
Requires-Dist: pydantic>=2.7
Requires-Dist: numpy>=1.26
Requires-Dist: openpyxl>=3.1
Requires-Dist: xlrd>=2.0.1
Requires-Dist: charset-normalizer>=3.0
Provides-Extra: pdf
Requires-Dist: pdfplumber>=0.10; extra == "pdf"
Provides-Extra: ocr
Requires-Dist: pytesseract>=0.3; extra == "ocr"
Requires-Dist: pdf2image>=1.16; extra == "ocr"
Requires-Dist: Pillow>=10.0; extra == "ocr"
Provides-Extra: ofx
Requires-Dist: ofxtools>=0.9; extra == "ofx"
Provides-Extra: llm
Requires-Dist: anthropic>=0.40; extra == "llm"
Provides-Extra: server
Requires-Dist: fastapi>=0.110; extra == "server"
Requires-Dist: uvicorn[standard]>=0.27; extra == "server"
Requires-Dist: python-multipart>=0.0.9; extra == "server"
Provides-Extra: api
Requires-Dist: accounting-bridge[server]; extra == "api"
Provides-Extra: hosted
Requires-Dist: supabase>=2.0; extra == "hosted"
Requires-Dist: stripe>=8.0; extra == "hosted"
Provides-Extra: all
Requires-Dist: accounting-bridge[hosted,llm,ocr,ofx,pdf,server]; extra == "all"
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"
Requires-Dist: pytest-cov>=5.0; extra == "dev"
Requires-Dist: hypothesis>=6.100; extra == "dev"
Requires-Dist: ruff>=0.8; extra == "dev"
Requires-Dist: mypy>=1.10; extra == "dev"
Requires-Dist: pre-commit>=3.5; extra == "dev"
Requires-Dist: pandas-stubs; extra == "dev"
Requires-Dist: types-openpyxl; extra == "dev"
Requires-Dist: httpx>=0.27; extra == "dev"
Provides-Extra: e2e
Requires-Dist: playwright>=1.40; extra == "e2e"
Provides-Extra: docs
Requires-Dist: mkdocs-material>=9.5; extra == "docs"
Requires-Dist: mkdocstrings[python]>=0.29; extra == "docs"
Dynamic: license-file

# accounting-bridge

**Deterministic multi-ERP financial consolidation, POS-to-journal conversion, and GL audit — as a typed Python library.**

[![CI](https://github.com/wietzesuijker/accounting-bridge/actions/workflows/ci.yml/badge.svg)](https://github.com/wietzesuijker/accounting-bridge/actions/workflows/ci.yml)
[![PyPI](https://img.shields.io/pypi/v/accounting-bridge.svg)](https://pypi.org/project/accounting-bridge/)
[![Python](https://img.shields.io/pypi/pyversions/accounting-bridge.svg)](https://pypi.org/project/accounting-bridge/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)

Every finance team with two or more entities runs the same manual loop each month: export trial balances from each ERP, rearrange columns, VLOOKUP account codes, reconcile currencies, and hunt for the difference when it doesn't balance. `accounting-bridge` does that loop in seconds — and it is **deterministic**: no LLM sits in the data path, so every number is reproducible and auditable, with row-level lineage back to the source file.

It reads exports from any accounting system (CSV, Excel, PDF, OFX/QFX, QuickBooks IIF, scanned images) and produces:

- **Consolidated trial balances** across entities and currencies, with IAS 21 FX translation and a cumulative translation adjustment.
- **POS-to-journal** conversion with balanced double entries and Canadian GST/QST tax splitting.
- **GL audit packages** with anomaly flags, balance checks, and Benford's-law analysis.

## Install

```bash
pip install accounting-bridge          # core library, zero UI/server deps
pip install "accounting-bridge[pdf]"   # + PDF table extraction
pip install "accounting-bridge[ocr]"   # + scanned-image OCR
pip install "accounting-bridge[all]"   # everything
```

Requires Python 3.11+.

## Library quickstart

The library's front door is a small set of typed functions that take a validated
config and return a named result.

```python
import pandas as pd
from accounting_bridge import consolidate, ConsolidationConfig

hq = pd.DataFrame({"account_code": ["4100"], "amount_local": [-10_000.0], "currency": ["USD"]})
eu = pd.DataFrame({"account_code": ["4100"], "amount_local": [-8_000.0], "currency": ["EUR"]})

cols = {"account_code": "account_code", "amount_local": "amount_local", "currency": "currency"}
config = ConsolidationConfig(
    columns_per_entity={"HQ": cols, "EU": cols},
    base_currency="USD",
    rates={"EUR": {"closing": 1.08, "average": 1.07, "historical": 1.05}},
)

result = consolidate([("HQ", hq), ("EU", eu)], config)
print(result.summary)        # consolidated by account, in USD
print(result.fx_warnings)    # any FX/rate issues surfaced
```

Other entry points follow the same shape:

```python
from accounting_bridge import convert_pos, audit_ledger, summarize_trial_balance
from accounting_bridge import PosConfig, AuditConfig

pos_result   = convert_pos(pos_df, PosConfig(columns=..., accounts=...))
audit_result = audit_ledger(gl_df, AuditConfig(columns=..., large_amount=100_000))
tb_result    = summarize_trial_balance(tb_df, {"account_code": "Acct", "amount": "Balance"})
```

Reading messy real-world files:

```python
from accounting_bridge.ingest import read_smart

df, diagnostics = read_smart("messy_export.xlsx")  # encoding, delimiter, header auto-detected
```

## Command line

```bash
# Consolidate several trial balances into one audit-ready workbook
accounting-bridge consolidate --files entity_a.csv entity_b.xlsx \
    --base-currency USD --rates EUR:closing=1.08,average=1.07 --output consolidated.xlsx

# Inspect how a file is parsed (encoding, delimiter, columns)
accounting-bridge read --file messy_export.csv
```

## Supported formats

| Format | Extensions | Extra |
|---|---|---|
| Delimited text | `.csv` `.tsv` `.txt` | core |
| Excel | `.xlsx` `.xls` `.xlsm` | core |
| PDF tables | `.pdf` | `[pdf]` |
| Open Financial Exchange | `.ofx` `.qfx` | `[ofx]` |
| QuickBooks Desktop | `.iif` | core |
| Scanned images | `.png` `.jpg` | `[ocr]` |

## Architecture

Library-first. The engine is the product; the app and server are thin layers over it.

```
accounting_bridge/        core library — pure, typed, no UI/server deps
  models/                 pydantic v2 config + result models (validated at the boundary)
  ingest/                 multi-format readers (encoding/delimiter/header auto-detection)
  engine/                 consolidation, POS, audit, trial balance, intercompany, FX
  processing.py           the typed public API (consolidate / convert_pos / audit_ledger / ...)
cli.py                    one-shot command-line consolidation
```

A FastAPI server and a dedicated web frontend are layered on the same library
(see the redesign in progress in `CHANGELOG.md`).

## Self-hosting

```bash
docker compose up           # single-user instance, SQLite, no secrets required
```

Authentication and billing ship disabled by default; set the documented
environment variables to enable a multi-tenant hosted deployment.

## Development

```bash
uv venv --python 3.12 && source .venv/bin/activate
uv pip install -e ".[all,dev]"
make test        # python -m pytest
make lint        # ruff check + ruff format --check
make typecheck   # mypy --strict
```

See [CONTRIBUTING.md](CONTRIBUTING.md) for conventions and
[SECURITY.md](SECURITY.md) to report vulnerabilities.

## License

[MIT](LICENSE) © Wietze Suijker
