Refactor stored procedure and update project structure
Playwright Tests / test (push) Has been cancelled
Playwright Tests / test (push) Has been cancelled
- 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.
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
---
|
||||
status: Accepted
|
||||
date: 2026-07-05
|
||||
applyTo:
|
||||
- "Fuchs/code/FuchsPdf.cs"
|
||||
- "Fuchs/Services/FuchsPdfService.cs"
|
||||
- "Fuchs/Services/InvoiceService.cs"
|
||||
- "Fuchs/Services/ReminderService.cs"
|
||||
- "eRechnungLib/**"
|
||||
supersededBy: ""
|
||||
---
|
||||
|
||||
# 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, and `Seite X von Y` page numbers aligned with it. Reference
|
||||
the shipped asset filenames exactly — `AddHeaderImage` no-ops on a missing file,
|
||||
so a wrong extension silently drops a logo.
|
||||
- **Rendering pipeline:** `FuchsPdf.DocToPdfBytes` renders MigraDoc → PDF and
|
||||
post-processes to PDF/A; `DocToImageCollection` / `BytesToImageCollection`
|
||||
rasterise via Spire for the on-screen invoice preview (`sprep`/`sedit`). The
|
||||
OCORE `OCOREFontResolver` must be installed before any PdfSharp rendering.
|
||||
- **Spire license comes from a managed secret.** `FuchsPdfService` reads the
|
||||
license from configuration key `SpirePdf_License` (Key Vault secret
|
||||
`fuchs--SpirePdf-License`, registered in `ManagedSecretKeys`) and passes it to
|
||||
`FuchsPdf.SetLicense(key)`. An embedded fallback key keeps local/dev rendering
|
||||
working without Key Vault.
|
||||
- **eRechnung via `eRechnungLib`.** The `eRechnungLib` submodule is the single
|
||||
library for structured invoices. Invoices are to be produced as eRechnung:
|
||||
build an `eRechnungLib.Model.Invoice` from the Fuchs invoice data, then
|
||||
`EInvoice.CreateInvoice(model).ToZugferd(ZugferdProfile.EN16931, visualPdfBytes)`
|
||||
to embed the CII XML into the FuchsPdf-rendered visual PDF (ZUGFeRD/Factur-X
|
||||
hybrid PDF/A-3), or `ToXRechnung(...)` for pure UBL/CII XML. The visual PDF is
|
||||
the FuchsPdf output — the two layers stay consistent (same amounts/parties).
|
||||
Default `ConversionOptions` runs model + XSD validation; use `StrictValidation`
|
||||
when 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 test
|
||||
`Fuchs.Tests/PdfPipelineTests.cs` exercises 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.
|
||||
Reference in New Issue
Block a user