Aller au contenu principal

Modèles PDF

L'écran Modèles PDF est la bibliothèque de mises en page PDF réutilisables utilisées par NomaUBL au moment du rendu d'une facture. Chaque mise en page est une ressource pdf-template enregistrée dans config-pdf.json ; les modèles de document désignent une mise en page par nom via leur propriété pdfTemplate — une même mise en page peut donc être partagée entre plusieurs documents.

La page couvre quatre opérations :

  • gérer le catalogue (Ajouter / Importer / Copier / Supprimer) ;
  • éditer une mise en page — liste de sections, bascules par section pour les sections prédéfinies, composition libre pour les sections block ;
  • désigner un défaut pour les documents qui ne portent pas de mise en page explicite ;
  • prévisualiser le résultat sur une facture d'exemple sans quitter la page.

La page fonctionne quel que soit le système source — JD Edwards, SAP, NetSuite ou ERP personnalisé. L'entrée utilisée est l'UBL 2.1 généré, et non le XML source.

Nouveauté en 2026.05.1

Les modèles PDF étaient auparavant édités en ligne sur la page Documents (onglet PDF Template) et stockés dans les propriétés du modèle de document. Ils sont désormais des ressources partageables à part entière, dotées de leur propre page. L'onglet de la page Documents existe toujours, mais il choisit désormais une mise en page par nom depuis le catalogue de cette page, au lieu de contenir le JSON en ligne.


Accès à la page

  • Barre latérale → Gestion → Modèles PDF.
  • La page liste toutes les mises en page du catalogue. L'entrée built-in est la mise en page par défaut livrée — en lecture seule, toujours présente comme filet de sécurité.
  • La mise en page par défaut courante — c'est-à-dire celle utilisée par tout document sans pdfTemplate explicite — est marquée d'une étoile jaune ★ dans la barre latérale.

Vue d'ensemble

Modèles PDF+ Ajouter↑ Importer⎘ Copier🗑 Supprimer★ Définir par défautRechercher…built-inModèle livré · lecture seulefactoryfacture-frMise en page FR standardavoirVariante facture d'avoirrecu-destinataireReçu compactfacture-frMise en page FR standardSaveSECTIONS+ header+ lineTable+ block⋮⋮HeaderFournisseur · méta facture⋮⋮PartiesBoîtes Client + Livraison⋮⋮Line TableTableau principal 7 colonnesMETAS☑ N° de facture☑ Date d'émission☐ Référence acheteurSUPPLIERS☑ SIREN☑ Forme légale☐ Téléphone⋮⋮Block · payment-termsPiloté par XPath⋮⋮VAT Breakdown👁 AperçuBarre d'actionsgestion + désignation du défautCatalogue★ marque le défaut · factory en lecture seuleSélecteur de sectionprédéfinies + block (XPath)Tiroir par sectionbascules groupées ou canvasSection blockmise en page XPath libreAperçu en directrendu sur un UBL d'exemple

La page comporte un catalogue à gauche qui liste les mises en page enregistrées, et un éditeur à droite dédié à la mise en page sélectionnée. L'éditeur est identique à l'onglet PDF Template d'un modèle de document — même liste de sections, même tiroir par section, même aperçu en direct. La différence : le résultat est enregistré dans le catalogue sous un nom, plutôt que rattaché à un seul document.


Résolution d'une mise en page

Au moment du rendu PDF d'une facture, NomaUBL parcourt une chaîne en trois temps pour choisir la mise en page :

  1. Le modèle de document de la facture (lu depuis F564231.UHTMPL) a une propriété pdfTemplate — si elle est renseignée, c'est ce nom qui s'applique.
  2. À défaut, c'est la propriété defaultPdfTemplate du modèle global qui s'applique — réglée sur cette page via le bouton Définir par défaut.
  3. À défaut, la mise en page intégrée built-in s'applique — toujours présente, jamais supprimable.

Cette troisième étape est le filet de sécurité : un environnement tout juste installé produit des PDF cohérents avant même qu'une mise en page soit créée.


Actions de la barre supérieure

La barre d'actions couvre le cycle de vie du catalogue et la désignation du défaut.

ActionEffet
AjouterOuvre une modale qui demande un nom et une description. Crée une ressource pdf-template vide — l'ajout des sections se fait ensuite dans l'éditeur.
ImporterCharge un fichier JSON produit par une autre instance (ou par l'action Exporter). Met à jour le modèle correspondant si le nom existe déjà, sinon le crée. Le nom réservé built-in est rejeté.
CopierDuplique la mise en page sélectionnée sous un nouveau nom. La méthode la plus rapide pour dériver une variante à partir de built-in ou d'un modèle existant spécifique à un client.
SupprimerSupprime la mise en page sélectionnée après confirmation. Bouton désactivé sur built-in.
Définir par défautEnregistre le nom de la mise en page sélectionnée dans global.defaultPdfTemplate. Tout document sans pdfTemplate explicite utilise alors cette mise en page.
Remettre par défautVide global.defaultPdfTemplate, ce qui ramène la résolution sur built-in.

Le catalogue

La barre latérale liste toutes les mises en page enregistrées, plus la built-in livrée.

  • built-in — épinglée en haut, en lecture seule, marquée d'un badge factory. Sa sélection ouvre l'éditeur en mode lecture seule, signalé par un bandeau. Copier est la seule manière d'en dériver une mise en page éditable.
  • Marqueur ★ — la mise en page utilisée comme défaut pour les documents sans pdfTemplate explicite. Une seule mise en page a l'étoile à un instant donné.
  • Description — libellé libre enregistré sur la ressource. Apparaît à la fois dans la barre latérale et dans le sélecteur PDF Template d'un modèle de document.

Deux types de sections

Une mise en page est une suite de sections. Deux familles cohabitent dans un même modèle.

Sections prédéfinies — éléments de mise en page éprouvés

Neuf sections prédéfinies réordonnables couvrent la forme standard d'un PDF de facture : Header, Parties, Agent, Line Table, Document Allowances, VAT Breakdown, Totals, Payment, Notes. Chacune s'appuie sur une classe Java qui rend la partie correspondante d'une facture EN 16931 ; l'utilisateur en règle la visibilité via les bascules par section dans le tiroir intégré.

Le tiroir regroupe les bascules par préfixe Catégorie · Nom et les présente en colonnes côte à côte qui reflètent la mise en page PDF — Header se lit comme METAS | SUPPLIERS, Line Table comme Group headers | Columns | Sub-details — au lieu d'une longue liste plate. Les bascules utilisent le composant Checkbox rond-bleu pour une cohérence visuelle en mode sombre.

Liste complète des bascules par section prédéfinie :

  • Header — huit bascules META · … (numéro de facture, date d'émission, date d'échéance, références contrat / commande / acheteur, type de facture, profil ID), plus six bascules Supplier · … (adresse, SIREN, forme légale, TVA, téléphone, e-mail).
  • Parties — boîtes Client et Livraison, avec bascules séparées pour SIREN, TVA, adresse, identifiant de localisation et un interrupteur principal Show Delivery box (désactivé, la mise en page rend un bloc Client en colonne unique).
  • Line Table — trois bascules d'en-tête de groupe (Delivery group, Page break per delivery, Document Reference group), sept bascules de colonnes (Line #, Description, Quantity, Unit, Unit Price, Amount, Tax) et sept bascules de sous-détail pour les métadonnées de ligne (BT-127, BT-134/135, BT-156, BT-157, BT-158, remises / charges, propriétés additionnelles d'article).
  • Document Allowances — bascules de colonnes pour type, motif, montant, taxe.
  • VAT Breakdown — bascules de colonnes pour catégorie, taux, base imposable, montant de TVA (une colonne d'exemption apparaît automatiquement lorsqu'elle est présente).
  • Totals — sept bascules de lignes couvrant la pile complète (Total HT, Allowances, Charges, Tax Exclusive, Total Tax, Total TTC, Amount Payable).
  • Payment — bascules pour moyen de paiement / IBAN / BIC / mention de conditions de paiement.
  • Notes — bascule unique pour développer les préfixes [PMD] / [PMT] à partir du catalogue note-types.

Sections block — composition libre pilotée par XPath

La nouvelle section block est une primitive pilotée par XPath qui permet de composer toute mise en page non couverte par les sections prédéfinies. Un block est un arbre de nœuds typés :

TypeUsage
textChaîne littérale.
fieldRend une valeur XPath, avec libellé inline optionnel et sélecteur de format — date, currency, number, percent.
imageInsère une image (logo, filigrane, signature).
spacer / hrEspace vertical ou filet horizontal.
row / columnConteneur avec contrôles align (start / center / end) et gap. align: end et align: center réduisent la ligne à environ 50 % pour qu'une paire libellé + valeur reste groupée plutôt qu'étirée sur toute la page.
repeatXPath retournant une NodeList ; le child du block est rendu une fois par occurrence.
ifXPath retournant un booléen ; le child du block est rendu si vrai, masqué sinon.
tableGrille lignes × colonnes avec bordures de cellules optionnelles et ligne d'en-tête stylée. Définir xpath la fait itérer (une ligne par occurrence), les enfants servant de gabarit par ligne.

Plusieurs blocks peuvent coexister dans un même modèle — par exemple un pour des mentions légales françaises, un pour une table structurée de conditions de paiement, un pour un filigrane image. Chaque block a un name utilisateur affiché à côté de la ligne de section dans l'éditeur ; un modèle qui contient trois blocks se lit ainsi Block · payment-terms, Block · legal-mentions, Block · watermark.

Conventions XPath dans un block

  • Le sélecteur garde les préfixes de namespace cbc: / cac: — requis par le moteur namespace-aware ; un XPath saisi à la main sans préfixe ne correspondra à rien.
  • Les sélections sont émises en /*/<chemin-complet> pour être indépendantes de la racine du document (le même chemin s'applique à Invoice comme à CreditNote).
  • À l'intérieur d'un ancêtre itérant (un repeat ou une table munie d'un xpath), le sélecteur supprime en plus le chemin de l'itérateur pour que les cellules enfants démarrent en XPath relatif (cbc:TaxAmount plutôt que /*/cac:TaxTotal/cac:TaxSubtotal/cbc:TaxAmount). Les gabarits de ligne restent ainsi portables quand l'itérateur change.

Éditeur visuel

Une section block s'ouvre dans le BlockCanvasEditor plutôt que dans une zone JSON brute. L'éditeur comporte trois panneaux empilés et une sortie de secours JSON.

PanneauRôle
ArbreVue indentée de tous les nœuds du block, avec une étiquette de type (text, field, repeat, table, …). Cliquer un nœud le sélectionne ; la sélection pilote à la fois la barre d'outils et l'inspecteur.
Barre d'outilsAjout d'enfant / encapsulation / dégagement / suppression / déplacement haut-bas — opérations appliquées au nœud sélectionné. Mêmes opérations disponibles via raccourcis clavier.
InspecteurFormulaire d'attributs par type (XPath, libellé, format, alignement, gap, …) plus un sous-panneau Style couvrant police, graisse, taille, couleur, alignement et marges intérieures.

Détail subtil mais important en haut de l'inspecteur : un sélecteur Type qui transforme le nœud sélectionné sur place — passage de column à repeat sans suppression / recréation. Les attributs compatibles (enfants, style) sont reportés par le helper transmuteKind. Même mécanisme pour le cas fréquent de promotion d'un block statique en block itérant une fois la forme des données identifiée.

Le bouton Aperçu en direct en haut du formulaire ouvre une modale 960 × 85vh qui rend la configuration courante sur une facture d'exemple — l'enregistrement (Enregistrer) pendant que la modale est ouverte met à jour l'iframe en direct. Le contrôle Charger un échantillon XML est remonté à l'en-tête du modèle ; ainsi un seul échantillon alimente l'autocomplétion XPath de chaque block du modèle.


API REST

La page lit et écrit via les endpoints de templates standards — mêmes routes que les autres types de ressources.

Méthode + cheminRôle
GET /api/templatesListe tous les modèles ; la page filtre par type = pdf-template.
GET /api/templates/{nom}Charge une mise en page (le JSON figure dans la propriété template).
POST /api/templatesCrée une mise en page (Add).
POST /api/templates/{from}/copy/{to}Duplique (Copy).
PUT /api/templates/{nom}Enregistre les modifications.
DELETE /api/templates/{nom}Supprime une mise en page. Le nom réservé built-in est rejeté.
POST /api/pdf-templates/previewRend un JSON pdfTemplate arbitraire face à une facture d'exemple — utilisé par l'iframe d'aperçu.
PUT /api/templates/global (avec defaultPdfTemplate)Backend des actions Set as default / Reset to factory.

Conseils & bonnes pratiques

  • Partir de built-in via Copier. La mise en page livrée est une base solide — préférer la dériver par copie et ajustement de bascules plutôt que de partir d'un modèle vide.
  • Un seul modèle, plusieurs documents. Pour chaque variante de facture (standard, avoir, reçu destinataire …), privilégier un modèle partagé plutôt qu'un JSON inline par document. Le bénéfice : un point d'édition unique quand les mentions légales ou le jeu de colonnes évoluent.
  • Désigner un défaut tôt. Marquer une mise en page comme défaut avant le branchement des modèles de document spécifiques aux clients — chaque nouveau document utilise alors ce défaut implicitement, et la propriété pdfTemplate explicite reste réservée aux vraies variantes.
  • Utiliser block pour ce que les sections prédéfinies ne couvrent pas. Mentions légales personnalisées, pieds de page spécifiques à un pays, blocs de signature structurés, filigranes — autant de cas mieux traités par un block que par une section prédéfinie.
  • Itérer dans la modale d'aperçu. Basculer une section et observer l'iframe se re-rendre dans la modale est le moyen le plus rapide d'arriver à une mise en page sans quitter l'éditeur.
  • Réutiliser l'échantillon XML. Un seul Charger un échantillon XML sur l'en-tête du modèle alimente le sélecteur de chaque block — chargement unique par session d'édition, et chaque autocomplétion XPath fonctionne immédiatement.
  • Ne pas supprimer built-in. Le bouton est désactivé sur cette entrée pour cette raison — c'est le filet de sécurité au bout de la chaîne de résolution.