--- title: "Intégration GNA → SAP-CPI" tags: [ERP, GNA, SAP-CPI, OAuth, middleware, API, BOO] status: draft standard_ref: architecture/erp-integration.md jira_refs: [LIM-89] confluence_refs: [] sources: - "LIM-89 GNA Mise en place de la communication API EasyWMS SAP CPI.md" - "recap_session_LIM-72_13-05-2026.md" last_updated: 2026-05-13 author: Arthur --- # Intégration GNA → SAP-CPI > **Résumé** : mise en place de la communication entre le GNA (middleware > EasyWMS) et SAP-CPI (middleware cloud SAP) pour l'envoi de tous les > messages WMS sortants. Authentification OAuth 2.0 client_credentials, > endpoint unique, routage par MessageType. > **Standard EasyWMS** : → voir [ERP Integration](../../concepts/erp-interface.md) > L'intégration standard cible généralement un ERP via API REST classique > (OAuth password grant). Chez Limagrain, la cible est **SAP-CPI** avec > un mécanisme spécifique. > Voir aussi : [LOC — Message périodique](loc-message-periodique.md), > [Référence messages](messages-reference.md), > [Mapping ERP-WMS](mapping-erp-wms.md) ## Contexte projet Dans le cadre du projet Limagrain, le middleware GNA doit envoyer les messages WMS vers SAP via la plateforme **SAP-CPI** (Cloud Platform Integration). Une implémentation de référence existe chez un autre client (AD) mais communique avec un ERP SAP-AIG via une API REST classique (OAuth password grant). L'intégration Limagrain est différente : elle cible **SAP-CPI** avec un **endpoint unique** et une authentification **OAuth 2.0 client_credentials**. ## Architecture technique ### Script principal Le script `CommonExportWebApi.boo` est le point d'entrée pour tous les exports WMS → SAP-CPI. Il gère l'authentification, le formatage et l'envoi des messages. ### Flux de communication ```mermaid sequenceDiagram participant WMS as EasyWMS participant GNA as GNA (BOO) participant OAuth as SAP OAuth Server participant CPI as SAP-CPI WMS->>GNA: Transaction WMS (LOC.SEND, REF01, etc.) GNA->>GNA: Vérifier cache token alt Token expiré ou absent GNA->>OAuth: POST /oauth/token (client_credentials) OAuth-->>GNA: Bearer token + expiration GNA->>GNA: Sauvegarder token sur disque end GNA->>CPI: POST /http/ATHInboundMessage Note right of CPI: Body: {MessageType, MessageSAP, data} CPI-->>GNA: HTTP 200 / erreur alt Erreur HTTP (hors 401) GNA->>CPI: Retry backoff (2s, 4s, 8s, 16s) end alt HTTP 401 GNA->>GNA: Échec immédiat (token invalide) end ``` ## Authentification OAuth 2.0 ### Mécanisme 1. Le GNA obtient un **token bearer** auprès du serveur SAP via un POST sur `/oauth/token` avec `client_id` et `client_secret` 2. Le grant type est `client_credentials` (pas de password grant) 3. Le token est **mis en cache sur disque** (fichier JSON) avec gestion de l'expiration (marge de sécurité de 60 secondes) 4. À chaque envoi, le GNA vérifie le cache : si le token est encore valide, il le réutilise ; sinon il en demande un nouveau ## Envoi des messages — Format du body Pour chaque message WMS exporté, le GNA envoie un POST vers l'endpoint unique SAP-CPI `/http/ATHInboundMessage` avec le body JSON suivant : ```json { "MessageType": "", "MessageSAP": "", "data": "" } ``` Le champ `MessageType` permet au iFlow CPI de **router le message** vers le bon traitement SAP. ## Table de correspondance MessageType → MessageSAP Le champ `MessageSAP` est déterminé par une table de correspondance entre le préfixe du MessageType WMS (3 premiers caractères) et le code SAP-CPI : | Code CPI | Équivalent WMS | Description | |----------|----------------|-------------| | ATH214 | Check flux retour (batch) | Vérification lot retour client | | ATH215 | REF (type = Supplier) | Finalisation réception fournisseur | | ATH217 | REF (type = Return) | Finalisation réception retour | | ATH201 | LOC | Message périodique delta mouvements | | ATH202 | LOF | Finalisation chargement | > ⚠️ Si un type de message n'a pas de correspondance dans la table, un > **warning** est logué et le champ MessageSAP n'est pas inclus dans le > body. ### Détermination conditionnelle du MessageSAP pour REF Le message REF peut être routé vers **ATH215** (Supplier) ou **ATH217** (Return) selon le type de préavis de réception (InboundOrder) lié : 1. Le **REF01Observer.boo** récupère le type de préavis via une requête LINQ sur `Context.RecLineInboundOrderLines` → `Context.InboundOrders` 2. Le type est transmis dans le champ `RecCustomAttributes.CstAtt20` du message REF01 3. Le script `CommonExportWebApi.boo` lit `CstAtt20` dans le payload JSON pour déterminer le `MessageSAP` : - Type Supplier → `ATH215` - Type Return → `ATH217` ## Cartographie complète des interfaces Athenzat Tous les flux entre SAP et EasyWMS sont identifiés par un code ATH. Source : doc CPI Maxime Tourrette (24/04/2026) + mail S15 Justine. ### Flux SAP → EasyWMS (entrants) | Code ATH | Type SAP | Type Easy | Description | |----------|----------|-----------|-------------| | ATH002 | BATMAS | ITM01 | Fiche article (Item) | | ATH103A | DELIVRY07 | ROR01 | Ordre de réception (Inbound delivery) | | ATH108 | ORDRSP | ROR01 | Ordre de réception retour (Return delivery) | | ATH103B | SHPUNT7 | RUT | Ordre de sortie (Outbound delivery) | | ATH102BOM | LOIPRO | SOR | Ordre d'expédition (Shipping order) | | ATH111 | ZSTKATH11 | ASN / STR | HU à recevoir / HU change | | ATH302 | ZQMINSPLOT | COR | Tâche inventaire / échantillon | ### Flux EasyWMS → SAP (sortants via CPI) | Code ATH | Type Easy | Type SAP | Description | |----------|-----------|----------|-------------| | ATH214 | Z_IATH214 | Z_IAT214 | Check Batch (vérification lot retour) | | ATH215 | REF | Z_IAT215 | Bon de réception fournisseur | | ATH217 | REF | Z_IAT217 | Bon de réception retour | | ATH201 | LOC / STV | Z_IAT201 | Mouvement stock (rangement ASRS, mvt HU, prep mix, customer flag, stock adjust) | | ATH202 | LOF | Z_IAT202 | Chargement (Loading / Goods Issue) | > **Note** : les flux ATH103A/B, ATH108, ATH111, ATH302 utilisent > l'infrastructure GNA standard (pas de custom CPI côté EasyWMS). > Seuls les flux sortants (ATH2xx) passent par `CommonExportWebApi.boo`. > **Note** : le flux ATH214 est le seul appelé **directement depuis un > workflow** (pas via GNA/BOO). Voir [Réception retour](../01-inbound/reception-retour.md). ## Gestion des erreurs — Retry avec backoff | Situation | Comportement | |-----------|-------------| | HTTP 200 | Succès — message envoyé | | HTTP 401 | **Échec immédiat** — token invalide, pas de retry | | Autre erreur HTTP | **Retry backoff exponentiel** : 2s → 4s → 8s → 16s | ## Configuration requise Six clés `CPI_*` à ajouter dans `CommonAppSettings.config` (section `appSettings`) : | Clé | Description | |-----|-------------| | CPI_AUTH_URL | URL du serveur d'authentification SAP OAuth | | CPI_CLIENT_ID | Identifiant OAuth | | CPI_CLIENT_SECRET | Secret OAuth (en clair dans le config) | | CPI_ENDPOINT_URL | Endpoint unique SAP-CPI (`/http/ATHInboundMessage`) | | CPI_TOKEN_PATH | Chemin du fichier cache token sur disque | | CPI_TIMEOUT | Timeout HTTP en secondes (auth + messages) | **Valeurs environnement TEST** : - `CPI_AUTH_URL` : `https://vilm-cpi-test-73ltxp48.authentication.eu30.hana.ondemand.com/oauth/token` - `CPI_ENDPOINT_URL` : `https://vilm-cpi-test-73ltxp48.it-cpi020-rt.cfapps.eu30.hana.ondemand.com/http/ATHInboundMessage` - Environnement PROD : URLs à définir ## Fichiers impactés | Fichier | Modification | |---------|-------------| | `Scripts2015/CommonExportWebApi.boo` | Script principal d'export WMS → SAP-CPI | | `Scripts2015/EasyWMS/XML/REF01/REF01Observer.boo` | Ajout requête InboundOrderType + écriture CstAtt20 | | `Configuration/LIMAGRAI2512/CommonAppSettings.config` | Ajout des 6 clés CPI_* | ## Logging Chaque étape (connexion, récupération token, envoi message) doit être loguée avec les détails de la requête et de la réponse. Le body JSON est logué en **format indenté** pour faciliter le debug. > ⚠️ Le **token ne doit jamais être logué** (sécurité). ## Cas de tests - [ ] Le GNA compile sans erreur - [ ] L'authentification OAuth client_credentials fonctionne (HTTP 200) - [ ] Le token est mis en cache sur disque et réutilisé tant qu'il est valide - [ ] Les messages WMS sont envoyés en POST avec le bon format JSON - [ ] Le champ MessageSAP est présent avec la bonne valeur selon le type - [ ] REF type Supplier → MessageSAP = ATH215 - [ ] REF type Return → MessageSAP = ATH217 - [ ] CstAtt20 renseigné dans le message REF01 par le REF01Observer - [ ] Warning logué si MessageType sans correspondance - [ ] Retry backoff fonctionne (hors 401) - [ ] Logs détaillés et lisibles (JSON indenté, token masqué) - [ ] HTTP 401 → échec immédiat sans retry ## Points d'attention ⚠️ Le **secret OAuth est en clair** dans le fichier de configuration — accès au fichier à restreindre. ⚠️ La marge de 60 secondes sur l'expiration du token évite les races conditions mais peut générer des re-authentifications prématurées sous forte charge. ⚠️ Le backoff exponentiel plafonne à 16 secondes — si SAP-CPI est durablement indisponible, les messages seront perdus (pas de file d'attente persistante). ## Questions ouvertes - [ ] Faut-il implémenter une file d'attente persistante pour les messages en échec après 4 retries ? (@Nicolas) - [ ] Le secret OAuth doit-il être chiffré dans le config ? (@Fabien) ## Historique des modifications | Date | Auteur | Modification | |------|--------|--------------| | 2026-05-12 | Arthur | Création depuis LIM-89 | | 2026-05-13 | Arthur | Ajout cartographie ATH complète, URLs TEST, note ATH214 hors GNA | ## Références | Source | Type | Date | |--------|------|------| | [LIM-89](https://easywmsfrance.atlassian.net/browse/LIM-89) | Ticket Jira | 2026 | | Athenzat SAP-CPI Webservices Documentation v1.0 | PDF (Maxime Tourrette) | 2026-04-24 | | Mail Justine S15 | Cartographie interfaces | 2026-04 |