Refactor error handling and enhance API interactions across Filament pages

- Introduced `ApiErrorTranslator` to normalize and translate API error messages, providing clearer feedback in French.
- Updated all Filament pages (Articles, Documents, Divers, Journaux, Tiers, TablesExplorer) to utilize the new error translation mechanism, improving user experience during API interactions.
- Added validation for required fields before API calls, ensuring users receive immediate feedback when mandatory inputs are missing.
- Implemented tracking properties to distinguish between "never searched" and "searched without results," enhancing the user interface.
- Removed the obsolete `$results` property from the Articles page and added a new `$barcode` property to align with API requirements.
- Updated documentation to reflect changes in API behavior and error handling, including new metadata returned by the `art_list` endpoint.
- Added new tests to verify the functionality of the barcode handling and validation logic.
This commit is contained in:
2026-02-23 10:15:17 +01:00
parent 7df94b64fa
commit bb1bbc2904
29 changed files with 1075 additions and 157 deletions

View File

@@ -1,6 +1,6 @@
# Documentation API Logistics (Flex/ESI Gescom)
Dernière mise à jour : 2026-02-21
Dernière mise à jour : 2026-02-23
---
@@ -162,7 +162,7 @@ Content-Type: application/json
{
"search": "chaise",
"results": 10,
"select": "artid,artname"
"select": "artid,name1"
}
```
@@ -185,6 +185,11 @@ Le service `LogisticsService` de l'application gère automatiquement :
- **Retry automatique** : en cas d'échec de connexion (`ConnectionException`), le service retente automatiquement selon la configuration (`retry.times` et `retry.sleep_ms`).
- **Logging** : chaque requête (réussie ou échouée) est enregistrée dans la table `api_request_logs` avec l'endpoint, les paramètres, le code de statut et la réponse.
- **Exceptions** : en cas d'erreur, une `LogisticsApiException` est levée avec un message explicite en français.
- **Traduction des erreurs** : la classe `App\Support\ApiErrorTranslator` normalise le champ `error` de la réponse API (qui peut être `null`, une chaîne ou un tableau de chaînes) et ajoute une explication en français aux messages d'erreur connus (ex : "Search terms are required" est enrichi de "Le champ de recherche est obligatoire.").
### Validation des champs
Avant chaque appel API, les pages Filament vérifient que les champs obligatoires sont remplis. Si un champ requis est vide, un message d'erreur en français est affiché et l'appel API n'est pas effectué. Les règles de validation sont basées sur la documentation fournisseur (`documentation/WEB-A-1 (3).md`). Cette validation côté client évite des appels API inutiles et fournit un retour immédiat à l'utilisateur.
---
@@ -213,15 +218,15 @@ Tous les endpoints retournent un objet JSON avec la même structure :
| `metadata` | `object` | Informations sur la requête. Contient toujours `rowcount` et `issuccess`. Peut contenir d'autres clés selon l'endpoint. |
| `metadata.rowcount` | `int` | Nombre d'éléments retournés dans `data`. |
| `metadata.issuccess` | `bool` | `true` si la requête a réussi, `false` sinon. |
| `error` | `string` ou `null` | Message d'erreur en cas d'échec. `null` si la requête a réussi. |
| `error` | `string`, `array` ou `null` | Message d'erreur en cas d'échec. Peut être une chaîne, un tableau de chaînes, ou `null` si la requête a réussi. L'application normalise ce champ via `ApiErrorTranslator`. |
### Exemple de réponse réussie
```json
{
"data": [
{ "artid": "ART001", "artname": "Chaise bureau" },
{ "artid": "ART002", "artname": "Chaise visiteur" }
{ "artid": "ART001", "name1": "Chaise bureau" },
{ "artid": "ART002", "name1": "Chaise visiteur" }
],
"metadata": {
"rowcount": 2,
@@ -398,7 +403,7 @@ Les articles sont les références produits du catalogue. Ils sont stockés dans
#### `art_list` -- Recherche d'articles
Retourne une liste d'articles correspondant aux critères de recherche. Permet de filtrer par texte libre ou par code-barres, et de sélectionner les colonnes à retourner.
Retourne une liste d'articles correspondant aux critères de recherche. L'API retourne un maximum fixe de **5 résultats** par appel, cette limite n'est pas configurable.
| | |
|---|---|
@@ -409,21 +414,58 @@ Retourne une liste d'articles correspondant aux critères de recherche. Permet d
| Paramètre | Type | Obligatoire | Description |
|-----------|------|:-----------:|-------------|
| `search` | `string` | Non | Filtre de recherche textuel. Recherche dans les champs principaux de l'article (identifiant, nom, description). Non requis si `barcode` est fourni. |
| `search` | `string` | Oui | Filtre de recherche textuel. Recherche dans les colonnes `artid` et `name1` de la table `art`. **Ce paramètre est obligatoire** : un appel sans `search` retourne une erreur "Search terms are required", même si `barcode` est fourni. |
| `select` | `string` | Non | Liste des colonnes à retourner, séparées par des virgules. Les noms de colonnes disponibles sont ceux de la table `art` (obtenables via `column_list/art`). Si omis, un jeu de colonnes par défaut est retourné. |
| `results` | `int` | Non | Nombre maximum de résultats à retourner. Par défaut, l'API retourne un nombre réduit de résultats (environ 5 à 10). |
| `barcode` | `string` | Non | Code-barres de l'article à rechercher. Si fourni, le paramètre `search` n'est pas requis. |
| `results` | `int` | Non | **Sans effet.** Ce paramètre est accepté par l'API mais n'influence pas le nombre de résultats retournés. L'API retourne toujours un maximum de 5 résultats, quelle que soit la valeur de `results` (testé avec 1, 3, 5, 10, 20, en int et en string). |
| `barcode` | `string` | Non | **Sans effet observable.** Ce paramètre est accepté par l'API mais ne modifie pas les résultats. Les données retournées sont strictement identiques avec ou sans `barcode`. Le paramètre `search` reste obligatoire même si `barcode` est fourni. |
**Métadonnées retournées** :
L'endpoint `art_list` retourne des métadonnées spécifiques dans la clé `metadata` :
| Clé | Type | Description |
|-----|------|-------------|
| `rowCount` | `int` | Nombre de résultats retournés. |
| `source` | `string` | Type de base de données (ex : `DBF`). |
| `executionTimeMs` | `int` | Temps d'exécution de la requête en millisecondes. |
| `searchColumns` | `string` | Colonnes utilisées pour la recherche (ex : `artid,name1`). |
| `selectColumns` | `string` | Colonnes demandées dans le paramètre `select`. |
| `searchTerms` | `string` | Termes de recherche utilisés. |
**Exemple de requête** :
```json
{
"search": "chaise",
"select": "artid,artname,saleprice1",
"results": 20
"select": "artid,name1,saleprice"
}
```
**Exemple de réponse** :
```json
{
"data": [
{ "artid": "003R92572", "name1": "Papier A4 80g", "saleprice": 12.50 },
{ "artid": "003R92573", "name1": "Papier A4 90g", "saleprice": 14.00 },
{ "artid": "003R98703", "name1": "Papier A3 80g", "saleprice": 18.75 },
{ "artid": "003R98711", "name1": "Papier A3 90g", "saleprice": 21.00 },
{ "artid": "003R98718", "name1": "Papier A4 100g", "saleprice": 16.50 }
],
"metadata": {
"rowCount": 5,
"source": "DBF",
"executionTimeMs": 720,
"searchColumns": "artid,name1",
"selectColumns": "artid,name1,saleprice",
"searchTerms": "papier"
},
"error": null
}
```
**Attention** : les noms de colonnes dans `select` doivent correspondre exactement aux noms retournes par `column_list/art` (ex : `name1`, pas `artname`). L'API ignore silencieusement les noms de colonnes invalides sans emettre d'erreur, ce qui peut donner l'impression que le parametre `select` ne fonctionne pas.
---
#### `art_getstk` -- Stock d'un article
@@ -673,15 +715,14 @@ Retourne une liste de tiers correspondant au filtre de recherche. Permet de trou
|-----------|------|:-----------:|-------------|
| `search` | `string` | Oui | Filtre de recherche. **Ce paramètre est obligatoire** : un appel sans filtre retourne une erreur. |
| `select` | `string` | Non | Colonnes à retourner, séparées par des virgules (colonnes de la table `cust`). |
| `results` | `int` | Non | Nombre maximum de résultats. |
| `results` | `int` | Non | **Sans effet.** Ce paramètre est accepté mais n'influence pas le nombre de résultats. L'API retourne toujours un maximum de 10 résultats (testé avec 3, 10, 20). |
**Exemple de requête** :
```json
{
"search": "Dupont",
"select": "custid,custname,city",
"results": 10
"select": "custid,custname,city"
}
```
@@ -950,19 +991,23 @@ Tiers (cust)
4. **Paramètre `search` obligatoire pour `third_list`** : l'endpoint `third_list` exige le paramètre `search`. Un appel sans ce paramètre retourne une erreur.
5. **Paramètre `results`** : limite le nombre de résultats retournés. Par défaut, l'API retourne un nombre réduit de résultats (environ 5 à 10). Augmentez cette valeur si vous avez besoin de plus de résultats.
5. **Paramètre `results`** : ce paramètre est documenté comme limitant le nombre de résultats, mais les tests réalisés montrent qu'il **n'a aucun effet observable** sur les endpoints `art_list` (toujours 5 résultats maximum) et `third_list` (toujours 10 résultats maximum). La limite semble être fixée côté serveur et non configurable via ce paramètre.
6. **Paramètre `select`** : permet de choisir les colonnes à retourner. Les noms de colonnes disponibles pour chaque table s'obtiennent via `column_list/{tablename}`. Si omis, un jeu de colonnes par défaut est retourné.
6. **Paramètre `TYPE` obligatoire pour `jnl_list`** : l'endpoint `jnl_list` exige le paramètre `TYPE`. Un appel sans ce paramètre retourne une erreur.
7. **Casse des paramètres** : la casse des noms de paramètres varie selon les endpoints. Par exemple, l'identifiant du tiers peut être `thirdid`, `Thirdid` ou `THIRDID` selon l'endpoint. Respectez la casse documentée pour chaque endpoint.
7. **Format du champ `error`** : le champ `error` de la réponse API peut être `null`, une chaîne ou un tableau de chaînes. L'application normalise ce champ automatiquement via `ApiErrorTranslator`.
8. **Fichiers attachés en base64** : lors de l'ajout ou la modification de documents, les fichiers joints doivent être encodés en base64 dans le champ `FileContentBase64`. Seul le contenu du fichier est encodé, pas le nom ni la description.
8. **Paramètre `select`** : permet de choisir les colonnes à retourner. Les noms de colonnes disponibles pour chaque table s'obtiennent via `column_list/{tablename}`. Si omis, un jeu de colonnes par défaut est retourné. **Attention** : les noms de colonnes doivent correspondre exactement à ceux retournés par `column_list` (ex : `name1`, pas `artname`). L'API ignore silencieusement les noms de colonnes invalides sans émettre d'erreur.
9. **Déduplication des colonnes** : l'endpoint `column_list` retourne chaque colonne en double. L'application effectue une déduplication automatique, mais si vous interrogez l'API directement, vous devez gérer ce doublon.
9. **Casse des paramètres** : la casse des noms de paramètres varie selon les endpoints. Par exemple, l'identifiant du tiers peut être `thirdid`, `Thirdid` ou `THIRDID` selon l'endpoint. Respectez la casse documentée pour chaque endpoint.
10. **Correspondance positionnelle des tableaux** : dans `document_add` et `document_mod`, les tableaux `Artid`, `Qty`, `Saleprice`, `Discount`, `Vatid` et `Vatpc` fonctionnent par correspondance positionnelle. Assurez-vous que tous les tableaux ont la même longueur.
10. **Fichiers attachés en base64** : lors de l'ajout ou la modification de documents, les fichiers joints doivent être encodés en base64 dans le champ `FileContentBase64`. Seul le contenu du fichier est encodé, pas le nom ni la description.
11. **Timeout** : certaines requêtes peuvent être lentes selon le volume de données. Le timeout par défaut est configuré à 300 secondes. En cas de timeout, vérifiez la configuration `LOGISTICS_API_TIMEOUT`.
11. **Déduplication des colonnes** : l'endpoint `column_list` retourne chaque colonne en double. L'application effectue une déduplication automatique, mais si vous interrogez l'API directement, vous devez gérer ce doublon.
12. **Correspondance positionnelle des tableaux** : dans `document_add` et `document_mod`, les tableaux `Artid`, `Qty`, `Saleprice`, `Discount`, `Vatid` et `Vatpc` fonctionnent par correspondance positionnelle. Assurez-vous que tous les tableaux ont la même longueur.
13. **Timeout** : certaines requêtes peuvent être lentes selon le volume de données. Le timeout par défaut est configuré à 300 secondes. En cas de timeout, vérifiez la configuration `LOGISTICS_API_TIMEOUT`.
---