cb625a7918
Context.{entity_type} attend le TableName du Metadata, pas le nom
d'entité de l'AD (Container -> Containers, mais Alias -> Alias) : un nom
faux partait en HTTP 500 de compilation LINQ. Nouveau service
entity-resolver.js : table Name|TableName (insensible à la casse) ->
TableName, agrégée sur les applications déployées (via
GET /configuration/applications — les applications sans contexte
requêtable n'y figurent pas et n'apportent 0 entité Metadata), cache TTL
partagé, invalidation par onSwitch (D8). Branché dans wms-query-service
(query/count/schema/search) et call_query_api.
Nom inconnu -> échec avant tout appel réseau de requête, suggestions
proches + renvoi vers get_entity_metadata. Metadata injoignable -> le
nom passe tel quel avec un warning dans la réponse.
Mesures (LIMAGRAIN, via le protocole) :
- query_wms_entities("Container", limit 1) -> succès, 1 ligne, résolu
Containers
- query_wms_entities("Alias") -> succès, invariant (pas de pluriel)
- query_wms_entities("Item") -> "Item" n'existe pas dans le modèle
Reading. Proches : RFMenuItems, Sites. 288 entités disponibles —
aucune ligne [API] POST dans stderr
- count_wms_entities("Product") -> 51160
- get_entity_schema("Container") et call_query_api("Container") : mêmes
résolutions
- 288 TableName distincts sur 5 applications, aucun conflit
Name -> TableName (mesuré le 24/08/2026)
Docs : D21 dans DECISIONS.md ; CLAUDE.md (piège retiré des points
ouverts, liste d'entités corrigée Aliases -> Alias, entity-resolver dans
la structure) ; exemple singulier/pluriel dans wms://query-examples ;
ROADMAP allégée (cause racine + L2.1 + L3.3 livrés).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
281 lines
8.1 KiB
JavaScript
281 lines
8.1 KiB
JavaScript
/**
|
|
* Query Examples Resources
|
|
* Provides example LINQ queries and diagnostic recipes for WMS entities.
|
|
*/
|
|
|
|
function listResources() {
|
|
return [
|
|
{
|
|
uri: 'wms://query-examples',
|
|
name: 'Query Examples',
|
|
description: 'LINQ query examples and diagnostic recipes for WMS entities',
|
|
mimeType: 'text/markdown',
|
|
},
|
|
];
|
|
}
|
|
|
|
async function readResource(uri) {
|
|
let content;
|
|
|
|
switch (uri) {
|
|
case 'wms://query-examples':
|
|
content = getQueryExamples();
|
|
break;
|
|
|
|
default:
|
|
throw new Error(`Unknown query examples resource: ${uri}`);
|
|
}
|
|
|
|
return {
|
|
contents: [{
|
|
uri,
|
|
mimeType: 'text/markdown',
|
|
text: content,
|
|
}],
|
|
};
|
|
}
|
|
|
|
function getQueryExamples() {
|
|
return `# WMS LINQ Query Examples & Diagnostic Recipes
|
|
|
|
> **Reading model** — \`query_wms_entities\` / \`count_wms_entities\` use \`QueryExecute\`
|
|
> (QueryType=Reading). Status/enum fields are **strings** (enum names), never integers.
|
|
> Always verify enum values via \`docs://entities/\` or \`get_entity_metadata\` before filtering.
|
|
|
|
## Entity names — singular AD name or TableName, both accepted
|
|
|
|
\`entity_type\` is resolved case-insensitively against the Metadata API: the AD
|
|
entity name (singular) and the TableName both work. The mapping is **not** a
|
|
pluralisation rule — only the Metadata \`TableName\` is authoritative:
|
|
|
|
\`\`\`
|
|
query_wms_entities(entity_type="Container") # AD name -> resolved to Containers
|
|
query_wms_entities(entity_type="Containers") # TableName -> used as-is
|
|
query_wms_entities(entity_type="Alias") # invariant: TableName IS "Alias" (no plural)
|
|
query_wms_entities(entity_type="Item") # fails fast: not in the Reading model,
|
|
# error lists close matches + get_entity_metadata
|
|
\`\`\`
|
|
|
|
---
|
|
|
|
## Diagnostic Recipes
|
|
|
|
Recipes below were validated against a live WMS. Use them as-is, substituting the
|
|
\`X\` placeholders.
|
|
|
|
### OS incomplètes par classe d'expédition
|
|
|
|
Compter les ordres de sortie incomplets, actifs, d'une classe donnée
|
|
(\`OutboundClassCode\`). Fields verified on the \`OutboundOrder\` Reading entity:
|
|
\`OutboundClassCode\` (string), \`IncompleteOrder\` (bool), \`IsActive\` (bool).
|
|
|
|
\`\`\`
|
|
# Toutes classes confondues
|
|
count_wms_entities(
|
|
entity_type="OutboundOrders",
|
|
filter='z.IncompleteOrder == true && z.IsActive == true'
|
|
)
|
|
|
|
# Pour une classe précise
|
|
count_wms_entities(
|
|
entity_type="OutboundOrders",
|
|
filter='z.OutboundClassCode == "SHIPPING_GROUP_01" && z.IncompleteOrder == true && z.IsActive == true'
|
|
)
|
|
|
|
# Lister le détail des OS concernées
|
|
query_wms_entities(
|
|
entity_type="OutboundOrders",
|
|
filter='z.OutboundClassCode == "SHIPPING_GROUP_01" && z.IncompleteOrder == true && z.IsActive == true',
|
|
limit=200
|
|
)
|
|
\`\`\`
|
|
|
|
### Containers bloquants sur un emplacement
|
|
|
|
Identifier les conteneurs qui retiennent un emplacement parce qu'ils ont des tâches
|
|
en attente. Fields verified on the \`Container\` Reading entity:
|
|
\`LocationCode\` (string), \`NumContainerPendingTasks\` (long).
|
|
|
|
\`\`\`
|
|
# Combien de containers ont des tâches en attente sur l'emplacement
|
|
count_wms_entities(
|
|
entity_type="Containers",
|
|
filter='z.LocationCode == "QUAI_EXP_01" && z.NumContainerPendingTasks > 0'
|
|
)
|
|
|
|
# Lister ces containers (renvoie toutes les colonnes du container)
|
|
query_wms_entities(
|
|
entity_type="Containers",
|
|
filter='z.LocationCode == "QUAI_EXP_01" && z.NumContainerPendingTasks > 0',
|
|
limit=200
|
|
)
|
|
|
|
# Vue globale : tous les containers bloquants du WMS
|
|
count_wms_entities(
|
|
entity_type="Containers",
|
|
filter='z.NumContainerPendingTasks > 0'
|
|
)
|
|
\`\`\`
|
|
|
|
### Paramètres système d'un entrepôt
|
|
|
|
Pour lire les paramètres de configuration WMS et leurs valeurs par entrepôt,
|
|
utiliser l'outil dédié \`get_system_parameters\` plutôt qu'une requête LINQ :
|
|
|
|
\`\`\`
|
|
get_system_parameters(warehouse="DOMBASLE") # tous les paramètres
|
|
get_system_parameters(warehouse="DOMBASLE", param_class="Shipping")
|
|
get_system_parameters(search="CROSSDOCK")
|
|
\`\`\`
|
|
|
|
### Modèles d'expédition — suivi des exécutions
|
|
|
|
> ⚠️ L'API ne conserve que la **dernière** exécution de chaque modèle d'expédition
|
|
> (\`ShipmentTemplate.LastExecuteDate\`). L'historique complet des exécutions n'existe
|
|
> que dans les logs serveur \`ApplyShipmentTemplates\`, non exposés par ce MCP.
|
|
|
|
Fields verified on the \`ShipmentTemplate\` Reading entity: \`Code\`, \`Status\`,
|
|
\`IsEnabled\`, \`IsActive\`, \`LastExecuteDate\`, \`WarehouseCode\`, \`Priority\`,
|
|
\`DirectiveCode\`.
|
|
|
|
\`\`\`
|
|
# Tous les modèles d'un entrepôt + leur dernière exécution et leur statut
|
|
query_wms_entities(
|
|
entity_type="ShipmentTemplates",
|
|
filter='z.WarehouseCode == "DOMBASLE"',
|
|
limit=200
|
|
)
|
|
|
|
# Modèles activés mais jamais exécutés (LastExecuteDate null)
|
|
query_wms_entities(
|
|
entity_type="ShipmentTemplates",
|
|
filter='z.IsEnabled == true && z.LastExecuteDate == null',
|
|
limit=200
|
|
)
|
|
|
|
# Combien de modèles exécutés au moins une fois
|
|
count_wms_entities(
|
|
entity_type="ShipmentTemplates",
|
|
filter='z.LastExecuteDate != null'
|
|
)
|
|
|
|
# Modèles exécutés depuis une date (littéral DateTime obligatoire — voir Date filters)
|
|
count_wms_entities(
|
|
entity_type="ShipmentTemplates",
|
|
filter='z.LastExecuteDate >= new DateTime(2025, 1, 1)'
|
|
)
|
|
\`\`\`
|
|
|
|
---
|
|
|
|
## Counting (\`count_wms_entities\`)
|
|
|
|
Always prefer \`count_wms_entities\` for any "combien" / "how many" question — it uses
|
|
\`QueryScalarExecute\` and never materialises rows.
|
|
|
|
\`\`\`
|
|
count_wms_entities(entity_type="OutboundOrders")
|
|
count_wms_entities(entity_type="Tasks", filter='z.TaskStatus == "InProcess"')
|
|
\`\`\`
|
|
|
|
---
|
|
|
|
## Basic Queries
|
|
|
|
### Get rows (with limit)
|
|
|
|
\`\`\`
|
|
query_wms_entities(entity_type="Products", limit=100)
|
|
query_wms_entities(entity_type="Tasks", limit=50)
|
|
\`\`\`
|
|
|
|
> Note: the \`select_expression\` parameter (LINQ projections) is currently unreliable
|
|
> against \`QueryExecute\` — prefer querying full rows and reading the fields you need.
|
|
|
|
## Filtering Examples
|
|
|
|
### Status filters (string enum names)
|
|
|
|
\`\`\`
|
|
# Tâches en cours / en attente
|
|
query_wms_entities(entity_type="Tasks", filter='z.TaskStatus == "InProcess"', limit=100)
|
|
query_wms_entities(entity_type="Tasks", filter='z.TaskStatus == "Pending"', limit=100)
|
|
|
|
# Ordres de sortie lancés
|
|
query_wms_entities(entity_type="OutboundOrders", filter='z.OutboundOrderStatus == "Release"', limit=100)
|
|
\`\`\`
|
|
|
|
### Date filters
|
|
|
|
> ⚠️ \`AddDays()\` et les dates relatives (\`DateTime.Now\`, \`DateTime.Today\`) ne sont
|
|
> **pas traduisibles** par le moteur de requête — toujours utiliser un littéral
|
|
> \`new DateTime(année, mois, jour)\`. Le nom du champ date dépend de l'entité
|
|
> (\`LastExecuteDate\`, \`InternalInfo.CreationDate\`, …) — le vérifier via
|
|
> \`get_entity_metadata\` ou \`docs://entities/\`.
|
|
|
|
\`\`\`
|
|
# Éléments depuis une date donnée (littéral DateTime obligatoire)
|
|
count_wms_entities(
|
|
entity_type="ShipmentTemplates",
|
|
filter='z.LastExecuteDate >= new DateTime(2025, 1, 1)'
|
|
)
|
|
\`\`\`
|
|
|
|
### Numeric filters
|
|
|
|
\`\`\`
|
|
query_wms_entities(entity_type="Stocks", filter="z.Quantity > 0", limit=100)
|
|
\`\`\`
|
|
|
|
### String filters
|
|
|
|
\`\`\`
|
|
query_wms_entities(entity_type="Products", filter='z.Code.StartsWith("ABC")', limit=100)
|
|
query_wms_entities(entity_type="Products", filter='z.Code.Contains("test")', limit=100)
|
|
\`\`\`
|
|
|
|
## Complex Filters
|
|
|
|
### Multiple conditions (AND / OR)
|
|
|
|
\`\`\`
|
|
query_wms_entities(
|
|
entity_type="Tasks",
|
|
filter='z.TaskStatus == "Pending" && z.Priority > 50',
|
|
limit=100
|
|
)
|
|
|
|
query_wms_entities(
|
|
entity_type="OutboundOrders",
|
|
filter='z.OutboundOrderStatus == "Release" || z.OutboundOrderStatus == "Creating"',
|
|
limit=100
|
|
)
|
|
\`\`\`
|
|
|
|
## Common Patterns
|
|
|
|
### Find an entity by code
|
|
|
|
\`\`\`
|
|
query_wms_entities(entity_type="Products", filter='z.Code == "PROD123"', limit=1)
|
|
query_wms_entities(entity_type="OutboundOrders", filter='z.Code == "ORDER123"', limit=1)
|
|
\`\`\`
|
|
|
|
## Performance Tips
|
|
|
|
1. **Always use limits** — max 1000 rows per query.
|
|
2. **Use \`count_wms_entities\` for counts** — never fetch rows just to count them.
|
|
3. **Verify enum values first** — Reading model uses string enum names.
|
|
4. **Use specific filters** — narrow results at the API level.
|
|
|
|
---
|
|
|
|
**Note:** All queries respect the maximum limit of 1000 rows configured in the server.
|
|
`;
|
|
}
|
|
|
|
module.exports = {
|
|
listResources,
|
|
readResource,
|
|
};
|