Skip to content

Feature: Multi-select annexes on Sales Invoice (PDF/A-3 embed + CII 916 XML embed) #261

@dafrose

Description

@dafrose

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.

  1. 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).

  2. Shared annex list (get_annex_attachments or equivalent) for XML generation and PDF building.

  3. 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.

  4. 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
  5. 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.

  6. 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#76before_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.

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request
No fields configured for Feature.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions