Metadata-Version: 2.4
Name: django-xrechnung
Version: 0.5.0
Summary: A Django app for handling XRechnung (German electronic invoicing standard)
Author-email: Fabian Braun <fsbraun@gmx.de>
Maintainer-email: Fabian Braun <fsbraun@gmx.de>
License: BSD-3-Clause
Project-URL: Homepage, https://codeberg.org/fsbraun/django-xrechnung
Project-URL: Documentation, https://django-xrechnung.readthedocs.io/en/stable/
Project-URL: Repository, https://codeberg.org/fsbraun/django-xrechnung
Project-URL: Issues, https://codeberg.org/fsbraun/django-xrechnung/issues
Project-URL: Changelog, https://codeberg.org/fsbraun/django-xrechnung/src/branch/main/CHANGELOG.md
Keywords: django,xrechnung,invoice,german,electronic,billing
Classifier: Development Status :: 4 - Beta
Classifier: Framework :: Django
Classifier: Framework :: Django :: 5.2
Classifier: Framework :: Django :: 6.0
Classifier: Framework :: Django :: 6.1
Classifier: License :: OSI Approved :: BSD License
Classifier: Operating System :: POSIX :: Linux
Classifier: Operating System :: MacOS
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Office/Business :: Financial :: Accounting
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: Django<6.2,>=5.2
Requires-Dist: lxml<7,>=5.3
Requires-Dist: weasyprint<71,>=70
Requires-Dist: tomli>=2; python_version < "3.11"
Provides-Extra: cii
Requires-Dist: drafthorse==2025.2.0; extra == "cii"
Requires-Dist: factur-x==6.8; extra == "cii"
Provides-Extra: hybrid
Requires-Dist: drafthorse==2025.2.0; extra == "hybrid"
Requires-Dist: pypdf==6.18.0; extra == "hybrid"
Requires-Dist: factur-x==6.8; extra == "hybrid"
Provides-Extra: inbound
Requires-Dist: drafthorse==2025.2.0; extra == "inbound"
Requires-Dist: pypdf==6.18.0; extra == "inbound"
Requires-Dist: factur-x==6.8; extra == "inbound"
Provides-Extra: dev
Requires-Dist: pytest>=7.0.0; extra == "dev"
Requires-Dist: pytest-django>=4.5.0; extra == "dev"
Requires-Dist: pytest-xdist>=3.6; extra == "dev"
Requires-Dist: pytest-cov>=7.0.0; extra == "dev"
Requires-Dist: coverage[toml]>=7.10.6; extra == "dev"
Requires-Dist: django-filer>=3.0; extra == "dev"
Requires-Dist: pypdf==6.18.0; extra == "dev"
Requires-Dist: factur-x==6.8; extra == "dev"
Requires-Dist: drafthorse==2025.2.0; extra == "dev"
Requires-Dist: ruff>=0.1.0; extra == "dev"
Requires-Dist: bandit>=1.7.0; extra == "dev"
Requires-Dist: pre-commit>=3.0.0; extra == "dev"
Provides-Extra: test
Requires-Dist: pytest>=7.0.0; extra == "test"
Requires-Dist: pytest-django>=4.5.0; extra == "test"
Requires-Dist: pytest-xdist>=3.6; extra == "test"
Requires-Dist: pytest-cov>=7.0.0; extra == "test"
Requires-Dist: coverage[toml]>=7.10.6; extra == "test"
Requires-Dist: django-filer>=3.0; extra == "test"
Requires-Dist: pypdf==6.18.0; extra == "test"
Requires-Dist: factur-x==6.8; extra == "test"
Requires-Dist: drafthorse==2025.2.0; extra == "test"
Provides-Extra: filer
Requires-Dist: django-filer>=3.0; extra == "filer"
Provides-Extra: postgres
Requires-Dist: psycopg[binary]>=3.2; extra == "postgres"
Dynamic: license-file

# django-xrechnung

[![PyPI version](https://badge.fury.io/py/django-xrechnung.svg)](https://pypi.org/project/django-xrechnung/)
[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/django-xrechnung)](https://pypi.org/project/django-xrechnung/)
[![PyPI - Django Versions from Framework Classifiers](https://img.shields.io/pypi/frameworkversions/django/django-xrechnung)](https://www.djangoproject.com/)
[![PyPI - License](https://img.shields.io/pypi/l/django-xrechnung)](https://codeberg.org/fsbraun/django-xrechnung/src/branch/main/LICENSE)
[![Latest on Django Packages](https://img.shields.io/badge/Django%20Packages-django--xrechnung-8c3c26)](https://djangopackages.org/packages/p/django-xrechnung/)

**Need XRechnung or Factur-X invoices inside an existing Django project?
Install this instead of implementing EN 16931 yourself.**

You pass in buyer and line items. You get back an XRechnung or Factur-X XML file
that has passed the official KoSIT validator, and a matching PDF, both stored on
the invoice. Everything runs on your own server.

```bash
pip install django-xrechnung
```

## From your order to a valid e-invoice

```python
from datetime import date
from decimal import Decimal

from django_xrechnung.line_sources import SourceLine, materialize_lines
from django_xrechnung.services import create_draft, finalize_invoice

invoice = create_draft({               # seller, bank account and terms come from settings
    "invoice_number": "RE-2026-0142",
    "invoice_date": date.today(),
    "service_date": date.today(),
    "buyer_name": "Beispielverwaltung",
    "buyer_street": "Rathausstraße 2", "buyer_postcode": "28195", "buyer_city": "Bremen",
    "buyer_endpoint": "eingang@example.org",
    "buyer_reference": "04011000-12345-03",   # Leitweg-ID
})
materialize_lines(invoice, [
    SourceLine(description="Beratung", quantity=Decimal("2"), unit_code="HUR", unit_price=Decimal("50")),
    SourceLine(description="Fachbuch", unit_price=Decimal("100"), tax_rate=Decimal("7")),
], source_type="shop.Order")

invoice = finalize_invoice(invoice)    # validate with KoSIT, render XML + PDF, lock the invoice
invoice.xml, invoice.pdf               # stored files, ready to send or download
```

For Factur-X, add `"output_format": "facturx_cii"` to the `create_draft` values. Use
`"facturx_hybrid"` for a PDF/A-3 file with the XML embedded.

## What comes out

This is the actual output of the code above. Files:
[`invoice.pdf`](https://codeberg.org/fsbraun/django-xrechnung/raw/branch/main/docs/_static/sample/invoice.pdf),
[`xrechnung-ubl.xml`](https://codeberg.org/fsbraun/django-xrechnung/src/branch/main/docs/_static/sample/xrechnung-ubl.xml),
[`facturx-cii.xml`](https://codeberg.org/fsbraun/django-xrechnung/src/branch/main/docs/_static/sample/facturx-cii.xml).

<table>
<tr>
<th>PDF</th>
<th>XRechnung XML (excerpt)</th>
</tr>
<tr>
<td valign="top" width="45%">
<img src="https://codeberg.org/fsbraun/django-xrechnung/raw/branch/main/docs/_static/sample/invoice.png" alt="Generated PDF invoice RE-2026-0142 with two VAT rates" width="380">
</td>
<td valign="top">

```xml
<Invoice ...>
  <cbc:CustomizationID>
    urn:cen.eu:en16931:2017#compliant
    #urn:xeinkauf.de:kosit:xrechnung_3.0
  </cbc:CustomizationID>
  <cbc:ID>RE-2026-0142</cbc:ID>
  <cbc:BuyerReference>
    04011000-12345-03
  </cbc:BuyerReference>
  <!-- seller, buyer, SEPA, terms … -->
  <cac:TaxTotal>
    <cbc:TaxAmount>26.00</cbc:TaxAmount>
    <cac:TaxSubtotal>
      <cbc:TaxableAmount>100.00</cbc:TaxableAmount>
      <cbc:TaxAmount>7.00</cbc:TaxAmount>
      <cac:TaxCategory>
        <cbc:ID>S</cbc:ID>
        <cbc:Percent>7.00</cbc:Percent>
      </cac:TaxCategory>
    </cac:TaxSubtotal>
    <!-- 19 % subtotal … -->
  </cac:TaxTotal>
  <cac:LegalMonetaryTotal>
    <cbc:TaxExclusiveAmount>200.00</cbc:TaxExclusiveAmount>
    <cbc:PayableAmount>226.00</cbc:PayableAmount>
  </cac:LegalMonetaryTotal>
  <!-- two InvoiceLine elements … -->
</Invoice>
```

</td>
</tr>
</table>

## Why not build it yourself?

The XML is the easy part. These are the parts that take the time:

- **Validation you can trust.** Every invoice goes through the official
  [KoSIT validator](https://github.com/itplr-kosit/validator) with pinned
  XRechnung 3.0.2 rules before it is issued. If it is rejected, nothing is stored
  and no invoice number is used up.
- **VAT arithmetic that matches the rules.** Mixed rates, exemptions, reverse charge,
  intra-community supply and export, line discounts and surcharges, prepaid and
  rounding amounts. Totals are calculated with correct decimal rounding.
- **Immutable issued documents.** Finalized invoices cannot be edited. XML, PDF,
  validation report and SHA-256 hashes are stored together. Corrections and credit
  notes refer back to the original invoice.
- **Gap-free numbering.** Number series per seller are allocated inside the
  issuing transaction.
- **All the formats.** XRechnung UBL, XRechnung CII, Factur-X EN 16931, and
  Factur-X PDF/A-3b hybrids that are checked with veraPDF.
- **Incoming invoices too.** Receive XRechnung or Factur-X files, validate them
  safely, and review the parsed data in the admin.
- **Django-native.** Admin screens, permissions, multiple sellers, JSON endpoints,
  signals before and after issuing, customizable PDF templates, and pluggable storage.

## Get started

```bash
pip install django-xrechnung              # add [cii], [hybrid] or [inbound] as needed
python -m django_xrechnung.kosit /opt/kosit   # one-time download of the pinned validator
```

```python
INSTALLED_APPS += ["django_xrechnung"]
DJANGO_XRECHNUNG = {
    "KOSIT_HOME": "/opt/kosit",
    "SELLER_DEFAULTS": {"supplier_name": "Example GmbH", ...},
}
```

Validation needs Java. PDF rendering uses
[WeasyPrint](https://weasyprint.org/). The
**[first-invoice tutorial](https://django-xrechnung.readthedocs.io/en/stable/tutorials/first-invoice.html)**
takes you from installation to your first downloaded XML and PDF. The
[installation guide](https://django-xrechnung.readthedocs.io/en/stable/how-to/install.html)
lists the system packages you need.

## Scope

**Beta (0.4.0)**, tested against real KoSIT acceptance and rejection.
Outgoing invoices currently support German sellers and buyers and EUR. Electronic
addresses can be an email address, a Leitweg-ID, a VAT ID or a GLN, and any UN/ECE
unit code works. Payment can be by SEPA credit transfer, SEPA direct debit, or card.
Document-level allowances and charges, other countries and currencies, and
sending (Peppol, e-mail) are not supported yet. The
[supported invoice scenarios](https://django-xrechnung.readthedocs.io/en/stable/reference/supported-invoices.html)
list the exact limits.

## Documentation

**[django-xrechnung.readthedocs.io](https://django-xrechnung.readthedocs.io/en/stable/)**

- [Fill invoices from your own models](https://django-xrechnung.readthedocs.io/en/stable/how-to/line-sources.html)
- [Choose CII or Factur-X output](https://django-xrechnung.readthedocs.io/en/stable/how-to/output-formats.html)
- [VAT exemptions and reverse charge](https://django-xrechnung.readthedocs.io/en/stable/how-to/vat-categories.html)
- [Credit notes and corrections](https://django-xrechnung.readthedocs.io/en/stable/how-to/adjustments.html)
- [Automatic numbering](https://django-xrechnung.readthedocs.io/en/stable/how-to/numbering.html)
- [Receive and review incoming invoices](https://django-xrechnung.readthedocs.io/en/stable/how-to/receive-documents.html)
- [Python API](https://django-xrechnung.readthedocs.io/en/stable/reference/python-api.html) ·
  [HTTP API](https://django-xrechnung.readthedocs.io/en/stable/reference/http-api.html) ·
  [Configuration](https://django-xrechnung.readthedocs.io/en/stable/reference/configuration.html)

There is also a [runnable example project](https://codeberg.org/fsbraun/django-xrechnung/src/branch/main/example/README.md),
along with the [changelog](https://codeberg.org/fsbraun/django-xrechnung/src/branch/main/CHANGELOG.md)
and the [contributing guide](https://codeberg.org/fsbraun/django-xrechnung/src/branch/main/CONTRIBUTING.md).

## License

[BSD 3-Clause](https://codeberg.org/fsbraun/django-xrechnung/src/branch/main/LICENSE).
KoSIT, WeasyPrint and the system fonts keep their own upstream licenses.
