- Created a new function `fds__getCompanyAddressJson` to return a company's postal address as a structured JSON object. - Modified stored procedures `fds__createInvoice`, `fds__setInvoice`, and `fds__prepInvoice` to include a new parameter `@SendToAddressJson` for handling the address data. - Updated the invoice table and user-defined types to accommodate the new `SendToAddressJson` field. - Ensured that the address data is properly retrieved and stored in the invoice records.
4.4 KiB
status, date, applyTo, supersededBy
| status | date | applyTo | supersededBy | |||||
|---|---|---|---|---|---|---|---|---|
| Accepted | 2026-07-17 |
|
0012 — eRechnung uses a single PDF/A engine (eRechnungLib owns PDF/A-3)
Context
ADR 0005 established that invoices are emitted as eRechnung by embedding the CII
XML into the FuchsPdf-rendered visual PDF via eRechnungLib.ToZugferd(...).
Two hard requirements then surfaced: the emitted invoice must (a) satisfy the ZUGFeRD 2.4 / Factur-X standard for DATEV ingestion, and (b) be a formally verifiable PDF/A-3 (veraPDF-clean).
A conflict became apparent in the rendering pipeline. FuchsPdf.DocToPdfBytes
post-processes its MigraDoc/PdfSharp output to PDF/A via Spire
(OCORE…pdfAFileContent). eRechnungLib's FacturXPdfBuilder also produces
a PDF/A layer (raises to PDF 1.7, writes pdfaid XMP, adds an sRGB output
intent, embeds factur-x.xml in /AF). Feeding a Spire-made PDF/A into
eRechnungLib stacks two PDF/A conversions → duplicate/conflicting output
intents and pdfaid markers, which veraPDF rejects. Spire's output is also
PDF/A-1/2 and does not carry the /AF associated-file structure ZUGFeRD
requires (PDF/A-3).
Separately, eRechnungLib shipped no sRGB ICC profile, so its output intent
was silently omitted (PDFA-ICC warning) — never formally PDF/A-3 conformant.
Decision
- eRechnungLib is the single PDF/A engine for eRechnung output. The invoice
visual PDF is rendered by
FuchsPdfwithout the Spire PDF/A step and handed toeRechnungLib.ToZugferd(ZugferdProfile.EN16931, rawPdfBytes), which owns the one PDF/A-3 conversion and embeds the CII XML. The render-only path isFuchsPdf.DocToPdfBytesRaw/IPdfService.DocToPdfBytesRaw(fonts still embedded viaOCOREFontResolver, no PDF/A post-processing). - Spire stays only for on-screen preview rasterisation (
DocToImageCollection/BytesToImageCollectionforsprep/sedit). It is not part of the eRechnung file's PDF/A path.DocToPdfBytes(render + Spire PDF/A) is unchanged and remains the path for non-eRechnung documents (e.g. reminders). - A bundled sRGB ICC profile is required.
eRechnungLibshipsResources/Color/sRGB.icc(sRGB IEC61966-2.1) so the PDF/A output intent is always attached. A caller may override it per conversion viaConversionOptions.IccProfile. - Profile is EN 16931. MINIMUM / BASIC WL are not offered for real invoices — DATEV needs at least EN 16931 (COMFORT) for full booking.
- Formal conformance is verified by an external online service (veraPDF for
PDF/A-3 + a ZUGFeRD/EN 16931 validator), behind the configurable
Fuchs:ERechnung:Validation:ServiceUrlseam. Until the URL is provisioned, verification reports "not configured / skipped".
Consequences
- The eRechnung invoice PDF and a plain Spire PDF/A must never both be produced for the same document — pick the render-only path when emitting eRechnung.
- The incoming visual PDF must itself be PDF/A-friendly (fonts embedded — handled; letterhead images must be RGB, not CMYK; transparency is allowed because we target PDF/A-3).
Fuchs:ERechnung:Enabledgates emission and staysfalseuntil theFdsInvoiceData→eRechnungLib.Model.Invoicemapping is wired (the ADR 0005 follow-up). Open item for that mapping: the buyer address is currently a free-text block (SendToAddress); EN 16931 needs structured buyer fields (name/postcode/city/country, VAT id), so structured customer master data must feed the mapping. Seller data (currently hard-coded inFuchsPdf: name, address, tax number, IBAN/BIC) must be lifted into the seller model.Fuchs.csprojmust add a project reference toeRechnungLibwhen the flow is wired (not present yet).
Alternatives considered
- Keep Spire PDF/A and have eRechnungLib only embed the XML: rejected — Spire
produces the wrong PDF/A part (1/2, no
/AF) and a second conversion collides with eRechnungLib's own output intent/XMP, failing veraPDF. - Drop Spire entirely: rejected — Spire is still needed to rasterise PDFs to the on-screen invoice/reminder preview images; PdfSharp/eRechnungLib cannot.
- Ship no ICC and rely on callers: rejected — formal PDF/A-3 requires an output intent; bundling a profile makes conformance the default.