Fehler 'unable to find page tree' beim ZUGFeRD-Export mancher PDFs (z.B. von PDF-XChange
erzeugte degewo-Rechnung): factur-x bettete die XML nicht ein und zerstoerte den Seitenbaum.
- build_zugferd_pdf versucht zuerst die Original-PDF; schlaegt das fehl (Absturz ODER XML
nicht eingebettet), wird die PDF mit pikepdf normalisiert (neu gespeichert) und erneut
versucht. Manche PDFs funktionieren nur original, andere nur normalisiert - beide Wege
abgedeckt, Erfolgskontrolle via pdf_has_embedded_facturx.
- Neue Helfer normalize_pdf_bytes() und pdf_has_embedded_facturx() in invoice_logic.
- Verifiziert auf beiden echten Rechnungen (degewo -> Fallback, Gemeinde -> Original).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Positionsscan bricht nur noch bei der ECHTEN Positionsnummer (len(items)+1) ab, nicht
bei alleinstehenden Ziffern-Fragmenten aufgesplitteter Seriennummern (Rechnung R26-224:
Position wurde sonst ganz verworfen). Seriennummern landen jetzt in der Beschreibung (BT-154).
- Angebotsnummer wird aus Vertrag (BT-12)/Vergabeangebot (BT-17) entfernt, falls das LLM sie
dort eingeordnet hat - Angebot gehoert nur in den Freitext (BT-22). Schema-Beschreibungen
entsprechend praezisiert.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Rechnung R26-232 Position 3 (Anfahrt, '2,00 pauschal') wurde uebersprungen, weil
'pauschal' nicht in der Einheiten-Erkennung stand. Ergaenzt: Pauschale/Pauschal/Psch.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Kundennummer jetzt BT-46 (eigenes Feld), getrennt von Leitweg-ID (BT-10)
- BT-10 Leitweg-ID: eigenes Feld, leer per Default; nur bei XRechnung Pflicht (BR-DE-15),
bei ZUGFeRD optional (kein Blocker, kein XML-Eintrag wenn leer)
- BT-12 nur noch Vertrag; Vergabeangebot/Ausschreibung als neues Feld BT-17
(UBL OriginatorDocumentReference, CII AdditionalReferencedDocument TypeCode 50)
- 'Angebot <Nr> vom <Datum>' wird erkannt und in den Freitext (BT-22) uebernommen
- BT-49 elektronische Adresse: bei ZUGFeRD optional (kein Blocker, in CII weggelassen wenn leer),
bei XRechnung weiterhin Pflicht; Hinweis: E-Mail oder Netzwerkcode
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Ganze Mengen erscheinen als 1.00 statt 1.0000; gebrochene Mengen (z.B. 1.375
Tage) bleiben vollstaendig erhalten. Vereinheitlicht mit dem UBL-Generator.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Move all dependency-free business logic (metadata schema, rounding/parsing
helpers, item extraction, and the XRechnung/ZUGFeRD XML generators plus the
PDF/A output-intent helpers) out of main.py into a new invoice_logic.py that
imports only pydantic and pikepdf. This makes the logic unit-testable without
a Streamlit runtime. Pure cut-and-paste, no behavior change; main.py now
imports these names from invoice_logic instead of defining them locally.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>