ZUGFeRD fix 4

This commit is contained in:
dfuhrmann3 2026-07-03 13:29:29 +02:00
parent d1604b0388
commit f1f8a5b97d
1 changed files with 5 additions and 25 deletions

30
main.py
View File

@ -282,7 +282,7 @@ def generate_compliant_xrechnung(data):
ET.SubElement(tax_total, f"{{{CBC}}}TaxAmount", {"currencyID": "EUR"}).text = f"{data['total_vat_amount']:.2f}" ET.SubElement(tax_total, f"{{{CBC}}}TaxAmount", {"currencyID": "EUR"}).text = f"{data['total_vat_amount']:.2f}"
tax_subtotal = ET.SubElement(tax_total, f"{{{CAC}}}TaxSubtotal") tax_subtotal = ET.SubElement(tax_total, f"{{{CAC}}}TaxSubtotal")
ET.SubElement(tax_subtotal, f"{{{CBC}}}TaxableAmount", {"currencyID": "EUR"}).text = f"{data['total_net_amount']:.2f}" ET.SubElement(tax_subtotal, f"{{{CBC}}}TaxableAmount", {"currencyID": "EUR"}).text = f"{data['total_net_amount']:.2f}"
ET.SubElement(tax_subtotal, f"{{{CBC}}}TaxAmount", {"currencyID": "EUR"}).text = f"{data['total_vat_amount']:.2f}" ET.SubElement(tax_subtotal, f"{{{CAC}}}TaxAmount", {"currencyID": "EUR"}).text = f"{data['total_vat_amount']:.2f}"
tax_cat = ET.SubElement(tax_subtotal, f"{{{CAC}}}TaxCategory") tax_cat = ET.SubElement(tax_subtotal, f"{{{CAC}}}TaxCategory")
ET.SubElement(tax_cat, f"{{{CBC}}}ID").text = vat_category ET.SubElement(tax_cat, f"{{{CBC}}}ID").text = vat_category
ET.SubElement(tax_cat, f"{{{CBC}}}Percent").text = f"{vat_rate:.2f}" ET.SubElement(tax_cat, f"{{{CBC}}}Percent").text = f"{vat_rate:.2f}"
@ -371,26 +371,7 @@ with col2:
sys_prompt = ( sys_prompt = (
"Du bist ein präziser OCR-Parser für deutsche B2B-Rechnungen. " "Du bist ein präziser OCR-Parser für deutsche B2B-Rechnungen. "
"Extrahiere die Metadaten fehlerfrei als valides JSON-Objekt. " "Extrahiere die Metadaten fehlerfrei als valides JSON-Objekt. "
"Das JSON MUSS zwingend exakt folgende Schlüssel (Keys) enthalten:\n" "Du musst zwingend exakt das vorgegebene JSON-Schema einhalten. "
"- invoice_number\n"
"- invoice_date (im Format YYYY-MM-DD)\n"
"- delivery_date (im Format YYYY-MM-DD)\n"
"- buyer_reference\n"
"- recipient_name\n"
"- recipient_street\n"
"- recipient_zip\n"
"- recipient_city\n"
"- recipient_email\n"
"- vat_rate_percent (als Zahl, z.B. 19.0)\n"
"- delivery_note_id\n"
"- order_id\n"
"- contract_id\n"
"- service_start_date\n"
"- service_end_date\n"
"- invoice_note\n\n"
"WICHTIGE REGEL: Analysiere den Text direkt VOR der ersten Tabellenposition '1'. "
"Sortiere alle dort vorlaufenden Zeilen vollständig in die dafür vorgesehenen ID-, Datums- und Freitext-Felder ein. "
"Schreibe diese vorlaufenden Metadaten NIEMALS in die Beschreibung der ersten Position hinein!\n\n"
"Antworte ausschließlich mit dem reinen JSON-Objekt. Schreibe keinen anderen Text." "Antworte ausschließlich mit dem reinen JSON-Objekt. Schreibe keinen anderen Text."
) )
prompt_meta = f"Rechnungstext:\n{pdf_text}" prompt_meta = f"Rechnungstext:\n{pdf_text}"
@ -583,19 +564,18 @@ with col2:
) )
else: else:
try: try:
# 🔥 FIX: Alle erfundenen Parameter entfernt. Nur valide Argumente verwendet.
original_pdf_bytes = uploaded_file.getvalue() original_pdf_bytes = uploaded_file.getvalue()
doc = fitz.open(stream=original_pdf_bytes, filetype="pdf") doc = fitz.open(stream=original_pdf_bytes, filetype="pdf")
# 🔥 OPTIMIERUNG 1: Setze das zwingend erforderliche PDF/A-3 Beziehungs-Flag 'Alternative'
doc.embfile_add( doc.embfile_add(
"factur-x.xml", "factur-x.xml",
xml_string.encode("utf-8"), xml_string.encode("utf-8"),
filename="factur-x.xml", filename="factur-x.xml",
desc="Factur-X/ZUGFeRD E-Invoice", desc="Factur-X/ZUGFeRD E-Invoice"
relationship="Alternative"
) )
# 🔥 OPTIMIERUNG 2: Injiziere das offizielle Factur-X / ZUGFeRD 2.x XMP-Schema in den PDF-Header # Injiziere das offizielle Factur-X / ZUGFeRD 2.x XMP-Schema in den PDF-Header
xmp_xml = """<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?> xmp_xml = """<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
<x:xmpmeta xmlns:x="adobe:ns:meta/"> <x:xmpmeta xmlns:x="adobe:ns:meta/">
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">