forked from seb_vallee/BillManager
correction pour conformité complete PDF/A-3
codé avec l'aide de claude IA
This commit is contained in:
@@ -159,29 +159,64 @@ def changer_statut_facture(
|
||||
|
||||
from generate_facturx_jinja2 import Invoice, Party, Address, InvoiceLine, filter_amount, filter_datefmt
|
||||
|
||||
|
||||
@router.get("/{facture_id}/pdf", response_class=HTMLResponse)
|
||||
@router.get("/{facture_id}/pdf")
|
||||
def telecharger_pdf(request: Request, facture_id: int, db: Session = Depends(get_db)):
|
||||
from weasyprint import HTML
|
||||
from weasyprint import HTML, Attachment
|
||||
from facturx import generate_from_binary
|
||||
import hashlib
|
||||
import pikepdf
|
||||
from pikepdf import Name
|
||||
import io
|
||||
|
||||
facture = db.query(Facture).get(facture_id)
|
||||
if not facture:
|
||||
raise HTTPException(status_code=404)
|
||||
|
||||
# 1. XML Factur-X
|
||||
invoice = get_invoice_data(facture_id, db)
|
||||
xml_str = generate_facturx_xml(invoice)
|
||||
xml_bytes = xml_str.encode("utf-8")
|
||||
|
||||
# 2. Rendu HTML → PDF simple (pas PDF/A-3 ici)
|
||||
html_content = templates.get_template("pdf/facture.html").render({
|
||||
"facture": facture,
|
||||
"settings": settings,
|
||||
})
|
||||
pdf_bytes = HTML(string=html_content, base_url=".").write_pdf(
|
||||
pdf_variant="pdf/a-3b",
|
||||
)
|
||||
|
||||
pdf_bytes = HTML(string=html_content, base_url=".").write_pdf()
|
||||
# 3. generate_from_binary gère :
|
||||
# - l'intégration du XML
|
||||
# - les métadonnées XMP Factur-X (DocumentType, DocumentFileName, etc.)
|
||||
# - la conformité PDF/A-3b
|
||||
pdf_bytes = generate_from_binary(
|
||||
pdf_bytes,
|
||||
xml_bytes,
|
||||
flavor="factur-x",
|
||||
level="BASIC",
|
||||
)
|
||||
|
||||
# 4. Corriger uniquement /EF/F/Subtype → /text/xml avec pikepdf
|
||||
pdf_io = io.BytesIO(pdf_bytes)
|
||||
with pikepdf.open(pdf_io) as pdf:
|
||||
names = pdf.Root.Names.EmbeddedFiles.Names
|
||||
i = 0
|
||||
while i < len(names):
|
||||
i += 1 # sauter la clé (string)
|
||||
if i < len(names):
|
||||
obj = names[i]
|
||||
try:
|
||||
obj.EF.F.Subtype = Name("/text/xml")
|
||||
except Exception:
|
||||
pass
|
||||
i += 1
|
||||
|
||||
output = io.BytesIO()
|
||||
pdf.save(output)
|
||||
pdf_bytes = output.getvalue()
|
||||
|
||||
filename = f"facture-{facture.numero}.pdf"
|
||||
|
||||
xml_bytes = generate_facturx_xml(get_invoice_data(facture_id, db))
|
||||
|
||||
pdf_bytes = generate_from_binary(pdf_bytes, xml_bytes)
|
||||
|
||||
filename = f"facture-{facture.numero}.pdf"
|
||||
|
||||
return Response(
|
||||
content=pdf_bytes,
|
||||
media_type="application/pdf",
|
||||
|
||||
Reference in New Issue
Block a user