Files
TimeTracker/docs/admin/configuration/PEPPOL_EINVOICING.md
T
Dries Peeters 70510a6622 fix: quote create 500, line order, and Factur-X PDF parity
Quotes (#583):
- Add requires_approval, approval_level, and can_be_sent; wire create form
- Migrations 145 (approval columns) and 146 (quote_items.position)
- Order Quote.items by position; set positions on create/edit/duplicate/API
- Fix view template approval branch (not_required); add web regression test

Invoices / PEPPOL:
- Use the same Factur-X embed and PDF/A-3 normalization for export and
  email attachments; Associated File Data + text/xml metadata
- CII/UBL validators, pdfa3, zugferd, and invoice_pdf_postprocess helper
- Bundle compact sRGB ICC (app/resources/icc/); INVOICE_SRGB_ICC_PATH override
- Package data in setup.py; extend PEPPOL_EINVOICING.md and tests
2026-04-12 13:34:58 +02:00

8.9 KiB
Raw Blame History

Peppol and Factur-X / ZUGFeRD e-invoicing (EN 16931)

TimeTracker supports both:

  • Peppol send invoices via the Peppol network (UBL 2.1, BIS Billing 3.0) to your Peppol Access Point.
  • Factur-X / ZUGFeRD export invoice PDFs that contain embedded CII XML (Cross-Industry Invoice, EN 16931 profile). These hybrid PDFs are both human-readable and machine-readable.

Supported standards

Standard Format Status
Peppol BIS Billing 3.0 UBL 2.1 Supported (transport + export)
Factur-X / ZUGFeRD 2.x CII (EN 16931 profile) Supported (embedded in PDF)
PDF/A-3b PDF archival Supported (with ICC profile)
XRechnung CII / UBL (German CIUS) Not supported

Peppol is the transport; Factur-X / ZUGFeRD is a format (PDF + embedded CII XML). Each uses its own XML payload — UBL for Peppol, CII for Factur-X.

What you need

  • A Peppol Access Point provider (e.g. your accountant's solution or a commercial AP)
  • Your sender identifiers (how your company is identified in Peppol)
  • Your customers' recipient endpoint identifiers

TimeTracker supports two transport modes:

  • Generic provider-agnostic HTTP adapter: you configure an access point URL that accepts the JSON contract below. No SML/SMP or AS4 required. Recommended for production.
  • Native (experimental) SML/SMP participant discovery and AS4 message send. Lacks WS-Security, digital signatures, and receipt handling. Use only for testing or when you have a compatible receiving AP.

Sender and recipient identifiers are validated (scheme and endpoint ID format) before send in both modes.

Enable Peppol

You can enable Peppol either:

  • via Admin → System Settings → Peppol e-Invoicing, or
  • via environment variables (see env.example).

Environment variables:

  • PEPPOL_ENABLED=true
  • PEPPOL_SENDER_ENDPOINT_ID: your company endpoint id (value depends on scheme/country/provider)
  • PEPPOL_SENDER_SCHEME_ID: the scheme id for the sender endpoint
  • PEPPOL_ACCESS_POINT_URL: the URL of your access point adapter endpoint
  • PEPPOL_ACCESS_POINT_TOKEN (optional): bearer token used by the adapter
  • PEPPOL_ACCESS_POINT_TIMEOUT (optional): request timeout seconds (default: 30)
  • PEPPOL_PROVIDER (optional): label stored in send history (default: generic)
  • PEPPOL_TRANSPORT_MODE (optional): generic or native (default: generic)
  • PEPPOL_SML_URL (required for native): SML directory URL (e.g. EU directory)
  • PEPPOL_NATIVE_CERT_PATH / PEPPOL_NATIVE_KEY_PATH (optional): client certificate and key for AS4 mTLS

Set recipient Peppol endpoint on a client

For now, recipient endpoint details are stored on the Client using custom_fields:

  • peppol_endpoint_id: the recipient endpoint identifier
  • peppol_scheme_id: the recipient scheme identifier
  • peppol_country (optional): 2-letter country code (e.g. BE)

When both peppol_endpoint_id and peppol_scheme_id are present, the invoice page will enable Send via Peppol.

Sending an invoice

On an invoice page, click Send via Peppol. Each attempt is stored in:

  • invoice_peppol_transmissions (status: pendingsent or failed)

The invoice page shows a Peppol History table (for auditing and troubleshooting).

Access Point adapter contract

TimeTracker sends a POST request like:

{
  "recipient": { "endpoint_id": "…", "scheme_id": "…" },
  "sender": { "endpoint_id": "…", "scheme_id": "…" },
  "document": {
    "id": "INV-…",
    "type_id": "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##…::2.1",
    "process_id": "urn:fdc:peppol.eu:2017:poacc:billing:01:1.0"
  },
  "payload": { "ubl_xml": "<?xml version=\"1.0\" …>…</Invoice>" }
}

Your adapter should:

  • forward the UBL to your access point provider API
  • return JSON (recommended) with a message id, for example:
{ "message_id": "…" }

If the adapter returns HTTP (\ge 400), TimeTracker marks the attempt as failed and stores the error.

Make all invoices PEPPOL compliant

In Admin → Settings → Peppol e-Invoicing you can enable Make all invoices PEPPOL compliant. When this is on:

  • PDFs include PEPPOL/EN 16931 identifiers (seller and buyer endpoint and VAT) where configured.
  • Invoice view shows warnings when required data is missing (company Tax ID, sender Endpoint/Scheme ID, or client peppol_endpoint_id / peppol_scheme_id).
  • UBL generated for Peppol includes mandatory BIS Billing 3.0 elements: InvoiceTypeCode (380) and BuyerReference (from invoice, project name, or invoice number).

You can optionally set Buyer reference (PEPPOL BT-10) on each invoice (create/edit). If left empty, the UBL uses the project name or invoice number.

When the setting is on and the client has Peppol endpoint details, the invoice view shows a Download UBL button to save the UBL 2.1 XML file.

Embed Factur-X / ZUGFeRD CII XML in invoice PDFs

In Admin → Settings → Peppol e-Invoicing you can enable Embed Factur-X / ZUGFeRD CII XML in invoice PDFs (EN 16931). When this is on:

  • Exported invoice PDFs (Export PDF) and invoice emails (PDF attachment) use the same pipeline: when these settings are on, the attachment contains an embedded file factur-x.xml with a CII (Cross-Industry Invoice) XML conforming to the Factur-X EN 16931 profile.
  • The embedded XML is attached as an Associated File with relationship Data (primary structured invoice), MIME type text/xml, and Factur-X XMP metadata is written so validators recognize the document.
  • The PDF remains human-readable; the embedded XML makes it machine-readable (e.g. for automated booking or archiving).
  • Strict behaviour: If embedding is enabled and the embed step fails (e.g. missing pikepdf, invalid PDF), the export is aborted and the user sees an error; the PDF is not returned without the XML.

Party data (seller/buyer) is taken from Settings and the invoice's client (including endpoint fields and VAT). For full EN 16931 compliance, configure seller and client data including addresses and country codes.

Validation: Validate the embedded XML with b2brouter or portinvoice.com. You can optionally enable Run veraPDF after export in Admin → Peppol e-Invoicing and set the veraPDF executable path to get a validation summary after each export (does not block the download).

Factur-X and PDF/A-3

You can enable Normalize Factur-X PDFs to PDF/A-3b in Admin → Peppol e-Invoicing. When this is on (and Factur-X embedding is enabled), exported and emailed PDFs are normalized to PDF/A-3b:

  • XMP identification (pdfaid:part=3, pdfaid:conformance=B)
  • Embedded sRGB ICC color profile (DestOutputProfile) using a bundled compact sRGB profile under app/resources/icc/, or override with environment variable INVOICE_SRGB_ICC_PATH pointing to a full .icc file on the server
  • GTS_PDFA1 output intent

If conversion fails, export (or sending the invoice email) is aborted and the user sees an error.

veraPDF and fonts: ReportLab invoice templates often use standard fonts without full PDF/A font embedding; veraPDF may still report failures until templates embed fonts or you use an external PDF/A conversion pipeline. Ghostscript and similar tools can help but may strip embedded XML if run after Factur-X embedding; prefer tools that preserve associated files, or re-embed factur-x.xml after conversion.

UBL validation

When exporting or sending UBL via Peppol, the generated XML is checked for structural compliance with Peppol BIS Billing 3.0 requirements (required elements, identifiers, line items). Full Schematron validation is not performed in-app; use your Access Point provider's validator or ecosio for deep validation.

CII validation

When embedding Factur-X CII XML, the generated XML is checked for EN 16931 structural requirements (required elements, party data, line items, monetary totals).

Migrations

After pulling these changes, run:

flask db upgrade

This applies (among others):

  • 112_add_invoices_peppol_compliant (adds settings.invoices_peppol_compliant)
  • 113_add_invoice_buyer_reference (adds invoices.buyer_reference)
  • 128_add_invoices_zugferd_pdf (adds settings.invoices_zugferd_pdf for Factur-X PDF embedding)
  • 130_add_peppol_transport_mode_and_native (adds peppol_transport_mode, peppol_sml_url, peppol_native_cert_path, peppol_native_key_path, invoices_pdfa3_compliant, invoices_validate_export, invoices_verapdf_path)

Testing

With your virtual environment activated:

pytest tests/test_peppol_service.py tests/test_peppol_identifiers.py tests/test_zugferd.py tests/test_pdfa3.py tests/test_invoice_pdf_postprocess.py tests/test_invoice_validators.py -v