Gutschriften Phase 3b/2: ZUGFeRD/Factur-X (hybrides PDF/A-3)

- zugferd.service.ts: CII-XML (EN 16931, urn:cen.eu:en16931:2017,
  Dokumenttyp 381 Gutschrift). Steuerkategorie S bei USt, sonst E mit
  Befreiungsgrund. Verkaeufer=Firma (CompanyProfile), Kaeufer=Kunde.
- zugferdPdf.service.ts: bettet factur-x.xml als AF /Data ein, setzt
  sRGB-OutputIntent + XMP (PDF/A-3B pdfaid + Factur-X-Extension-Schema)
  via pdf-lib.
- creditNotePdf: eingebettete DejaVuSans-Fonts (Pflicht fuer PDF/A)
  statt Standard-Helvetica; nach PDF-Erzeugung ZUGFeRD-Embedding.
- assets/fonts (DejaVuSans + Bold) + assets/icc (sRGB) ins Repo;
  Dockerfile kopiert backend/assets ins Runtime-Image.

Lokal strukturell verifiziert: 1 Seite, /AF, /Metadata, /OutputIntents,
EmbeddedFiles, Font eingebettet, XML wohlgeformt (xmllint), TypeCode
381, GrandTotal korrekt.

WICHTIG: vor Prod gegen einen ZUGFeRD-/Factur-X-Validator pruefen
(Staging + echte Firmendaten). Feinheiten (Trailer-ID, XMP, XML-MIME)
ggf. nach erstem Validator-Lauf nachziehen.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-07 12:56:12 +02:00
co-authored by Claude Opus 4.8
parent 043bc173b7
commit 5423c83009
9 changed files with 348 additions and 11 deletions
@@ -478,11 +478,11 @@ export default function CreditNotesSection({ contractId, canEdit }: { contractId
{canEdit && (
<div className="flex items-center gap-1">
{cn.pdfPath ? (
<a href={fileUrl(cn.pdfPath, { inline: true })} target="_blank" rel="noopener noreferrer" className="text-gray-400 hover:text-blue-600 p-1" title="PDF ansehen">
<a href={fileUrl(cn.pdfPath, { inline: true })} target="_blank" rel="noopener noreferrer" className="text-gray-400 hover:text-blue-600 p-1" title="PDF (ZUGFeRD) ansehen">
<FileText className="w-4 h-4" />
</a>
) : (
<button onClick={() => pdfMutation.mutate(cn.id)} disabled={pdfMutation.isPending} className="text-gray-400 hover:text-blue-600 p-1" title="PDF erzeugen">
<button onClick={() => pdfMutation.mutate(cn.id)} disabled={pdfMutation.isPending} className="text-gray-400 hover:text-blue-600 p-1" title="PDF (ZUGFeRD) erzeugen">
<FileText className="w-4 h-4" />
</button>
)}