Test
This commit is contained in:
parent
91fd15621c
commit
2384b27ae1
41
main.py
41
main.py
|
|
@ -470,6 +470,7 @@ def generate_compliant_zugferd_cii(data):
|
||||||
ET.SubElement(header_sum, f"{{{RAM}}}LineTotalAmount").text = f"{data['total_net_amount']:.2f}"
|
ET.SubElement(header_sum, f"{{{RAM}}}LineTotalAmount").text = f"{data['total_net_amount']:.2f}"
|
||||||
ET.SubElement(header_sum, f"{{{RAM}}}TaxBasisTotalAmount").text = f"{data['total_net_amount']:.2f}"
|
ET.SubElement(header_sum, f"{{{RAM}}}TaxBasisTotalAmount").text = f"{data['total_net_amount']:.2f}"
|
||||||
ET.SubElement(header_sum, f"{{{RAM}}}TaxTotalAmount", {"currencyID": "EUR"}).text = f"{data['total_vat_amount']:.2f}"
|
ET.SubElement(header_sum, f"{{{RAM}}}TaxTotalAmount", {"currencyID": "EUR"}).text = f"{data['total_vat_amount']:.2f}"
|
||||||
|
header_sum.find(f"{{{RAM}}}TaxTotalAmount").set("currencyID", "EUR")
|
||||||
ET.SubElement(header_sum, f"{{{RAM}}}GrandTotalAmount").text = f"{data['total_gross_amount']:.2f}"
|
ET.SubElement(header_sum, f"{{{RAM}}}GrandTotalAmount").text = f"{data['total_gross_amount']:.2f}"
|
||||||
ET.SubElement(header_sum, f"{{{RAM}}}DuePayableAmount").text = f"{data['total_gross_amount']:.2f}"
|
ET.SubElement(header_sum, f"{{{RAM}}}DuePayableAmount").text = f"{data['total_gross_amount']:.2f}"
|
||||||
|
|
||||||
|
|
@ -731,6 +732,7 @@ with col2:
|
||||||
original_pdf_bytes = uploaded_file.read()
|
original_pdf_bytes = uploaded_file.read()
|
||||||
doc = fitz.open(stream=original_pdf_bytes, filetype="pdf")
|
doc = fitz.open(stream=original_pdf_bytes, filetype="pdf")
|
||||||
|
|
||||||
|
# 1. XML-Datei einbetten nach ZUGFeRD Standard
|
||||||
doc.embfile_add(
|
doc.embfile_add(
|
||||||
"factur-x.xml",
|
"factur-x.xml",
|
||||||
cii_xml_string.encode("utf-8"),
|
cii_xml_string.encode("utf-8"),
|
||||||
|
|
@ -738,9 +740,14 @@ with col2:
|
||||||
desc="Factur-X/ZUGFeRD E-Invoice"
|
desc="Factur-X/ZUGFeRD E-Invoice"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# 2. XMP-Metadaten inkl. PDF/A-3-Identifikation & ZUGFeRD-Schema aufbauen
|
||||||
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#">
|
||||||
|
<rdf:Description rdf:about="" xmlns:pdfaid="http://www.aiim.org/pdfa/ns/id/">
|
||||||
|
<pdfaid:part>3</pdfaid:part>
|
||||||
|
<pdfaid:conformance>B</pdfaid:conformance>
|
||||||
|
</rdf:Description>
|
||||||
<rdf:Description rdf:about="" xmlns:pdfaExtension="http://www.aiim.org/pdfa/ns/extension/" xmlns:pdfaSchema="http://www.aiim.org/pdfa/ns/schema/" xmlns:pdfaProperty="http://www.aiim.org/pdfa/ns/property#">
|
<rdf:Description rdf:about="" xmlns:pdfaExtension="http://www.aiim.org/pdfa/ns/extension/" xmlns:pdfaSchema="http://www.aiim.org/pdfa/ns/schema/" xmlns:pdfaProperty="http://www.aiim.org/pdfa/ns/property#">
|
||||||
<pdfaExtension:schemas>
|
<pdfaExtension:schemas>
|
||||||
<rdf:Bag>
|
<rdf:Bag>
|
||||||
|
|
@ -790,7 +797,37 @@ with col2:
|
||||||
</x:xmpmeta>
|
</x:xmpmeta>
|
||||||
<?xpacket end="w"?>"""
|
<?xpacket end="w"?>"""
|
||||||
|
|
||||||
doc.set_xml_metadata(xmp_xml)
|
doc.set_metadata(doc.metadata, xmp=xmp_xml)
|
||||||
|
|
||||||
|
# 3. Low-Level XREF-Injektion für strikte PDF/A-3 & ZUGFeRD Konformität
|
||||||
|
filespec_xref = None
|
||||||
|
for xref in range(1, doc.xref_length()):
|
||||||
|
obj_str = doc.xref_object(xref)
|
||||||
|
if "/Type /Filespec" in obj_str and "factur-x.xml" in obj_str:
|
||||||
|
filespec_xref = xref
|
||||||
|
break
|
||||||
|
|
||||||
|
if filespec_xref:
|
||||||
|
# 3.1 Erzwinge das /AFRelationship Attribut am eingebetteten FileSpec
|
||||||
|
doc.xref_set_key(filespec_xref, "AFRelationship", "/Alternative")
|
||||||
|
|
||||||
|
# 3.2 Ermittle den Catalog-Knoten und verknüpfe das XML im globalen /AF Array
|
||||||
|
cat_xref = doc.pdf_catalog()
|
||||||
|
doc.xref_set_key(cat_xref, "AF", f"[{filespec_xref} 0 R]")
|
||||||
|
|
||||||
|
# 3.3 Standard-sRGB OutputIntent erstellen & injizieren (Farbprofil-Marker für PDF/A)
|
||||||
|
oi_xref = doc.xref_create()
|
||||||
|
oi_dict = (
|
||||||
|
"<< /Type /OutputIntent "
|
||||||
|
"/S /GTS_PDFA1 "
|
||||||
|
"/OutputConditionIdentifier (sRGB) "
|
||||||
|
"/RegistryName (http://www.color.org) "
|
||||||
|
"/Info (sRGB IEC61966-2.1) >>"
|
||||||
|
)
|
||||||
|
doc.xref_update(oi_xref, oi_dict)
|
||||||
|
doc.xref_set_key(cat_xref, "OutputIntents", f"[{oi_xref} 0 R]")
|
||||||
|
|
||||||
|
# PDF finalisieren und umwandeln
|
||||||
zugferd_pdf_bytes = doc.tobytes()
|
zugferd_pdf_bytes = doc.tobytes()
|
||||||
doc.close()
|
doc.close()
|
||||||
|
|
||||||
|
|
@ -810,7 +847,7 @@ st.markdown("---")
|
||||||
st.caption(
|
st.caption(
|
||||||
"📝 **Hinweise:**\n\n"
|
"📝 **Hinweise:**\n\n"
|
||||||
"**Human-in-the-Loop:** "
|
"**Human-in-the-Loop:** "
|
||||||
"Das Tool dient as Automations-Assistent. Vor dem finalen XML-Export ist eine visuelle Endkontrolle der extrahierten Daten "
|
"Das Tool dient als Automations-Assistent. Vor dem finalen XML-Export ist eine visuelle Endkontrolle der extrahierten Daten "
|
||||||
"(insbesondere Rechnungsnummer und Empfängeradresse) durch den Sachbearbeiter zwingend erforderlich.\n\n"
|
"(insbesondere Rechnungsnummer und Empfängeradresse) durch den Sachbearbeiter zwingend erforderlich.\n\n"
|
||||||
"**GoBD-Konformität:** "
|
"**GoBD-Konformität:** "
|
||||||
"Das Tool generiert ausschließlich das strukturierte XML-Format. Für die Einhaltung der GoBD-Richtlinien "
|
"Das Tool generiert ausschließlich das strukturierte XML-Format. Für die Einhaltung der GoBD-Richtlinien "
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue