lint(limagrain): corrections completes Phase 1+2

- Bloquants: mermaid 03-picking/_index reconstitue (archive 11-05), 13 liens vers pages squelette retires, 2 liens recibles (anoxie, application-dictionary)
- Conventions: 910 em dashes -> tirets simples, 145 checklists -> puces question, 13 questions resolues barrees
- Liens: 9 ancres reparees (slugs GitHub)
- Delta: 12 standard_ref remappes, blocs Standard EasyWMS + sections References ajoutes, front matter complete
- Glossaire: 15 termes standard deplaces en section rappel avec renvoi
- Rapport: limagrain/_lint_report.md (Phase 1 + Phase 2 + re-scan final)
- Inclut les pages des sessions precedentes non commitees + CLAUDE.md et consume.log en l'etat
This commit is contained in:
2026-07-20 12:56:42 +02:00
parent 23eb3f3c84
commit 7496aafe64
59 changed files with 6457 additions and 2023 deletions
+79 -48
View File
@@ -1,14 +1,16 @@
---
title: "Intégration GNA → SAP-CPI"
tags: [ERP, GNA, SAP-CPI, OAuth, middleware, API, BOO]
status: draft
standard_ref: architecture/erp-integration.md
status: review
standard_ref: concepts/erp-interface.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
- "Jira LIM-89 (lecture directe, revue de code validée 2026-05-21)"
last_updated: 2026-07-17
author: Arthur
---
@@ -24,7 +26,7 @@ author: Arthur
> (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),
> Voir aussi : [LOC - Message périodique](loc-message-periodique.md),
> [Référence messages](messages-reference.md),
> [Mapping ERP-WMS](mapping-erp-wms.md)
@@ -47,6 +49,16 @@ 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.
Structure (revue de code LIM-89) :
| Élément | Rôle |
|---|---|
| `CheckConnection()` | Authentification OAuth 2.0 client_credentials. Retry backoff exponentiel **4 tentatives (2s/4s/8s)**. Token persisté en JSON sur disque, gestion d'expiration (marge 60s). Arrêt immédiat sur 401 |
| `SendWebApiMessage` | Envoi POST vers l'endpoint unique. Détermination du `MessageSAP` puis construction du body. Retry backoff **5 tentatives (2s/4s/8s/16s)**. Token relu depuis le cache à chaque envoi |
| `CpiTokenResponse` | Désérialisation de la réponse OAuth (`access_token`, `token_type`, `expires_in`) |
| `CpiTokenCache` | Cache token JSON sur disque (`AccessToken`, `ExpiresAtUtc`) |
| `ReadWebApiFile`, `GenerateWebApiError`, `RegisterObservers` | Inchangés (template Mecalux standard) |
### Flux de communication
```mermaid
@@ -86,7 +98,7 @@ sequenceDiagram
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
## 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 :
@@ -109,29 +121,44 @@ 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 |
| ATH214 | Check flux retour (BAPI) | Vérification lot retour client |
| ATH215 | REF (type = Retour) | Finalisation réception retour |
| ATH217 | REF (type = Supplier) **ou ROF** | Finalisation réception fournisseur / clôture OE |
| ATH201 | LOC | Message périodique delta mouvements |
| ATH202 | LOF | Finalisation chargement |
> ⚠️ **Correction (revue de code LIM-89, 2026-05-21)** : le sens
> `REF Retour → ATH215` / `REF Supplier → ATH217` retenu ici est celui
> de la table de l'intégrateur ERP et de l'implémentation. Une version
> antérieure de cette page inversait les deux codes. `ROF` est mappé sur
> `ATH217` (et non `ATH215` comme le suggérait la description initiale).
> ⚠️ 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é :
Le message REF est routé vers **ATH215** (type Retour) ou **ATH217**
(type Supplier) selon le type de préavis de réception 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`
**Implémentation définitive (revue de code)** : la détermination se fait
**dans `CommonExportWebApi.boo`** (bloc `SendWebApiMessage`), via une
requête LINQ sur `Context.Receptions` en utilisant le `ReceiptCode`
extrait du payload JSON. Le préfixe 3 caractères du `MessageType`
(`REF01``REF`) sert au lookup dans le dictionnaire `messageSapMap` ;
pour REF, la logique conditionnelle sur le type de préavis choisit
ATH215 (Retour) ou ATH217 (Supplier).
- Type Retour → `ATH215`
- Type Supplier → `ATH217`
> **Note (reversal)** : la conception initiale prévoyait de porter le
> type via `RecCustomAttributes.CstAtt20` écrit par le `REF01Observer.boo`
> (requête sur `Context.RecLineInboundOrderLines` → `Context.InboundOrders`).
> Cette approche a été **abandonnée** : le type est désormais résolu
> directement dans `CommonExportWebApi.boo` via le `ReceiptCode`
> (`Context.Receptions`). `REF01Observer.boo` n'est donc pas modifié.
## Cartographie complète des interfaces Athenzat
@@ -155,8 +182,8 @@ Source : doc CPI Maxime Tourrette (24/04/2026) + mail S15 Justine.
| 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 |
| ATH215 | REF (Retour) | Z_IAT215 | Bon de réception retour |
| ATH217 | REF (Supplier) / ROF | Z_IAT217 | Bon de réception fournisseur / clôture OE |
| 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) |
@@ -167,13 +194,14 @@ Source : doc CPI Maxime Tourrette (24/04/2026) + mail S15 Justine.
> **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
## 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 |
| HTTP 200 | Succès - message envoyé |
| HTTP 401 | **Échec immédiat** - token invalide, pas de retry |
| Autre erreur HTTP (auth) | **Retry backoff** : 4 tentatives (2s → 4s → 8s) |
| Autre erreur HTTP (envoi message) | **Retry backoff** : 5 tentatives (2s → 4s → 8s → 16s) |
## Configuration requise
@@ -184,7 +212,7 @@ Six clés `CPI_*` à ajouter dans `CommonAppSettings.config`
|-----|-------------|
| 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_CLIENT_SECRET | Secret OAuth (**chiffré via `PasswordEncrypt.exe`**) |
| 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) |
@@ -201,9 +229,9 @@ Six clés `CPI_*` à ajouter dans `CommonAppSettings.config`
| 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_* |
| `Scripts2015/CommonExportWebApi.boo` | Script principal d'export WMS → SAP-CPI (auth, MessageSAP, envoi) |
| `Configuration/LIMAGRAI2512/CommonAppSettings.config` | Ajout des 6 clés CPI_* (secret chiffré) |
| ~~`Scripts2015/EasyWMS/XML/REF01/REF01Observer.boo`~~ | Prévu initialement (CstAtt20) - **non retenu** : type REF résolu via `ReceiptCode` dans `CommonExportWebApi.boo` |
## Logging
@@ -215,39 +243,39 @@ est logué en **format indenté** pour faciliter le debug.
## 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
- 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
- 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 Retour → MessageSAP = ATH215
- REF type Supplier → MessageSAP = ATH217
- ❓ REF type résolu via `ReceiptCode` (query `Context.Receptions`)
- 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.
Le **secret OAuth est chiffré** via `PasswordEncrypt.exe` dans le
fichier de configuration (résout la question initiale du secret en clair).
⚠️ 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
⚠️ 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)
- Faut-il implémenter une file d'attente persistante pour les
messages en échec après 5 retries ? (@Nicolas)
- [x] ~~Le secret OAuth doit-il être chiffré dans le config ?~~
**Résolu** (revue de code) : oui, chiffré via `PasswordEncrypt.exe`
## Historique des modifications
@@ -255,11 +283,14 @@ d'attente persistante).
|------|--------|--------------|
| 2026-05-12 | Arthur | Création depuis LIM-89 |
| 2026-05-13 | Arthur | Ajout cartographie ATH complète, URLs TEST, note ATH214 hors GNA |
| 2026-07-17 | Arthur | Delta revue de code : structure du script (CheckConnection/SendWebApiMessage/CpiTokenCache), retry auth 4 vs envoi 5, secret chiffré PasswordEncrypt.exe (question résolue) ; **correction du sens REF Retour→ATH215 / Supplier→ATH217 + ROF→ATH217** ; type REF résolu via ReceiptCode (REF01Observer/CstAtt20 abandonné) ; statut préprod |
## Références
| Source | Type | Date |
|--------|------|------|
| [LIM-89](https://easywmsfrance.atlassian.net/browse/LIM-89) | Ticket Jira | 2026 |
| [LIM-89](https://easywmsfrance.atlassian.net/browse/LIM-89) | Ticket Jira (statut préprod / test client) | 2026 |
| Revue de code LIM-89 (Arthur, N. Chabanis) | Revue de code validée | 2026-05-21 |
| Table de correspondance intégrateur ERP | Commentaire LIM-89 | 2026-05-11 |
| Athenzat SAP-CPI Webservices Documentation v1.0 | PDF (Maxime Tourrette) | 2026-04-24 |
| Mail Justine S15 | Cartographie interfaces | 2026-04 |