misc: allow PDF attachments on Factur-X files (#83897)

This commit is contained in:
Benjamin Dauvergne 2024-02-20 16:09:02 +01:00
parent caa4309db9
commit 1ad965ffa1
3 changed files with 53 additions and 2 deletions

View File

@ -18,6 +18,7 @@ import logging
import os
import subprocess
import tempfile
import typing
import facturx
from django.template.loader import render_to_string
@ -60,7 +61,19 @@ def to_pdfa(pdf_bytes: bytes, icc_profile: str = DEFAULT_ICC_PROFILE):
DEFAULT_FACTURX_TEMPLATE = 'factur-x.xml'
def add_facturx_from_bytes(pdf_bytes: bytes, facturx_context: dict, template: str = DEFAULT_FACTURX_TEMPLATE):
def add_facturx_from_bytes(
pdf_bytes: bytes,
facturx_context: dict,
template: str = DEFAULT_FACTURX_TEMPLATE,
attachments: typing.Sequence[tuple[str, bytes]] = (),
):
pdfa_bytes = to_pdfa(pdf_bytes)
attachments_dict = {filename: {'filedata': content} for filename, content in attachments}
facturx_xml = str(render_to_string(template, facturx_context)).encode('utf-8')
return facturx.generate_facturx_from_binary(pdfa_bytes, facturx_xml)
with tempfile.NamedTemporaryFile(prefix='invoice-facturx-', suffix='.pdf') as f:
f.write(pdfa_bytes)
facturx.generate_facturx_from_file(f, facturx_xml, attachments=attachments_dict)
f.seek(0)
result = f.read()
f.close()
return result

View File

@ -19,6 +19,7 @@ import io
import xml.etree.ElementTree as ET
import facturx
import pypdf
import pytest
from eo_gestion.eo_facture.facturx import add_facturx_from_bytes, to_pdfa
@ -212,3 +213,39 @@ def test_add_facturx_from_bytes_facture_avoir(fake_invoice_bytes):
],
],
]
# https://stackoverflow.com/questions/2438800/what-is-the-smallest-legal-zip-jar-file
MINIMAL_ZIP_FILE = b'PK\x05\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
def test_add_facturx_from_bytes_with_attachments(fake_invoice_bytes):
facturx_ctx = {
'numero_de_facture': 'F20190001',
'type_facture': '380',
'date_emission': datetime.date(2019, 1, 1),
'chorus_service_code': 'service-code',
'vendeur': 'Entr\'ouvert',
'vendeur_siret': '44317013900036',
'vendeur_tvai': 'FR09491081899',
'client_siret': '1234',
'client_name': 'RGFIPD',
'numero_engagement': '5678',
'numero_marche': 'ABCD',
'montant_ht': '10',
'montant_ttc': '12',
'montant_tva': '2',
'taux_tva': 20.0,
}
attachments = [
('PJ1.zip', MINIMAL_ZIP_FILE),
('PJ2.zip', MINIMAL_ZIP_FILE),
]
facturx_bytes = add_facturx_from_bytes(fake_invoice_bytes, facturx_ctx, attachments=attachments)
pdf_reader = pypdf.PdfReader(io.BytesIO(facturx_bytes))
assert [(k, v) for k, v in pdf_reader.attachments.items() if k != 'factur-x.xml'] == [
('PJ1.zip', [MINIMAL_ZIP_FILE]),
('PJ2.zip', [MINIMAL_ZIP_FILE]),
]

View File

@ -20,6 +20,7 @@ setenv =
deps =
-rtest-requirements.txt
factur-x==1.8
pypdf
commands =
py.test {env:COVERAGE:} {env:JUNIT:} {posargs}