ediverse Explorer la plateforme

À la une PEPPOL BIS Billing 3.0 L’obligation européenne d’e-invoicing arrive : France sept 2026, Belgique janv 2026, Allemagne 2025.

Content Enricher

Un message EDI ne porte presque jamais tout ce dont l'aval a besoin. Le Content Enricher remplit les vides en consultant un référentiel externe : GLN → adresse, GTIN → libellé, code pays → nom long. Le pattern de l'injection de contexte.

Problème

Les messages EDIFACT et X12 sont conçus pour être compacts : ils portent des identifiants (GLN sur 13 chiffres, GTIN sur 13 chiffres, SIRET sur 14) plutôt que des libellés. Le partenaire émetteur s'attend à ce que le récepteur sache résoudre ces identifiants vers les informations associées — nom, adresse, TVA, catégorie produit. Mais quand on alimente un ERP, un système de facturation ou un portail fournisseur, on a souvent besoin de ces champs en clair. Sans enrichissement, on doit faire ces lookups à 200 endroits dans le code aval.

Forces

  • Compacité du protocole vs richesse de l'application. EDIFACT optimise la bande passante des années 80. L'application moderne veut tout en clair.
  • Source de vérité externe. Le référentiel (Master Data Management, ERP) est l'autorité — pas le message qui transite.
  • Coût des lookups. Chaque lookup a un coût (latence, réseau). À l'échelle d'un ORDERS avec 200 lignes, 200 lookups séquentiels deviennent prohibitifs.
  • Cohérence temporelle. Le nom associé à un GLN peut changer (rebranding, fusion). On doit donc choisir entre figer l'enrichissement au moment de la réception ou re-résoudre à la consultation.

Solution

EIP §336 (Hohpe & Woolf, 2003) modélise le Content Enricher comme un composant qui : (a) reçoit un message canonique, (b) extrait les identifiants à enrichir, (c) consulte un référentiel externe, (d) injecte les champs résolus dans le message et (e) republie. La consultation peut être synchrone (lookup immédiat) ou asynchrone (pré-cache mis à jour par flux séparé).

plaintext topology.txt
ORDERS canonique          Content Enricher        ORDERS enrichi
   (GLN seul)               (resolves GLN → addr)
   ─────────────             ─────────────────         ───────────────
   {                                                    {
     "buyer": {              ┌─────────────┐             "buyer": {
       "gln": "871234..."  ──▶ external    │              "gln": "871234...",
     }                       │ partner-db  │              "name": "Carrefour",
   }                         │             ├──▶          "address": {
                              └─────────────┘                "street": "...",
                                                            "city": "Massy",
                                                            "country": "FR"
                                                          }
                                                        }
                                                      }

Topologie

Trois variantes principales :

  • Synchronous Enricher. Lookup à chaque message. Simple, mais sensible à la latence et à la disponibilité du référentiel.
  • Cached Enricher. Lookup avec cache TTL (10 minutes à 24 heures selon le domaine). Réduit drastiquement la charge sur le référentiel.
  • Pre-loaded Enricher. Réplique locale du référentiel maintenue à jour par changefeed (CDC, événements master data). Latence quasi-nulle, mais nécessite une infrastructure d'événementiel maître.

Implémentation EDI

Trois enrichissements emblématiques :

  • GLN → partner record. Le partenaire envoie NAD+BY+8712345600014::9. L'enricher résout vers une fiche partenaire avec nom, adresse, IBAN, TVA, contact. La table de résolution est typiquement la base des fournisseurs/clients de l'ERP.
  • GTIN → produit. Le partenaire envoie LIN+1++4006381333931:EN. L'enricher résout vers une fiche produit avec libellé, catégorie, conditionnement, taux de TVA. La table de résolution est le catalogue produits (PIM).
  • Code pays ISO 3166 → nom + zone fiscale. Le message porte FR ; l'enricher injecte « France », zone EU, code monétaire EUR par défaut. Cas du référentiel statique embarqué (pas besoin de lookup externe).

Avant enrichissement :

json order-before.json
{
  "type": "ORDER",
  "number": "PO-12345",
  "buyer": { "gln": "8712345600014" },
  "supplier": { "gln": "5412345600015" },
  "lines": [
    { "item": { "gtin": "4006381333931" }, "quantity": 24 }
  ]
}

Après enrichissement :

json order-after.json
{
  "type": "ORDER",
  "number": "PO-12345",
  "buyer": {
    "gln": "8712345600014",
    "name": "Carrefour Centrale Massy",
    "address": {
      "street": "33 Avenue Émile Zola",
      "city": "Massy",
      "postalCode": "91300",
      "country": "FR"
    },
    "vatId": "FR12652014051"
  },
  "supplier": {
    "gln": "5412345600015",
    "name": "Brasserie XY",
    "vatId": "BE0405841683"
  },
  "lines": [
    {
      "item": {
        "gtin": "4006381333931",
        "name": "Pelikan rollerball ink black",
        "category": "stationery"
      },
      "quantity": 24
    }
  ]
}

Cache, fraîcheur et politique d'échec

Trois questions à trancher :

  • Quel TTL ? Pour les données partenaires relativement stables (nom, adresse), 24 heures est raisonnable. Pour des données plus volatiles (prix produit, stock), 5-15 minutes ou pas de cache.
  • Que faire si le lookup échoue ? Trois options : (a) bloquer le message en Dead Letter Channel pour examen, (b) passer le message en aval sans enrichissement avec un flag enrichmentSkipped: true, (c) appliquer une valeur par défaut documentée. La bonne réponse dépend du criticité métier.
  • Quoi figer dans le message ? Si l'ordre doit survivre à un changement de référentiel (un GLN qui change de nom), figer le snapshot des champs enrichis. Sinon, ne stocker que l'identifiant et re-résoudre à la lecture.

Anti-patterns

  • Lookup synchrone sans timeout. Si le référentiel met 30 secondes à répondre, on bloque le pipeline EDI pour 30 secondes. Toujours définir un timeout strict (1-3 secondes) avec circuit breaker.
  • Lookup dans une boucle. 200 lignes = 200 appels séquentiels = inacceptable. Bulk lookup obligatoire.
  • Pas de cache. Pour les données stables, ne pas cacher c'est multiplier inutilement la charge sur l'ERP.
  • Cache sans invalidation. Un cache 24h sans mécanisme d'invalidation propagera une donnée obsolète pendant 24h après un changement maître. Si le référentiel publie des événements de mutation, l'enricher doit y être abonné.
  • Enrichissement en silence partiel. Si seule la moitié des champs a pu être résolue, le message doit le signaler explicitement. Le consommateur aval doit voir la trace de l'incomplétude.

Patterns liés

  • Canonical Model — le canonique doit prévoir les champs optionnels pour les données enrichies.
  • Circuit Breaker — protéger le pipeline contre une panne du référentiel.
  • Content-Based Router — souvent placé après l'enrichissement, parce que la décision a besoin des champs résolus.

Sources