Wiki
Pipeline de generation PDF
Comment QuoteNode genere des documents PDF brandises a partir de snapshots d'offre avec Thymeleaf et Gotenberg.
Pipeline de generation PDF
QuoteNode genere des documents PDF prets a l’impression a partir des donnees d’offre au moyen d’un pipeline en deux etapes : rendu HTML via des templates Thymeleaf, puis conversion PDF via Gotenberg.
Vue d’ensemble du pipeline
Offer Snapshot (JSON)
│
▼
Thymeleaf Template Engine
├── fragments de layout (header, tableau des lignes, totaux, footer)
├── CSS inline pour compatibilite Gotenberg
├── images produit embarquees en URI base64
└── support de pagination (Page X/Y)
│
▼
Document HTML (complet, autonome)
│
▼
Gotenberg (conteneur base sur Chromium)
│
▼
Fichier PDF (stocke avec checksum SHA-256)
Rendu base sur snapshots
Les PDF sont toujours rendus a partir de snapshots immuables, jamais a partir des donnees d’offre vivantes. Quand une offre est envoyee :
- Le systeme capture un snapshot JSON complet de l’etat de l’offre
- Ce snapshot inclut : donnees client, toutes les lignes, prix, taux FX, configuration de branding et reglages de modele
- Le snapshot est stocke et versionne (incrementation de
snapshot_versiona chaque renvoi)
Cela garantit que le PDF represente exactement ce qui a ete propose a une date donnee, quelles que soient les modifications ulterieures du catalogue, des donnees client ou du branding.
Systeme de modeles
Familles de modeles
L’implementation actuelle inclut la famille de modeles CLASSIC_B2B_TECHNICAL. D’autres variantes sont prevues :
MINIMAL_B2B— layout epure pour des offres simplesB2C_FRIENDLY— presentation orientee grand public avec images produitMULTI_CURRENCY— optimise pour les tableaux multi-devisesSERVICE_HOURS— centre sur les offres de service au temps passe
Structure du modele
Chaque modele PDF est compose de :
- Header — logo vendeur, nom de societe, adresse et coordonnees
- Meta section — adresse destinataire, numero d’offre, nom du commercial, date et validite
- Items table — colonnes configurables avec details de prix
- Totals summary — sous-total, remises, transport, ventilation TVA et total general
- Trading conditions — conditions de paiement, garantie, livraison et transport
- Signature block — espace reserve aux signatures
- Footer — informations legales de l’entreprise (NIP, KRS, tribunal d’enregistrement)
Colonnes configurables
Les colonnes du tableau de lignes sont pilotees par offre via les reglages de modele :
| Reglage | Effet |
|---|---|
showSku | Affiche / masque la colonne SKU |
showImages | Affiche les photos produit dans le tableau |
imageSize | Petit (60px), moyen (90px) ou aucun |
showDescription | Inclut les descriptions produit |
showUnit | Affiche la colonne unite de mesure |
showVatColumn | Affiche la colonne TVA (auto-detectee si plusieurs taux sont presents) |
priceMode | Affichage NET, GROSS ou NET+VAT+GROSS |
discountDisplay | BAKED_IN, SHOW_COLUMN ou HIDDEN |
Integration du branding
Le PDF applique automatiquement le branding du tenant :
- Logo — logo entreprise (PNG ou SVG) place dans le header avec taille automatique
- Primary color — appliquee aux titres, bordures et accents
- Accent color — appliquee aux elements secondaires
- Company details — nom, adresse, telephone, email, informations d’enregistrement
- Custom offer title — surcharge du titre par defaut “OFERTA CENOWA”
- “Powered by” badge — affiche sur l’edition gratuite, supprimable a partir de Pro
Modes de traitement
Synchrone (par defaut)
Pour les offres de moins de 50 lignes :
- La requete API declenche la generation du PDF
- Thymeleaf rend le HTML puis Gotenberg convertit en PDF
- Le flux PDF est renvoye dans la meme reponse HTTP
- Objectif SLA : p95 < 3 secondes
Asynchrone
Pour les grosses offres (50+ lignes) ou lorsque le serveur est charge :
- La requete API renvoie HTTP 202 avec un
jobId - Un enregistrement
PdfJobest cree en base avec le statutPENDING - Un worker recupere le job (pattern SKIP LOCKED, 2 workers concurrents)
- En cas de succes : le PDF est stocke, le statut passe a
COMPLETED, une notification est envoyee - En cas d’echec : retry avec backoff exponentiel (30s → 120s → 600s, 3 tentatives max)
- Les jobs en echec definitif sont deplaces dans une table Dead Letter Queue (DLQ)
Stockage et retention
Les PDF generes sont stockes comme fichiers, avec metadonnees dans la table generated_documents :
- Filename — identifiant unique
- File size — taille en octets
- SHA-256 checksum — verification d’integrite
- Snapshot version — lien vers le snapshot utilise pour la generation
- Created at — timestamp de generation
Politique de retention : les PDF sont conserves 365 jours par defaut (configurable). Apres cette periode, les fichiers peuvent etre nettoyes mais l’enregistrement de metadonnees reste conserve pour audit.
Configuration de Gotenberg
Gotenberg tourne comme un conteneur Docker separe dans la stack de deploiement. Il utilise Chromium pour la conversion HTML → PDF, ce qui apporte :
- un rendu CSS precis, y compris flexbox, grid et CSS moderne,
- une pagination avec marges configurables,
- la prise en charge de plusieurs formats de page (A4 par defaut, Letter, tailles personnalisees),
- le rendu des headers et footers avec pagination.
Le backend communique avec Gotenberg via son API HTTP. Aucune interaction directe avec Chromium n’est necessaire.