mardi 23 août 2011

Gestion des échanges EDI avec Talend

Il existe aujourd'hui sur le marché pas mal d'outils de "mapping" EDI, c'est-à-dire permettant de faire la correspondance, de manière plus ou moins graphique, entre des colonnes de un ou plusieurs éléments source et un ou plusieurs éléments cible. Ces éléments pouvant être des fichiers (au format EDIFACT, XML, CSV, ...), ou des tables.

Mais la traduction des fichiers échangés entre partenaires (client, fournisseurs, sous traitants, ...) ne s'arrête pas là. Il faut en général gérer un certain nombre de règles de gestion, dépendant du métier, du partenaire (plus ou moins "souple"), voire d'un dossier en particulier.

Certaines règles sont simples (formatage de zones, calcul simple entre 2 ou plusieurs zones, ...) mais d'autres viennent déstructurer le flux normal des données présentes dans l'élément source.
Par exemple, on imagine un flux de données source contenant des commandes et des lignes de commande organisées par article / produit, chaque ligne contenant également des informations sur le client destinataire de la ligne.

Mais le partenaire a besoin des données organisées par client destinataire, avec un sous total par article, et une ligne de total général, pour contrôle.
Et c'est là que le bât blesse : on arrive dans ce cas là (qui est loin d'être la minorité) aux limites de la grande majorité des outils de mapping EDI : il est alors nécessaire d'effectuer des pré ou post traitements soit avec le langage inclus dans l'outil, ou pire avec un outil externe.

Par expérience, je peux vous assurer que ces traitements peuvent devenir des usines à gaz et diminuer fortement la maintenabilité des échanges développés avec ces outils.

Talend quand à lui possède un composant de mapping relativement puissant mais ne gère pas (encore) toutes les subtilités des formats de fichier en entrée, notamment les formats EDI (EDIFACT ou INOVERT par exemple).
J'utilise donc une stratégie simple, efficace et, ce qui ne gâche rien, performante. Elle est utilisable avec n'importe quel outil d'échange de données normalement constitué.
Le principe est le suivant :
  • on charge les données des fichiers en entrée dans des tables d'une base de données relationnelle
  • chaque table possède des données identifiantes en plus des données des fichiers, qui permettent l'exécution simultanée de plusieurs jobs, sans se marcher sur les pieds (sans écraser les données du job voisin)
  • des requêtes SQL permettent d'extraire les données nécessaires en sortie, selon n'importe quel ordre et structure
    (je n'ai encore jamais vu un besoin auquel SQL ne savait pas répondre)
  • on formate le résultat en fonction du type de fichier en sortie
Les avantages de cette méthode sont multiples :
  • utilisable quelque soit l'outil d'échanges
  • beaucoup plus simple à écrire et à maintenir (sous réserve de bien structurer et commenter le SQL)
  • très performant (les moteurs de bases de données ont fait leurs preuves) : rapport de 1 à 10 sur certains traitements
  • Les données stockées en base de données peuvent être réutilisées pour envoyer des informations métiers aux utilisateurs ou leur permettre de rechercher eux même de l'information si on développe une petite application web pour cela (exemple : est-ce que la commande n° 234FR567 a bien été réceptionnée ?)
Voyons maintenant un exemple concret.
Nous allons traiter des données de facture au format EDIFACT (format de message INVOICE : http://www.stylusstudio.com/edifact/d96a/INVOIC.htm)
Globalement, le format du fichier est le suivant, chaque bloc est un segment (type de ligne) du message :
Le format attendu par le partenaire est propriétaire et le schéma ci-dessous résume les transformations à réaliser au niveau de la structure des données.





















1° étape : lecture du fichier au format EDIFACT

Non seulement la structure de ce type de fichier est complexe mais le format des données de chaque segment est tout à fait original. Qu'on en juge par un exemple :

UNB+UNOC:3+000272450154900013FIEV00+ACME+101203:1530+19146'
Les 3 premiers caractères indiquent le type de la ligne (ou segment).
le caractère "+" est le séparateur de chaque donnée.
Une même donnée peut être divisée en sous parties, séparées par le caractère ":", dans l'exemple ci dessus l'avant dernière donnée comporte une date (101203 => 03/12/2010) et une heure (1530 => 15:30).
Chaque ligne se termine par le caractère <'> (simple quote).

A part les 3 premiers caractères, déterminant le type de ligne, le format de chaque ligne varie complètement d'une ligne à l'autre. On va donc dans un premier temps utiliser un composant tFileInputPositional pour séparer les 3 premiers caractères et le reste de la ligne.















Le schéma en sortie de ce composant est le suivant :













La colonne "type" va nous permettre de reconnaître le type de ligne (segment) et la colonne "data" va être traitée (découpée), on va voir comment dans la suite de cet article.

Tout d'abord, un composant tJavaRow nous permet de renseigner quelques variables qui seront utilisées dans la suite du traitement et qui sont passées dans le schéma en sortie. Par exemple :

// le NAD party_qualifier est utilisé dans le tMap pour lier les segments NAD et RFF entre eux
if (input_row.type.equals("NAD")) {
globalMap.put("nadPartyQualifier", SixITUtils.getEdiElement(output_row.data, 1, 0));
}
A noter qu'une fonction faisant partie de la bibliothèque de fonctions 6 IT ("SixITUtils") est ici utilisée, afin de factoriser et simplifier le développement : la fonction "getEdiElement" permet de récupérer une partie d'une donnée contenue dans la ligne.

Ensuite, on utilise le composant tMap pour enregistrer les données du message dans des tables correspondant aux différents segments du message.















Le "type" de la ligne est utilisé pour envoyer les données dans les bonnes tables, grâce à l'option de filtre des éléments en sortie du composant tMap.
Chaque donnée contenue dans la ligne est extraite, grâce à la fonction déjà vue (getEdiElement) dans la colonne correspondante dans la table cible.
Certaines colonnes permettent de faire le lien entre les tables, par exemple les tables NAD et RFF.
D'autres colonnes permettent d'identifier de manière unique chaque ligne et de lier entre elles toutes les données traitées par le même job (process_id, message_ref).
Ci-dessous un extrait du paramétrage du tMap :

















Les tables en sortie sont toutes sur le même modèle :
  • une partie des colonnes permettent d'identifier chaque ligne et de lier les tables entre elles
  • la seconde partie contient les données propres à chaque type de ligne










Maintenant que l'ensemble des données du message EDI sont stockées dans des tables, vous allez pouvoir produire n'importe quel format de fichier ou fournir de l'information à vos utilisateurs, via une console de supervision métier par exemple, dans laquelle les utilisateurs pourront vérifier si une commande a bien été envoyée ou une facture a bien été reçue.

Nous verrons dans un prochain article la 2° étape du flux EDI : comment produire un fichier au format présenté au début de cet article.