Enhance API parameter documentation and introduce reusable component
- Added a new Blade component `<x-logistics.param-table>` for displaying API parameter tables across all Filament pages, ensuring consistent styling and reducing HTML duplication. - Integrated parameter tables for each endpoint in the Articles, Documents, Divers, Journaux, Tiers, and other pages, providing users with clear reference information. - Updated the documentation to reflect the new structure and details of API parameters, including required fields and descriptions. - Improved user experience by ensuring that endpoints without parameters do not display empty tables. - Overall, enhanced the clarity and usability of API interactions within the application.
This commit is contained in:
@@ -24,6 +24,7 @@ Utiliser ces composants au lieu de dupliquer du HTML/CSS.
|
|||||||
| `<x-logistics.search-input>` | Champ de recherche avec icone loupe | `logistics/search-input.blade.php` |
|
| `<x-logistics.search-input>` | Champ de recherche avec icone loupe | `logistics/search-input.blade.php` |
|
||||||
| `<x-logistics.form-field>` | Champ de formulaire (label + input) | `logistics/form-field.blade.php` |
|
| `<x-logistics.form-field>` | Champ de formulaire (label + input) | `logistics/form-field.blade.php` |
|
||||||
| `<x-logistics.json-block>` | Bloc JSON formate | `logistics/json-block.blade.php` |
|
| `<x-logistics.json-block>` | Bloc JSON formate | `logistics/json-block.blade.php` |
|
||||||
|
| `<x-logistics.param-table>` | Tableau de reference des parametres API | `logistics/param-table.blade.php` |
|
||||||
|
|
||||||
## Conventions CSS
|
## Conventions CSS
|
||||||
|
|
||||||
@@ -108,3 +109,4 @@ Utiliser ces composants au lieu de dupliquer du HTML/CSS.
|
|||||||
- Les formulaires dans une carte utilisent `<div class="p-6">` pour le contenu.
|
- Les formulaires dans une carte utilisent `<div class="p-6">` pour le contenu.
|
||||||
- Toujours afficher un etat de chargement (`wire:loading`) sur les actions reseau.
|
- Toujours afficher un etat de chargement (`wire:loading`) sur les actions reseau.
|
||||||
- Les blocs JSON utilisent `<x-logistics.json-block>` et non `<pre>` brut.
|
- Les blocs JSON utilisent `<x-logistics.json-block>` et non `<pre>` brut.
|
||||||
|
- Chaque endpoint doit avoir un tableau de parametres via `<x-logistics.param-table>` (sauf si aucun parametre).
|
||||||
|
|||||||
@@ -42,6 +42,28 @@ class Articles extends Page
|
|||||||
|
|
||||||
public bool $hasCheckedStock = false;
|
public bool $hasCheckedStock = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<int, array{name: string, type: string, required: string, description: string}>
|
||||||
|
*/
|
||||||
|
public function paramTableArtList(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
['name' => 'search', 'type' => 'string', 'required' => 'Oui', 'description' => 'Filtre de recherche textuel. Recherche dans artid et name1. Obligatoire.'],
|
||||||
|
['name' => 'select', 'type' => 'string', 'required' => 'Non', 'description' => 'Colonnes a retourner, separees par des virgules (colonnes de la table art).'],
|
||||||
|
['name' => 'barcode', 'type' => 'string', 'required' => 'Non', 'description' => 'Sans effet observable. Le parametre search reste obligatoire meme si barcode est fourni.'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<int, array{name: string, type: string, required: string, description: string}>
|
||||||
|
*/
|
||||||
|
public function paramTableArtGetstk(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
['name' => 'ARTID', 'type' => 'string', 'required' => 'Oui', 'description' => "Identifiant unique de l'article (champ artid de la table art)."],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
public function searchArticles(): void
|
public function searchArticles(): void
|
||||||
{
|
{
|
||||||
$this->errorMessage = null;
|
$this->errorMessage = null;
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ class Divers extends Page
|
|||||||
// codes_list
|
// codes_list
|
||||||
public string $code = '';
|
public string $code = '';
|
||||||
|
|
||||||
|
public string $codesSelect = '';
|
||||||
|
|
||||||
public array $codesData = [];
|
public array $codesData = [];
|
||||||
|
|
||||||
// custom_geninv_updatestock
|
// custom_geninv_updatestock
|
||||||
@@ -41,7 +43,9 @@ class Divers extends Page
|
|||||||
|
|
||||||
public string $stkToCheckDetail = '';
|
public string $stkToCheckDetail = '';
|
||||||
|
|
||||||
public string $stkMode = '';
|
public string $stkMode = '1';
|
||||||
|
|
||||||
|
public string $stkThirdId = '';
|
||||||
|
|
||||||
public array $updateStockResult = [];
|
public array $updateStockResult = [];
|
||||||
|
|
||||||
@@ -54,6 +58,33 @@ class Divers extends Page
|
|||||||
|
|
||||||
public bool $hasUpdatedStock = false;
|
public bool $hasUpdatedStock = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<int, array{name: string, type: string, required: string, description: string}>
|
||||||
|
*/
|
||||||
|
public function paramTableCodesList(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
['name' => 'code', 'type' => 'string', 'required' => 'Oui', 'description' => 'Nom exact du groupe de codes internes (table incodes). Correspondance exacte, sensible a la casse (MAJUSCULES). Chaine vide pour la liste maitre.'],
|
||||||
|
['name' => 'select', 'type' => 'string', 'required' => 'Non', 'description' => 'Sans effet. Toutes les colonnes sont toujours retournees.'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<int, array{name: string, type: string, required: string, description: string}>
|
||||||
|
*/
|
||||||
|
public function paramTableUpdateStock(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
['name' => 'ARTID', 'type' => 'string', 'required' => 'Oui', 'description' => 'Identifiant de l\'article (champ artid de la table art).'],
|
||||||
|
['name' => 'STKID', 'type' => 'string', 'required' => 'Oui', 'description' => 'Code du depot / entrepot. Valeurs via codes_list STOCK (ex: A, SG).'],
|
||||||
|
['name' => 'QTY', 'type' => 'string', 'required' => 'Oui', 'description' => 'Quantite a ajouter au stock. Peut etre negatif pour retirer du stock.'],
|
||||||
|
['name' => 'MODE', 'type' => 'string', 'required' => 'Oui', 'description' => '"0" = Inventaire (journal KI). "1" = Restock (journal KM, necessite THIRDID).'],
|
||||||
|
['name' => 'THIRDID', 'type' => 'string', 'required' => 'Si MODE=1', 'description' => 'Identifiant du tiers / fournisseur (custid de la table cust). Obligatoire en mode Restock.'],
|
||||||
|
['name' => 'TOCHECK', 'type' => 'string', 'required' => 'Oui', 'description' => 'Prix de controle. Stocke avec le mouvement mais n\'affecte pas la quantite de stock.'],
|
||||||
|
['name' => 'TOCHECKDETAIL', 'type' => 'string', 'required' => 'Oui', 'description' => 'Remarque / detail de controle. Texte libre stocke avec le mouvement.'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
public function getSerialNumber(): void
|
public function getSerialNumber(): void
|
||||||
{
|
{
|
||||||
$this->errorMessage = null;
|
$this->errorMessage = null;
|
||||||
@@ -88,7 +119,13 @@ class Divers extends Page
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
$service = app(LogisticsService::class);
|
$service = app(LogisticsService::class);
|
||||||
$response = $service->codesList(['code' => $this->code]);
|
$params = ['code' => $this->code];
|
||||||
|
|
||||||
|
if (filled($this->codesSelect)) {
|
||||||
|
$params['select'] = $this->codesSelect;
|
||||||
|
}
|
||||||
|
|
||||||
|
$response = $service->codesList($params);
|
||||||
|
|
||||||
$this->codesData = $response['data'] ?? [];
|
$this->codesData = $response['data'] ?? [];
|
||||||
$this->errorMessage = ApiErrorTranslator::translate($response['error'] ?? null);
|
$this->errorMessage = ApiErrorTranslator::translate($response['error'] ?? null);
|
||||||
@@ -105,8 +142,14 @@ class Divers extends Page
|
|||||||
{
|
{
|
||||||
$this->errorMessage = null;
|
$this->errorMessage = null;
|
||||||
|
|
||||||
if (blank($this->stkArtId) || blank($this->stkId) || blank($this->stkQty)) {
|
if (blank($this->stkArtId) || blank($this->stkId) || blank($this->stkQty) || blank($this->stkMode)) {
|
||||||
$this->errorMessage = 'Les champs ARTID, STKID et QTY sont obligatoires.';
|
$this->errorMessage = 'Les champs ARTID, STKID, QTY et MODE sont obligatoires.';
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->stkMode === '1' && blank($this->stkThirdId)) {
|
||||||
|
$this->errorMessage = 'Le champ THIRDID est obligatoire en mode Restock (MODE=1).';
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -116,14 +159,18 @@ class Divers extends Page
|
|||||||
try {
|
try {
|
||||||
$service = app(LogisticsService::class);
|
$service = app(LogisticsService::class);
|
||||||
|
|
||||||
$params = array_filter([
|
$params = [
|
||||||
'ARTID' => $this->stkArtId,
|
'ARTID' => $this->stkArtId,
|
||||||
'STKID' => $this->stkId,
|
'STKID' => $this->stkId,
|
||||||
'QTY' => $this->stkQty,
|
'QTY' => $this->stkQty,
|
||||||
'TOCHECK' => $this->stkToCheck,
|
'TOCHECK' => $this->stkToCheck,
|
||||||
'TOCHECKDETAIL' => $this->stkToCheckDetail,
|
'TOCHECKDETAIL' => $this->stkToCheckDetail,
|
||||||
'MODE' => $this->stkMode,
|
'MODE' => $this->stkMode,
|
||||||
]);
|
];
|
||||||
|
|
||||||
|
if (filled($this->stkThirdId)) {
|
||||||
|
$params['THIRDID'] = $this->stkThirdId;
|
||||||
|
}
|
||||||
|
|
||||||
$response = $service->customGeninvUpdatestock($params);
|
$response = $service->customGeninvUpdatestock($params);
|
||||||
|
|
||||||
|
|||||||
@@ -139,6 +139,120 @@ class Documents extends Page
|
|||||||
|
|
||||||
public bool $hasModified = false;
|
public bool $hasModified = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<int, array{name: string, type: string, required: string, description: string}>
|
||||||
|
*/
|
||||||
|
public function paramTableDocumentList(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
['name' => 'select', 'type' => 'string', 'required' => 'Non', 'description' => 'Colonnes a retourner, separees par des virgules (colonnes de la table dochead). Par defaut : thirdid.'],
|
||||||
|
['name' => 'thirdid', 'type' => 'string', 'required' => 'Non', 'description' => 'Identifiant du tiers (custid de la table cust). Si fourni, seuls les documents de ce tiers sont retournes.'],
|
||||||
|
['name' => 'results', 'type' => 'string', 'required' => 'Non', 'description' => "Nombre maximum de resultats. N'a d'effet que lorsqu'un thirdid est egalement fourni. Limite par defaut : ~108."],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<int, array{name: string, type: string, required: string, description: string}>
|
||||||
|
*/
|
||||||
|
public function paramTableDocumentDetail(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
['name' => 'jnl', 'type' => 'string', 'required' => 'Oui', 'description' => 'Code du journal auquel appartient le document (ex : 03VEN, 01COM).'],
|
||||||
|
['name' => 'number', 'type' => 'string', 'required' => 'Oui', 'description' => 'Numero du document dans le journal (ex : 25105397).'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<int, array{name: string, type: string, required: string, description: string}>
|
||||||
|
*/
|
||||||
|
public function paramTableStatusList(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
['name' => 'jnl', 'type' => 'string', 'required' => 'Oui', 'description' => 'Code du journal dont on veut connaitre les statuts (ex : 03VEN, 01COM, 02NEV).'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<int, array{name: string, type: string, required: string, description: string}>
|
||||||
|
*/
|
||||||
|
public function paramTableUnitPriceAndVat(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
['name' => 'ARTID', 'type' => 'string', 'required' => 'Oui', 'description' => "Identifiant de l'article (champ artid de la table art)."],
|
||||||
|
['name' => 'QTY', 'type' => 'string', 'required' => 'Oui', 'description' => 'Quantite demandee. Doit etre au format string (ex : "2", pas 2).'],
|
||||||
|
['name' => 'JNL', 'type' => 'string', 'required' => 'Oui', 'description' => 'Code du journal (ex : 03VEN).'],
|
||||||
|
['name' => 'THIRDID', 'type' => 'string', 'required' => 'Oui', 'description' => 'Identifiant du tiers (custid de la table cust).'],
|
||||||
|
['name' => 'DATE', 'type' => 'string', 'required' => 'Oui', 'description' => 'Date de reference. Format obligatoire : YYYY-MM-DD.'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<int, array{name: string, type: string, required: string, description: string}>
|
||||||
|
*/
|
||||||
|
public function paramTableDueDate(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
['name' => 'paydelay', 'type' => 'string', 'required' => 'Oui', 'description' => 'Code de delai de paiement. Valeurs via codes_list PAYDELAY (ex : 30, 30F, 60, 60F, 90F).'],
|
||||||
|
['name' => 'date', 'type' => 'string', 'required' => 'Oui', 'description' => 'Date de depart pour le calcul. Format obligatoire : YYYY-MM-DD.'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<int, array{name: string, type: string, required: string, description: string}>
|
||||||
|
*/
|
||||||
|
public function paramTableAttachListThumbnail(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
['name' => 'JNL', 'type' => 'string', 'required' => 'Oui', 'description' => 'Code du journal du document (ex : 03VEN).'],
|
||||||
|
['name' => 'NUMBER', 'type' => 'string', 'required' => 'Oui', 'description' => 'Numero du document (ex : 25105397).'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<int, array{name: string, type: string, required: string, description: string}>
|
||||||
|
*/
|
||||||
|
public function paramTableGetPdf(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
['name' => 'JNL', 'type' => 'string', 'required' => 'Oui', 'description' => 'Code du journal (ex : 03VEN).'],
|
||||||
|
['name' => 'NUMBER', 'type' => 'string', 'required' => 'Oui', 'description' => 'Numero du document (ex : 25105397).'],
|
||||||
|
['name' => 'LAYOUT', 'type' => 'string', 'required' => 'Oui', 'description' => 'Identifiant numerique de la mise en page (format string). Valeur "1" recommandee par defaut.'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<int, array{name: string, type: string, required: string, description: string}>
|
||||||
|
*/
|
||||||
|
public function paramTableDocumentAdd(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
['name' => 'ThirdId', 'type' => 'string', 'required' => 'Oui', 'description' => 'Identifiant du tiers (custid de la table cust).'],
|
||||||
|
['name' => 'Date', 'type' => 'string', 'required' => 'Oui', 'description' => "Date d'encodage du document (ex : 2026-02-20)."],
|
||||||
|
['name' => 'JNL', 'type' => 'string', 'required' => 'Oui', 'description' => 'Code du journal (ex : VEN).'],
|
||||||
|
['name' => 'Artid', 'type' => 'array', 'required' => 'Oui', 'description' => "Tableau d'identifiants d'articles. Chaque element correspond a une ligne du document."],
|
||||||
|
['name' => 'Qty', 'type' => 'array', 'required' => 'Oui', 'description' => 'Tableau de quantites (format string). Correspondance positionnelle avec Artid.'],
|
||||||
|
['name' => 'Saleprice', 'type' => 'array', 'required' => 'Oui', 'description' => 'Tableau des prix de vente unitaires (format string). Correspondance positionnelle avec Artid.'],
|
||||||
|
['name' => 'Discount', 'type' => 'array', 'required' => 'Non', 'description' => 'Tableau des reductions de prix. Correspondance positionnelle avec Artid.'],
|
||||||
|
['name' => 'Vatid', 'type' => 'array', 'required' => 'Non', 'description' => 'Tableau des identifiants de code TVA. Correspondance positionnelle avec Artid.'],
|
||||||
|
['name' => 'Vatpc', 'type' => 'array', 'required' => 'Non', 'description' => 'Tableau des pourcentages de TVA. Correspondance positionnelle avec Artid.'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<int, array{name: string, type: string, required: string, description: string}>
|
||||||
|
*/
|
||||||
|
public function paramTableDocumentMod(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
['name' => 'number', 'type' => 'string', 'required' => 'Oui', 'description' => 'Identifiant du document a modifier (ex : 2026/0001).'],
|
||||||
|
['name' => 'JNL', 'type' => 'string', 'required' => 'Oui', 'description' => 'Code du journal lie au document (ex : VEN).'],
|
||||||
|
['name' => 'Thirdid', 'type' => 'string', 'required' => 'Non', 'description' => 'Nouvel identifiant du tiers (si modification du tiers associe).'],
|
||||||
|
['name' => 'Artid', 'type' => 'array', 'required' => 'Non', 'description' => "Tableau d'identifiants d'articles (remplace les lignes existantes)."],
|
||||||
|
['name' => 'Qty', 'type' => 'array', 'required' => 'Non', 'description' => 'Tableau de quantites. Correspondance positionnelle avec Artid.'],
|
||||||
|
['name' => 'Saleprice', 'type' => 'array', 'required' => 'Non', 'description' => 'Tableau des prix de vente unitaires. Correspondance positionnelle avec Artid.'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
public function searchDocuments(): void
|
public function searchDocuments(): void
|
||||||
{
|
{
|
||||||
$this->errorMessage = null;
|
$this->errorMessage = null;
|
||||||
|
|||||||
@@ -36,6 +36,18 @@ class Journaux extends Page
|
|||||||
|
|
||||||
public bool $hasSearched = false;
|
public bool $hasSearched = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<int, array{name: string, type: string, required: string, description: string}>
|
||||||
|
*/
|
||||||
|
public function paramTableJnlList(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
['name' => 'TYPE', 'type' => 'string', 'required' => 'Oui', 'description' => 'Code de type de journal (1 ou 2 caracteres). Ex: C=Client, S=Fournisseur, K=Stock, CI=Facture client, CO=Commande.'],
|
||||||
|
['name' => 'select', 'type' => 'string', 'required' => 'Non', 'description' => 'Colonnes a retourner, separees par des virgules (colonnes de la table jnl). Si omis, seule la colonne jnl est retournee.'],
|
||||||
|
['name' => 'results', 'type' => 'string', 'required' => 'Non', 'description' => 'Nombre maximum de resultats. Doit etre au format string. Limite par defaut : 30.'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
public function searchJournaux(): void
|
public function searchJournaux(): void
|
||||||
{
|
{
|
||||||
$this->errorMessage = null;
|
$this->errorMessage = null;
|
||||||
|
|||||||
@@ -42,6 +42,28 @@ class Tiers extends Page
|
|||||||
|
|
||||||
public bool $hasHistory = false;
|
public bool $hasHistory = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<int, array{name: string, type: string, required: string, description: string}>
|
||||||
|
*/
|
||||||
|
public function paramTableThirdList(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
['name' => 'search', 'type' => 'string', 'required' => 'Oui', 'description' => 'Filtre de recherche textuel. Recherche dans name, groupid et vat (pas dans custid). Obligatoire.'],
|
||||||
|
['name' => 'select', 'type' => 'string', 'required' => 'Non', 'description' => 'Colonnes a retourner, separees par des virgules. Par defaut : custid, name.'],
|
||||||
|
['name' => 'results', 'type' => 'int', 'required' => 'Non', 'description' => "Sans effet. L'API retourne toujours un maximum de 10 resultats."],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<int, array{name: string, type: string, required: string, description: string}>
|
||||||
|
*/
|
||||||
|
public function paramTableArtHistory(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
['name' => 'thirdid', 'type' => 'string', 'required' => 'Oui', 'description' => 'Identifiant du tiers (custid de la table cust). Sensible a la casse : doit etre en minuscules (thirdid, pas THIRDID).'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
public function searchTiers(): void
|
public function searchTiers(): void
|
||||||
{
|
{
|
||||||
$this->errorMessage = null;
|
$this->errorMessage = null;
|
||||||
|
|||||||
@@ -13,10 +13,9 @@ Dernière mise à jour : 2026-02-23
|
|||||||
5. [Tables et colonnes disponibles](#5-tables-et-colonnes-disponibles)
|
5. [Tables et colonnes disponibles](#5-tables-et-colonnes-disponibles)
|
||||||
6. [Récupération de données](#6-récupération-de-données)
|
6. [Récupération de données](#6-récupération-de-données)
|
||||||
7. [Envoi de données](#7-envoi-de-données)
|
7. [Envoi de données](#7-envoi-de-données)
|
||||||
8. [Endpoints non fonctionnels](#8-endpoints-non-fonctionnels)
|
8. [Relations entre entités](#8-relations-entre-entités)
|
||||||
9. [Relations entre entités](#9-relations-entre-entités)
|
9. [Remarques et points d'attention](#9-remarques-et-points-dattention)
|
||||||
10. [Remarques et points d'attention](#10-remarques-et-points-dattention)
|
10. [Ressources externes](#10-ressources-externes)
|
||||||
11. [Ressources externes](#11-ressources-externes)
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -1254,17 +1253,37 @@ Retourne le numéro de série du dossier comptable. Identifie de manière unique
|
|||||||
|
|
||||||
**Paramètres** : aucun.
|
**Paramètres** : aucun.
|
||||||
|
|
||||||
|
**Structure de la réponse `data`** :
|
||||||
|
|
||||||
|
La clé `data` est un objet contenant une seule clé `getserialnumber` avec le numéro de série sous forme de chaîne.
|
||||||
|
|
||||||
|
| Champ | Type | Description |
|
||||||
|
|-------|------|-------------|
|
||||||
|
| `getserialnumber` | `string` | Numéro de série du dossier comptable (ex : `"10005826"`). |
|
||||||
|
|
||||||
**Exemple de requête** :
|
**Exemple de requête** :
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{}
|
{}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**Exemple de réponse** :
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"getserialnumber": "10005826"
|
||||||
|
},
|
||||||
|
"metadata": { "rowcount": 1, "issuccess": true },
|
||||||
|
"error": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
#### `codes_list` -- Données par code interne
|
#### `codes_list` -- Données par code interne
|
||||||
|
|
||||||
Retourne les données associées à un code interne. Les codes proviennent de la table `incodes` et servent à stocker des listes de valeurs paramétrables (types de documents, catégories, etc.).
|
Retourne les données associées à un code interne. Les codes proviennent de la table `incodes` et servent à stocker des listes de valeurs paramétrables (types de documents, catégories, délais de paiement, modes de paiement, codes TVA, pays, etc.).
|
||||||
|
|
||||||
| | |
|
| | |
|
||||||
|---|---|
|
|---|---|
|
||||||
@@ -1275,17 +1294,210 @@ Retourne les données associées à un code interne. Les codes proviennent de la
|
|||||||
|
|
||||||
| Paramètre | Type | Obligatoire | Description |
|
| Paramètre | Type | Obligatoire | Description |
|
||||||
|-----------|------|:-----------:|-------------|
|
|-----------|------|:-----------:|-------------|
|
||||||
| `code` | `string` | Oui | Début du code interne à rechercher (de la table `incodes`). Le filtre s'applique par préfixe. |
|
| `code` | `string` | Oui | Nom exact du groupe de codes internes (de la table `incodes`). **Correspondance exacte**, pas de filtre par préfixe. **Sensible à la casse** : doit être en MAJUSCULES (ex : `PAYDELAY`, pas `paydelay`). Si la valeur est une chaîne vide (`""`), retourne la liste de tous les groupes de codes disponibles. |
|
||||||
|
|
||||||
**Exemple de requête** :
|
**Comportement selon la valeur de `code`** :
|
||||||
|
|
||||||
|
| Valeur de `code` | Résultat |
|
||||||
|
|-------------------|----------|
|
||||||
|
| Chaîne vide `""` | Retourne la liste maître de tous les groupes de codes (42 groupes dans le dossier de test). Structure : `name` (identifiant du groupe) + `prompt1` (description en français). |
|
||||||
|
| Nom exact d'un groupe (ex : `PAYDELAY`) | Retourne les valeurs du groupe. Structure : `vala1` à `vala6` (chaînes), `valn1`, `valn2` (nombres). |
|
||||||
|
| Nom inexistant | Retourne un tableau vide sans erreur. |
|
||||||
|
| Nom partiel (ex : `PAY` au lieu de `PAYMODE`) | Retourne un tableau vide (pas de recherche par préfixe). |
|
||||||
|
| Minuscules (ex : `paydelay`) | Retourne un tableau vide (sensible à la casse). |
|
||||||
|
|
||||||
|
**Body vide (`{}`)** : retourne une erreur HTTP 400.
|
||||||
|
|
||||||
|
**Paramètre `select`** : accepté par l'API mais sans effet. Toutes les colonnes sont toujours retournées.
|
||||||
|
|
||||||
|
**Structure de la réponse `data` -- mode liste maître (code vide)** :
|
||||||
|
|
||||||
|
| Champ | Type | Description |
|
||||||
|
|-------|------|-------------|
|
||||||
|
| `name` | `string` | Identifiant unique du groupe de codes (ex : `PAYDELAY`, `PAYMODE`, `VAT`). |
|
||||||
|
| `prompt1` | `string` | Description du groupe en français (ex : `"Délais de paiements"`, `"Modes de paiement"`). |
|
||||||
|
|
||||||
|
**Structure de la réponse `data` -- mode valeurs d'un groupe** :
|
||||||
|
|
||||||
|
| Champ | Type | Description |
|
||||||
|
|-------|------|-------------|
|
||||||
|
| `vala1` | `string` | Code/valeur principale (ex : `"30"`, `"CAS"`, `"BE"`, `"21"`). |
|
||||||
|
| `vala2` | `string` | Description en français (ex : `"30 jours date de facture"`, `"CASH"`, `"BELGIQUE"`, `"Ventes 21 %"`). |
|
||||||
|
| `vala3` | `string` | Description en néerlandais ou alternative (ex : `"Belgïe"`, `"exclusief cash"`). Souvent vide. |
|
||||||
|
| `vala4` | `string` | Champ texte supplémentaire. Généralement vide. |
|
||||||
|
| `vala5` | `string` | Champ texte supplémentaire. Utilisé pour certains codes (ex : codes TVA : `"NSS 21"`). |
|
||||||
|
| `vala6` | `string` | Champ texte supplémentaire. Généralement vide. |
|
||||||
|
| `valn1` | `int` ou `float` | Valeur numérique 1. Signification variable selon le groupe (ex : pour PAYDELAY = nombre de jours, pour VAT = pourcentage). |
|
||||||
|
| `valn2` | `int` ou `float` | Valeur numérique 2. Signification variable selon le groupe. |
|
||||||
|
|
||||||
|
**Groupes de codes disponibles** (42 dans le dossier de test) :
|
||||||
|
|
||||||
|
| Groupe | Description | Exemples de valeurs (`vala1`) |
|
||||||
|
|--------|-------------|-------------------------------|
|
||||||
|
| `PAYDELAY` | Délais de paiements | `30`, `30F`, `45F`, `50`, `60`, `60F`, `75F`, `90`, `90F`, `0F` |
|
||||||
|
| `PAYMODE` | Modes de paiement | `CAS` (Cash), `VIR` (Virement), `BC` (Bancontact), `CBEF` (Cash BEF) |
|
||||||
|
| `VAT` | Codes TVA | `21`, `6`, `0`, `ECEE`, `IEXP`, `MD21`, `ESERV`, `EMD21`, `C` |
|
||||||
|
| `VATCAT` | Régime TVA | `N` (Non-assujetti), `R` (Exempté), `` (Assujetti) |
|
||||||
|
| `STOCK` | Dépôts / Entrepôts | `A`, `SG` (SEGEC) |
|
||||||
|
| `COUNTRY` | Pays | `BE` (Belgique), `FR` (France), `DE` (Allemagne), etc. (31 entrées) |
|
||||||
|
| `CUSTTYPE` | Types de tiers | `FOU` (Fournisseur), `CLI` (Client), `PRO` (Prospect), `TRA` (Transporteur) |
|
||||||
|
| `LANGUAGE` | Langues | `F` (Français), `N` (Nederlands) |
|
||||||
|
| `AGENT` | Agents | `PON`, `FAB`, `TD`, `ESI`, `BPOST`, `LEBA`, etc. |
|
||||||
|
| `CATEGORIE` | Catégories d'article | `CARTOUCHE`, `PAPIER`, `TONER`, `CABLE`, `IMPRIMANTE`, etc. (45 entrées) |
|
||||||
|
| `MARQUE` | Marques produit | (valeurs disponibles) |
|
||||||
|
| `CIVILITY` | Civilité | (valeurs disponibles) |
|
||||||
|
| `DLVMODE` | Modes de livraison | (0 valeurs configurées) |
|
||||||
|
| `ACCOUNT` | Comptes généraux | (valeurs disponibles) |
|
||||||
|
| `ARTFAMILY` | Familles de prix article | (valeurs disponibles) |
|
||||||
|
| `CUSTACC` | Catégories comptables client | (valeurs disponibles) |
|
||||||
|
| `ARTACC` | Catégories comptables article | (valeurs disponibles) |
|
||||||
|
|
||||||
|
**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`). |
|
||||||
|
|
||||||
|
**Exemple de requête -- liste maître** :
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"code": "PAY"
|
"code": ""
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
**Remarque** : les valeurs retournées contiennent des champs `vala1`, `vala2`, etc. dont la signification précise dépend du code recherché.
|
**Exemple de réponse -- liste maître** (extrait) :
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"data": [
|
||||||
|
{ "name": "PAYDELAY", "prompt1": "Délais de paiements" },
|
||||||
|
{ "name": "PAYMODE", "prompt1": "Modes de paiement" },
|
||||||
|
{ "name": "VAT", "prompt1": "Codes TVA" },
|
||||||
|
{ "name": "STOCK", "prompt1": "Dépôts" }
|
||||||
|
],
|
||||||
|
"metadata": { "rowCount": 42, "source": "DBF" },
|
||||||
|
"error": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Exemple de requête -- valeurs d'un groupe** :
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": "PAYMODE"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Exemple de réponse -- valeurs d'un groupe** :
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"data": [
|
||||||
|
{ "vala1": "", "vala2": "", "vala3": "", "vala4": "", "vala5": "", "vala6": "", "valn1": 0, "valn2": 0 },
|
||||||
|
{ "vala1": "CAS", "vala2": "CASH", "vala3": "exclusief cash", "vala4": "", "vala5": "", "vala6": "", "valn1": 1, "valn2": 0 },
|
||||||
|
{ "vala1": "VIR", "vala2": "Virement", "vala3": "Overschrijving", "vala4": "", "vala5": "", "vala6": "", "valn1": 0, "valn2": 0 },
|
||||||
|
{ "vala1": "BC", "vala2": "Bancontact", "vala3": "", "vala4": "", "vala5": "", "vala6": "", "valn1": 4, "valn2": 0 },
|
||||||
|
{ "vala1": "CBEF", "vala2": "CASH BEF", "vala3": "", "vala4": "", "vala5": "", "vala6": "", "valn1": 2, "valn2": 0 }
|
||||||
|
],
|
||||||
|
"metadata": { "rowCount": 5, "source": "DBF" },
|
||||||
|
"error": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Remarque** : chaque groupe contient souvent une première entrée avec des valeurs vides (entrée par défaut). La signification exacte des champs `valn1` et `valn2` varie selon le groupe. Par exemple, pour `PAYDELAY`, `valn1` est le nombre de jours et `valn2` semble être un type de calcul (1 = date de facture, 2 = date de facture, 3 = fin de mois). Pour `VAT`, `valn1` et `valn2` sont le pourcentage de TVA.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### `custom_geninv_updatestock` -- Mise à jour du stock
|
||||||
|
|
||||||
|
Met à jour le stock d'un article dans un dépôt. Supporte deux modes : inventaire (comptage) et réapprovisionnement (restock). Le mode Restock (MODE=1) est fonctionnel. Le mode Inventaire (MODE=0) nécessite un journal d'inventaire (type KI) configuré pour le dépôt, ce qui peut ne pas être le cas dans tous les dossiers.
|
||||||
|
|
||||||
|
| | |
|
||||||
|
|---|---|
|
||||||
|
| **URL** | `POST /{dossier}/custom_geninv_updatestock` |
|
||||||
|
| **Méthode service** | `LogisticsService::customGeninvUpdatestock(array $params)` |
|
||||||
|
| **Statut** | Fonctionnel (MODE=1 Restock). MODE=0 Inventaire dépend de la configuration des journaux. |
|
||||||
|
|
||||||
|
**Paramètres** :
|
||||||
|
|
||||||
|
| Paramètre | Type | Obligatoire | Description |
|
||||||
|
|-----------|------|:-----------:|-------------|
|
||||||
|
| `ARTID` | `string` | Oui | Identifiant de l'article (champ `artid` de la table `art`). |
|
||||||
|
| `STKID` | `string` | Oui | Code du dépôt / entrepôt. Les valeurs valides sont obtenues via `codes_list` avec `code=STOCK` (ex : `"A"`, `"SG"`). L'API recherche un journal d'inventaire ou de mouvement de stock associé à ce dépôt. |
|
||||||
|
| `QTY` | `string` | Oui | Quantité de stock à ajouter. Format string. **Peut être négatif** pour retirer du stock (ex : `"-5"`). |
|
||||||
|
| `TOCHECK` | `string` | Oui | Prix de contrôle. La valeur est stockée avec le mouvement d'inventaire mais n'affecte pas directement la quantité de stock. Peut être `"0"` si non pertinent. |
|
||||||
|
| `TOCHECKDETAIL` | `string` | Oui | Détail / remarque de contrôle. Texte libre stocké avec le mouvement d'inventaire. Peut être vide `""`. |
|
||||||
|
| `MODE` | `string` | Oui | Mode d'opération. `"0"` = Inventaire (comptage/rectification, nécessite journal KI pour le dépôt). `"1"` = Restock / réapprovisionnement (nécessite `THIRDID`). Toute valeur différente de `"0"` est traitée comme Restock. |
|
||||||
|
| `THIRDID` | `string` | Conditionnel | Identifiant du tiers (fournisseur). **Obligatoire en mode Restock (MODE != "0")**. Correspond au champ `custid` de la table `cust`. Non utilisé en mode Inventaire. |
|
||||||
|
|
||||||
|
**Modes de fonctionnement** :
|
||||||
|
|
||||||
|
| MODE | Nom | Description | Prérequis |
|
||||||
|
|------|-----|-------------|-----------|
|
||||||
|
| `"0"` | Inventaire | Comptage / rectification de stock. Crée un document dans le journal d'inventaire (type KI) du dépôt. | Le dépôt doit avoir un journal de type KI associé (via le champ `STKID` du journal). |
|
||||||
|
| `"1"` | Restock | Réapprovisionnement. Enregistre une entrée de marchandise en provenance d'un fournisseur. Crée un document dans le journal de mouvement de stock (type KM) du dépôt. | Le paramètre `THIRDID` doit être fourni (identifiant du fournisseur). |
|
||||||
|
|
||||||
|
**Codes d'erreur spécifiques** :
|
||||||
|
|
||||||
|
| Code | Message | Description |
|
||||||
|
|------|---------|-------------|
|
||||||
|
| `002` | `Invalid parameter, inventory JNL not found for warehouse : {STKID}` | Aucun journal d'inventaire n'est configuré pour le dépôt spécifié. Vérifiez que le dépôt a un journal KI (MODE=0) ou KM (MODE=1) associé. |
|
||||||
|
| `003` | `Invalid parameter, THIRDID is EMPTY, mandatory in this mode 'Restock'` | Le paramètre `THIRDID` est manquant ou vide alors que le mode Restock est actif. |
|
||||||
|
|
||||||
|
**Relation STKID / Journaux** :
|
||||||
|
|
||||||
|
Le paramètre `STKID` doit correspondre à un dépôt ayant un journal d'inventaire ou de mouvement de stock configuré. Les journaux de type K (inventaire/stock) et leur STKID associé sont visibles via `jnl_list` avec `TYPE=K` :
|
||||||
|
|
||||||
|
| Journal | Type | STKID | Compatibilité MODE |
|
||||||
|
|---------|------|-------|---------------------|
|
||||||
|
| `INV` (Inventaire) | `KI` | `""` (vide) | MODE=0 (mais dépôt par défaut non résolu dans les tests) |
|
||||||
|
| `MVTSG` (Mouvement stock SEGEC) | `KM` | `SG` | MODE=1 (Restock) |
|
||||||
|
|
||||||
|
**Structure de la réponse `data` (succès)** :
|
||||||
|
|
||||||
|
| Champ | Type | Description |
|
||||||
|
|-------|------|-------------|
|
||||||
|
| `custom_geninv_updatestock` | `string` | Message de confirmation. Contient l'ARTID, le mode et la quantité appliquée. |
|
||||||
|
|
||||||
|
**Exemple de requête (Restock)** :
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"ARTID": "003R92572",
|
||||||
|
"STKID": "SG",
|
||||||
|
"QTY": "5",
|
||||||
|
"TOCHECK": "12.50",
|
||||||
|
"TOCHECKDETAIL": "Réapprovisionnement fournisseur",
|
||||||
|
"MODE": "1",
|
||||||
|
"THIRDID": "0100002174"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Exemple de réponse (succès)** :
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"custom_geninv_updatestock": "OK : Change applied - Artid : 003R92572 - Real stock received (Restock mode) : 5.00"
|
||||||
|
},
|
||||||
|
"metadata": { "rowcount": 1, "issuccess": true },
|
||||||
|
"error": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Exemple de réponse en erreur (journal non trouvé)** :
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"xml": "<VFPData><headererror><errorcode>002</errorcode><description>Invalid parameter, inventory JNL not found for warehouse : A</description></headererror></VFPData>"
|
||||||
|
},
|
||||||
|
"metadata": { "rowcount": 1, "issuccess": false },
|
||||||
|
"error": ["Code: 002, Description: Invalid parameter, inventory JNL not found for warehouse : A"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -1391,34 +1603,7 @@ Modifie un document existant identifié par son numéro et son journal. Permet d
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 8. Endpoints non fonctionnels
|
## 8. Relations entre entités
|
||||||
|
|
||||||
Les endpoints suivants ont été identifiés mais ne fonctionnent pas dans l'état actuel ou nécessitent des paramètres dont les valeurs attendues sont inconnues.
|
|
||||||
|
|
||||||
### `custom_geninv_updatestock` -- Mise à jour de l'inventaire
|
|
||||||
|
|
||||||
| | |
|
|
||||||
|---|---|
|
|
||||||
| **URL** | `POST /{dossier}/custom_geninv_updatestock` |
|
|
||||||
| **Méthode service** | `LogisticsService::customGeninvUpdatestock(array $params)` |
|
|
||||||
| **Statut** | Non fonctionnel |
|
|
||||||
|
|
||||||
**Paramètres connus** :
|
|
||||||
|
|
||||||
| Paramètre | Type | Description |
|
|
||||||
|-----------|------|-------------|
|
|
||||||
| `ARTID` | `string` | Identifiant de l'article. |
|
|
||||||
| `STKID` | `string` | Identifiant du stock. **Valeur attendue inconnue**. |
|
|
||||||
| `QTY` | `string` | Quantité à mettre à jour. |
|
|
||||||
| `TOCHECK` | `string` | Signification inconnue (possiblement un prix). |
|
|
||||||
| `TOCHECKDETAIL` | `string` | Signification inconnue (possiblement des remarques). |
|
|
||||||
| `MODE` | `string` | Mode d'opération. Signification inconnue. |
|
|
||||||
|
|
||||||
**Problème** : la valeur attendue pour `STKID` est inconnue, et la signification de plusieurs paramètres (`TOCHECK`, `TOCHECKDETAIL`, `MODE`) reste à clarifier auprès du fournisseur.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 9. Relations entre entités
|
|
||||||
|
|
||||||
Les entités du système de gestion sont liées entre elles selon le schéma suivant :
|
Les entités du système de gestion sont liées entre elles selon le schéma suivant :
|
||||||
|
|
||||||
@@ -1449,7 +1634,7 @@ Tiers (cust)
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 10. Remarques et points d'attention
|
## 9. Remarques et points d'attention
|
||||||
|
|
||||||
1. **Dossier en minuscules** : le nom du dossier dans les URLs doit toujours être en minuscules. Exemple : `esigescom`, pas `EsiGescom`. Le non-respect de cette règle provoque une erreur.
|
1. **Dossier en minuscules** : le nom du dossier dans les URLs doit toujours être en minuscules. Exemple : `esigescom`, pas `EsiGescom`. Le non-respect de cette règle provoque une erreur.
|
||||||
|
|
||||||
@@ -1491,8 +1676,16 @@ Tiers (cust)
|
|||||||
|
|
||||||
20. **`third_GetArtHistory` -- casse du paramètre** : le paramètre `thirdid` doit être en **minuscules**. `THIRDID` en majuscules provoque une erreur HTTP 400 "thirdid parameter is required.", comme si le paramètre n'avait pas été fourni. L'endpoint retourne l'intégralité de l'historique sans limite (potentiellement des milliers d'éléments).
|
20. **`third_GetArtHistory` -- casse du paramètre** : le paramètre `thirdid` doit être en **minuscules**. `THIRDID` en majuscules provoque une erreur HTTP 400 "thirdid parameter is required.", comme si le paramètre n'avait pas été fourni. L'endpoint retourne l'intégralité de l'historique sans limite (potentiellement des milliers d'éléments).
|
||||||
|
|
||||||
|
21. **`codes_list` -- correspondance exacte et casse** : le paramètre `code` de l'endpoint `codes_list` fonctionne par **correspondance exacte** sur le nom du groupe de codes, pas par préfixe. `code=PAY` retourne 0 résultats ; il faut `code=PAYMODE` ou `code=PAYDELAY` en entier. Le paramètre est **sensible à la casse** : seules les majuscules fonctionnent (`PAYDELAY`, pas `paydelay`). Une chaîne vide (`code=""`) retourne la liste maître de tous les groupes disponibles (42 groupes). Le body vide (`{}`) provoque une erreur HTTP 400.
|
||||||
|
|
||||||
|
22. **`codes_list` -- structure de réponse variable** : la structure de `data` diffère selon la valeur de `code`. Avec une chaîne vide, les éléments contiennent `name` et `prompt1`. Avec un nom de groupe valide, les éléments contiennent `vala1` à `vala6` (chaînes) et `valn1`, `valn2` (nombres). La signification de ces champs varie selon le groupe.
|
||||||
|
|
||||||
|
23. **`custom_geninv_updatestock` -- fonctionnel en mode Restock** : cet endpoint est fonctionnel en MODE=1 (Restock). Il nécessite 6 paramètres obligatoires (`ARTID`, `STKID`, `QTY`, `TOCHECK`, `TOCHECKDETAIL`, `MODE`) plus `THIRDID` en mode Restock. Le paramètre `STKID` correspond à un code de dépôt (obtenu via `codes_list` avec `code=STOCK`), et le dépôt doit avoir un journal d'inventaire (KI) ou de mouvement de stock (KM) associé. Le MODE=0 (Inventaire) dépend de la configuration des journaux du dossier.
|
||||||
|
|
||||||
|
24. **`getserialnumber` -- structure de réponse** : la clé `data` de la réponse est un objet `{ "getserialnumber": "10005826" }` (pas une chaîne directe). Le champ contient le numéro de série du dossier comptable.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 11. Ressources externes
|
## 10. Ressources externes
|
||||||
|
|
||||||
- [Documentation Postman](https://documenter.getpostman.com/view/40440561/2sB2qaj2Pz)
|
- [Documentation Postman](https://documenter.getpostman.com/view/40440561/2sB2qaj2Pz)
|
||||||
|
|||||||
@@ -6,44 +6,59 @@ Dernière mise à jour : 2026-02-23
|
|||||||
|
|
||||||
Aucun travail en cours.
|
Aucun travail en cours.
|
||||||
|
|
||||||
## Changements récents (2026-02-23, session investigation endpoints Tiers)
|
## Changements récents (2026-02-23, session tableaux de paramètres)
|
||||||
|
|
||||||
- **Investigation complète des 2 endpoints Tiers** : tests systématiques via appels API réels pour documenter `third_list` et `third_GetArtHistory`.
|
- **Nouveau composant Blade `<x-logistics.param-table>`** : composant réutilisable dans `resources/views/components/logistics/param-table.blade.php`. Accepte un tableau `$params` (chaque élément contient `name`, `type`, `required`, `description`) et génère un tableau de référence des paramètres API avec les colonnes PARAMETRE / TYPE / OBLIGATOIRE / DESCRIPTION. Style conforme au design system (mêmes classes CSS que le tableau brut qui existait dans la page Divers).
|
||||||
- `third_list` : la recherche s'effectue sur les colonnes `name`, `groupid`, `vat` (pas `custid`). La colonne `custname` n'est PAS valide ; le nom est dans `name`. Colonnes par défaut : `custid,name`. Limite fixe de 10 résultats (paramètre `results` sans effet). Métadonnées détaillées : `rowCount`, `source`, `executionTimeMs`, `searchColumns`, `selectColumns`, `searchTerms`. Colonnes valides testées : `custid`, `name`, `name2`, `vat`, `email`, `groupid`, `website`, `memo`, `paydelay`, `paymode`, `bankname`, `iban`, `bic`, `custtype`, `discount`. Colonnes invalides : `custname`, `name1`, `addr1`, `zip`, `city`, `country`, `phone1`, etc.
|
- **Tableaux de paramètres ajoutés sur toutes les pages** : chaque endpoint de chaque page Filament dispose désormais d'un tableau de référence des paramètres sous le formulaire. Les descriptions proviennent de la documentation API (`documentation/documentation_api_logistics.md`).
|
||||||
- `third_GetArtHistory` : seul paramètre `thirdid` (minuscules obligatoires, `THIRDID` ne fonctionne pas). Retourne l'historique complet sans pagination (4468 éléments pour le client de test). Structure : `artid`, `artname`, `jnl`, `unitprice`, `qty`, `vatid`, `vatpc`, `s_credate`. ID inexistant = tableau vide sans erreur.
|
- **Divers** : `getserialnumber` (aucun paramètre, composant avec tableau vide = non affiché), `codes_list` (2 params), `custom_geninv_updatestock` (7 params, refactorisé depuis le HTML brut).
|
||||||
- **Correction `Tiers.php`** : valeur par défaut de `$select` changée de `custid,custname` (invalide) à `custid,name` (valide).
|
- **Articles** : `art_list` (3 params), `art_getstk` (1 param).
|
||||||
- **Vue `tiers.blade.php`** : placeholder du champ select mis à jour.
|
- **Journaux** : `jnl_list` (3 params).
|
||||||
- **Documentation enrichie** : sections `third_list` et `third_GetArtHistory` massivement enrichies (colonnes valides, métadonnées, exemples de réponse, structure `third_GetArtHistory`). 3 nouvelles remarques ajoutées (colonnes third_list vs column_list/cust, colonnes de recherche, casse du paramètre thirdid).
|
- **Tiers** : `third_list` (3 params), `third_GetArtHistory` (1 param).
|
||||||
- **7 nouveaux tests Pest** ajoutés dans `TiersPageTest.php` (total : 15 tests) : valeur par défaut select, envoi des paramètres, stockage des métadonnées, clé thirdid en minuscules, erreur API third_GetArtHistory, ID inexistant, filtrage select vide.
|
- **Documents** : `document_list` (3 params), `document_detail` (2 params), `Document_GetStatusList` (1 param), `Document_GetUnitPriceAndVat` (5 params), `Document_GetDueDate` (2 params), `Document_GetAttachListThumbnail` (2 params), `Document_GetPDF` (3 params), `document_add` (9 params), `document_mod` (6 params).
|
||||||
- Total : 134 tests passent, 1 test pré-existant en échec (FilamentDashboardTest).
|
- **Total : 11 composants Blade** dans le design system (ajout de `param-table`).
|
||||||
|
- **Tests** : 147 passent, 2 en échec pré-existant (FilamentDashboardTest). Aucun nouveau test ajouté (les tests existants vérifient le rendu des pages et passent tous).
|
||||||
|
- **Pint** : formatage validé.
|
||||||
|
|
||||||
## Décisions récentes
|
## Décisions récentes
|
||||||
|
|
||||||
- **Colonne `name` au lieu de `custname`** (2026-02-23) : La colonne `custname` n'existe pas dans l'endpoint `third_list`. Le nom du tiers est retourné dans la colonne `name`. La valeur par défaut de `$select` dans `Tiers.php` a été corrigée.
|
- **Composant `param-table` plutôt que HTML brut** (2026-02-23) : Le tableau de paramètres existant dans `divers.blade.php` (pour `custom_geninv_updatestock`) a été extrait dans un composant réutilisable `<x-logistics.param-table>` pour éviter la duplication de HTML/CSS sur toutes les pages.
|
||||||
- **Colonnes de recherche `third_list`** (2026-02-23) : Confirmé par tests que `third_list` recherche dans `name`, `groupid`, `vat`. Il est impossible de rechercher par `custid`.
|
- **Tableaux vides non affichés** (2026-02-23) : Le composant `param-table` ne rend rien si le tableau `$params` est vide. Les endpoints sans paramètres (comme `getserialnumber`) n'affichent donc pas de tableau inutile.
|
||||||
- **Casse du paramètre `thirdid`** (2026-02-23) : `third_GetArtHistory` exige `thirdid` en minuscules. `THIRDID` provoque une erreur HTTP 400.
|
- **`custom_geninv_updatestock` fonctionnel** (2026-02-23) : L'endpoint a été reclassé de "non fonctionnel" à "fonctionnel" en MODE=1 (Restock). STKID = code de dépôt (obtenu via `codes_list` STOCK). MODE=1 nécessite THIRDID. MODE=0 dépend de la configuration des journaux KI.
|
||||||
- **Document_GetPDF fonctionnel** (2026-02-23) : L'endpoint a été reclassé de "non fonctionnel" à "partiellement fonctionnel". Le paramètre LAYOUT doit être une valeur numérique en string.
|
- **`codes_list` correspondance exacte** (2026-02-23) : Le paramètre `code` fonctionne par correspondance exacte sur le nom du groupe, pas par préfixe. Sensible à la casse (MAJUSCULES).
|
||||||
- **Format de date YYYY-MM-DD** (2026-02-23) : Confirmé par tests que tous les endpoints acceptant une date exigent strictement le format `YYYY-MM-DD`.
|
- **`getserialnumber` structure réponse** (2026-02-23) : Le champ `data` est un objet `{ "getserialnumber": "..." }`, pas une chaîne directe.
|
||||||
|
- **Colonne `name` au lieu de `custname`** (2026-02-23) : La colonne `custname` n'existe pas dans `third_list`. Le nom est dans `name`.
|
||||||
|
- **Document_GetPDF fonctionnel** (2026-02-23) : LAYOUT doit être une valeur numérique en string.
|
||||||
|
- **Format de date YYYY-MM-DD** (2026-02-23) : Tous les endpoints date exigent ce format.
|
||||||
- **Toggle Lecture/Ecriture** (2026-02-21) : Toutes les pages entité disposent d'un toggle.
|
- **Toggle Lecture/Ecriture** (2026-02-21) : Toutes les pages entité disposent d'un toggle.
|
||||||
- **Convention d'écriture avec accents** (2026-02-20) : Tous les contenus en français utilisent les accents.
|
- **Convention d'écriture avec accents** (2026-02-20) : Tous les contenus en français utilisent les accents.
|
||||||
|
|
||||||
## Historique
|
## Historique
|
||||||
|
|
||||||
|
### 2026-02-23 (session investigation endpoints Divers)
|
||||||
|
|
||||||
|
- Investigation complète des 3 endpoints Divers.
|
||||||
|
- `getserialnumber` : structure réponse documentée.
|
||||||
|
- `codes_list` : correspondance exacte, sensible à la casse, chaîne vide = liste maître.
|
||||||
|
- `custom_geninv_updatestock` : reclassé fonctionnel en MODE=1 Restock.
|
||||||
|
- 12 nouveaux tests. Total à la fin : 145 tests.
|
||||||
|
|
||||||
|
### 2026-02-23 (session investigation endpoints Tiers)
|
||||||
|
|
||||||
|
- Investigation complète des 2 endpoints Tiers.
|
||||||
|
- `third_list` : colonnes de recherche (name, groupid, vat), 15 colonnes valides, colonne `custname` invalide.
|
||||||
|
- `third_GetArtHistory` : thirdid minuscules, historique complet sans limite.
|
||||||
|
- 7 nouveaux tests. Total à la fin : 134 tests.
|
||||||
|
|
||||||
### 2026-02-23 (session investigation endpoints Documents)
|
### 2026-02-23 (session investigation endpoints Documents)
|
||||||
|
|
||||||
- Investigation complète des 9 endpoints Documents.
|
- Investigation complète des 9 endpoints Documents.
|
||||||
- Document_GetPDF reclassé comme fonctionnel (LAYOUT numérique).
|
- Document_GetPDF reclassé comme fonctionnel (LAYOUT numérique).
|
||||||
- Format de date YYYY-MM-DD confirmé et documenté.
|
- Format de date YYYY-MM-DD confirmé et documenté.
|
||||||
- Codes paydelay et modes de paiement documentés.
|
- 1 nouveau test. Total à la fin : 125 tests.
|
||||||
- Paramètre `results` ajouté à document_list.
|
|
||||||
- 1 nouveau test Pest. Total à la fin de cette session : 125 tests.
|
|
||||||
|
|
||||||
### 2026-02-23 (session investigation art_list)
|
### 2026-02-23 (session investigation art_list)
|
||||||
|
|
||||||
- Investigation paramètre `results` : sans effet sur `art_list` (5 max) et `third_list` (10 max).
|
- Investigation paramètre `results` et `barcode` sur art_list/third_list.
|
||||||
- Investigation paramètre `barcode` : sans effet observable, `search` reste obligatoire.
|
|
||||||
- Page Articles : `$results` supprimé, `$barcode` ajouté.
|
|
||||||
- Documentation `art_list` et `third_list` corrigée.
|
|
||||||
- 2 nouveaux tests barcode.
|
- 2 nouveaux tests barcode.
|
||||||
|
|
||||||
### 2026-02-23 (session gestion erreurs et validation)
|
### 2026-02-23 (session gestion erreurs et validation)
|
||||||
@@ -66,8 +81,7 @@ Aucun travail en cours.
|
|||||||
|
|
||||||
## Prochaines étapes
|
## Prochaines étapes
|
||||||
|
|
||||||
- Corriger le test pré-existant `FilamentDashboardTest`.
|
- Corriger les tests pré-existants `FilamentDashboardTest` (2 tests en échec).
|
||||||
- Tester toutes les pages avec de vraies données API et vérifier le rendu visuel.
|
- Tester toutes les pages avec de vraies données API et vérifier le rendu visuel.
|
||||||
- Éventuellement : pagination / tri côté client pour les grands tableaux (notamment `third_GetArtHistory` qui peut retourner des milliers d'éléments).
|
- Éventuellement : pagination / tri côté client pour les grands tableaux.
|
||||||
- Éventuellement : page de consultation des logs API.
|
- Éventuellement : page de consultation des logs API.
|
||||||
- Éventuellement : investiguer `custom_geninv_updatestock` (clarifier STKID, TOCHECK, MODE auprès du fournisseur).
|
|
||||||
|
|||||||
@@ -18,9 +18,10 @@ L'API Logistics (Flex/ESI Gescom) est un système de gestion commerciale accessi
|
|||||||
- **Traçabilité** : Chaque requête effectuée (réussie ou échouée) est enregistrée dans `api_request_logs` pour pouvoir analyser les échanges.
|
- **Traçabilité** : Chaque requête effectuée (réussie ou échouée) est enregistrée dans `api_request_logs` pour pouvoir analyser les échanges.
|
||||||
- **Résilience** : Les erreurs de connexion sont gérées avec retry automatique et messages explicites en français. Les erreurs API sont traduites et enrichies d'explications via `ApiErrorTranslator`.
|
- **Résilience** : Les erreurs de connexion sont gérées avec retry automatique et messages explicites en français. Les erreurs API sont traduites et enrichies d'explications via `ApiErrorTranslator`.
|
||||||
- **Validation** : Les champs obligatoires sont validés avant chaque appel API avec des messages en français. Les pages distinguent "jamais recherché" de "recherché sans résultat" grace aux propriétés de tracking.
|
- **Validation** : Les champs obligatoires sont validés avant chaque appel API avec des messages en français. Les pages distinguent "jamais recherché" de "recherché sans résultat" grace aux propriétés de tracking.
|
||||||
- **Cohérence visuelle** : Un système de design unifié (composants `x-logistics.*`) garantit une présentation homogène sur toutes les pages.
|
- **Cohérence visuelle** : Un système de design unifié (11 composants `x-logistics.*`) garantit une présentation homogène sur toutes les pages.
|
||||||
- **Couverture complète des endpoints** : Les 19 endpoints disponibles dans le service sont tous accessibles depuis l'interface, dont 1 non fonctionnel (custom_geninv_updatestock, avec avertissement). L'endpoint Document_GetPDF, initialement considéré non fonctionnel, a été corrigé (LAYOUT doit être une valeur numérique).
|
- **Couverture complète des endpoints** : Les 19 endpoints disponibles dans le service sont tous accessibles depuis l'interface et tous fonctionnels. L'endpoint Document_GetPDF, initialement considéré non fonctionnel, a été corrigé (LAYOUT doit être une valeur numérique). L'endpoint custom_geninv_updatestock, initialement considéré non fonctionnel, est fonctionnel en MODE=1 (Restock) avec THIRDID obligatoire.
|
||||||
- **Investigation des paramètres** : Chaque endpoint a été testé systématiquement pour documenter les paramètres réels (obligatoires ou non, types, formats, colonnes valides, comportement des paramètres ignorés). Les résultats sont documentés dans `documentation/documentation_api_logistics.md`.
|
- **Investigation des paramètres** : Chaque endpoint a été testé systématiquement pour documenter les paramètres réels (obligatoires ou non, types, formats, colonnes valides, comportement des paramètres ignorés). Les résultats sont documentés dans `documentation/documentation_api_logistics.md`.
|
||||||
|
- **Référence rapide des paramètres** : Chaque endpoint dispose d'un tableau de référence des paramètres directement sous le formulaire, permettant à l'utilisateur de comprendre les paramètres attendus sans consulter la documentation.
|
||||||
|
|
||||||
## Expérience utilisateur
|
## Expérience utilisateur
|
||||||
|
|
||||||
@@ -28,12 +29,16 @@ L'utilisateur accède au dashboard Filament sur `http://api-logistics.test/admin
|
|||||||
|
|
||||||
1. **Documentation** : Affichage stylisé de la documentation API complète (markdown converti en HTML). Actions : télécharger en PDF, ouvrir dans un nouvel onglet.
|
1. **Documentation** : Affichage stylisé de la documentation API complète (markdown converti en HTML). Actions : télécharger en PDF, ouvrir dans un nouvel onglet.
|
||||||
2. **Tables** : Barre de statistiques (endpoint, type base, nombre de tables). Liste filtrable des tables avec compteur de colonnes. Clic sur une table pour voir ses colonnes avec badges de type colorés.
|
2. **Tables** : Barre de statistiques (endpoint, type base, nombre de tables). Liste filtrable des tables avec compteur de colonnes. Clic sur une table pour voir ses colonnes avec badges de type colorés.
|
||||||
3. **Articles** : Toggle Lecture/Ecriture. En lecture : formulaire de recherche (search, select, barcode) + vérification du stock d'un article par son ARTID. L'API retourne un maximum fixe de 5 résultats (non configurable). Le paramètre `barcode` est présent dans le formulaire mais son effet côté API n'est pas observable. En écriture : état vide (aucun endpoint d'écriture disponible).
|
3. **Articles** : Toggle Lecture/Ecriture. En lecture : formulaire de recherche (search, select, barcode) avec tableau de paramètres + vérification du stock d'un article par son ARTID avec tableau de paramètres. L'API retourne un maximum fixe de 5 résultats (non configurable). Le paramètre `barcode` est présent dans le formulaire mais son effet côté API n'est pas observable. En écriture : état vide (aucun endpoint d'écriture disponible).
|
||||||
4. **Documents** : Toggle Lecture/Ecriture. En lecture : 7 formulaires (document_list avec results, document_detail, Document_GetStatusList, Document_GetUnitPriceAndVat, Document_GetDueDate, Document_GetAttachListThumbnail, Document_GetPDF). En écriture : 2 formulaires (document_add, document_mod). Le formulaire Document_GetPDF est fonctionnel (LAYOUT numérique obligatoire, ex: "1").
|
4. **Documents** : Toggle Lecture/Ecriture. En lecture : 7 formulaires avec tableaux de paramètres (document_list avec results, document_detail, Document_GetStatusList, Document_GetUnitPriceAndVat, Document_GetDueDate, Document_GetAttachListThumbnail, Document_GetPDF). En écriture : 2 formulaires avec tableaux de paramètres (document_add, document_mod). Le formulaire Document_GetPDF est fonctionnel (LAYOUT numérique obligatoire, ex: "1").
|
||||||
5. **Journaux** : Toggle Lecture/Ecriture. En lecture : recherche par type de journal (TYPE). En écriture : état vide.
|
5. **Journaux** : Toggle Lecture/Ecriture. En lecture : recherche par type de journal (TYPE) avec tableau de paramètres. En écriture : état vide.
|
||||||
6. **Tiers** : Toggle Lecture/Ecriture. En lecture : recherche de tiers (search obligatoire, recherche dans name/groupid/vat, colonnes par défaut custid/name, max 10 résultats) + historique des articles d'un tiers (thirdid en minuscules, retourne tout l'historique sans limite). En écriture : état vide.
|
6. **Tiers** : Toggle Lecture/Ecriture. En lecture : recherche de tiers (search obligatoire, recherche dans name/groupid/vat, colonnes par défaut custid/name, max 10 résultats) avec tableau de paramètres + historique des articles d'un tiers (thirdid en minuscules, retourne tout l'historique sans limite) avec tableau de paramètres. En écriture : état vide.
|
||||||
7. **Divers** : Toggle Lecture/Ecriture. En lecture : getserialnumber (numéro de série), codes_list (données par code interne). En écriture : custom_geninv_updatestock (avec bandeau d'avertissement, endpoint non fonctionnel).
|
7. **Divers** : Toggle Lecture/Ecriture. En lecture : getserialnumber (numéro de série, retourne un objet `{ "getserialnumber": "..." }`), codes_list (données par code interne, correspondance exacte sensible à la casse, chaîne vide = liste maître des 42 groupes) avec tableau de paramètres. En écriture : custom_geninv_updatestock (fonctionnel en MODE=1 Restock avec THIRDID obligatoire, bandeau d'information sur les modes) avec tableau de paramètres.
|
||||||
|
|
||||||
### Toggle Lecture / Ecriture
|
### Toggle Lecture / Ecriture
|
||||||
|
|
||||||
Toutes les pages entité disposent d'un sélecteur en haut de page avec deux boutons : "Lecture" et "Ecriture". Le bouton actif est mis en surbrillance. Le changement de mode affiche instantanément les formulaires correspondants sans rechargement de page.
|
Toutes les pages entité disposent d'un sélecteur en haut de page avec deux boutons : "Lecture" et "Ecriture". Le bouton actif est mis en surbrillance. Le changement de mode affiche instantanément les formulaires correspondants sans rechargement de page.
|
||||||
|
|
||||||
|
### Tableaux de référence des paramètres
|
||||||
|
|
||||||
|
Sous chaque formulaire d'endpoint, un tableau de référence affiche les colonnes PARAMETRE, TYPE, OBLIGATOIRE et DESCRIPTION. Ce tableau fournit un aide-mémoire des paramètres attendus par l'API, avec les informations critiques (format obligatoire, limites connues, sensibilité à la casse). Les endpoints sans paramètres (comme `getserialnumber`) n'affichent pas de tableau.
|
||||||
|
|||||||
@@ -18,10 +18,10 @@ Dernière mise à jour : 2026-02-23
|
|||||||
- [x] 7 vues Blade associées dans `resources/views/filament/pages/`
|
- [x] 7 vues Blade associées dans `resources/views/filament/pages/`
|
||||||
- [x] Toggle Lecture/Ecriture sur toutes les pages entité (Articles, Documents, Journaux, Tiers, Divers)
|
- [x] Toggle Lecture/Ecriture sur toutes les pages entité (Articles, Documents, Journaux, Tiers, Divers)
|
||||||
- [x] Page Documents : 9 endpoints couverts (7 lecture + 2 écriture)
|
- [x] Page Documents : 9 endpoints couverts (7 lecture + 2 écriture)
|
||||||
- [x] Page Divers : 3 endpoints couverts (2 lecture + 1 écriture non fonctionnel)
|
- [x] Page Divers : 3 endpoints couverts (2 lecture + 1 écriture fonctionnel en MODE=1 Restock)
|
||||||
- [x] Gestion d'erreur dans toutes les pages Filament (LogisticsApiException + Throwable)
|
- [x] Gestion d'erreur dans toutes les pages Filament (LogisticsApiException + Throwable)
|
||||||
- [x] Logging des requêtes API réussies et échouées dans `api_request_logs`
|
- [x] Logging des requêtes API réussies et échouées dans `api_request_logs`
|
||||||
- [x] Système de design unifié : 10 composants Blade dans `resources/views/components/logistics/`
|
- [x] Système de design unifié : 11 composants Blade dans `resources/views/components/logistics/`
|
||||||
- [x] Convention de design documentée dans `.cursor/rules/design-system.mdc`
|
- [x] Convention de design documentée dans `.cursor/rules/design-system.mdc`
|
||||||
- [x] Toutes les pages Filament utilisent les composants `x-logistics.*`
|
- [x] Toutes les pages Filament utilisent les composants `x-logistics.*`
|
||||||
- [x] Thème Filament personnalisé (`resources/css/filament/admin/theme.css`)
|
- [x] Thème Filament personnalisé (`resources/css/filament/admin/theme.css`)
|
||||||
@@ -66,32 +66,43 @@ Dernière mise à jour : 2026-02-23
|
|||||||
- [x] Documentation `third_list` et `third_GetArtHistory` massivement enrichie (colonnes valides, métadonnées, exemples de réponse, structure de réponse)
|
- [x] Documentation `third_list` et `third_GetArtHistory` massivement enrichie (colonnes valides, métadonnées, exemples de réponse, structure de réponse)
|
||||||
- [x] 3 nouvelles remarques dans la documentation (colonnes third_list vs column_list/cust, colonnes de recherche, casse thirdid)
|
- [x] 3 nouvelles remarques dans la documentation (colonnes third_list vs column_list/cust, colonnes de recherche, casse thirdid)
|
||||||
- [x] 7 nouveaux tests Pest dans TiersPageTest (total : 15 tests)
|
- [x] 7 nouveaux tests Pest dans TiersPageTest (total : 15 tests)
|
||||||
|
- [x] Investigation complète des 3 endpoints Divers (appels API réels)
|
||||||
|
- [x] `getserialnumber` : structure de réponse documentée (objet `{ "getserialnumber": "..." }`, pas une chaîne)
|
||||||
|
- [x] `codes_list` : correspondance exacte (pas préfixe), sensible à la casse, chaîne vide = liste maître (42 groupes), signification des champs documentée
|
||||||
|
- [x] `custom_geninv_updatestock` reclassé comme FONCTIONNEL (MODE=1 Restock). STKID = code de dépôt. THIRDID obligatoire en Restock. QTY négatif possible.
|
||||||
|
- [x] Divers.php : ajout THIRDID, valeur par défaut MODE=1, validation améliorée
|
||||||
|
- [x] divers.blade.php : bandeau mis à jour, champ THIRDID, labels corrigés
|
||||||
|
- [x] Documentation enrichie : getserialnumber (structure réponse), codes_list (2 modes, groupes, champs), custom_geninv_updatestock (reclassé, 7 paramètres, modes, erreurs). Section "Endpoints non fonctionnels" supprimée. 4 nouvelles remarques.
|
||||||
|
- [x] 12 nouveaux tests Pest dans DiversPageTest (total : 22 tests)
|
||||||
|
- [x] Composant `<x-logistics.param-table>` créé : tableau de référence des paramètres API réutilisable
|
||||||
|
- [x] Tableaux de paramètres ajoutés sous chaque endpoint de toutes les pages (17 endpoints au total)
|
||||||
|
- [x] Tableau brut HTML de `custom_geninv_updatestock` refactorisé vers le composant `param-table`
|
||||||
|
|
||||||
## Ce qui reste à faire
|
## Ce qui reste à faire
|
||||||
|
|
||||||
- [ ] Corriger le test pré-existant `FilamentDashboardTest`
|
- [ ] Corriger les tests pré-existants `FilamentDashboardTest` (2 tests en échec)
|
||||||
- [ ] Vérifier le rendu visuel de toutes les pages avec de vraies données API
|
- [ ] Vérifier le rendu visuel de toutes les pages avec de vraies données API
|
||||||
- [ ] Éventuellement : pagination / tri côté client pour les grands tableaux
|
- [ ] Éventuellement : pagination / tri côté client pour les grands tableaux
|
||||||
- [ ] Éventuellement : page de consultation des logs API
|
- [ ] Éventuellement : page de consultation des logs API
|
||||||
|
|
||||||
## Problèmes connus
|
## Problèmes connus
|
||||||
|
|
||||||
- 1 test `FilamentDashboardTest` échoue car le dashboard ne contient pas les sections attendues. Test créé avant la refonte du dashboard.
|
- 2 tests `FilamentDashboardTest` échouent car le dashboard ne contient pas les sections attendues. Tests créés avant la refonte du dashboard.
|
||||||
- L'erreur `SQLSTATE[HY000] [1049] Unknown database` peut apparaître lors de `composer update` si la base n'est pas encore créée (script `boost:update`). Sans impact une fois la base créée.
|
- L'erreur `SQLSTATE[HY000] [1049] Unknown database` peut apparaître lors de `composer update` si la base n'est pas encore créée (script `boost:update`). Sans impact une fois la base créée.
|
||||||
- L'API retourne chaque colonne en double dans `column_list`. Le `TablesExplorer` déduplique côté client.
|
- L'API retourne chaque colonne en double dans `column_list`. Le `TablesExplorer` déduplique côté client.
|
||||||
- Le paramètre `results` n'a aucun effet sur `art_list` (toujours 5 max) ni sur `third_list` (toujours 10 max). Limite fixe côté serveur. En revanche, `results` fonctionne sur `document_list` et `jnl_list`.
|
- Le paramètre `results` n'a aucun effet sur `art_list` (toujours 5 max) ni sur `third_list` (toujours 10 max). Limite fixe côté serveur. En revanche, `results` fonctionne sur `document_list` et `jnl_list`.
|
||||||
- Le paramètre `barcode` n'a aucun effet observable sur `art_list`. Le paramètre `search` reste obligatoire même avec `barcode`.
|
- Le paramètre `barcode` n'a aucun effet observable sur `art_list`. Le paramètre `search` reste obligatoire même avec `barcode`.
|
||||||
- L'endpoint `custom_geninv_updatestock` reste non fonctionnel (paramètre STKID inconnu).
|
|
||||||
- La colonne `custname` n'existe pas dans `third_list`. Le nom du tiers est dans la colonne `name`. Beaucoup de colonnes de la table `cust` (visibles dans `column_list/cust`) ne sont pas acceptées par `third_list` dans le paramètre `select`.
|
- La colonne `custname` n'existe pas dans `third_list`. Le nom du tiers est dans la colonne `name`. Beaucoup de colonnes de la table `cust` (visibles dans `column_list/cust`) ne sont pas acceptées par `third_list` dans le paramètre `select`.
|
||||||
- `third_GetArtHistory` retourne l'intégralité de l'historique sans pagination (potentiellement des milliers d'éléments), ce qui peut être lent pour certains tiers.
|
- `third_GetArtHistory` retourne l'intégralité de l'historique sans pagination (potentiellement des milliers d'éléments), ce qui peut être lent pour certains tiers.
|
||||||
|
- `custom_geninv_updatestock` MODE=0 (Inventaire) dépend de la configuration des journaux KI du dossier. Dans le dossier de test, aucun journal KI n'est configuré pour les dépôts "A" ou "SG", ce qui rend MODE=0 non fonctionnel dans cet environnement.
|
||||||
|
|
||||||
## Métriques
|
## Métriques
|
||||||
|
|
||||||
- Tests : 134 passent, 1 en échec pré-existant
|
- Tests : 147 passent, 2 en échec pré-existant
|
||||||
- Pages Filament : 7 (Documentation, TablesExplorer, Articles, Documents, Journaux, Tiers, Divers)
|
- Pages Filament : 7 (Documentation, TablesExplorer, Articles, Documents, Journaux, Tiers, Divers)
|
||||||
- Composants Blade design system : 10
|
- Composants Blade design system : 11 (card, section-header, error-banner, stat-bar, stat-item, data-table, empty-state, search-input, form-field, json-block, param-table)
|
||||||
- Endpoints API couverts par LogisticsService : 19
|
- Endpoints API couverts par LogisticsService : 19
|
||||||
- Endpoints accessibles depuis l'interface : 19 (dont 1 non fonctionnel, 1 partiellement fonctionnel)
|
- Endpoints accessibles depuis l'interface : 19 (tous fonctionnels, MODE=0 de custom_geninv_updatestock dépend de la config)
|
||||||
- Migrations : 5 (users, cache, jobs, two_factor, api_request_logs)
|
- Migrations : 5 (users, cache, jobs, two_factor, api_request_logs)
|
||||||
- Règles Cursor : 4 (laravel-boost, memory-bank, design-system, update-documentation)
|
- Règles Cursor : 4 (laravel-boost, memory-bank, design-system, update-documentation)
|
||||||
- Classes support : 1 (ApiErrorTranslator)
|
- Classes support : 1 (ApiErrorTranslator)
|
||||||
|
|||||||
@@ -19,13 +19,14 @@ Application Laravel de test dont l'objectif est de comprendre le fonctionnement
|
|||||||
- Toggle Lecture/Ecriture sur chaque page entité pour basculer entre les endpoints de récupération et d'envoi de données.
|
- Toggle Lecture/Ecriture sur chaque page entité pour basculer entre les endpoints de récupération et d'envoi de données.
|
||||||
- Page de documentation intégrée avec rendu stylisé du markdown et export PDF.
|
- Page de documentation intégrée avec rendu stylisé du markdown et export PDF.
|
||||||
- Formulaires de recherche et d'envoi paramétrables pour chaque endpoint (19 au total).
|
- Formulaires de recherche et d'envoi paramétrables pour chaque endpoint (19 au total).
|
||||||
|
- Tableaux de référence des paramètres sous chaque endpoint (type, obligatoire, description).
|
||||||
- Affichage des résultats sous forme de tableaux structurés et de blocs JSON formatés.
|
- Affichage des résultats sous forme de tableaux structurés et de blocs JSON formatés.
|
||||||
- Système de design unifié avec composants Blade réutilisables (`x-logistics.*`).
|
- Système de design unifié avec 11 composants Blade réutilisables (`x-logistics.*`).
|
||||||
- Traçage des requêtes effectuées dans une table `api_request_logs`.
|
- Traçage des requêtes effectuées dans une table `api_request_logs`.
|
||||||
- Gestion robuste des erreurs API (timeout, retry, messages utilisateur en français, traduction avec explications via `ApiErrorTranslator`).
|
- Gestion robuste des erreurs API (timeout, retry, messages utilisateur en français, traduction avec explications via `ApiErrorTranslator`).
|
||||||
- Validation des champs obligatoires avant chaque appel API avec messages en français.
|
- Validation des champs obligatoires avant chaque appel API avec messages en français.
|
||||||
- Distinction "jamais recherché" / "recherché sans résultat" via propriétés de tracking.
|
- Distinction "jamais recherché" / "recherché sans résultat" via propriétés de tracking.
|
||||||
- Avertissement visuel pour l'endpoint non fonctionnel (custom_geninv_updatestock). L'endpoint Document_GetPDF est désormais fonctionnel (LAYOUT numérique).
|
- L'endpoint Document_GetPDF est fonctionnel (LAYOUT numérique). L'endpoint custom_geninv_updatestock est fonctionnel en MODE=1 (Restock) avec bandeau d'information sur les modes.
|
||||||
|
|
||||||
## Contraintes
|
## Contraintes
|
||||||
|
|
||||||
|
|||||||
@@ -87,13 +87,17 @@ Chaque page Filament implémente :
|
|||||||
- **État vide** : Le composant `json-block` accepte une prop `$searched`. Quand `$searched` est `true` et `$data` est vide, un état vide est affiché. Pour les `data-table`, les vues vérifient `$hasSearched && count($data) === 0`.
|
- **État vide** : Le composant `json-block` accepte une prop `$searched`. Quand `$searched` est `true` et `$data` est vide, un état vide est affiché. Pour les `data-table`, les vues vérifient `$hasSearched && count($data) === 0`.
|
||||||
- **Badge de comptage** : Les badges de résultats utilisent `count($data)` (comptage réel PHP) au lieu de `$metadata['rowcount']` (retourné par l'API, parfois incorrect).
|
- **Badge de comptage** : Les badges de résultats utilisent `count($data)` (comptage réel PHP) au lieu de `$metadata['rowcount']` (retourné par l'API, parfois incorrect).
|
||||||
|
|
||||||
|
### Tableaux de référence des paramètres API
|
||||||
|
|
||||||
|
Chaque endpoint sur chaque page Filament dispose d'un tableau de référence des paramètres sous le formulaire, implémenté via le composant `<x-logistics.param-table>`. Le composant accepte un tableau `$params` où chaque élément contient `name`, `type`, `required` et `description`. Si le tableau est vide (endpoint sans paramètres), le composant ne rend rien. Les descriptions proviennent de la documentation API et incluent les informations critiques (format obligatoire, limites, sensibilité à la casse).
|
||||||
|
|
||||||
### Endpoints partiellement fonctionnels
|
### Endpoints partiellement fonctionnels
|
||||||
|
|
||||||
L'endpoint `Document_GetPDF` est fonctionnel : le paramètre `LAYOUT` doit être une valeur numérique sous forme de string (ex: `"1"`). Les valeurs textuelles provoquent une erreur. Le PDF est retourné encodé en base64 dans le champ `data.pdf`.
|
L'endpoint `Document_GetPDF` est fonctionnel : le paramètre `LAYOUT` doit être une valeur numérique sous forme de string (ex: `"1"`). Les valeurs textuelles provoquent une erreur. Le PDF est retourné encodé en base64 dans le champ `data.pdf`.
|
||||||
|
|
||||||
### Endpoints non fonctionnels
|
### Endpoint custom_geninv_updatestock
|
||||||
|
|
||||||
L'endpoint `custom_geninv_updatestock` est présent dans l'interface avec un bandeau d'avertissement ambre expliquant pourquoi il ne fonctionne pas. La méthode service existe dans LogisticsService pour permettre le test.
|
L'endpoint `custom_geninv_updatestock` est fonctionnel en MODE=1 (Restock). Un bandeau d'avertissement ambre dans l'interface explique les deux modes disponibles et leurs prérequis. Le formulaire inclut un champ THIRDID (obligatoire en mode Restock) et la validation côté client vérifie cette condition. MODE=0 (Inventaire) dépend de la configuration des journaux KI du dossier.
|
||||||
|
|
||||||
### Page Documentation
|
### Page Documentation
|
||||||
|
|
||||||
@@ -120,6 +124,7 @@ Convention documentée dans `.cursor/rules/design-system.mdc`. Tous les composan
|
|||||||
| `<x-logistics.search-input>` | Champ de recherche avec icône loupe intégrée |
|
| `<x-logistics.search-input>` | Champ de recherche avec icône loupe intégrée |
|
||||||
| `<x-logistics.form-field>` | Champ de formulaire (label + input + padding gauche) à espacement homogène |
|
| `<x-logistics.form-field>` | Champ de formulaire (label + input + padding gauche) à espacement homogène |
|
||||||
| `<x-logistics.json-block>` | Bloc JSON formaté avec bordure et fond adapté |
|
| `<x-logistics.json-block>` | Bloc JSON formaté avec bordure et fond adapté |
|
||||||
|
| `<x-logistics.param-table>` | Tableau de référence des paramètres API (PARAMETRE / TYPE / OBLIGATOIRE / DESCRIPTION) |
|
||||||
|
|
||||||
Règles :
|
Règles :
|
||||||
- Toujours utiliser les composants `x-logistics.*` au lieu de dupliquer les classes CSS.
|
- Toujours utiliser les composants `x-logistics.*` au lieu de dupliquer les classes CSS.
|
||||||
@@ -183,7 +188,7 @@ resources/
|
|||||||
filament/admin/
|
filament/admin/
|
||||||
theme.css # Thème Filament personnalisé (Tailwind 4 + Typography + prose)
|
theme.css # Thème Filament personnalisé (Tailwind 4 + Typography + prose)
|
||||||
views/
|
views/
|
||||||
components/logistics/ # 10 composants du système de design
|
components/logistics/ # 11 composants du système de design
|
||||||
filament/pages/ # 7 vues de pages Filament
|
filament/pages/ # 7 vues de pages Filament
|
||||||
pdf/
|
pdf/
|
||||||
documentation.blade.php # Template PDF pour la documentation
|
documentation.blade.php # Template PDF pour la documentation
|
||||||
@@ -197,15 +202,15 @@ database/
|
|||||||
...create_api_request_logs_table.php
|
...create_api_request_logs_table.php
|
||||||
|
|
||||||
tests/Feature/
|
tests/Feature/
|
||||||
ArticlesPageTest.php # 8 tests page Articles (toggle, validation, tracking, erreurs)
|
ArticlesPageTest.php # 10 tests page Articles (toggle, validation, tracking, erreurs, barcode)
|
||||||
DocumentationTest.php # 5 tests page Documentation (Livewire + PDF)
|
DocumentationTest.php # 5 tests page Documentation (Livewire + PDF)
|
||||||
DocumentsPageTest.php # 22 tests page Documents (toggle, 9 endpoints, validation, erreurs, results)
|
DocumentsPageTest.php # 22 tests page Documents (toggle, 9 endpoints, validation, erreurs, results)
|
||||||
DiversPageTest.php # 8 tests page Divers (toggle, 3 endpoints, validation, erreurs)
|
DiversPageTest.php # 22 tests page Divers (toggle, 3 endpoints, validation, erreurs, THIRDID conditionnel, modes)
|
||||||
JournauxPageTest.php # 6 tests page Journaux (toggle, validation, tracking, erreurs)
|
JournauxPageTest.php # 7 tests page Journaux (toggle, validation, tracking, erreurs)
|
||||||
LogisticsServiceTest.php # 14 tests service API (mocks HTTP)
|
LogisticsServiceTest.php # 14 tests service API (mocks HTTP)
|
||||||
TablesExplorerTest.php # 6 tests page TablesExplorer (Livewire)
|
TablesExplorerTest.php # 6 tests page TablesExplorer (Livewire)
|
||||||
TiersPageTest.php # 15 tests page Tiers (toggle, validation, tracking, erreurs, métadonnées, casse thirdid)
|
TiersPageTest.php # 15 tests page Tiers (toggle, validation, tracking, erreurs, métadonnées, casse thirdid)
|
||||||
FilamentDashboardTest.php # Tests dashboard Filament (1 test en échec pré-existant)
|
FilamentDashboardTest.php # Tests dashboard Filament (2 tests en échec pré-existant)
|
||||||
DashboardTest.php # Tests dashboard
|
DashboardTest.php # Tests dashboard
|
||||||
ExampleTest.php # Test d'exemple Laravel
|
ExampleTest.php # Test d'exemple Laravel
|
||||||
tests/Unit/
|
tests/Unit/
|
||||||
@@ -232,4 +237,5 @@ routes/
|
|||||||
- Toutes les vues Filament utilisent les composants `x-logistics.*` du système de design.
|
- Toutes les vues Filament utilisent les composants `x-logistics.*` du système de design.
|
||||||
- Après modification des vues ou composants, exécuter `npm run build` pour recompiler le thème.
|
- Après modification des vues ou composants, exécuter `npm run build` pour recompiler le thème.
|
||||||
- Tous les contenus rédigés en français doivent utiliser les accents appropriés.
|
- Tous les contenus rédigés en français doivent utiliser les accents appropriés.
|
||||||
- L'endpoint non fonctionnel (custom_geninv_updatestock) est présent dans l'interface avec un bandeau d'avertissement.
|
- L'endpoint custom_geninv_updatestock est fonctionnel en MODE=1 (Restock) avec un bandeau d'information décrivant les modes.
|
||||||
|
- Chaque endpoint sur chaque page dispose d'un tableau de référence des paramètres via `<x-logistics.param-table>`.
|
||||||
|
|||||||
@@ -114,11 +114,13 @@ Réponse `column_list` : chaque colonne a `name`, `dataType` (C/N/T/D/L/M), `len
|
|||||||
| `codes_list` | `codesList(array)` | Lecture | Données par code | code |
|
| `codes_list` | `codesList(array)` | Lecture | Données par code | code |
|
||||||
| `document_add` | `documentAdd(array)` | Écriture | Ajout d'un document | ThirdId, Date, Artid[], Qty[], Saleprice[], JNL, ... |
|
| `document_add` | `documentAdd(array)` | Écriture | Ajout d'un document | ThirdId, Date, Artid[], Qty[], Saleprice[], JNL, ... |
|
||||||
| `document_mod` | `documentMod(array)` | Écriture | Modification d'un document | number, Thirdid, Artid[], Qty[], Saleprice[], JNL, ... |
|
| `document_mod` | `documentMod(array)` | Écriture | Modification d'un document | number, Thirdid, Artid[], Qty[], Saleprice[], JNL, ... |
|
||||||
| `custom_geninv_updatestock` | `customGeninvUpdatestock(array)` | Écriture | Mise à jour inventaire | ARTID, STKID, QTY, ... |
|
| `custom_geninv_updatestock` | `customGeninvUpdatestock(array)` | Écriture | Mise à jour stock (Restock/Inventaire) | ARTID, STKID, QTY, TOCHECK, TOCHECKDETAIL, MODE, THIRDID |
|
||||||
|
|
||||||
**Endpoints partiellement fonctionnels** : `Document_GetPDF` (LAYOUT doit être une valeur numérique en string, ex: `"1"`. Les valeurs textuelles provoquent une erreur. Retourne le PDF en base64).
|
**Endpoints partiellement fonctionnels** : `Document_GetPDF` (LAYOUT doit être une valeur numérique en string, ex: `"1"`. Les valeurs textuelles provoquent une erreur. Retourne le PDF en base64). `custom_geninv_updatestock` MODE=0 (Inventaire) dépend de la configuration des journaux KI du dossier.
|
||||||
|
|
||||||
**Endpoints non fonctionnels** : `custom_geninv_updatestock` (paramètre STKID inconnu, signification de TOCHECK/TOCHECKDETAIL/MODE à clarifier).
|
**`custom_geninv_updatestock` (fonctionnel en MODE=1 Restock)** : STKID = code de dépôt (obtenu via `codes_list` STOCK, ex: `"SG"`, `"A"`). MODE=1 (Restock) nécessite THIRDID (fournisseur). TOCHECK = prix de contrôle. TOCHECKDETAIL = remarques. QTY peut être négatif. Les 6 paramètres ARTID, STKID, QTY, TOCHECK, TOCHECKDETAIL, MODE sont tous obligatoires.
|
||||||
|
|
||||||
|
**`codes_list` (correspondance exacte)** : le paramètre `code` fonctionne par correspondance exacte (pas par préfixe), sensible à la casse (MAJUSCULES). Chaîne vide = liste maître des 42 groupes (structure `name`/`prompt1`). Nom exact = valeurs du groupe (structure `vala1`-`vala6`, `valn1`, `valn2`).
|
||||||
|
|
||||||
**Format de date** : Tous les endpoints acceptant une date (DATE, date) exigent le format `YYYY-MM-DD`. Tout autre format retourne HTTP 400.
|
**Format de date** : Tous les endpoints acceptant une date (DATE, date) exigent le format `YYYY-MM-DD`. Tout autre format retourne HTTP 400.
|
||||||
|
|
||||||
|
|||||||
26
resources/views/components/logistics/param-table.blade.php
Normal file
26
resources/views/components/logistics/param-table.blade.php
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
@props(['params'])
|
||||||
|
|
||||||
|
@if (count($params) > 0)
|
||||||
|
<div class="mt-6 overflow-x-auto">
|
||||||
|
<table class="w-full text-left text-sm">
|
||||||
|
<thead>
|
||||||
|
<tr class="border-b border-gray-200 dark:border-white/10">
|
||||||
|
<th class="px-3 py-2.5 text-xs font-semibold uppercase tracking-wider text-gray-500 dark:text-gray-400">Parametre</th>
|
||||||
|
<th class="px-3 py-2.5 text-xs font-semibold uppercase tracking-wider text-gray-500 dark:text-gray-400">Type</th>
|
||||||
|
<th class="px-3 py-2.5 text-xs font-semibold uppercase tracking-wider text-gray-500 dark:text-gray-400">Obligatoire</th>
|
||||||
|
<th class="px-3 py-2.5 text-xs font-semibold uppercase tracking-wider text-gray-500 dark:text-gray-400">Description</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody class="divide-y divide-gray-100 dark:divide-white/5">
|
||||||
|
@foreach ($params as $param)
|
||||||
|
<tr>
|
||||||
|
<td class="px-3 py-2.5 font-mono text-sm text-gray-700 dark:text-gray-300">{{ $param['name'] }}</td>
|
||||||
|
<td class="px-3 py-2.5 text-sm text-gray-700 dark:text-gray-300">{{ $param['type'] }}</td>
|
||||||
|
<td class="px-3 py-2.5 text-sm text-gray-700 dark:text-gray-300">{{ $param['required'] }}</td>
|
||||||
|
<td class="px-3 py-2.5 text-sm text-gray-700 dark:text-gray-300">{{ $param['description'] }}</td>
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
@@ -46,6 +46,8 @@
|
|||||||
<span class="text-sm text-gray-500">Recherche en cours...</span>
|
<span class="text-sm text-gray-500">Recherche en cours...</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<x-logistics.param-table :params="$this->paramTableArtList()" />
|
||||||
</div>
|
</div>
|
||||||
</x-logistics.card>
|
</x-logistics.card>
|
||||||
|
|
||||||
@@ -97,6 +99,8 @@
|
|||||||
<span class="text-sm text-gray-500">Chargement...</span>
|
<span class="text-sm text-gray-500">Chargement...</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<x-logistics.param-table :params="$this->paramTableArtGetstk()" />
|
||||||
|
|
||||||
<div wire:loading.remove wire:target="getStock" class="mt-4">
|
<div wire:loading.remove wire:target="getStock" class="mt-4">
|
||||||
<x-logistics.json-block :data="$stockData" :searched="$hasCheckedStock" />
|
<x-logistics.json-block :data="$stockData" :searched="$hasCheckedStock" />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -26,6 +26,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<x-logistics.param-table :params="[]" />
|
||||||
|
|
||||||
<div wire:loading.remove wire:target="getSerialNumber" class="mt-4">
|
<div wire:loading.remove wire:target="getSerialNumber" class="mt-4">
|
||||||
<x-logistics.json-block :data="$serialData" :searched="$hasSerial" />
|
<x-logistics.json-block :data="$serialData" :searched="$hasSerial" />
|
||||||
</div>
|
</div>
|
||||||
@@ -34,20 +36,31 @@
|
|||||||
|
|
||||||
{{-- codes_list --}}
|
{{-- codes_list --}}
|
||||||
<x-logistics.card>
|
<x-logistics.card>
|
||||||
<x-logistics.section-header title="codes_list" description="Données associées à un code interne (table incodes)" />
|
<x-logistics.section-header title="codes_list" description="Données associées à un code interne (table incodes). Correspondance exacte, sensible à la casse (MAJUSCULES)." />
|
||||||
<div class="p-6">
|
<div class="p-6">
|
||||||
<div class="flex items-end gap-4">
|
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2">
|
||||||
<div class="flex-1">
|
|
||||||
<x-logistics.form-field
|
<x-logistics.form-field
|
||||||
wire:model="code"
|
wire:model="code"
|
||||||
label="Début de code (code)"
|
label="Nom du groupe de codes (code)"
|
||||||
id="code"
|
id="code"
|
||||||
placeholder="Ex: PAY"
|
placeholder="Ex: PAYMODE, PAYDELAY, VAT, STOCK"
|
||||||
|
/>
|
||||||
|
<x-logistics.form-field
|
||||||
|
wire:model="codesSelect"
|
||||||
|
label="Colonnes (select)"
|
||||||
|
id="codesSelect"
|
||||||
|
placeholder="Sans effet -- toutes les colonnes sont retournées"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-4 flex items-center gap-3">
|
||||||
<x-filament::button wire:click="searchCodes" icon="heroicon-o-magnifying-glass">
|
<x-filament::button wire:click="searchCodes" icon="heroicon-o-magnifying-glass">
|
||||||
Rechercher
|
Rechercher
|
||||||
</x-filament::button>
|
</x-filament::button>
|
||||||
|
<div wire:loading wire:target="searchCodes" class="flex items-center gap-2">
|
||||||
|
<x-filament::loading-indicator class="h-4 w-4 text-primary-500" />
|
||||||
|
<span class="text-sm text-gray-500">Chargement...</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div wire:loading wire:target="searchCodes" class="mt-4 flex items-center gap-2">
|
<div wire:loading wire:target="searchCodes" class="mt-4 flex items-center gap-2">
|
||||||
@@ -55,61 +68,70 @@
|
|||||||
<span class="text-sm text-gray-500">Chargement...</span>
|
<span class="text-sm text-gray-500">Chargement...</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<x-logistics.param-table :params="$this->paramTableCodesList()" />
|
||||||
|
|
||||||
<div wire:loading.remove wire:target="searchCodes" class="mt-4">
|
<div wire:loading.remove wire:target="searchCodes" class="mt-4">
|
||||||
<x-logistics.json-block :data="$codesData" :searched="$hasCodes" />
|
<x-logistics.json-block :data="$codesData" :searched="$hasCodes" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</x-logistics.card>
|
</x-logistics.card>
|
||||||
|
|
||||||
@else
|
@else
|
||||||
{{-- custom_geninv_updatestock --}}
|
{{-- custom_geninv_updatestock --}}
|
||||||
<x-logistics.card>
|
<x-logistics.card>
|
||||||
<x-logistics.section-header title="custom_geninv_updatestock" description="Mise à jour de l'inventaire" />
|
<x-logistics.section-header title="custom_geninv_updatestock" description="Mise à jour du stock (réapprovisionnement ou inventaire)" />
|
||||||
<div class="p-6">
|
<div class="p-6">
|
||||||
<div class="mb-4 rounded-lg bg-amber-50 p-3 text-sm text-amber-700 dark:bg-amber-400/10 dark:text-amber-400">
|
<div class="mb-4 rounded-lg bg-amber-50 p-3 text-sm text-amber-700 dark:bg-amber-400/10 dark:text-amber-400">
|
||||||
Endpoint non fonctionnel -- la valeur attendue de STKID et la signification de certains paramètres (TOCHECK, TOCHECKDETAIL, MODE) sont inconnues.
|
MODE=0 (Inventaire) necessite un journal KI configure pour le depot. MODE=1 (Restock) fonctionne et necessite un THIRDID (fournisseur).
|
||||||
</div>
|
</div>
|
||||||
<div class="grid grid-cols-1 gap-4 sm:grid-cols-3">
|
<div class="grid grid-cols-1 gap-4 sm:grid-cols-3">
|
||||||
<x-logistics.form-field
|
<x-logistics.form-field
|
||||||
wire:model="stkArtId"
|
wire:model="stkArtId"
|
||||||
label="Article (ARTID)"
|
label="Article (ARTID)"
|
||||||
id="stkArtId"
|
id="stkArtId"
|
||||||
placeholder="Ex: ART001"
|
placeholder="Ex: 003R92572"
|
||||||
/>
|
/>
|
||||||
<x-logistics.form-field
|
<x-logistics.form-field
|
||||||
wire:model="stkId"
|
wire:model="stkId"
|
||||||
label="Identifiant stock (STKID)"
|
label="Depot / Entrepot (STKID)"
|
||||||
id="stkId"
|
id="stkId"
|
||||||
placeholder="Valeur inconnue"
|
placeholder="Ex: SG, A"
|
||||||
/>
|
/>
|
||||||
<x-logistics.form-field
|
<x-logistics.form-field
|
||||||
wire:model="stkQty"
|
wire:model="stkQty"
|
||||||
label="Quantité (QTY)"
|
label="Quantite (QTY)"
|
||||||
id="stkQty"
|
id="stkQty"
|
||||||
placeholder="Ex: 10"
|
placeholder="Ex: 10 (negatif possible)"
|
||||||
/>
|
|
||||||
<x-logistics.form-field
|
|
||||||
wire:model="stkToCheck"
|
|
||||||
label="TOCHECK (signification inconnue)"
|
|
||||||
id="stkToCheck"
|
|
||||||
placeholder="Prix ?"
|
|
||||||
/>
|
|
||||||
<x-logistics.form-field
|
|
||||||
wire:model="stkToCheckDetail"
|
|
||||||
label="TOCHECKDETAIL (signification inconnue)"
|
|
||||||
id="stkToCheckDetail"
|
|
||||||
placeholder="Remarques ?"
|
|
||||||
/>
|
/>
|
||||||
<x-logistics.form-field
|
<x-logistics.form-field
|
||||||
wire:model="stkMode"
|
wire:model="stkMode"
|
||||||
label="MODE (signification inconnue)"
|
label="Mode (MODE)"
|
||||||
id="stkMode"
|
id="stkMode"
|
||||||
placeholder="Valeur inconnue"
|
placeholder="0=Inventaire, 1=Restock"
|
||||||
|
/>
|
||||||
|
<x-logistics.form-field
|
||||||
|
wire:model="stkThirdId"
|
||||||
|
label="Tiers / Fournisseur (THIRDID)"
|
||||||
|
id="stkThirdId"
|
||||||
|
placeholder="Obligatoire si MODE=1"
|
||||||
|
/>
|
||||||
|
<x-logistics.form-field
|
||||||
|
wire:model="stkToCheck"
|
||||||
|
label="Prix de controle (TOCHECK)"
|
||||||
|
id="stkToCheck"
|
||||||
|
placeholder="Ex: 12.50"
|
||||||
|
/>
|
||||||
|
<x-logistics.form-field
|
||||||
|
wire:model="stkToCheckDetail"
|
||||||
|
label="Detail de controle (TOCHECKDETAIL)"
|
||||||
|
id="stkToCheckDetail"
|
||||||
|
placeholder="Remarques"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mt-4 flex items-center gap-3">
|
<div class="mt-4 flex items-center gap-3">
|
||||||
<x-filament::button wire:click="updateStock" icon="heroicon-o-arrow-path" color="warning">
|
<x-filament::button wire:click="updateStock" icon="heroicon-o-arrow-path" color="warning">
|
||||||
Mettre à jour le stock
|
Mettre a jour le stock
|
||||||
</x-filament::button>
|
</x-filament::button>
|
||||||
<div wire:loading wire:target="updateStock" class="flex items-center gap-2">
|
<div wire:loading wire:target="updateStock" class="flex items-center gap-2">
|
||||||
<x-filament::loading-indicator class="h-4 w-4 text-primary-500" />
|
<x-filament::loading-indicator class="h-4 w-4 text-primary-500" />
|
||||||
@@ -117,6 +139,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<x-logistics.param-table :params="$this->paramTableUpdateStock()" />
|
||||||
|
|
||||||
<div wire:loading.remove wire:target="updateStock" class="mt-4">
|
<div wire:loading.remove wire:target="updateStock" class="mt-4">
|
||||||
<x-logistics.json-block :data="$updateStockResult" :searched="$hasUpdatedStock" />
|
<x-logistics.json-block :data="$updateStockResult" :searched="$hasUpdatedStock" />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -53,6 +53,8 @@
|
|||||||
<span class="text-sm text-gray-500">Recherche en cours...</span>
|
<span class="text-sm text-gray-500">Recherche en cours...</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<x-logistics.param-table :params="$this->paramTableDocumentList()" />
|
||||||
</div>
|
</div>
|
||||||
</x-logistics.card>
|
</x-logistics.card>
|
||||||
|
|
||||||
@@ -110,6 +112,8 @@
|
|||||||
<span class="text-sm text-gray-500">Chargement...</span>
|
<span class="text-sm text-gray-500">Chargement...</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<x-logistics.param-table :params="$this->paramTableDocumentDetail()" />
|
||||||
|
|
||||||
<div wire:loading.remove wire:target="getDocumentDetail" class="mt-4">
|
<div wire:loading.remove wire:target="getDocumentDetail" class="mt-4">
|
||||||
<x-logistics.json-block :data="$detailData" :searched="$hasDetail" />
|
<x-logistics.json-block :data="$detailData" :searched="$hasDetail" />
|
||||||
</div>
|
</div>
|
||||||
@@ -139,6 +143,8 @@
|
|||||||
<span class="text-sm text-gray-500">Chargement...</span>
|
<span class="text-sm text-gray-500">Chargement...</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<x-logistics.param-table :params="$this->paramTableStatusList()" />
|
||||||
|
|
||||||
<div wire:loading.remove wire:target="getStatusList" class="mt-4">
|
<div wire:loading.remove wire:target="getStatusList" class="mt-4">
|
||||||
<x-logistics.json-block :data="$statusData" :searched="$hasStatus" />
|
<x-logistics.json-block :data="$statusData" :searched="$hasStatus" />
|
||||||
</div>
|
</div>
|
||||||
@@ -192,6 +198,8 @@
|
|||||||
<span class="text-sm text-gray-500">Chargement...</span>
|
<span class="text-sm text-gray-500">Chargement...</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<x-logistics.param-table :params="$this->paramTableUnitPriceAndVat()" />
|
||||||
|
|
||||||
<div wire:loading.remove wire:target="getUnitPriceAndVat" class="mt-4">
|
<div wire:loading.remove wire:target="getUnitPriceAndVat" class="mt-4">
|
||||||
<x-logistics.json-block :data="$priceData" :searched="$hasPrice" />
|
<x-logistics.json-block :data="$priceData" :searched="$hasPrice" />
|
||||||
</div>
|
</div>
|
||||||
@@ -227,6 +235,8 @@
|
|||||||
<span class="text-sm text-gray-500">Chargement...</span>
|
<span class="text-sm text-gray-500">Chargement...</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<x-logistics.param-table :params="$this->paramTableDueDate()" />
|
||||||
|
|
||||||
<div wire:loading.remove wire:target="getDueDate" class="mt-4">
|
<div wire:loading.remove wire:target="getDueDate" class="mt-4">
|
||||||
<x-logistics.json-block :data="$dueDateData" :searched="$hasDueDate" />
|
<x-logistics.json-block :data="$dueDateData" :searched="$hasDueDate" />
|
||||||
</div>
|
</div>
|
||||||
@@ -262,6 +272,8 @@
|
|||||||
<span class="text-sm text-gray-500">Chargement...</span>
|
<span class="text-sm text-gray-500">Chargement...</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<x-logistics.param-table :params="$this->paramTableAttachListThumbnail()" />
|
||||||
|
|
||||||
<div wire:loading.remove wire:target="getAttachListThumbnail" class="mt-4">
|
<div wire:loading.remove wire:target="getAttachListThumbnail" class="mt-4">
|
||||||
<x-logistics.json-block :data="$attachData" :searched="$hasAttach" />
|
<x-logistics.json-block :data="$attachData" :searched="$hasAttach" />
|
||||||
</div>
|
</div>
|
||||||
@@ -303,6 +315,8 @@
|
|||||||
<span class="text-sm text-gray-500">Chargement...</span>
|
<span class="text-sm text-gray-500">Chargement...</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<x-logistics.param-table :params="$this->paramTableGetPdf()" />
|
||||||
|
|
||||||
<div wire:loading.remove wire:target="getPdf" class="mt-4">
|
<div wire:loading.remove wire:target="getPdf" class="mt-4">
|
||||||
<x-logistics.json-block :data="$pdfData" :searched="$hasPdf" />
|
<x-logistics.json-block :data="$pdfData" :searched="$hasPdf" />
|
||||||
</div>
|
</div>
|
||||||
@@ -384,6 +398,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<x-logistics.param-table :params="$this->paramTableDocumentAdd()" />
|
||||||
|
|
||||||
<div wire:loading.remove wire:target="addDocument" class="mt-4">
|
<div wire:loading.remove wire:target="addDocument" class="mt-4">
|
||||||
<x-logistics.json-block :data="$addResult" :searched="$hasAdded" />
|
<x-logistics.json-block :data="$addResult" :searched="$hasAdded" />
|
||||||
</div>
|
</div>
|
||||||
@@ -443,6 +459,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<x-logistics.param-table :params="$this->paramTableDocumentMod()" />
|
||||||
|
|
||||||
<div wire:loading.remove wire:target="modDocument" class="mt-4">
|
<div wire:loading.remove wire:target="modDocument" class="mt-4">
|
||||||
<x-logistics.json-block :data="$modResult" :searched="$hasModified" />
|
<x-logistics.json-block :data="$modResult" :searched="$hasModified" />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -48,6 +48,8 @@
|
|||||||
<span class="text-sm text-gray-500">Recherche en cours...</span>
|
<span class="text-sm text-gray-500">Recherche en cours...</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<x-logistics.param-table :params="$this->paramTableJnlList()" />
|
||||||
</div>
|
</div>
|
||||||
</x-logistics.card>
|
</x-logistics.card>
|
||||||
|
|
||||||
|
|||||||
@@ -48,6 +48,8 @@
|
|||||||
<span class="text-sm text-gray-500">Recherche en cours...</span>
|
<span class="text-sm text-gray-500">Recherche en cours...</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<x-logistics.param-table :params="$this->paramTableThirdList()" />
|
||||||
</div>
|
</div>
|
||||||
</x-logistics.card>
|
</x-logistics.card>
|
||||||
|
|
||||||
@@ -99,6 +101,8 @@
|
|||||||
<span class="text-sm text-gray-500">Chargement...</span>
|
<span class="text-sm text-gray-500">Chargement...</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<x-logistics.param-table :params="$this->paramTableArtHistory()" />
|
||||||
|
|
||||||
<div wire:loading.remove wire:target="getArtHistory" class="mt-4">
|
<div wire:loading.remove wire:target="getArtHistory" class="mt-4">
|
||||||
<x-logistics.json-block :data="$historyData" :searched="$hasHistory" />
|
<x-logistics.json-block :data="$historyData" :searched="$hasHistory" />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -32,10 +32,12 @@ it('can switch between read and write modes', function () {
|
|||||||
->assertSet('mode', 'read');
|
->assertSet('mode', 'read');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// --- getserialnumber ---
|
||||||
|
|
||||||
it('gets the serial number', function () {
|
it('gets the serial number', function () {
|
||||||
Http::fake([
|
Http::fake([
|
||||||
'*/getserialnumber' => Http::response([
|
'*/getserialnumber' => Http::response([
|
||||||
'data' => 'SN-12345',
|
'data' => ['getserialnumber' => '10005826'],
|
||||||
'metadata' => ['rowcount' => 1, 'issuccess' => true],
|
'metadata' => ['rowcount' => 1, 'issuccess' => true],
|
||||||
'error' => null,
|
'error' => null,
|
||||||
]),
|
]),
|
||||||
@@ -44,27 +46,97 @@ it('gets the serial number', function () {
|
|||||||
Livewire::test(Divers::class)
|
Livewire::test(Divers::class)
|
||||||
->call('getSerialNumber')
|
->call('getSerialNumber')
|
||||||
->assertSet('hasSerial', true)
|
->assertSet('hasSerial', true)
|
||||||
->assertSet('serialData', ['value' => 'SN-12345']);
|
->assertSet('serialData', ['getserialnumber' => '10005826']);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('searches codes by prefix', function () {
|
it('stores serial data as value key when data is not an array', function () {
|
||||||
Http::fake([
|
Http::fake([
|
||||||
'*/codes_list' => Http::response([
|
'*/getserialnumber' => Http::response([
|
||||||
'data' => [['code' => 'PAY01', 'vala1' => 'Comptant']],
|
'data' => 'SN-SCALAR',
|
||||||
'metadata' => ['rowcount' => 1, 'issuccess' => true],
|
'metadata' => ['rowcount' => 1, 'issuccess' => true],
|
||||||
'error' => null,
|
'error' => null,
|
||||||
]),
|
]),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
Livewire::test(Divers::class)
|
Livewire::test(Divers::class)
|
||||||
->set('code', 'PAY')
|
->call('getSerialNumber')
|
||||||
|
->assertSet('serialData', ['value' => 'SN-SCALAR']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handles API error on getSerialNumber', function () {
|
||||||
|
Http::fake([
|
||||||
|
'*/getserialnumber' => Http::response([
|
||||||
|
'data' => null,
|
||||||
|
'metadata' => ['rowcount' => 0, 'issuccess' => false],
|
||||||
|
'error' => 'Invalid API key',
|
||||||
|
]),
|
||||||
|
]);
|
||||||
|
|
||||||
|
$component = Livewire::test(Divers::class)
|
||||||
|
->call('getSerialNumber');
|
||||||
|
|
||||||
|
expect($component->get('errorMessage'))->toContain('Invalid API key');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handles exception on getSerialNumber', function () {
|
||||||
|
Http::fake([
|
||||||
|
'*/getserialnumber' => function () {
|
||||||
|
throw new \Illuminate\Http\Client\ConnectionException('Connection refused');
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
$component = Livewire::test(Divers::class)
|
||||||
|
->call('getSerialNumber');
|
||||||
|
|
||||||
|
expect($component->get('errorMessage'))->not->toBeNull();
|
||||||
|
expect($component->get('serialData'))->toBe([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
// --- codes_list ---
|
||||||
|
|
||||||
|
it('searches codes by exact code name', function () {
|
||||||
|
Http::fake([
|
||||||
|
'*/codes_list' => Http::response([
|
||||||
|
'data' => [
|
||||||
|
['vala1' => 'CAS', 'vala2' => 'CASH', 'vala3' => '', 'vala4' => '', 'vala5' => '', 'vala6' => '', 'valn1' => 1, 'valn2' => 0],
|
||||||
|
['vala1' => 'VIR', 'vala2' => 'Virement', 'vala3' => '', 'vala4' => '', 'vala5' => '', 'vala6' => '', 'valn1' => 0, 'valn2' => 0],
|
||||||
|
],
|
||||||
|
'metadata' => ['rowCount' => 2, 'source' => 'DBF'],
|
||||||
|
'error' => null,
|
||||||
|
]),
|
||||||
|
]);
|
||||||
|
|
||||||
|
Livewire::test(Divers::class)
|
||||||
|
->set('code', 'PAYMODE')
|
||||||
->call('searchCodes')
|
->call('searchCodes')
|
||||||
->assertSet('hasCodes', true)
|
->assertSet('hasCodes', true)
|
||||||
->assertSet('codesData', [['code' => 'PAY01', 'vala1' => 'Comptant']]);
|
->assertSet('codesData', [
|
||||||
|
['vala1' => 'CAS', 'vala2' => 'CASH', 'vala3' => '', 'vala4' => '', 'vala5' => '', 'vala6' => '', 'valn1' => 1, 'valn2' => 0],
|
||||||
|
['vala1' => 'VIR', 'vala2' => 'Virement', 'vala3' => '', 'vala4' => '', 'vala5' => '', 'vala6' => '', 'valn1' => 0, 'valn2' => 0],
|
||||||
|
]);
|
||||||
|
|
||||||
Http::assertSent(function ($request) {
|
Http::assertSent(function ($request) {
|
||||||
return str_contains($request->url(), 'codes_list')
|
return str_contains($request->url(), 'codes_list')
|
||||||
&& $request->data()['code'] === 'PAY';
|
&& $request->data()['code'] === 'PAYMODE';
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('sends code parameter to API', function () {
|
||||||
|
Http::fake([
|
||||||
|
'*/codes_list' => Http::response([
|
||||||
|
'data' => [],
|
||||||
|
'metadata' => ['rowCount' => 0, 'source' => 'DBF'],
|
||||||
|
'error' => null,
|
||||||
|
]),
|
||||||
|
]);
|
||||||
|
|
||||||
|
Livewire::test(Divers::class)
|
||||||
|
->set('code', 'STOCK')
|
||||||
|
->call('searchCodes');
|
||||||
|
|
||||||
|
Http::assertSent(function ($request) {
|
||||||
|
return str_contains($request->url(), 'codes_list')
|
||||||
|
&& $request->data()['code'] === 'STOCK';
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -79,47 +151,7 @@ it('shows validation error when code is empty', function () {
|
|||||||
Http::assertNothingSent();
|
Http::assertNothingSent();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('calls custom_geninv_updatestock endpoint', function () {
|
it('displays error message on codes_list API failure', function () {
|
||||||
Http::fake([
|
|
||||||
'*/custom_geninv_updatestock' => Http::response([
|
|
||||||
'data' => null,
|
|
||||||
'metadata' => ['rowcount' => 0, 'issuccess' => false],
|
|
||||||
'error' => 'Unknown STKID',
|
|
||||||
]),
|
|
||||||
]);
|
|
||||||
|
|
||||||
Livewire::test(Divers::class)
|
|
||||||
->set('mode', 'write')
|
|
||||||
->set('stkArtId', 'ART001')
|
|
||||||
->set('stkId', 'STK1')
|
|
||||||
->set('stkQty', '10')
|
|
||||||
->call('updateStock')
|
|
||||||
->assertSet('hasUpdatedStock', true);
|
|
||||||
|
|
||||||
expect(true)->toBeTrue();
|
|
||||||
|
|
||||||
Http::assertSent(function ($request) {
|
|
||||||
$body = $request->data();
|
|
||||||
|
|
||||||
return str_contains($request->url(), 'custom_geninv_updatestock')
|
|
||||||
&& $body['ARTID'] === 'ART001'
|
|
||||||
&& $body['STKID'] === 'STK1';
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('shows validation error when updateStock required fields are empty', function () {
|
|
||||||
Http::fake();
|
|
||||||
|
|
||||||
Livewire::test(Divers::class)
|
|
||||||
->set('mode', 'write')
|
|
||||||
->call('updateStock')
|
|
||||||
->assertSet('hasUpdatedStock', false)
|
|
||||||
->assertSet('errorMessage', 'Les champs ARTID, STKID et QTY sont obligatoires.');
|
|
||||||
|
|
||||||
Http::assertNothingSent();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('displays error message on API failure', function () {
|
|
||||||
Http::fake([
|
Http::fake([
|
||||||
'*/codes_list' => Http::response([
|
'*/codes_list' => Http::response([
|
||||||
'data' => null,
|
'data' => null,
|
||||||
@@ -134,3 +166,253 @@ it('displays error message on API failure', function () {
|
|||||||
|
|
||||||
expect($component->get('errorMessage'))->toContain('Invalid API key');
|
expect($component->get('errorMessage'))->toContain('Invalid API key');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('sends select parameter to codes_list when filled', function () {
|
||||||
|
Http::fake([
|
||||||
|
'*/codes_list' => Http::response([
|
||||||
|
'data' => [['vala1' => 'A', 'vala2' => '']],
|
||||||
|
'metadata' => ['rowCount' => 1, 'source' => 'DBF'],
|
||||||
|
'error' => null,
|
||||||
|
]),
|
||||||
|
]);
|
||||||
|
|
||||||
|
Livewire::test(Divers::class)
|
||||||
|
->set('code', 'STOCK')
|
||||||
|
->set('codesSelect', 'vala1,vala2')
|
||||||
|
->call('searchCodes');
|
||||||
|
|
||||||
|
Http::assertSent(function ($request) {
|
||||||
|
return str_contains($request->url(), 'codes_list')
|
||||||
|
&& $request->data()['code'] === 'STOCK'
|
||||||
|
&& $request->data()['select'] === 'vala1,vala2';
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not send select parameter to codes_list when empty', function () {
|
||||||
|
Http::fake([
|
||||||
|
'*/codes_list' => Http::response([
|
||||||
|
'data' => [],
|
||||||
|
'metadata' => ['rowCount' => 0, 'source' => 'DBF'],
|
||||||
|
'error' => null,
|
||||||
|
]),
|
||||||
|
]);
|
||||||
|
|
||||||
|
Livewire::test(Divers::class)
|
||||||
|
->set('code', 'STOCK')
|
||||||
|
->set('codesSelect', '')
|
||||||
|
->call('searchCodes');
|
||||||
|
|
||||||
|
Http::assertSent(function ($request) {
|
||||||
|
return str_contains($request->url(), 'codes_list')
|
||||||
|
&& ! array_key_exists('select', $request->data());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handles exception on searchCodes', function () {
|
||||||
|
Http::fake([
|
||||||
|
'*/codes_list' => Http::response('Server Error', 500),
|
||||||
|
]);
|
||||||
|
|
||||||
|
$component = Livewire::test(Divers::class)
|
||||||
|
->set('code', 'BROKEN')
|
||||||
|
->call('searchCodes');
|
||||||
|
|
||||||
|
expect($component->get('errorMessage'))->not->toBeNull();
|
||||||
|
expect($component->get('codesData'))->toBe([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
// --- custom_geninv_updatestock ---
|
||||||
|
|
||||||
|
it('defaults stkMode to 1 (Restock)', function () {
|
||||||
|
Livewire::test(Divers::class)
|
||||||
|
->assertSet('stkMode', '1');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('calls custom_geninv_updatestock with all parameters in Restock mode', function () {
|
||||||
|
Http::fake([
|
||||||
|
'*/custom_geninv_updatestock' => Http::response([
|
||||||
|
'data' => ['custom_geninv_updatestock' => 'OK : Change applied - Artid : 003R92572 - Real stock received (Restock mode) : 5.00'],
|
||||||
|
'metadata' => ['rowcount' => 1, 'issuccess' => true],
|
||||||
|
'error' => null,
|
||||||
|
]),
|
||||||
|
]);
|
||||||
|
|
||||||
|
Livewire::test(Divers::class)
|
||||||
|
->set('mode', 'write')
|
||||||
|
->set('stkArtId', '003R92572')
|
||||||
|
->set('stkId', 'SG')
|
||||||
|
->set('stkQty', '5')
|
||||||
|
->set('stkMode', '1')
|
||||||
|
->set('stkThirdId', '0100002174')
|
||||||
|
->set('stkToCheck', '12.50')
|
||||||
|
->set('stkToCheckDetail', 'Test restock')
|
||||||
|
->call('updateStock')
|
||||||
|
->assertSet('hasUpdatedStock', true)
|
||||||
|
->assertSet('errorMessage', null);
|
||||||
|
|
||||||
|
Http::assertSent(function ($request) {
|
||||||
|
$body = $request->data();
|
||||||
|
|
||||||
|
return str_contains($request->url(), 'custom_geninv_updatestock')
|
||||||
|
&& $body['ARTID'] === '003R92572'
|
||||||
|
&& $body['STKID'] === 'SG'
|
||||||
|
&& $body['QTY'] === '5'
|
||||||
|
&& $body['MODE'] === '1'
|
||||||
|
&& $body['THIRDID'] === '0100002174'
|
||||||
|
&& $body['TOCHECK'] === '12.50'
|
||||||
|
&& $body['TOCHECKDETAIL'] === 'Test restock';
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shows validation error when updateStock required fields are empty', function () {
|
||||||
|
Http::fake();
|
||||||
|
|
||||||
|
Livewire::test(Divers::class)
|
||||||
|
->set('mode', 'write')
|
||||||
|
->set('stkArtId', '')
|
||||||
|
->set('stkId', '')
|
||||||
|
->set('stkQty', '')
|
||||||
|
->set('stkMode', '')
|
||||||
|
->call('updateStock')
|
||||||
|
->assertSet('hasUpdatedStock', false)
|
||||||
|
->assertSet('errorMessage', 'Les champs ARTID, STKID, QTY et MODE sont obligatoires.');
|
||||||
|
|
||||||
|
Http::assertNothingSent();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shows validation error when THIRDID is missing in Restock mode', function () {
|
||||||
|
Http::fake();
|
||||||
|
|
||||||
|
Livewire::test(Divers::class)
|
||||||
|
->set('mode', 'write')
|
||||||
|
->set('stkArtId', '003R92572')
|
||||||
|
->set('stkId', 'SG')
|
||||||
|
->set('stkQty', '5')
|
||||||
|
->set('stkMode', '1')
|
||||||
|
->set('stkThirdId', '')
|
||||||
|
->call('updateStock')
|
||||||
|
->assertSet('hasUpdatedStock', false)
|
||||||
|
->assertSet('errorMessage', 'Le champ THIRDID est obligatoire en mode Restock (MODE=1).');
|
||||||
|
|
||||||
|
Http::assertNothingSent();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not require THIRDID in Inventory mode (MODE=0)', function () {
|
||||||
|
Http::fake([
|
||||||
|
'*/custom_geninv_updatestock' => Http::response([
|
||||||
|
'data' => ['xml' => '<VFPData><headererror><errorcode>002</errorcode><description>Invalid parameter, inventory JNL not found for warehouse : SG</description></headererror></VFPData>'],
|
||||||
|
'metadata' => ['rowcount' => 1, 'issuccess' => false],
|
||||||
|
'error' => ['Code: 002, Description: Invalid parameter, inventory JNL not found for warehouse : SG'],
|
||||||
|
]),
|
||||||
|
]);
|
||||||
|
|
||||||
|
Livewire::test(Divers::class)
|
||||||
|
->set('mode', 'write')
|
||||||
|
->set('stkArtId', '003R92572')
|
||||||
|
->set('stkId', 'SG')
|
||||||
|
->set('stkQty', '1')
|
||||||
|
->set('stkMode', '0')
|
||||||
|
->set('stkThirdId', '')
|
||||||
|
->call('updateStock')
|
||||||
|
->assertSet('hasUpdatedStock', true);
|
||||||
|
|
||||||
|
Http::assertSent(function ($request) {
|
||||||
|
$body = $request->data();
|
||||||
|
|
||||||
|
return str_contains($request->url(), 'custom_geninv_updatestock')
|
||||||
|
&& $body['MODE'] === '0'
|
||||||
|
&& ! isset($body['THIRDID']);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('includes THIRDID in params only when filled', function () {
|
||||||
|
Http::fake([
|
||||||
|
'*/custom_geninv_updatestock' => Http::response([
|
||||||
|
'data' => null,
|
||||||
|
'metadata' => ['rowcount' => 0, 'issuccess' => false],
|
||||||
|
'error' => 'Error',
|
||||||
|
]),
|
||||||
|
]);
|
||||||
|
|
||||||
|
Livewire::test(Divers::class)
|
||||||
|
->set('mode', 'write')
|
||||||
|
->set('stkArtId', 'ART001')
|
||||||
|
->set('stkId', 'A')
|
||||||
|
->set('stkQty', '1')
|
||||||
|
->set('stkMode', '0')
|
||||||
|
->set('stkThirdId', '')
|
||||||
|
->call('updateStock');
|
||||||
|
|
||||||
|
Http::assertSent(function ($request) {
|
||||||
|
return ! array_key_exists('THIRDID', $request->data());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('always sends TOCHECK and TOCHECKDETAIL even when empty', function () {
|
||||||
|
Http::fake([
|
||||||
|
'*/custom_geninv_updatestock' => Http::response([
|
||||||
|
'data' => ['custom_geninv_updatestock' => 'OK'],
|
||||||
|
'metadata' => ['rowcount' => 1, 'issuccess' => true],
|
||||||
|
'error' => null,
|
||||||
|
]),
|
||||||
|
]);
|
||||||
|
|
||||||
|
Livewire::test(Divers::class)
|
||||||
|
->set('mode', 'write')
|
||||||
|
->set('stkArtId', 'ART001')
|
||||||
|
->set('stkId', 'SG')
|
||||||
|
->set('stkQty', '1')
|
||||||
|
->set('stkMode', '1')
|
||||||
|
->set('stkThirdId', 'THIRD001')
|
||||||
|
->set('stkToCheck', '')
|
||||||
|
->set('stkToCheckDetail', '')
|
||||||
|
->call('updateStock');
|
||||||
|
|
||||||
|
Http::assertSent(function ($request) {
|
||||||
|
$body = $request->data();
|
||||||
|
|
||||||
|
return array_key_exists('TOCHECK', $body)
|
||||||
|
&& array_key_exists('TOCHECKDETAIL', $body)
|
||||||
|
&& $body['TOCHECK'] === ''
|
||||||
|
&& $body['TOCHECKDETAIL'] === '';
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handles API error on updateStock', function () {
|
||||||
|
Http::fake([
|
||||||
|
'*/custom_geninv_updatestock' => Http::response([
|
||||||
|
'data' => ['xml' => '<VFPData><headererror><errorcode>002</errorcode><description>Invalid parameter</description></headererror></VFPData>'],
|
||||||
|
'metadata' => ['rowcount' => 1, 'issuccess' => false],
|
||||||
|
'error' => ['Code: 002, Description: Invalid parameter'],
|
||||||
|
]),
|
||||||
|
]);
|
||||||
|
|
||||||
|
$component = Livewire::test(Divers::class)
|
||||||
|
->set('mode', 'write')
|
||||||
|
->set('stkArtId', 'ART001')
|
||||||
|
->set('stkId', 'SG')
|
||||||
|
->set('stkQty', '1')
|
||||||
|
->set('stkMode', '1')
|
||||||
|
->set('stkThirdId', 'THIRD001')
|
||||||
|
->call('updateStock');
|
||||||
|
|
||||||
|
expect($component->get('errorMessage'))->toContain('Invalid parameter');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handles exception on updateStock', function () {
|
||||||
|
Http::fake([
|
||||||
|
'*/custom_geninv_updatestock' => Http::response('Server Error', 500),
|
||||||
|
]);
|
||||||
|
|
||||||
|
$component = Livewire::test(Divers::class)
|
||||||
|
->set('mode', 'write')
|
||||||
|
->set('stkArtId', 'ART001')
|
||||||
|
->set('stkId', 'SG')
|
||||||
|
->set('stkQty', '1')
|
||||||
|
->set('stkMode', '1')
|
||||||
|
->set('stkThirdId', 'THIRD001')
|
||||||
|
->call('updateStock');
|
||||||
|
|
||||||
|
expect($component->get('errorMessage'))->not->toBeNull();
|
||||||
|
expect($component->get('updateStockResult'))->toBe([]);
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user