diff --git a/app/Filament/Pages/Journaux.php b/app/Filament/Pages/Journaux.php index 839e01a..d7831b7 100644 --- a/app/Filament/Pages/Journaux.php +++ b/app/Filament/Pages/Journaux.php @@ -24,7 +24,7 @@ class Journaux extends Page public string $select = ''; - public int $results = 10; + public int $results = 30; public string $type = ''; @@ -53,7 +53,7 @@ class Journaux extends Page $params = array_filter([ 'select' => $this->select, - 'results' => $this->results, + 'results' => (string) $this->results, 'TYPE' => $this->type, ]); diff --git a/documentation/documentation_api_logistics.md b/documentation/documentation_api_logistics.md index 5e83602..5efeee9 100644 --- a/documentation/documentation_api_logistics.md +++ b/documentation/documentation_api_logistics.md @@ -510,17 +510,96 @@ Retourne la liste des journaux correspondant au type demandé. Un journal contie | Paramètre | Type | Obligatoire | Description | |-----------|------|:-----------:|-------------| -| `TYPE` | `string` | Oui | Code de type de journal. Filtre les journaux par leur type (ex : ventes, achats). Les codes de type disponibles dépendent de la configuration du dossier. | -| `select` | `string` | Non | Colonnes à retourner, séparées par des virgules (colonnes de la table `jnl`). | -| `results` | `int` | Non | Nombre maximum de résultats. | +| `TYPE` | `string` | Oui | Code de type de journal (1 ou 2 caractères). Voir la section "Codes de type" ci-dessous. | +| `select` | `string` | Non | Colonnes à retourner, séparées par des virgules (colonnes de la table `jnl`). Insensible à la casse. Si omis, seule la colonne `jnl` est retournée par défaut. | +| `results` | `string` | Non | Nombre maximum de résultats. **Doit être au format string** (ex : `"50"`), pas un nombre. Un entier provoque une erreur HTTP 400. La limite par défaut (sans ce paramètre) est de 30 résultats. Contrairement à `art_list` et `third_list`, ce paramètre fonctionne réellement pour `jnl_list`. | + +**Codes de type de journal** : + +La colonne `TYPE` de la table `jnl` contient un code à 2 caractères suivant le schéma `[Domaine][TypeDocument]` : + +| Domaine (1er caractère) | Signification | +|---|---| +| `C` | Client | +| `S` | Supplier / Fournisseur | +| `K` | stocK / Inventaire | + +| Type document (2e caractère) | Signification | +|---|---| +| `O` | Order / Commande | +| `D` | Delivery / Livraison (note d'envoi) | +| `I` | Invoice / Facture | +| `C` | Credit note / Note de crédit | +| `P` | Proposal / Offre de prix (pro forma) | +| `A` | Achat | +| `M` | Mouvement (stock) | + +Le paramètre `TYPE` accepte 1 ou 2 caractères : + +- **1 caractère** : filtre tous les journaux dont le code de type contient ce caractère (première ou deuxième position). Exemples : + - `TYPE=C` retourne tous les journaux client (CO, CD, CI, CC, CP, CA, CM) -- 42 résultats dans le dossier de test. + - `TYPE=I` retourne toutes les factures (CI, KI) -- 26 résultats. + - `TYPE=O` retourne toutes les commandes (CO, SO) -- 7 résultats. + - `TYPE=D` retourne toutes les livraisons (CD, SD) -- 5 résultats. + - `TYPE=S` retourne tous les journaux fournisseur (SD, SO) -- 2 résultats. + - `TYPE=K` retourne tous les journaux inventaire (KI, KM) -- 2 résultats. + - `TYPE=P` retourne toutes les offres de prix (CP) -- 3 résultats. + - `TYPE=A` retourne tous les journaux d'achat (CA) -- 2 résultats. +- **2 caractères** : correspondance exacte sur le code de type. Exemples : + - `TYPE=CO` retourne uniquement les commandes client -- 6 résultats. + - `TYPE=CI` retourne uniquement les factures client -- 25 résultats. + - `TYPE=CC` retourne uniquement les notes de crédit client -- 1 résultat. + +**Métadonnées retournées** : + +| Clé | Type | Description | +|-----|------|-------------| +| `rowCount` | `int` | Nombre de résultats retournés. | +| `source` | `string` | Type de base de données (ex : `DBF`). | +| `unlimited` | `bool` | Indique si la requête est sans limite (toujours `false` dans les tests). | + +**Colonnes utiles de la table `jnl`** : + +| Colonne | Type | Description | +|---------|------|-------------| +| `JNL` | `C(8)` | Code unique du journal (ex : `03VEN`, `01COM`). | +| `NAME` | `C(40)` | Nom du journal (ex : `FACTURE CLIENT`). | +| `NAME1` | `C(40)` | Nom alternatif 1 (ex : `FACTURE 03VEN`). | +| `NAME2` | `C(40)` | Nom alternatif 2 (ex : `FAKTUUR`). | +| `TYPE` | `C(2)` | Code de type (ex : `CI`, `CO`, `SD`). | +| `NUMBER` | `N(8)` | Dernier numéro de document dans ce journal. | +| `JNLORDER` | `C(8)` | Journal de commande lié. | +| `JNLINV` | `C(8)` | Journal de facturation lié. | +| `JNLCRED` | `C(8)` | Journal de note de crédit lié. | +| `JNLMVT` | `C(8)` | Journal de mouvement de stock lié. | +| `STKID` | `C(2)` | Identifiant de stock associé. | +| `STATUSINIT` | `C(2)` | Statut initial des documents créés dans ce journal. | **Exemple de requête** : ```json { - "TYPE": "V", - "select": "jnlid,jnlname", - "results": 50 + "TYPE": "C", + "select": "JNL,NAME,TYPE,NUMBER", + "results": "50" +} +``` + +**Exemple de réponse** : + +```json +{ + "data": [ + { "jnl": "01COM", "name": "COMMANDE", "type": "CO", "number": 25100123 }, + { "jnl": "03VEN", "name": "FACTURE CLIENT", "type": "CI", "number": 25105451 }, + { "jnl": "04NCV", "name": "NOTE DE CREDIT CLIENT", "type": "CC", "number": 25400010 } + ], + "metadata": { + "rowCount": 3, + "source": "DBF", + "unlimited": false + }, + "error": null } ``` @@ -987,13 +1066,13 @@ Tiers (cust) 2. **Méthode POST uniquement** : tous les endpoints utilisent la méthode POST, y compris pour les opérations de lecture. N'utilisez pas GET, PUT ou DELETE. -3. **Paramètre `QTY` en string** : dans l'endpoint `Document_GetUnitPriceAndVat`, le paramètre `QTY` doit impérativement être au format string (`"2"`), pas numérique (`2`). Le non-respect de ce format provoque un comportement inattendu. +3. **Paramètres numériques en string** : plusieurs paramètres qui représentent des nombres doivent être transmis au format `string`. Le paramètre `QTY` dans `Document_GetUnitPriceAndVat` (`"2"`, pas `2`) et le paramètre `results` dans `jnl_list` (`"50"`, pas `50`) provoquent une erreur HTTP 400 s'ils sont envoyés comme entiers. Toujours caster en string les valeurs numériques en cas de doute. 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`** : 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. +5. **Paramètre `results`** : le comportement de ce paramètre varie selon l'endpoint. Pour `art_list`, il n'a **aucun effet** (toujours 5 résultats maximum). Pour `third_list`, il n'a **aucun effet** non plus (toujours 10 résultats maximum). En revanche, pour `jnl_list`, le paramètre `results` **fonctionne réellement** et limite le nombre de résultats retournés (la limite par défaut sans ce paramètre est de 30). Le paramètre doit être au format string pour `jnl_list`. -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. +6. **Paramètre `TYPE` obligatoire pour `jnl_list`** : l'endpoint `jnl_list` exige le paramètre `TYPE`. Le filtre accepte 1 caractère (filtre large : `C` pour tous les journaux client) ou 2 caractères (filtre exact : `CI` pour les factures client uniquement). Un appel sans ce paramètre retourne une erreur. 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`. diff --git a/tests/Feature/JournauxPageTest.php b/tests/Feature/JournauxPageTest.php index b8b2948..3705f8b 100644 --- a/tests/Feature/JournauxPageTest.php +++ b/tests/Feature/JournauxPageTest.php @@ -46,23 +46,43 @@ it('shows validation error when TYPE is empty', function () { it('searches journaux via jnl_list', function () { Http::fake([ '*/jnl_list' => Http::response([ - 'data' => [['jnlid' => 'VEN', 'jnlname' => 'Ventes']], - 'metadata' => ['rowcount' => 1, 'issuccess' => true], + 'data' => [['jnl' => '03VEN', 'name' => 'FACTURE CLIENT', 'type' => 'CI']], + 'metadata' => ['rowCount' => 1, 'source' => 'DBF', 'unlimited' => false], 'error' => null, ]), ]); Livewire::test(Journaux::class) - ->set('type', 'V') - ->set('select', 'jnlid,jnlname') + ->set('type', 'I') + ->set('select', 'jnl,name,type') ->call('searchJournaux') ->assertSet('hasSearched', true) - ->assertSet('data', [['jnlid' => 'VEN', 'jnlname' => 'Ventes']]) + ->assertSet('data', [['jnl' => '03VEN', 'name' => 'FACTURE CLIENT', 'type' => 'CI']]) ->assertSet('errorMessage', null); Http::assertSent(function ($request) { return str_contains($request->url(), 'jnl_list') - && $request->data()['TYPE'] === 'V'; + && $request->data()['TYPE'] === 'I'; + }); +}); + +it('sends results as string to avoid HTTP 400', function () { + Http::fake([ + '*/jnl_list' => Http::response([ + 'data' => [], + 'metadata' => ['rowCount' => 0, 'source' => 'DBF', 'unlimited' => false], + 'error' => null, + ]), + ]); + + Livewire::test(Journaux::class) + ->set('type', 'C') + ->set('results', 50) + ->call('searchJournaux'); + + Http::assertSent(function ($request) { + return str_contains($request->url(), 'jnl_list') + && $request->data()['results'] === '50'; }); });