Problem Statement
Today Sales Invoice supports only one supporting document via einvoice_embedded_document (one 916 in CII). Customers need several invoice-related files in the submit PDF and in the e-invoice, as PDF/A-3 embedded files (paperclip / Associated Files), not merged into the invoice pages.
When pdf_on_submit is installed, it calls attach_xml_to_pdf, which runs Ghostscript PDF/A-3 and then embeds only the invoice XML. That path cannot add N user annexes: pre-embedding with pypdf and then calling attach_xml_to_pdf drops annexes because Ghostscript strips existing embedded files.
This issue is essentially moved from alyf-de/erpnext_pdf-on-submit#76 (LMK-16). pdf_on_submit might expose a generic before_attach_pdf hook; annex data model, validation, XML, and PDF transformation stay in eu_einvoice.
Suggested Solution
Scope: Sales Invoice only.
-
Child table on Sales Invoice for additional annexes (explicit opt-in per row; link File, display name, order). Keep einvoice_embedded_document as the primary supporting document. Freeze the table on submit. E Invoice Settings: prompt to add SI attachments — always / ask / never (default ask on submit). Expose the list in print formats via doc (docs/snippet only).
-
Shared annex list (get_annex_attachments or equivalent) for XML generation and PDF building.
-
XML: N×AdditionalReferencedDocument with TypeCode 916 by default; #ef=<filename> links to PDF embeds for EN 16931 / EXTENDED; base64-encoded embedding in XML for XRECHNUNG. XRECHNUNG: no invoice XML in PDF (unchanged); Any standalone .xml includes annexes.
-
PDF (ZUGFeRD / EN 16931 / EXTENDED):
- Plain print PDF →
_convert_pdf_to_pdfa(plain) once (Ghostscript when gs is available)
facturx.generate_from_binary(pdfa, xml, attachments={…}) — invoice CII + all annexes in one call
- Unique embedded filenames (BR-DE-22)
- Refactor
attach_xml_to_pdf and reuse the same builder for before_attach_pdf (once pdf_on_submit ships the hook, or integrate into attach_xml_to_pdf otherwise) and download_pdf
-
Validation: XRechnung §8.2 MIME allowlist (7 types, including application/xml); OZG-RE Tier 1 hard limits — 15 MB total, 200 files; warn threshold from E Invoice Settings.
-
Tests on v16; mandatory v15 backport after v16 is stable.
Acceptance (summary): Multi-annex submit PDF + matching CII; Schematron-valid fixture; MIME/size rejects; XRECHNUNG behaviour preserved; PDF/A-3b on a representative hybrid sample.
Alternatives
| Alternative |
Why not |
Page-merge annexes into invoice PDF (PdfWriter) |
Does not meet customer requirement to embed attachements |
pypdf embed → then attach_xml_to_pdf |
Ghostscript strips user annexes. Embed needs to happen after PDF/A-3 conversion. |
drafthorse attach_xml for N annexes |
Only embeds invoice XM, no other filetypes. |
| factur-x on plain print without prior PDF/A |
veraPDF PDF/A-3b-compliance test fails |
| pdftopdfa instead of Ghostscript |
Works and is a pip-shippable alternative to Ghostscript; young project, while Ghostscript is well known and mature. |
| Child table in pdf_on_submit / ERPNext core |
Sales-Invoice focused feature. DocType-agnostic solution is not needed. |
| Auto-convert Word/Excel to PDF |
Rejected; enforce MIME allowlist |
| OZG-RE Tier 2 (BT-124 URI, 200 MB refs) |
Higher file size limits for large attachments. Out of scope v1, but might be added later. |
| Draft preview = submit PDF |
Requested by customer, but deferred to after first implementation run. |
Additional Context
- Depends on: erpnext_pdf-on-submit#76 —
before_attach_pdf hook in pdf_on_submit (replaces direct attach_xml_to_pdf import). Can be mitigated by implementing everything into attach_xml_to_pdf but that is actually out of scope for that function.
- Docs: OZG-RE size limits, ZUGFeRD, XRechnung §8.2 / §11.2.
Problem Statement
Today Sales Invoice supports only one supporting document via
einvoice_embedded_document(one 916 in CII). Customers need several invoice-related files in the submit PDF and in the e-invoice, as PDF/A-3 embedded files (paperclip / Associated Files), not merged into the invoice pages.When pdf_on_submit is installed, it calls
attach_xml_to_pdf, which runs Ghostscript PDF/A-3 and then embeds only the invoice XML. That path cannot add N user annexes: pre-embedding with pypdf and then callingattach_xml_to_pdfdrops annexes because Ghostscript strips existing embedded files.This issue is essentially moved from alyf-de/erpnext_pdf-on-submit#76 (LMK-16). pdf_on_submit might expose a generic
before_attach_pdfhook; annex data model, validation, XML, and PDF transformation stay in eu_einvoice.Suggested Solution
Scope: Sales Invoice only.
Child table on Sales Invoice for additional annexes (explicit opt-in per row; link File, display name, order). Keep
einvoice_embedded_documentas the primary supporting document. Freeze the table on submit. E Invoice Settings: prompt to add SI attachments —always/ask/never(default ask on submit). Expose the list in print formats viadoc(docs/snippet only).Shared annex list (
get_annex_attachmentsor equivalent) for XML generation and PDF building.XML: N×AdditionalReferencedDocument with TypeCode 916 by default;
#ef=<filename>links to PDF embeds for EN 16931 / EXTENDED; base64-encoded embedding in XML for XRECHNUNG. XRECHNUNG: no invoice XML in PDF (unchanged); Any standalone.xmlincludes annexes.PDF (ZUGFeRD / EN 16931 / EXTENDED):
_convert_pdf_to_pdfa(plain)once (Ghostscript whengsis available)facturx.generate_from_binary(pdfa, xml, attachments={…})— invoice CII + all annexes in one callattach_xml_to_pdfand reuse the same builder forbefore_attach_pdf(once pdf_on_submit ships the hook, or integrate intoattach_xml_to_pdfotherwise) anddownload_pdfValidation: XRechnung §8.2 MIME allowlist (7 types, including
application/xml); OZG-RE Tier 1 hard limits — 15 MB total, 200 files; warn threshold from E Invoice Settings.Tests on v16; mandatory v15 backport after v16 is stable.
Acceptance (summary): Multi-annex submit PDF + matching CII; Schematron-valid fixture; MIME/size rejects; XRECHNUNG behaviour preserved; PDF/A-3b on a representative hybrid sample.
Alternatives
PdfWriter)attach_xml_to_pdfattach_xmlfor N annexesAdditional Context
before_attach_pdfhook in pdf_on_submit (replaces directattach_xml_to_pdfimport). Can be mitigated by implementing everything intoattach_xml_to_pdfbut that is actually out of scope for that function.