Add function to retrieve company address as JSON and update invoice procedures

- 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.
This commit is contained in:
2026-07-18 18:01:24 +02:00
parent 5ccd85c38f
commit 628802db19
45 changed files with 1892 additions and 26 deletions
@@ -0,0 +1,81 @@
---
status: Accepted
date: 2026-07-17
applyTo:
- "Fuchs/code/FuchsPdf.cs"
- "Fuchs/Services/FuchsPdfService.cs"
- "Fuchs/Services/InvoiceService.cs"
- "Fuchs/Services/ERechnungSettings.cs"
- "eRechnungLib/**"
supersededBy: ""
---
# 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 `FuchsPdf` **without** the Spire PDF/A step and handed
to `eRechnungLib.ToZugferd(ZugferdProfile.EN16931, rawPdfBytes)`, which owns the
one PDF/A-3 conversion and embeds the CII XML. The render-only path is
`FuchsPdf.DocToPdfBytesRaw` / `IPdfService.DocToPdfBytesRaw` (fonts still
embedded via `OCOREFontResolver`, no PDF/A post-processing).
- **Spire stays only for on-screen preview rasterisation** (`DocToImageCollection`
/ `BytesToImageCollection` for `sprep`/`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.** `eRechnungLib` ships
`Resources/Color/sRGB.icc` (sRGB IEC61966-2.1) so the PDF/A output intent is
always attached. A caller may override it per conversion via
`ConversionOptions.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:ServiceUrl` seam. 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:Enabled` gates emission and stays `false` until the
`FdsInvoiceData``eRechnungLib.Model.Invoice` mapping 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 in `FuchsPdf`:
name, address, tax number, IBAN/BIC) must be lifted into the seller model.
- `Fuchs.csproj` must add a project reference to `eRechnungLib` when 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.