diff --git a/CLAUDE.md b/CLAUDE.md index aa72877..d1489f1 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -28,6 +28,7 @@ pour le debug et l'analyse. **Fonctionnel et en service.** | API | Endpoint | Usage | |---|---|---| | Query | `POST {api}/QueryExecute` | requêtes LINQ, lignes | +| Référence complète | `https:///ApplicationService/Help` | page d'aide générée du service — **la source de vérité** sur les champs et les endpoints | | Query scalaire | `POST {api}/QueryScalarExecute` | `Count()`, `Sum()` — à préférer pour « combien » | | Command | `POST {api}/CommandExecute` | exécution de commandes WMS | | Metadata | `GET {api}/Metadata/Entities`, `GET {api}/Metadata/EntityProperties` | entités interrogeables et leurs champs | diff --git a/DECISIONS.md b/DECISIONS.md index ed6d323..0201779 100644 --- a/DECISIONS.md +++ b/DECISIONS.md @@ -46,17 +46,25 @@ Voir `src/services/api-service.js`, méthode `authenticate()`. ## D3 — `QueryType: 0` (Reading), pas 1 -**Piège.** `QueryType` sélectionne le modèle de données interrogé : +**Piège.** `QueryType` (type `QueryContextType`) sélectionne le contexte de +données interrogé. Il a **quatre** valeurs, pas deux — vérifiées une à une sur +le tenant `LIMAGRAI2512` : -| Valeur | Modèle | Champs de statut | +| Valeur | Contexte | Statut sur ce tenant | |---|---|---| -| `0` | **Reading** | chaînes de caractères (`"Release"`) | -| `1` | Writing | énumérations | +| `0` | **Reading** — `ApplicationReadingContext` | opérationnel, champs de statut en **chaînes** (`"Release"`) | +| `1` | Writing — `ApplicationWritingRepository` | opérationnel, champs de statut en **énumérations** | +| `2` | DataWarehouse | **non configuré** : `Could not resolve serviceType 'IDataWarehouse…'` | +| `3` | Metrics — `ApplicationMetricDataContext` | contexte présent, modèle de données non exploré | Les comparaisons de statut par chaîne — de loin le cas le plus courant en debug — **échouent** en `QueryType: 1`. Le code force donc `0` dans `executeQuery()` et `executeScalarQuery()`. +Le message d'erreur nomme le contexte (`ApplicationReadingContext`, +`ApplicationWritingRepository`, …) : c'est le moyen le plus rapide de savoir +quel `QueryType` a réellement été utilisé. + **Attention.** D'anciens exemples (dont le PHP de référence) utilisent `1`. Ne les recopiez pas. diff --git a/MONITORING.md b/MONITORING.md index 084bf84..fcfb832 100644 --- a/MONITORING.md +++ b/MONITORING.md @@ -148,6 +148,11 @@ Sortie attendue : Code de sortie `0` si tout passe, `1` sinon — utilisable tel quel dans une tâche planifiée. +Sonde plus légère, si l'on veut seulement savoir si le WMS répond (sans +authentification applicative) : `GET https:///ApplicationService/api/healthcheck?tenantCode=` +et `.../api/ready?tenantCode=` renvoient 200. Elles ne disent rien de la +validité des credentials — pour ça, `npm test`. + C'est le premier réflexe quand Claude signale une erreur WMS : il isole en quelques secondes une panne de connectivité d'un problème de requête. diff --git a/ROADMAP.md b/ROADMAP.md index 29c51a0..e447525 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -159,17 +159,22 @@ chiffres ci-dessous sont mesurés sur le tenant `LIMAGRAI2512`. ### L4.1 — Le modèle Writing est inatteignable `QueryType` est figé à `0` (Reading) en dur dans `api-service.js` -(`executeQuery` et `executeScalarQuery`). Aucun outil ne permet d'interroger le -modèle **Writing**. +(`executeQuery` et `executeScalarQuery`). Or `QueryContextType` a **quatre** +valeurs. Testées une à une : -Ce n'est pas une limite de l'API : `{"Application":"EasyWMS","QueryType":1, -"Expression":"Context.Products.OrderBy(z => z.Id)","Take":1}` répond -correctement. Il manque simplement le paramètre. +| Valeur | Contexte | Résultat sur `LIMAGRAI2512` | +|---|---|---| +| `0` | Reading | opérationnel (seul utilisé aujourd'hui) | +| `1` | Writing | **opérationnel** — `Context.Products` répond | +| `2` | DataWarehouse | **non configuré** : `Could not resolve serviceType 'IDataWarehouse…'` | +| `3` | Metrics | contexte présent (`ApplicationMetricDataContext`), modèle non exploré | -Attention en l'exposant : D3 reste vrai — en `QueryType: 1` les champs de statut -sont des **énumérations**, donc les comparaisons par chaîne (`== "Release"`) -échouent. Le défaut doit rester `0`, et la bascule être un choix explicite et -documenté, pas une option qu'on active au hasard. +Exposer `query_type` sur les outils de requête, défaut `0`. Attention : D3 reste +vrai — en Writing les champs de statut sont des **énumérations**, donc +`== "Release"` échoue. La bascule doit être un choix explicite et documenté. + +Le contexte `Metrics` mérite une exploration à part : c'est probablement là que +vivent les données agrégées produites par les jobs `MetricGatherer`. ### L4.2 — Une seule application sur neuf est visible @@ -203,13 +208,76 @@ suffit d'un paramètre `application` sur les outils AD et workflow, avec une cl de cache incluant l'application (sinon un cache pollué mélange les applications). -**QueryExecute — non résolu, à investiguer.** Passer `Application: "CustomApp"` -ne change **pas** le contexte de lecture : l'erreur reste -`ApplicationReadingContext ne contient pas de définition pour …`. Les 11 entités -`CST_` ne sont atteignables ni au singulier ni au pluriel, et **aucune** n'est -présente dans les 232 entités du Metadata `EasyWMS` (vérifié). Elles sont -définies dans EasyBuilder (`FromMetadata: false`) — reste à déterminer si elles -sont interrogeables, et sous quel nom. Ne rien promettre avant d'avoir tranché. +**QueryExecute — tranché : le champ `Application` ne partitionne rien.** +`Context.AgvTasks` (entité de l'application AGV) répond aussi bien avec +`Application: "AGV"` qu'avec `Application: "EasyWMS"`. Le contexte de lecture est +**commun au tenant** : toutes les applications y déversent leurs entités. + +Conséquence pour L2.1 : la table de résolution doit **agréger le Metadata de +toutes les applications** (`GET /Metadata/Entities?applicationName=…` par +application, 232 + 20 + 6 + …), et non se limiter à `EasyWMS`. Inutile en +revanche d'ajouter un paramètre `application` à `QueryExecute` : il ne changerait +rien. + +**Les entités `CustomApp` ne sont interrogeables dans aucun contexte.** Les 11 +entités `CST_` ont été testées sous les quatre `QueryType`, au singulier et au +pluriel : échec partout, et `Metadata/Entities` comme `Metadata/EntitiesAll` +renvoient **0 entité** pour `CustomApp`. Aucune n'est marquée +`isDataWarehouse`. Ce sont des définitions EasyBuilder (`FromMetadata: false`) +sans projection dans un contexte requêtable. + +**L'API AD reste donc le seul accès au spécifique client** — ce qui rend le +paramètre `application` sur les outils AD et workflow d'autant plus utile. + +### L4.3 — Identifier le MCP dans les logs du WMS + +`QueryExecute` accepte un champ **`ClientModule`** que le MCP n'envoie pas. +Résultat : ses requêtes apparaissent dans les logs du WMS sous +`Execute error. Client: GNA` — le client OAuth partagé — donc indistinguables de +celles du vrai client GNA. + +Renseigner `ClientModule` (`"MCP-WMS"` ou le nom du profil actif) rend chaque +requête du MCP traçable côté serveur. Vérifié : le champ est accepté. + +### L4.4 — Historique d'exécution des workflows par API + +`ApplicationService` expose une API `WorkflowLog` que le MCP n'utilise pas : + +| Endpoint | Usage | +|---|---| +| `GET /WorkflowLog/GetInstances?processDefinitionId=&skip=&take=&startDateFrom=&startDateTo=` | instances d'un workflow sur une plage de dates, filtrables par attribut | +| `GET /WorkflowLog/GetInstance?processId=` | une instance | +| `GET /WorkflowLog/GetLogs?processId=&skip=&take=&logDateFrom=&logDateTo=` | journal d'exécution d'une instance | +| `GET /WorkflowLog/Validate?applicationName=&processDefinitionId=` | validation d'une définition | + +Endpoints joignables et fonctionnels — `Validate` renvoie +`{"Success":true,"ErrorMessage":null,"Warnings":[]}`. `GetInstances` répond `[]` +sur le workflow testé : à confirmer sur un workflow ayant réellement tourné, la +journalisation n'étant pas forcément active partout. + +**Peut remettre en cause D16** (historique des shipment templates jugé hors de +portée faute de logs fichier) : si l'historique d'exécution est disponible par +API, la conclusion change. À vérifier avant d'écrire quoi que ce soit. + +### L4.5 — Champs de `QueryExecute` inexploités + +La référence de l'API documente des champs que le MCP n'envoie jamais : + +| Champ | Intérêt | +|---|---| +| `Parameters` | requêtes **paramétrées** (dictionnaire `nom -> {TypeName, Value}`) — supprimerait toute concaténation de chaîne dans les filtres, et pourrait débloquer D13 (`Select`) | +| `CommandTimeout` | timeout par requête, au lieu du timeout HTTP global de 30 s | +| `QueryId` + `POST /QueryCancel` | annulation d'une requête longue | +| `POST /QueryExecuteStream` | résultats en flux — piste sérieuse pour L3.1 (sorties volumineuses) | + +Autres endpoints jamais utilisés, à évaluer : `QueryEvents`, `QueryCommands`, +`QueryCorrelationEvents`, `QuerySnapshots` (event sourcing — utile en debug), +`GET /Metadata/Commands|Events|Aggregates` et leurs variantes `…All`, +`GET /configuration/applications` (liste les applications **avec leur version**, +plus riche que `/AD/api/Application/GetAll`), `GET /healthcheck?tenantCode=` et +`GET /ready?tenantCode=` (sondes de disponibilité, répondent 200). + +--- ---