- Modified the stored procedure `fds__admin_getReportCatalog.sql` to use the correct schema for `all_objects`. - Added new folders and projects for `eRechnungLib` in the solution file `Fuchs_Intranet.slnx`, including validation and test projects. - Updated submodule reference for `OCORE`. - Added new submodule `eRechnungLib` with initial commit.
4.7 KiB
status, date, applyTo, supersededBy
| status | date | applyTo | supersededBy | |||||
|---|---|---|---|---|---|---|---|---|
| Accepted | 2026-07-05 |
|
0005 — PDF generation, rendering, and eRechnung output
Context
Fuchs produces letters, invoices, and reminders as PDFs. The layout is a faithful
port of the legacy VB module fuchs_fds_pdf.vb (letterhead, DIN address window,
admin block, four-block footer with page numbers, invoice item table, GiroCode).
The port had silently drifted — wrong letterhead image filenames (image1.png
instead of the shipped image1.jpeg, which AddHeaderImage skips via
File.Exists), a too-small bottom margin, and a reworked footer/admin block — so
generated PDFs (e.g. the sprep invoice preview) rendered broken.
Separately, German B2B/B2G invoicing now requires eRechnung (structured electronic invoices). The company direction is that all invoices are emitted as eRechnung, not just human-readable PDFs.
Rendering also depends on Spire.PDF (commercial, licensed) for PDF/A conversion and rasterising PDFs to preview images.
Decision
- PDF layout stays a 1:1 port of the legacy
fuchs_fds_pdf.vb.FuchsPdf(MigraDoc/PdfSharp) is the single source of the visual layout. When changing the letter/invoice/reminder layout, compare against the legacy module and keep the letterhead assets (Fuchs/Data/image1-3.jpeg,image4.png,overlay.png), margins, sender line, label-over-value admin block, absolutely-positioned four-block footer, andSeite X von Ypage numbers aligned with it. Reference the shipped asset filenames exactly —AddHeaderImageno-ops on a missing file, so a wrong extension silently drops a logo. - Rendering pipeline:
FuchsPdf.DocToPdfBytesrenders MigraDoc → PDF and post-processes to PDF/A;DocToImageCollection/BytesToImageCollectionrasterise via Spire for the on-screen invoice preview (sprep/sedit). The OCOREOCOREFontResolvermust be installed before any PdfSharp rendering. - Spire license comes from a managed secret.
FuchsPdfServicereads the license from configuration keySpirePdf_License(Key Vault secretfuchs--SpirePdf-License, registered inManagedSecretKeys) and passes it toFuchsPdf.SetLicense(key). An embedded fallback key keeps local/dev rendering working without Key Vault. - eRechnung via
eRechnungLib. TheeRechnungLibsubmodule is the single library for structured invoices. Invoices are to be produced as eRechnung: build aneRechnungLib.Model.Invoicefrom the Fuchs invoice data, thenEInvoice.CreateInvoice(model).ToZugferd(ZugferdProfile.EN16931, visualPdfBytes)to embed the CII XML into the FuchsPdf-rendered visual PDF (ZUGFeRD/Factur-X hybrid PDF/A-3), orToXRechnung(...)for pure UBL/CII XML. The visual PDF is the FuchsPdf output — the two layers stay consistent (same amounts/parties). DefaultConversionOptionsruns model + XSD validation; useStrictValidationwhen a malformed invoice must withhold output rather than ship with findings.
Consequences
- Layout edits must be validated against the legacy reference and the shipped
Data/assets; do not invent new positions/sizes. The pipeline testFuchs.Tests/PdfPipelineTests.csexercises the full chain (PdfSharp visual PDF → Spire preview images → eRechnung hybrid/XML) and must stay green. - Do not upgrade Spire.PDF beyond 8.10.5 (see project libraries rule). The
license must never be hard-coded in new code paths — read it from
SpirePdf_License. - Wiring the app's invoice flow to emit eRechnung is the follow-up: map
FdsInvoiceData/InvoiceRegistration→eRechnungLib.Model.Invoice(parties, lines, VAT breakdown, payment/IBAN, buyer reference, seller electronic address) and persist/deliver the ZUGFeRD PDF and/or XRechnung XML. - eRechnungLib depends only on open-source libraries (PDFsharp/MigraDoc; optional SaxonCS-HE for Schematron) — no new commercial dependency for the structured output itself.
Alternatives considered
- Hand-rolling ZUGFeRD/XRechnung XML in Fuchs: rejected — EN 16931 + CIUS validation, multiple profiles/syntaxes, and PDF/A-3 embedding are error-prone; a dedicated, validated library is safer.
- Rewriting the PDF layout from scratch rather than porting the legacy module: rejected — the letterhead is a fixed corporate design; the legacy VB is the authoritative spec, so faithful porting avoids visual regressions.
- Bundling a Spire license file / hard-coding the key: rejected in favor of the managed-secret path so the production key is centrally rotated and never committed, with the embedded key only as a dev fallback.