diff --git a/.cursor/rules/design-system.mdc b/.cursor/rules/design-system.mdc new file mode 100644 index 0000000..fd022da --- /dev/null +++ b/.cursor/rules/design-system.mdc @@ -0,0 +1,110 @@ +--- +description: Design system conventions for all Filament page views in this application +globs: + - resources/views/filament/pages/**/*.blade.php + - resources/views/components/logistics/**/*.blade.php +--- + +# Design System -- API Logistics + +## Composants Blade reutilisables + +Tous les elements visuels recurrents sont centralises dans `resources/views/components/logistics/`. +Utiliser ces composants au lieu de dupliquer du HTML/CSS. + +| Composant | Usage | Fichier | +|---|---|---| +| `` | Conteneur principal (panneau blanc arrondi) | `logistics/card.blade.php` | +| `` | En-tete de section (titre + description + slot actions) | `logistics/section-header.blade.php` | +| `` | Bandeau d'erreur API | `logistics/error-banner.blade.php` | +| `` | Barre de metadata/statistiques | `logistics/stat-bar.blade.php` | +| `` | Element individuel dans stat-bar | `logistics/stat-item.blade.php` | +| `` | Tableau de donnees dynamique | `logistics/data-table.blade.php` | +| `` | Etat vide (icone + texte) | `logistics/empty-state.blade.php` | +| `` | Champ de recherche avec icone loupe | `logistics/search-input.blade.php` | +| `` | Champ de formulaire (label + input) | `logistics/form-field.blade.php` | +| `` | Bloc JSON formate | `logistics/json-block.blade.php` | + +## Conventions CSS + +### Carte (card) +- `rounded-xl bg-white shadow-sm ring-1 ring-gray-950/5 dark:bg-gray-900 dark:ring-white/10` + +### En-tete de section dans une carte +- Wrapper: `border-b border-gray-200 px-6 py-4 dark:border-white/10` +- Titre: `text-base font-semibold text-gray-950 dark:text-white` +- Description: `mt-1 text-xs text-gray-500 dark:text-gray-400` + +### Contenu de carte +- Padding: `p-6` + +### Tableau de donnees +- Conteneur: `overflow-x-auto` +- Table: `w-full text-left text-sm` +- Thead tr: `border-b border-gray-200 dark:border-white/10` +- Th: `px-3 py-2.5 text-xs font-semibold uppercase tracking-wider text-gray-500 dark:text-gray-400` +- Tbody: `divide-y divide-gray-100 dark:divide-white/5` +- Tr: `transition-colors hover:bg-gray-50 dark:hover:bg-white/5` +- Td: `px-3 py-2.5 text-sm text-gray-700 dark:text-gray-300` +- Td valeur technique (ID, code): ajouter `font-mono` + +### Badge compteur +- `rounded-full px-2 py-0.5 text-xs font-medium tabular-nums bg-gray-100 text-gray-600 dark:bg-white/10 dark:text-gray-300` + +### Champ de formulaire (input) +- `w-full rounded-lg border-gray-300 py-2 text-sm shadow-sm focus:border-primary-500 focus:ring-primary-500 dark:border-white/10 dark:bg-white/5 dark:text-white` +- Label: `block text-sm font-medium text-gray-700 dark:text-gray-300` +- Espacement label/input: `mt-1.5` + +### Bloc JSON (pre) +- `rounded-lg border border-gray-200 bg-gray-50 p-4 text-xs font-mono leading-relaxed text-gray-700 dark:border-white/10 dark:bg-gray-800 dark:text-gray-300` + +### Etat vide +- Conteneur: `flex flex-col items-center justify-center py-12 text-center` +- Icone: `h-10 w-10 text-gray-300 dark:text-gray-600` +- Titre: `mt-3 text-sm font-medium text-gray-900 dark:text-white` +- Description: `mt-1 text-sm text-gray-500 dark:text-gray-400` + +### Erreur API +- `rounded-lg bg-danger-50 p-4 text-sm text-danger-600 dark:bg-danger-400/10 dark:text-danger-400` + +### Stat bar +- `flex flex-wrap items-center gap-x-6 gap-y-2` +- Chaque item: icone h-4 w-4 + texte text-sm text-gray-500 + +### Loading +- Utiliser `` + `wire:loading` / `wire:loading.remove` + +## Structure d'une page type + +```blade + + + + {{-- Stat bar optionnelle --}} + + {{-- Section formulaire --}} + + +
+ {{-- Formulaire avec grille --}} +
+
+ + {{-- Section resultats --}} + + +
+ +
+
+
+``` + +## Regles + +- Toujours utiliser les composants `x-logistics.*` au lieu de dupliquer les classes CSS. +- Un composant `` n'a PAS de padding interne. Le padding est gere par les enfants. +- Les formulaires dans une carte utilisent `
` pour le contenu. +- Toujours afficher un etat de chargement (`wire:loading`) sur les actions reseau. +- Les blocs JSON utilisent `` et non `
` brut.
diff --git a/.cursor/rules/laravel-boost.mdc b/.cursor/rules/laravel-boost.mdc
index 711aee4..115fc5d 100644
--- a/.cursor/rules/laravel-boost.mdc
+++ b/.cursor/rules/laravel-boost.mdc
@@ -13,6 +13,7 @@ The Laravel Boost guidelines are specifically curated by Laravel maintainers for
 This application is a Laravel application and its main Laravel ecosystems package & versions are below. You are an expert with them all. Ensure you abide by these specific packages & versions.
 
 - php - 8.4.16
+- filament/filament (FILAMENT) - v5
 - laravel/fortify (FORTIFY) - v1
 - laravel/framework (LARAVEL) - v12
 - laravel/prompts (PROMPTS) - v0
@@ -23,6 +24,7 @@ This application is a Laravel application and its main Laravel ecosystems packag
 - laravel/sail (SAIL) - v1
 - pestphp/pest (PEST) - v4
 - phpunit/phpunit (PHPUNIT) - v12
+- tailwindcss (TAILWINDCSS) - v4
 
 ## Skills Activation
 
@@ -31,6 +33,7 @@ This project has domain-specific skills available. You MUST activate the relevan
 - `fluxui-development` — Develops UIs with Flux UI Free components. Activates when creating buttons, forms, modals, inputs, dropdowns, checkboxes, or UI components; replacing HTML form elements with Flux; working with flux: components; or when the user mentions Flux, component library, UI components, form fields, or asks about available Flux components.
 - `livewire-development` — Develops reactive Livewire 4 components. Activates when creating, updating, or modifying Livewire components; working with wire:model, wire:click, wire:loading, or any wire: directives; adding real-time updates, loading states, or reactivity; debugging component behavior; writing Livewire tests; or when the user mentions Livewire, component, counter, or reactive UI.
 - `pest-testing` — Tests applications using the Pest 4 PHP framework. Activates when writing tests, creating unit or feature tests, adding assertions, testing Livewire components, browser testing, debugging test failures, working with datasets or mocking; or when the user mentions test, spec, TDD, expects, assertion, coverage, or needs to verify functionality works.
+- `tailwindcss-development` — Styles applications using Tailwind CSS v4 utilities. Activates when adding styles, restyling components, working with gradients, spacing, layout, flex, grid, responsive design, dark mode, colors, typography, or borders; or when the user mentions CSS, styling, classes, Tailwind, restyle, hero section, cards, buttons, or any visual/UI changes.
 
 ## Conventions
 
@@ -261,4 +264,12 @@ protected function isAccessible(User $user, ?string $path = null): bool
 - Do NOT delete tests without approval.
 - CRITICAL: ALWAYS use `search-docs` tool for version-specific Pest documentation and updated code examples.
 - IMPORTANT: Activate `pest-testing` every time you're working with a Pest or testing-related task.
+
+=== tailwindcss/core rules ===
+
+# Tailwind CSS
+
+- Always use existing Tailwind conventions; check project patterns before adding new ones.
+- IMPORTANT: Always use `search-docs` tool for version-specific Tailwind CSS documentation and updated code examples. Never rely on training data.
+- IMPORTANT: Activate `tailwindcss-development` every time you're working with a Tailwind CSS or styling-related task.
 
diff --git a/.cursor/rules/update-documentation.mdc b/.cursor/rules/update-documentation.mdc
new file mode 100644
index 0000000..5317d0a
--- /dev/null
+++ b/.cursor/rules/update-documentation.mdc
@@ -0,0 +1,69 @@
+# Update Documentation
+
+Quand l'utilisateur dit **"update documentation"**, tu DOIS mettre a jour le fichier `documentation/documentation_api_logistics.md` en suivant cette procedure.
+
+## Procedure de mise a jour
+
+1. **Lire les sources suivantes** (dans cet ordre) :
+   - `app/Services/LogisticsService.php` : toutes les methodes publiques = endpoints disponibles. Les PHPDoc `@param` contiennent les parametres attendus.
+   - `config/logistics.php` : configuration de connexion (variables d'environnement, valeurs par defaut).
+   - `.env` : valeurs actuelles des variables de configuration.
+   - `documentation/documentation_api_logistics.md` : documentation existante a mettre a jour.
+   - `memory-bank/techContext.md` : contexte technique (tables, types de colonnes, endpoints connus).
+
+2. **Identifier les changements** :
+   - Nouvelles methodes dans `LogisticsService` = nouveaux endpoints a documenter.
+   - Methodes supprimees = endpoints a retirer.
+   - Parametres modifies (PHPDoc `@param`) = mise a jour des tableaux de parametres.
+   - Nouvelles variables d'environnement dans `config/logistics.php` = mise a jour de la section pre-requis.
+
+3. **Mettre a jour le fichier** en preservant strictement cette structure :
+
+```
+# Documentation API Logistics (Flex/ESI Gescom)
+Derniere mise a jour : 
+
+## Table des matieres
+## 1. Pre-requis
+## 2. Comment effectuer des requetes
+## 3. Structure de reponse
+## 4. Tables et colonnes disponibles
+## 5. Recuperation de donnees
+   ### 5.1 Structure de la base de donnees (tables_list, column_list)
+   ### 5.2 Articles (art_list, art_getstk)
+   ### 5.3 Journaux (jnl_list)
+   ### 5.4 Documents (document_list, document_detail, Document_GetStatusList, Document_GetUnitPriceAndVat, Document_GetDueDate, Document_GetAttachListThumbnail)
+   ### 5.5 Tiers (third_list, third_GetArtHistory)
+   ### 5.6 Divers (getserialnumber, codes_list)
+## 6. Envoi de donnees
+   ### 6.1 Ajout d'un document (document_add)
+   ### 6.2 Modification d'un document (document_mod)
+## 7. Endpoints non fonctionnels
+## 8. Relations entre entites
+## 9. Remarques et points d'attention
+## 10. Ressources externes
+```
+
+4. **Pour chaque endpoint, documenter** :
+   - Description fonctionnelle (a quoi il sert).
+   - URL au format `POST /{dossier}/{endpoint}`.
+   - Methode service correspondante (`LogisticsService::methode()`).
+   - Tableau des parametres : nom, type, obligatoire (Oui/Non), description detaillee.
+   - Exemple de requete (body JSON).
+   - Exemple de reponse si disponible.
+
+5. **Classer les endpoints** :
+   - Section 5 (Recuperation) : endpoints qui lisent des donnees (toutes les methodes sauf `documentAdd` et `documentMod`).
+   - Section 6 (Envoi) : endpoints qui creent ou modifient des donnees (`documentAdd`, `documentMod`).
+   - Section 7 : endpoints identifies mais non fonctionnels.
+
+6. **Mettre a jour la date** en haut du fichier (`Derniere mise a jour : `).
+
+## Regles
+
+- Ne jamais supprimer d'information existante sans raison (endpoint supprime du service).
+- Ton factuel et concis, sans emojis.
+- Toujours inclure les chemins de fichiers exacts dans les references.
+- Les exemples de requete doivent utiliser des valeurs realistes.
+- La table des matieres doit refleter les sections du document.
+- Les endpoints non fonctionnels restent documentes avec le statut "Non fonctionnel" et la description du probleme.
\ No newline at end of file
diff --git a/.cursor/skills/tailwindcss-development/SKILL.md b/.cursor/skills/tailwindcss-development/SKILL.md
new file mode 100644
index 0000000..12bd896
--- /dev/null
+++ b/.cursor/skills/tailwindcss-development/SKILL.md
@@ -0,0 +1,124 @@
+---
+name: tailwindcss-development
+description: >-
+  Styles applications using Tailwind CSS v4 utilities. Activates when adding styles, restyling components,
+  working with gradients, spacing, layout, flex, grid, responsive design, dark mode, colors,
+  typography, or borders; or when the user mentions CSS, styling, classes, Tailwind, restyle,
+  hero section, cards, buttons, or any visual/UI changes.
+---
+
+# Tailwind CSS Development
+
+## When to Apply
+
+Activate this skill when:
+
+- Adding styles to components or pages
+- Working with responsive design
+- Implementing dark mode
+- Extracting repeated patterns into components
+- Debugging spacing or layout issues
+
+## Documentation
+
+Use `search-docs` for detailed Tailwind CSS v4 patterns and documentation.
+
+## Basic Usage
+
+- Use Tailwind CSS classes to style HTML. Check and follow existing Tailwind conventions in the project before introducing new patterns.
+- Offer to extract repeated patterns into components that match the project's conventions (e.g., Blade, JSX, Vue).
+- Consider class placement, order, priority, and defaults. Remove redundant classes, add classes to parent or child elements carefully to reduce repetition, and group elements logically.
+
+## Tailwind CSS v4 Specifics
+
+- Always use Tailwind CSS v4 and avoid deprecated utilities.
+- `corePlugins` is not supported in Tailwind v4.
+
+### CSS-First Configuration
+
+In Tailwind v4, configuration is CSS-first using the `@theme` directive — no separate `tailwind.config.js` file is needed:
+
+
+@theme {
+  --color-brand: oklch(0.72 0.11 178);
+}
+
+
+### Import Syntax
+
+In Tailwind v4, import Tailwind with a regular CSS `@import` statement instead of the `@tailwind` directives used in v3:
+
+
+- @tailwind base;
+- @tailwind components;
+- @tailwind utilities;
++ @import "tailwindcss";
+
+
+### Replaced Utilities
+
+Tailwind v4 removed deprecated utilities. Use the replacements shown below. Opacity values remain numeric.
+
+| Deprecated | Replacement |
+|------------|-------------|
+| bg-opacity-* | bg-black/* |
+| text-opacity-* | text-black/* |
+| border-opacity-* | border-black/* |
+| divide-opacity-* | divide-black/* |
+| ring-opacity-* | ring-black/* |
+| placeholder-opacity-* | placeholder-black/* |
+| flex-shrink-* | shrink-* |
+| flex-grow-* | grow-* |
+| overflow-ellipsis | text-ellipsis |
+| decoration-slice | box-decoration-slice |
+| decoration-clone | box-decoration-clone |
+
+## Spacing
+
+Use `gap` utilities instead of margins for spacing between siblings:
+
+
+
+
Item 1
+
Item 2
+
+
+ +## Dark Mode + +If existing pages and components support dark mode, new pages and components must support it the same way, typically using the `dark:` variant: + + +
+ Content adapts to color scheme +
+
+ +## Common Patterns + +### Flexbox Layout + + +
+
Left content
+
Right content
+
+
+ +### Grid Layout + + +
+
Card 1
+
Card 2
+
Card 3
+
+
+ +## Common Pitfalls + +- Using deprecated v3 utilities (bg-opacity-*, flex-shrink-*, etc.) +- Using `@tailwind` directives instead of `@import "tailwindcss"` +- Trying to use `tailwind.config.js` instead of CSS `@theme` directive +- Using margins for spacing between siblings instead of gap utilities +- Forgetting to add dark mode variants when the project uses dark mode \ No newline at end of file diff --git a/README.md b/README.md index aa5e3ce..861750a 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,13 @@ # API Logistics -Application Laravel 12 de test pour comprendre et documenter l'API Logistics (Flex/ESI Gescom). Elle fournit un dashboard Filament v5 permettant d'interroger les differents endpoints de l'API. +Application Laravel 12 de test pour comprendre et documenter l'API Logistics (Flex/ESI Gescom). Elle fournit un dashboard Filament v5 permettant d'interroger les différents endpoints de l'API. -## Prerequis +## Prérequis - PHP 8.4+ - Composer - Node.js et npm - MySQL -- Laravel Herd (recommande) ## Installation @@ -23,9 +22,9 @@ php artisan key:generate ## Configuration -### Base de donnees +### Base de données -Creer une base de donnees MySQL nommee `api_logistics`, puis configurer le fichier `.env` : +Créer une base de données MySQL nommée `api_logistics`, puis configurer le fichier `.env` : ``` DB_CONNECTION=mysql @@ -36,7 +35,7 @@ DB_USERNAME=root DB_PASSWORD= ``` -Executer les migrations : +Exécuter les migrations : ```bash php artisan migrate @@ -44,7 +43,7 @@ php artisan migrate ### API Logistics -Configurer la connexion a l'API Logistics dans le fichier `.env` : +Configurer la connexion à l'API Logistics dans le fichier `.env` : ``` LOGISTICS_API_BASE_URL=http://tse-10-test.esiweb.pro @@ -53,40 +52,41 @@ LOGISTICS_API_FOLDER=esigescom ``` - **LOGISTICS_API_BASE_URL** : URL de base du serveur Logistics -- **LOGISTICS_API_KEY** : Cle API transmise via le header `X-API-KEY` -- **LOGISTICS_API_FOLDER** : Nom du dossier (en minuscules) utilise dans les routes de l'API +- **LOGISTICS_API_KEY** : Clé API transmise via le header `X-API-KEY` +- **LOGISTICS_API_FOLDER** : Nom du dossier (en minuscules) utilisé dans les routes de l'API -## Demarrage +## Démarrage ```bash npm run build ``` -L'application est disponible via Laravel Herd a l'adresse `http://api-logistics.test`. +L'application est disponible à l'adresse `http://api-logistics.test`. -Le dashboard Filament est accessible a l'adresse `http://api-logistics.test/admin`. +Le dashboard Filament est accessible à l'adresse `http://api-logistics.test/admin`. ## Structure du dashboard Le dashboard Filament propose les pages suivantes : +- **Documentation** : Documentation de l'API Logistics - **Tables** : Explorer les tables disponibles dans l'API et visualiser leurs colonnes -- **Articles** : Rechercher des articles et verifier le stock -- **Documents** : Lister des documents et consulter leurs details +- **Articles** : Rechercher des articles et vérifier le stock +- **Documents** : Lister des documents et consulter leurs détails - **Journaux** : Rechercher et lister les journaux - **Tiers** : Rechercher des tiers et consulter l'historique des articles ## Architecture technique - `config/logistics.php` : Configuration de l'API Logistics -- `app/Services/LogisticsService.php` : Service centralise pour les appels HTTP vers l'API +- `app/Services/LogisticsService.php` : Service centralisé pour les appels HTTP vers l'API - `app/Filament/Pages/` : Pages Filament du dashboard -- `database/migrations/` : Migrations incluant la table `api_request_logs` pour le suivi des requetes +- `database/migrations/` : Migrations incluant la table `api_request_logs` pour le suivi des requêtes ## Documentation de l'API - [Documentation Postman](https://documenter.getpostman.com/view/40440561/2sB2qaj2Pz) -- Documentation interne : `documentation/WEB-A-1 (3).md` +- Documentation interne : `documentation/documentation_api_logistics.md` ## Tests diff --git a/app/Filament/Pages/Dashboard.php b/app/Filament/Pages/Dashboard.php new file mode 100644 index 0000000..77e7e33 --- /dev/null +++ b/app/Filament/Pages/Dashboard.php @@ -0,0 +1,19 @@ +htmlContent = Str::markdown($markdown); + } + + public function getHeaderActions(): array + { + return [ + Action::make('download') + ->label('Télécharger en PDF') + ->icon(Heroicon::OutlinedArrowDownTray) + ->url(route('documentation.download-pdf')) + ->openUrlInNewTab(), + + Action::make('see_in_another_tab') + ->label('Voir dans un nouvel onglet') + ->icon(Heroicon::OutlinedArrowTopRightOnSquare) + ->url(Documentation::getUrl()) + ->openUrlInNewTab(), + ]; + } +} diff --git a/app/Filament/Pages/TablesExplorer.php b/app/Filament/Pages/TablesExplorer.php index 4963945..ecc3e4b 100644 --- a/app/Filament/Pages/TablesExplorer.php +++ b/app/Filament/Pages/TablesExplorer.php @@ -23,24 +23,75 @@ class TablesExplorer extends Page #[Url] public string $selectedTable = ''; + public string $tableFilter = ''; + public array $tables = []; public array $columns = []; + public ?array $tablesMetadata = null; + + public ?array $columnsMetadata = null; + public ?string $errorMessage = null; + /** + * @var array + */ + private static array $dataTypeLabels = [ + 'C' => 'Caractère', + 'N' => 'Numérique', + 'T' => 'Date/Heure', + 'D' => 'Date', + 'L' => 'Logique', + 'M' => 'Mémo', + ]; + public function mount(): void { $this->loadTables(); + + if (filled($this->selectedTable)) { + $this->loadColumns(); + } } - public function loadTables(): void + public function selectTable(string $tableName): void + { + $this->selectedTable = $tableName; + $this->loadColumns(); + } + + /** + * @return array> + */ + public function getFilteredTablesProperty(): array + { + if (blank($this->tableFilter)) { + return $this->tables; + } + + $filter = mb_strtolower($this->tableFilter); + + return array_values(array_filter( + $this->tables, + fn (array $table): bool => str_contains(mb_strtolower($table['name'] ?? ''), $filter), + )); + } + + public static function getDataTypeLabel(string $type): string + { + return self::$dataTypeLabels[strtoupper($type)] ?? $type; + } + + private function loadTables(): void { try { $service = app(LogisticsService::class); $response = $service->tablesList(); $this->tables = $response['data'] ?? []; + $this->tablesMetadata = $response['metadata'] ?? null; $this->errorMessage = $response['error'] ?? null; } catch (LogisticsApiException $e) { $this->errorMessage = $e->getMessage(); @@ -49,10 +100,11 @@ class TablesExplorer extends Page } } - public function loadColumns(): void + private function loadColumns(): void { if (blank($this->selectedTable)) { $this->columns = []; + $this->columnsMetadata = null; return; } @@ -61,12 +113,36 @@ class TablesExplorer extends Page $service = app(LogisticsService::class); $response = $service->columnList($this->selectedTable); - $this->columns = $response['data'] ?? []; + $rawColumns = $response['data'] ?? []; + $this->columns = $this->deduplicateColumns($rawColumns); + $this->columnsMetadata = $response['metadata'] ?? null; $this->errorMessage = $response['error'] ?? null; } catch (LogisticsApiException $e) { $this->errorMessage = $e->getMessage(); + $this->columns = []; } catch (\Throwable $e) { $this->errorMessage = "Erreur inattendue : {$e->getMessage()}"; + $this->columns = []; } } + + /** + * @param array> $columns + * @return array> + */ + private function deduplicateColumns(array $columns): array + { + $seen = []; + $unique = []; + + foreach ($columns as $column) { + $key = ($column['name'] ?? '').'|'.($column['dataType'] ?? ''); + if (! isset($seen[$key])) { + $seen[$key] = true; + $unique[] = $column; + } + } + + return $unique; + } } diff --git a/app/Providers/Filament/AdminPanelProvider.php b/app/Providers/Filament/AdminPanelProvider.php index 055298b..fac9ef6 100644 --- a/app/Providers/Filament/AdminPanelProvider.php +++ b/app/Providers/Filament/AdminPanelProvider.php @@ -2,13 +2,12 @@ namespace App\Providers\Filament; +use App\Filament\Pages\Dashboard; use Filament\Http\Middleware\DisableBladeIconComponents; use Filament\Http\Middleware\DispatchServingFilamentEvent; -use Filament\Pages\Dashboard; use Filament\Panel; use Filament\PanelProvider; use Filament\Support\Colors\Color; -use Filament\Widgets\FilamentInfoWidget; use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse; use Illuminate\Cookie\Middleware\EncryptCookies; use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken; @@ -24,6 +23,7 @@ class AdminPanelProvider extends PanelProvider ->default() ->id('admin') ->path('admin') + ->viteTheme('resources/css/filament/admin/theme.css') ->brandName('API Logistics') ->colors([ 'primary' => Color::Blue, @@ -34,9 +34,7 @@ class AdminPanelProvider extends PanelProvider Dashboard::class, ]) ->discoverWidgets(in: app_path('Filament/Widgets'), for: 'App\Filament\Widgets') - ->widgets([ - FilamentInfoWidget::class, - ]) + ->widgets([]) ->middleware([ EncryptCookies::class, AddQueuedCookiesToResponse::class, diff --git a/boost.json b/boost.json index 357cba1..dc0400d 100644 --- a/boost.json +++ b/boost.json @@ -9,6 +9,7 @@ "skills": [ "fluxui-development", "livewire-development", - "pest-testing" + "pest-testing", + "tailwindcss-development" ] } diff --git a/composer.json b/composer.json index ee9d489..8d969a5 100644 --- a/composer.json +++ b/composer.json @@ -7,6 +7,7 @@ "license": "MIT", "require": { "php": "^8.2", + "barryvdh/laravel-dompdf": "^3.1", "filament/filament": "5.0", "laravel/fortify": "^1.30", "laravel/framework": "^12.0", diff --git a/composer.lock b/composer.lock index 49645fe..ad72455 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "72e464a39ce3e36d3ef8c75498225c48", + "content-hash": "3cb29f1ae8d0f5968aae9270bea812f0", "packages": [ { "name": "anourvalar/eloquent-serialize", @@ -127,6 +127,83 @@ }, "time": "2025-11-19T17:15:36+00:00" }, + { + "name": "barryvdh/laravel-dompdf", + "version": "v3.1.1", + "source": { + "type": "git", + "url": "https://github.com/barryvdh/laravel-dompdf.git", + "reference": "8e71b99fc53bb8eb77f316c3c452dd74ab7cb25d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/barryvdh/laravel-dompdf/zipball/8e71b99fc53bb8eb77f316c3c452dd74ab7cb25d", + "reference": "8e71b99fc53bb8eb77f316c3c452dd74ab7cb25d", + "shasum": "" + }, + "require": { + "dompdf/dompdf": "^3.0", + "illuminate/support": "^9|^10|^11|^12", + "php": "^8.1" + }, + "require-dev": { + "larastan/larastan": "^2.7|^3.0", + "orchestra/testbench": "^7|^8|^9|^10", + "phpro/grumphp": "^2.5", + "squizlabs/php_codesniffer": "^3.5" + }, + "type": "library", + "extra": { + "laravel": { + "aliases": { + "PDF": "Barryvdh\\DomPDF\\Facade\\Pdf", + "Pdf": "Barryvdh\\DomPDF\\Facade\\Pdf" + }, + "providers": [ + "Barryvdh\\DomPDF\\ServiceProvider" + ] + }, + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "psr-4": { + "Barryvdh\\DomPDF\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Barry vd. Heuvel", + "email": "barryvdh@gmail.com" + } + ], + "description": "A DOMPDF Wrapper for Laravel", + "keywords": [ + "dompdf", + "laravel", + "pdf" + ], + "support": { + "issues": "https://github.com/barryvdh/laravel-dompdf/issues", + "source": "https://github.com/barryvdh/laravel-dompdf/tree/v3.1.1" + }, + "funding": [ + { + "url": "https://fruitcake.nl", + "type": "custom" + }, + { + "url": "https://github.com/barryvdh", + "type": "github" + } + ], + "time": "2025-02-13T15:07:54+00:00" + }, { "name": "blade-ui-kit/blade-heroicons", "version": "2.6.0", @@ -962,6 +1039,161 @@ ], "time": "2024-02-05T11:56:58+00:00" }, + { + "name": "dompdf/dompdf", + "version": "v3.1.4", + "source": { + "type": "git", + "url": "https://github.com/dompdf/dompdf.git", + "reference": "db712c90c5b9868df3600e64e68da62e78a34623" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dompdf/dompdf/zipball/db712c90c5b9868df3600e64e68da62e78a34623", + "reference": "db712c90c5b9868df3600e64e68da62e78a34623", + "shasum": "" + }, + "require": { + "dompdf/php-font-lib": "^1.0.0", + "dompdf/php-svg-lib": "^1.0.0", + "ext-dom": "*", + "ext-mbstring": "*", + "masterminds/html5": "^2.0", + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "ext-gd": "*", + "ext-json": "*", + "ext-zip": "*", + "mockery/mockery": "^1.3", + "phpunit/phpunit": "^7.5 || ^8 || ^9 || ^10 || ^11", + "squizlabs/php_codesniffer": "^3.5", + "symfony/process": "^4.4 || ^5.4 || ^6.2 || ^7.0" + }, + "suggest": { + "ext-gd": "Needed to process images", + "ext-gmagick": "Improves image processing performance", + "ext-imagick": "Improves image processing performance", + "ext-zlib": "Needed for pdf stream compression" + }, + "type": "library", + "autoload": { + "psr-4": { + "Dompdf\\": "src/" + }, + "classmap": [ + "lib/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-2.1" + ], + "authors": [ + { + "name": "The Dompdf Community", + "homepage": "https://github.com/dompdf/dompdf/blob/master/AUTHORS.md" + } + ], + "description": "DOMPDF is a CSS 2.1 compliant HTML to PDF converter", + "homepage": "https://github.com/dompdf/dompdf", + "support": { + "issues": "https://github.com/dompdf/dompdf/issues", + "source": "https://github.com/dompdf/dompdf/tree/v3.1.4" + }, + "time": "2025-10-29T12:43:30+00:00" + }, + { + "name": "dompdf/php-font-lib", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/dompdf/php-font-lib.git", + "reference": "a6e9a688a2a80016ac080b97be73d3e10c444c9a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dompdf/php-font-lib/zipball/a6e9a688a2a80016ac080b97be73d3e10c444c9a", + "reference": "a6e9a688a2a80016ac080b97be73d3e10c444c9a", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "phpunit/phpunit": "^7.5 || ^8 || ^9 || ^10 || ^11 || ^12" + }, + "type": "library", + "autoload": { + "psr-4": { + "FontLib\\": "src/FontLib" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-2.1-or-later" + ], + "authors": [ + { + "name": "The FontLib Community", + "homepage": "https://github.com/dompdf/php-font-lib/blob/master/AUTHORS.md" + } + ], + "description": "A library to read, parse, export and make subsets of different types of font files.", + "homepage": "https://github.com/dompdf/php-font-lib", + "support": { + "issues": "https://github.com/dompdf/php-font-lib/issues", + "source": "https://github.com/dompdf/php-font-lib/tree/1.0.2" + }, + "time": "2026-01-20T14:10:26+00:00" + }, + { + "name": "dompdf/php-svg-lib", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/dompdf/php-svg-lib.git", + "reference": "8259ffb930817e72b1ff1caef5d226501f3dfeb1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dompdf/php-svg-lib/zipball/8259ffb930817e72b1ff1caef5d226501f3dfeb1", + "reference": "8259ffb930817e72b1ff1caef5d226501f3dfeb1", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": "^7.1 || ^8.0", + "sabberworm/php-css-parser": "^8.4 || ^9.0" + }, + "require-dev": { + "phpunit/phpunit": "^7.5 || ^8 || ^9 || ^10 || ^11" + }, + "type": "library", + "autoload": { + "psr-4": { + "Svg\\": "src/Svg" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0-or-later" + ], + "authors": [ + { + "name": "The SvgLib Community", + "homepage": "https://github.com/dompdf/php-svg-lib/blob/master/AUTHORS.md" + } + ], + "description": "A library to read, parse and export to PDF SVG files.", + "homepage": "https://github.com/dompdf/php-svg-lib", + "support": { + "issues": "https://github.com/dompdf/php-svg-lib/issues", + "source": "https://github.com/dompdf/php-svg-lib/tree/1.0.2" + }, + "time": "2026-01-02T16:01:13+00:00" + }, { "name": "dragonmantank/cron-expression", "version": "v3.6.0", @@ -5305,6 +5537,80 @@ ], "time": "2025-02-25T09:09:36+00:00" }, + { + "name": "sabberworm/php-css-parser", + "version": "v9.1.0", + "source": { + "type": "git", + "url": "https://github.com/MyIntervals/PHP-CSS-Parser.git", + "reference": "1b363fdbdc6dd0ca0f4bf98d3a4d7f388133f1fb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/MyIntervals/PHP-CSS-Parser/zipball/1b363fdbdc6dd0ca0f4bf98d3a4d7f388133f1fb", + "reference": "1b363fdbdc6dd0ca0f4bf98d3a4d7f388133f1fb", + "shasum": "" + }, + "require": { + "ext-iconv": "*", + "php": "^7.2.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0", + "thecodingmachine/safe": "^1.3 || ^2.5 || ^3.3" + }, + "require-dev": { + "php-parallel-lint/php-parallel-lint": "1.4.0", + "phpstan/extension-installer": "1.4.3", + "phpstan/phpstan": "1.12.28 || 2.1.25", + "phpstan/phpstan-phpunit": "1.4.2 || 2.0.7", + "phpstan/phpstan-strict-rules": "1.6.2 || 2.0.6", + "phpunit/phpunit": "8.5.46", + "rawr/phpunit-data-provider": "3.3.1", + "rector/rector": "1.2.10 || 2.1.7", + "rector/type-perfect": "1.0.0 || 2.1.0" + }, + "suggest": { + "ext-mbstring": "for parsing UTF-8 CSS" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "9.2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Sabberworm\\CSS\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Raphael Schweikert" + }, + { + "name": "Oliver Klee", + "email": "github@oliverklee.de" + }, + { + "name": "Jake Hotson", + "email": "jake.github@qzdesign.co.uk" + } + ], + "description": "Parser for CSS Files written in PHP", + "homepage": "https://www.sabberworm.com/blog/2010/6/10/php-css-parser", + "keywords": [ + "css", + "parser", + "stylesheet" + ], + "support": { + "issues": "https://github.com/MyIntervals/PHP-CSS-Parser/issues", + "source": "https://github.com/MyIntervals/PHP-CSS-Parser/tree/v9.1.0" + }, + "time": "2025-09-14T07:37:21+00:00" + }, { "name": "scrivo/highlight.php", "version": "v9.18.1.10", @@ -8134,6 +8440,149 @@ ], "time": "2026-01-01T22:13:48+00:00" }, + { + "name": "thecodingmachine/safe", + "version": "v3.4.0", + "source": { + "type": "git", + "url": "https://github.com/thecodingmachine/safe.git", + "reference": "705683a25bacf0d4860c7dea4d7947bfd09eea19" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thecodingmachine/safe/zipball/705683a25bacf0d4860c7dea4d7947bfd09eea19", + "reference": "705683a25bacf0d4860c7dea4d7947bfd09eea19", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "php-parallel-lint/php-parallel-lint": "^1.4", + "phpstan/phpstan": "^2", + "phpunit/phpunit": "^10", + "squizlabs/php_codesniffer": "^3.2" + }, + "type": "library", + "autoload": { + "files": [ + "lib/special_cases.php", + "generated/apache.php", + "generated/apcu.php", + "generated/array.php", + "generated/bzip2.php", + "generated/calendar.php", + "generated/classobj.php", + "generated/com.php", + "generated/cubrid.php", + "generated/curl.php", + "generated/datetime.php", + "generated/dir.php", + "generated/eio.php", + "generated/errorfunc.php", + "generated/exec.php", + "generated/fileinfo.php", + "generated/filesystem.php", + "generated/filter.php", + "generated/fpm.php", + "generated/ftp.php", + "generated/funchand.php", + "generated/gettext.php", + "generated/gmp.php", + "generated/gnupg.php", + "generated/hash.php", + "generated/ibase.php", + "generated/ibmDb2.php", + "generated/iconv.php", + "generated/image.php", + "generated/imap.php", + "generated/info.php", + "generated/inotify.php", + "generated/json.php", + "generated/ldap.php", + "generated/libxml.php", + "generated/lzf.php", + "generated/mailparse.php", + "generated/mbstring.php", + "generated/misc.php", + "generated/mysql.php", + "generated/mysqli.php", + "generated/network.php", + "generated/oci8.php", + "generated/opcache.php", + "generated/openssl.php", + "generated/outcontrol.php", + "generated/pcntl.php", + "generated/pcre.php", + "generated/pgsql.php", + "generated/posix.php", + "generated/ps.php", + "generated/pspell.php", + "generated/readline.php", + "generated/rnp.php", + "generated/rpminfo.php", + "generated/rrd.php", + "generated/sem.php", + "generated/session.php", + "generated/shmop.php", + "generated/sockets.php", + "generated/sodium.php", + "generated/solr.php", + "generated/spl.php", + "generated/sqlsrv.php", + "generated/ssdeep.php", + "generated/ssh2.php", + "generated/stream.php", + "generated/strings.php", + "generated/swoole.php", + "generated/uodbc.php", + "generated/uopz.php", + "generated/url.php", + "generated/var.php", + "generated/xdiff.php", + "generated/xml.php", + "generated/xmlrpc.php", + "generated/yaml.php", + "generated/yaz.php", + "generated/zip.php", + "generated/zlib.php" + ], + "classmap": [ + "lib/DateTime.php", + "lib/DateTimeImmutable.php", + "lib/Exceptions/", + "generated/Exceptions/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHP core functions that throw exceptions instead of returning FALSE on error", + "support": { + "issues": "https://github.com/thecodingmachine/safe/issues", + "source": "https://github.com/thecodingmachine/safe/tree/v3.4.0" + }, + "funding": [ + { + "url": "https://github.com/OskarStark", + "type": "github" + }, + { + "url": "https://github.com/shish", + "type": "github" + }, + { + "url": "https://github.com/silasjoisten", + "type": "github" + }, + { + "url": "https://github.com/staabm", + "type": "github" + } + ], + "time": "2026-02-04T18:08:13+00:00" + }, { "name": "tijsverkoyen/css-to-inline-styles", "version": "v2.4.0", diff --git a/documentation/documentation_api_logistics.md b/documentation/documentation_api_logistics.md index b8d7f2e..067e3a3 100644 --- a/documentation/documentation_api_logistics.md +++ b/documentation/documentation_api_logistics.md @@ -1,75 +1,152 @@ # Documentation API Logistics (Flex/ESI Gescom) -Derniere mise a jour : 2026-02-20 +Dernière mise à jour : 2026-02-20 --- -## Table des matieres +## Table des matières -- [Informations generales](#informations-generales) -- [Authentification](#authentification) -- [Structure de reponse](#structure-de-reponse) -- [Tables disponibles](#tables-disponibles) -- [Endpoints](#endpoints) - - [Structure](#structure) - - [Articles](#articles) - - [Journaux](#journaux) - - [Documents](#documents) - - [Tiers](#tiers) - - [Divers](#divers) -- [Endpoints non fonctionnels](#endpoints-non-fonctionnels) -- [Relations entre entites](#relations-entre-entites) -- [Remarques et points d'attention](#remarques-et-points-dattention) +1. [Pré-requis](#1-pré-requis) +2. [Comment effectuer des requêtes](#2-comment-effectuer-des-requêtes) +3. [Structure de réponse](#3-structure-de-réponse) +4. [Tables et colonnes disponibles](#4-tables-et-colonnes-disponibles) +5. [Récupération de données](#5-récupération-de-données) +6. [Envoi de données](#6-envoi-de-données) +7. [Endpoints non fonctionnels](#7-endpoints-non-fonctionnels) +8. [Relations entre entités](#8-relations-entre-entités) +9. [Remarques et points d'attention](#9-remarques-et-points-dattention) +10. [Ressources externes](#10-ressources-externes) --- -## Informations generales +## 1. Pré-requis -| Element | Valeur | +### Accès au serveur + +L'API Logistics est hébergée sur un serveur privé. Les informations de connexion sont les suivantes : + +| Élément | Valeur | |---------|--------| | Serveur | TSE-10-TEST | -| Hote | `tse-10-test.esiweb.pro` | +| Hôte | `tse-10-test.esiweb.pro` (public) / `tse-10-test.esi.local` (réseau privé) | | Port HTTP | 5186 | | Port HTTPS | 7126 | -| Methode | POST (pour tous les endpoints) | -| Format de reponse | JSON | -L'URL de base de chaque requete suit le schema : +L'accès au serveur nécessite soit une connexion au réseau privé, soit l'utilisation de l'hôte public avec le port adéquat. -``` -http://:// -``` +### Clé API -Le nom du dossier **doit etre en minuscules** dans toutes les requetes. +Toutes les requêtes sont protégées par une clé API. Cette clé doit être transmise dans le header HTTP `X-API-KEY` de chaque requête. Sans clé valide, l'API retourne une erreur d'authentification. + +### Dossier + +Chaque requête cible un dossier comptable spécifique. Le nom du dossier est inclus dans l'URL de la requête. Le nom du dossier **doit impérativement être en minuscules** dans toutes les URLs (exemple : `esigescom`, et non `EsiGescom`). + +### Variables d'environnement + +L'application Laravel utilise les variables d'environnement suivantes pour se connecter à l'API. Elles doivent être configurées dans le fichier `.env` : + +| Variable | Description | Exemple | +|----------|-------------|---------| +| `LOGISTICS_API_BASE_URL` | URL de base du serveur API | `http://tse-10-test.esi.local` | +| `LOGISTICS_API_KEY` | Clé d'authentification API | `ztpyQX1ajtzb10ypdPs3C8N2w3XY1A` | +| `LOGISTICS_API_FOLDER` | Nom du dossier comptable (minuscules) | `esigescom` | +| `LOGISTICS_API_TIMEOUT` | Timeout total de la requête en secondes | `300` | +| `LOGISTICS_API_CONNECT_TIMEOUT` | Timeout de connexion en secondes | `10` | +| `LOGISTICS_API_RETRY_TIMES` | Nombre de tentatives en cas d'échec de connexion | `3` | +| `LOGISTICS_API_RETRY_SLEEP_MS` | Délai entre les tentatives en millisecondes | `500` | + +### Configuration Laravel + +Les variables d'environnement sont lues par le fichier de configuration `config/logistics.php` : + +| Clé de config | Variable .env | Défaut | +|---------------|---------------|--------| +| `logistics.base_url` | `LOGISTICS_API_BASE_URL` | - | +| `logistics.api_key` | `LOGISTICS_API_KEY` | - | +| `logistics.folder` | `LOGISTICS_API_FOLDER` | - | +| `logistics.timeout` | `LOGISTICS_API_TIMEOUT` | `30` | +| `logistics.connect_timeout` | `LOGISTICS_API_CONNECT_TIMEOUT` | `10` | +| `logistics.retry.times` | `LOGISTICS_API_RETRY_TIMES` | `3` | +| `logistics.retry.sleep_ms` | `LOGISTICS_API_RETRY_SLEEP_MS` | `500` | + +Le service `App\Services\LogisticsService` utilise ces valeurs pour configurer automatiquement les appels HTTP (URL, headers, timeouts, retry). En cas d'échec de connexion, le service effectue un retry automatique selon la configuration. --- -## Authentification +## 2. Comment effectuer des requêtes -Toutes les requetes sont protegees par une cle API. Elle doit etre transmise dans le header HTTP : +### Méthode HTTP -| Header | Valeur | -|--------|--------| -| `X-API-KEY` | `` | +**Tous les endpoints utilisent la méthode POST**, y compris les opérations de lecture. Aucun endpoint ne répond aux méthodes GET, PUT, PATCH ou DELETE. -Exemple : +### Format de l'URL + +L'URL de chaque requête suit le schéma suivant : + +``` +POST {base_url}/{dossier}/{endpoint} +``` + +Où : + +- `{base_url}` est l'URL de base du serveur (ex : `http://tse-10-test.esi.local`) +- `{dossier}` est le nom du dossier comptable en minuscules (ex : `esigescom`) +- `{endpoint}` est le nom de l'endpoint (ex : `art_list`, `document_detail`) + +### Headers obligatoires + +| Header | Valeur | Description | +|--------|--------|-------------| +| `X-API-KEY` | `` | Clé d'authentification (obligatoire) | +| `Content-Type` | `application/json` | Type de contenu du body (obligatoire si body présent) | + +### Exemple de requête complète ```http -POST /esigescom/tables_list HTTP/1.1 +POST /esigescom/art_list HTTP/1.1 Host: tse-10-test.esiweb.pro:5186 X-API-KEY: votre-cle-api Content-Type: application/json + +{ + "search": "chaise", + "results": 10, + "select": "artid,artname" +} ``` +### Paramètres des requêtes + +Les paramètres sont transmis dans le body de la requête au format JSON. Certains endpoints n'exigent aucun paramètre (body vide ou `{}`). Les paramètres peuvent être de différents types : + +| Type | Description | Exemple | +|------|-------------|---------| +| `string` | Chaîne de caractères | `"ART001"` | +| `int` | Nombre entier | `10` | +| `array` | Tableau de valeurs | `["ART001", "ART002"]` | + +**Attention** : certains paramètres qui représentent des nombres doivent être transmis au format `string` (ex : `QTY` dans `Document_GetUnitPriceAndVat` doit être `"2"` et non `2`). + +### Gestion des erreurs + +Le service `LogisticsService` de l'application gère automatiquement : + +- **Retry automatique** : en cas d'échec de connexion (`ConnectionException`), le service retente automatiquement selon la configuration (`retry.times` et `retry.sleep_ms`). +- **Logging** : chaque requête (réussie ou échouée) est enregistrée dans la table `api_request_logs` avec l'endpoint, les paramètres, le code de statut et la réponse. +- **Exceptions** : en cas d'erreur, une `LogisticsApiException` est levée avec un message explicite en français. + --- -## Structure de reponse +## 3. Structure de réponse -Tous les endpoints retournent un objet JSON avec la meme structure : +### Format standard + +Tous les endpoints retournent un objet JSON avec la même structure : ```json { - "data": "", + "data": "", "metadata": { "rowcount": 0, "issuccess": true @@ -78,53 +155,148 @@ Tous les endpoints retournent un objet JSON avec la meme structure : } ``` -| Cle | Type | Description | +### Description des clés + +| Clé | Type | Description | |-----|------|-------------| -| `data` | mixed | Le resultat de la requete (tableau d'objets, objet, ou null) | -| `metadata.rowcount` | int | Nombre d'elements retournes | -| `metadata.issuccess` | bool | Indique si la requete a reussi | -| `error` | string/null | Message d'erreur en cas d'echec, `null` sinon | +| `data` | `mixed` | Le résultat de la requête. Peut être un tableau d'objets, un objet unique, une chaîne, ou `null`. | +| `metadata` | `object` | Informations sur la requête. Contient toujours `rowcount` et `issuccess`. Peut contenir d'autres clés selon l'endpoint. | +| `metadata.rowcount` | `int` | Nombre d'éléments retournés dans `data`. | +| `metadata.issuccess` | `bool` | `true` si la requête a réussi, `false` sinon. | +| `error` | `string` ou `null` | Message d'erreur en cas d'échec. `null` si la requête a réussi. | ---- - -## Tables disponibles - -Les tables suivantes sont exposees par l'API. Leurs colonnes peuvent etre recuperees via l'endpoint `column_list` et utilisees dans le parametre `select` des endpoints de recherche. - -| Table | Description probable | Table | Description probable | -|-------|---------------------|-------|---------------------| -| `art` | Articles | `docpay` | Paiements documents | -| `attach` | Fichiers attaches | `file` | Fichiers | -| `barcode` | Codes-barres | `hist` | Historique | -| `category` | Categories | `incodes` | Codes internes | -| `codes` | Codes | `jnl` | Journaux | -| `cust` | Clients / Tiers | `pers` | Personnes | -| `docdet` | Detail documents | `price` | Prix | -| `dochead` | En-tete documents | `stk` | Stock | - ---- - -## Endpoints - -### Structure - -Ces endpoints permettent de decouvrir la structure de la base de donnees exposee par l'API. - -#### `tables_list` -- Liste des tables - -Retourne la liste de toutes les tables accessibles. - -| | | -|---|---| -| **URL** | `POST //tables_list` | -| **Parametres** | Aucun | - -Exemple de reponse : +### Exemple de réponse réussie ```json { - "data": ["art", "attach", "barcode", "category", "codes", "cust", "docdet", "dochead", "docpay", "file", "hist", "incodes", "jnl", "pers", "price", "stk"], - "metadata": { "rowcount": 16, "issuccess": true }, + "data": [ + { "artid": "ART001", "artname": "Chaise bureau" }, + { "artid": "ART002", "artname": "Chaise visiteur" } + ], + "metadata": { + "rowcount": 2, + "issuccess": true + }, + "error": null +} +``` + +### Exemple de réponse en erreur + +```json +{ + "data": null, + "metadata": { + "rowcount": 0, + "issuccess": false + }, + "error": "Invalid API key" +} +``` + +### Métadonnées spécifiques par endpoint + +Certains endpoints retournent des clés supplémentaires dans `metadata` : + +| Endpoint | Clés supplémentaires | Description | +|----------|---------------------|-------------| +| `tables_list` | `tableCount`, `folderType`, `endpoint` | Nombre total de tables, type de base de données (ex : `DBF`), nom de l'endpoint | +| `column_list` | `columnCount`, `tableName` | Nombre de colonnes retournées, nom de la table interrogée | + +--- + +## 4. Tables et colonnes disponibles + +### Liste des tables + +L'API expose 16 tables. Chacune correspond à un domaine fonctionnel de la gestion commerciale : + +| Table | Colonnes | Description | +|-------|----------|-------------| +| `art` | 160 | **Articles** : références produits du catalogue. Contient l'identifiant, le nom, la description, les prix, les unités, les catégories, etc. | +| `attach` | 13 | **Fichiers attachés** : pièces jointes associées aux documents (factures, bons de commande, etc.). | +| `barcode` | 12 | **Codes-barres** : codes-barres associés aux articles pour l'identification et le scan. | +| `category` | 10 | **Catégories** : catégories de classification pour organiser les articles. | +| `codes` | 50 | **Codes système** : codes de configuration internes au système de gestion. | +| `cust` | 216 | **Tiers/Clients** : fiches tiers (clients, fournisseurs). Contient l'identifiant, le nom, l'adresse, les conditions commerciales, les coordonnées, etc. | +| `docdet` | 82 | **Lignes de documents** : lignes de détail des documents commerciaux. Chaque ligne référence un article avec sa quantité, son prix, sa TVA, etc. | +| `dochead` | 212 | **En-têtes de documents** : en-têtes des documents commerciaux (devis, commandes, factures). Contient le tiers, la date, le journal, le statut, les totaux, etc. | +| `docpay` | 22 | **Paiements** : paiements associés aux documents (montant, date, mode de paiement). | +| `file` | 17 | **Fichiers** : fichiers système gérés par l'application. | +| `hist` | 50 | **Historique** : historique des opérations effectuées dans le système. | +| `incodes` | 24 | **Codes internes** : codes internes paramétrables, utilisés pour les listes de valeurs, les types, etc. | +| `jnl` | 155 | **Journaux** : journaux comptables et commerciaux. Chaque journal regroupe des documents du même type (ventes, achats, etc.). | +| `pers` | 78 | **Personnes/Contacts** : fiches de contacts associées aux tiers ou à l'entreprise. | +| `price` | 28 | **Tarifs** : grilles de prix et conditions tarifaires par article, client ou catégorie. | +| `stk` | 20 | **Stock** : quantités en stock par article et par emplacement. | + +### Types de colonnes + +Chaque colonne d'une table possède un type de données identifié par un code à une lettre : + +| Code | Label | Description | +|------|-------|-------------| +| `C` | Caractère | Chaîne de caractères (texte libre, identifiants, noms, etc.) | +| `N` | Numérique | Nombre entier ou décimal (quantités, prix, montants, etc.) | +| `T` | Date/Heure | Timestamp combinant date et heure | +| `D` | Date | Date seule (sans composante horaire) | +| `L` | Logique | Booléen (`true`/`false`) | +| `M` | Mémo | Texte long (champs de description étendus, remarques, etc.) | + +### Exploration des colonnes + +Pour connaître les colonnes disponibles dans une table, utiliser les endpoints `tables_list` et `column_list/{tablename}` décrits dans la section 5. + +**Remarque importante** : l'API retourne les colonnes en double dans la réponse de `column_list`. L'application effectue une déduplication automatique côté client. + +--- + +## 5. Récupération de données + +Tous les endpoints de cette section servent à lire des données depuis l'API. Ils utilisent la méthode POST et retournent des données dans la clé `data` de la réponse. + +### 5.1 Structure de la base de données + +#### `tables_list` -- Liste des tables + +Retourne la liste de toutes les tables accessibles dans le dossier comptable. Utile pour découvrir la structure de la base de données. + +| | | +|---|---| +| **URL** | `POST /{dossier}/tables_list` | +| **Méthode service** | `LogisticsService::tablesList()` | + +**Paramètres** : aucun. + +**Exemple de requête** : + +```json +{} +``` + +**Exemple de réponse** : + +```json +{ + "data": [ + { "name": "art", "columnCount": 160 }, + { "name": "attach", "columnCount": 13 }, + { "name": "barcode", "columnCount": 12 }, + { "name": "category", "columnCount": 10 }, + { "name": "codes", "columnCount": 50 }, + { "name": "cust", "columnCount": 216 }, + { "name": "docdet", "columnCount": 82 }, + { "name": "dochead", "columnCount": 212 }, + { "name": "docpay", "columnCount": 22 }, + { "name": "file", "columnCount": 17 }, + { "name": "hist", "columnCount": 50 }, + { "name": "incodes", "columnCount": 24 }, + { "name": "jnl", "columnCount": 155 }, + { "name": "pers", "columnCount": 78 }, + { "name": "price", "columnCount": 28 }, + { "name": "stk", "columnCount": 20 } + ], + "metadata": { "tableCount": 16, "folderType": "DBF", "endpoint": "tables_list", "rowcount": 16, "issuccess": true }, "error": null } ``` @@ -133,136 +305,452 @@ Exemple de reponse : #### `column_list/{tablename}` -- Colonnes d'une table -Retourne la liste des colonnes d'une table donnee. Utile pour connaitre les champs utilisables dans le parametre `select` des autres endpoints. +Retourne la liste des colonnes d'une table donnée, avec leur type, leur longueur et leur précision. Indispensable pour connaître les champs utilisables dans le paramètre `select` des autres endpoints. | | | |---|---| -| **URL** | `POST //column_list/{tablename}` | -| **Parametres** | `tablename` dans l'URL (nom de la table, issu de `tables_list`) | +| **URL** | `POST /{dossier}/column_list/{tablename}` | +| **Méthode service** | `LogisticsService::columnList(string $table)` | + +**Paramètres** : + +| Paramètre | Emplacement | Type | Obligatoire | Description | +|-----------|-------------|------|:-----------:|-------------| +| `tablename` | URL | `string` | Oui | Nom de la table (issu de `tables_list`). Exemple : `art`, `cust`, `dochead`. | + +**Exemple de requête** : + +``` +POST /esigescom/column_list/stk +``` + +**Exemple de réponse** : + +```json +{ + "data": [ + { "name": "ARTID", "dataType": "C", "length": 20, "precision": 0 }, + { "name": "STOCK", "dataType": "N", "length": 10, "precision": 2 }, + { "name": "DEPOT", "dataType": "C", "length": 10, "precision": 0 } + ], + "metadata": { "columnCount": 3, "tableName": "stk", "rowcount": 3, "issuccess": true }, + "error": null +} +``` + +**Remarque** : l'API retourne chaque colonne en double. L'application effectue une déduplication automatique. --- -### Articles +### 5.2 Articles -Un document contient un ou plusieurs articles. Les articles sont stockes dans la table `art`. +Les articles sont les références produits du catalogue. Ils sont stockés dans la table `art`. #### `art_list` -- Recherche d'articles -Retourne une liste d'articles correspondant aux criteres de recherche. +Retourne une liste d'articles correspondant aux critères de recherche. Permet de filtrer par texte libre ou par code-barres, et de sélectionner les colonnes à retourner. | | | |---|---| -| **URL** | `POST //art_list` | +| **URL** | `POST /{dossier}/art_list` | +| **Méthode service** | `LogisticsService::artList(array $params)` | -| Parametre | Type | Obligatoire | Description | +**Paramètres** : + +| Paramètre | Type | Obligatoire | Description | |-----------|------|:-----------:|-------------| -| `select` | string | Non | Colonnes a retourner (colonnes de la table `art`) | -| `results` | int | Non | Nombre de resultats a retourner | -| `search` | string | Non | Filtre de recherche | -| `barcode` | string | Non | Code-barres de l'article | +| `search` | `string` | Non | Filtre de recherche textuel. Recherche dans les champs principaux de l'article (identifiant, nom, description). Non requis si `barcode` est fourni. | +| `select` | `string` | Non | Liste des colonnes à retourner, séparées par des virgules. Les noms de colonnes disponibles sont ceux de la table `art` (obtenables via `column_list/art`). Si omis, un jeu de colonnes par défaut est retourné. | +| `results` | `int` | Non | Nombre maximum de résultats à retourner. Par défaut, l'API retourne un nombre réduit de résultats (environ 5 à 10). | +| `barcode` | `string` | Non | Code-barres de l'article à rechercher. Si fourni, le paramètre `search` n'est pas requis. | -Remarque : lors d'une recherche par `barcode`, le parametre `search` n'est pas requis. +**Exemple de requête** : + +```json +{ + "search": "chaise", + "select": "artid,artname,saleprice1", + "results": 20 +} +``` --- #### `art_getstk` -- Stock d'un article -Retourne les informations de stock pour un article donne. +Retourne les informations de stock pour un article donné. Permet de vérifier la disponibilité d'un article dans les différents dépôts. | | | |---|---| -| **URL** | `POST //art_getstk` | +| **URL** | `POST /{dossier}/art_getstk` | +| **Méthode service** | `LogisticsService::artGetStock(string $artId)` | -| Parametre | Type | Obligatoire | Description | +**Paramètres** : + +| Paramètre | Type | Obligatoire | Description | |-----------|------|:-----------:|-------------| -| `ARTID` | string | Oui | Identifiant de l'article | +| `ARTID` | `string` | Oui | Identifiant unique de l'article (champ `artid` de la table `art`). | + +**Exemple de requête** : + +```json +{ + "ARTID": "ART001" +} +``` --- -### Journaux +### 5.3 Journaux -Un journal contient un ou plusieurs documents. Les journaux sont stockes dans la table `jnl`. +Les journaux regroupent les documents commerciaux par type (ventes, achats, retours, etc.). Ils sont stockés dans la table `jnl`. #### `jnl_list` -- Liste des journaux -Retourne la liste des journaux correspondant aux criteres. +Retourne la liste des journaux correspondant au type demandé. Un journal contient un ou plusieurs documents. | | | |---|---| -| **URL** | `POST //jnl_list` | +| **URL** | `POST /{dossier}/jnl_list` | +| **Méthode service** | `LogisticsService::jnlList(array $params)` | -| Parametre | Type | Obligatoire | Description | +**Paramètres** : + +| Paramètre | Type | Obligatoire | Description | |-----------|------|:-----------:|-------------| -| `select` | string | Non | Colonnes a retourner (colonnes de la table `jnl`) | -| `results` | int | Non | Nombre de resultats a retourner | -| `TYPE` | string | Oui | Code de type de journal | +| `TYPE` | `string` | Oui | Code de type de journal. Filtre les journaux par leur type (ex : ventes, achats). Les codes de type disponibles dépendent de la configuration du dossier. | +| `select` | `string` | Non | Colonnes à retourner, séparées par des virgules (colonnes de la table `jnl`). | +| `results` | `int` | Non | Nombre maximum de résultats. | + +**Exemple de requête** : + +```json +{ + "TYPE": "V", + "select": "jnlid,jnlname", + "results": 50 +} +``` --- -### Documents +### 5.4 Documents -Un journal contient un ou plusieurs documents, et un document contient un ou plusieurs articles. Les en-tetes de documents sont dans la table `dochead`, les lignes de detail dans `docdet`. +Les documents commerciaux (devis, commandes, factures, avoirs, etc.) constituent le coeur du système. Chaque document possède un en-tête (`dochead`) et une ou plusieurs lignes de détail (`docdet`). Un document appartient à un journal et est associé à un tiers. #### `document_list` -- Liste des documents -Retourne une liste de documents, eventuellement filtree par tiers. +Retourne une liste de documents, éventuellement filtrée par tiers. Permet de consulter les documents commerciaux associés à un client. | | | |---|---| -| **URL** | `POST //document_list` | +| **URL** | `POST /{dossier}/document_list` | +| **Méthode service** | `LogisticsService::documentList(array $params)` | -| Parametre | Type | Obligatoire | Description | +**Paramètres** : + +| Paramètre | Type | Obligatoire | Description | |-----------|------|:-----------:|-------------| -| `select` | string | Non | Colonnes a retourner (colonnes de la table `dochead`) | -| `thirdid` | string | Non | Identifiant du tiers (`custid` de la table `cust`) | +| `select` | `string` | Non | Colonnes à retourner, séparées par des virgules (colonnes de la table `dochead`). | +| `thirdid` | `string` | Non | Identifiant du tiers (champ `custid` de la table `cust`). Si fourni, seuls les documents de ce tiers sont retournés. | + +**Exemple de requête** : + +```json +{ + "select": "docid,docdate,thirdid,totalht", + "thirdid": "CUST001" +} +``` --- -#### `document_detail` -- Detail d'un document +#### `document_detail` -- Détail d'un document -Retourne le detail complet d'un document (en-tete + lignes). +Retourne le détail complet d'un document spécifique : l'en-tête (informations générales) et toutes les lignes de détail (articles, quantités, prix). | | | |---|---| -| **URL** | `POST //document_detail` | +| **URL** | `POST /{dossier}/document_detail` | +| **Méthode service** | `LogisticsService::documentDetail(string $jnl, string $number)` | -| Parametre | Type | Obligatoire | Description | +**Paramètres** : + +| Paramètre | Type | Obligatoire | Description | |-----------|------|:-----------:|-------------| -| `jnl` | string | Oui | Code du journal | -| `number` | string | Oui | Identifiant du document | +| `jnl` | `string` | Oui | Code du journal auquel appartient le document. | +| `number` | `string` | Oui | Identifiant unique du document dans le journal. | + +**Exemple de requête** : + +```json +{ + "jnl": "VEN", + "number": "2026/0001" +} +``` --- -#### `document_add` -- Ajout d'un document +#### `Document_GetStatusList` -- Statuts disponibles d'un journal -Cree un nouveau document dans un journal. +Retourne la liste des statuts disponibles pour les documents d'un journal donné. Utile pour connaître les états possibles d'un document (brouillon, validé, envoyé, etc.). | | | |---|---| -| **URL** | `POST //document_add` | +| **URL** | `POST /{dossier}/Document_GetStatusList` | +| **Méthode service** | `LogisticsService::documentGetStatusList(string $jnl)` | -| Parametre | Type | Obligatoire | Description | +**Paramètres** : + +| Paramètre | Type | Obligatoire | Description | |-----------|------|:-----------:|-------------| -| `ThirdId` | string | Oui | Identifiant du tiers (`custid` de la table `cust`) | -| `Date` | string | Oui | Date d'encodage | -| `Artid` | array | Oui | Tableau d'identifiants d'articles (`artid` de la table `art`) | -| `Qty` | array | Oui | Tableau de quantites (correspond position par position a `Artid`) | -| `Saleprice` | array | Oui | Tableau des prix de vente unitaires | -| `JNL` | string | Oui | Code du journal affecte | -| `Discount` | array | Non | Tableau des reductions de prix | -| `Vatid` | array | Non | Tableau des identifiants de TVA | -| `Vatpc` | array | Non | Tableau des pourcentages de TVA | -| `Attachments` | array | Non | Liste de fichiers joints (voir structure ci-dessous) | +| `jnl` | `string` | Oui | Code du journal dont on veut connaître les statuts. | -Structure d'un element `Attachments` : +**Exemple de requête** : -| Cle | Type | Description | +```json +{ + "jnl": "VEN" +} +``` + +--- + +#### `Document_GetUnitPriceAndVat` -- Prix unitaire et TVA + +Retourne le prix unitaire et la TVA applicable pour un article dans un contexte précis (journal, tiers, date, quantité). Utile pour calculer le montant d'une ligne de document avant création. + +| | | +|---|---| +| **URL** | `POST /{dossier}/Document_GetUnitPriceAndVat` | +| **Méthode service** | `LogisticsService::documentGetUnitPriceAndVat(array $params)` | + +**Paramètres** : + +| Paramètre | Type | Obligatoire | Description | +|-----------|------|:-----------:|-------------| +| `ARTID` | `string` | Oui | Identifiant de l'article. | +| `QTY` | `string` | Oui | Quantité demandée. **Doit être au format string** (ex : `"2"`), pas un nombre. | +| `JNL` | `string` | Oui | Code du journal. | +| `THIRDID` | `string` | Oui | Identifiant du tiers (champ `custid` de la table `cust`). | +| `DATE` | `string` | Oui | Date de référence pour le calcul du prix. | + +**Exemple de requête** : + +```json +{ + "ARTID": "ART001", + "QTY": "5", + "JNL": "VEN", + "THIRDID": "CUST001", + "DATE": "2026-02-20" +} +``` + +--- + +#### `Document_GetDueDate` -- Échéance de paiement + +Calcule la date d'échéance de paiement à partir d'un type de délai de paiement et d'une date de départ. Utile pour déterminer automatiquement la date limite de paiement d'un document. + +| | | +|---|---| +| **URL** | `POST /{dossier}/Document_GetDueDate` | +| **Méthode service** | `LogisticsService::documentGetDueDate(string $payDelay, string $date)` | + +**Paramètres** : + +| Paramètre | Type | Obligatoire | Description | +|-----------|------|:-----------:|-------------| +| `paydelay` | `string` | Oui | Type de délai de paiement (code identifiant les conditions de paiement, ex : `30J`, `60J`, `FDM`). | +| `date` | `string` | Oui | Date de départ à partir de laquelle calculer l'échéance. | + +**Exemple de requête** : + +```json +{ + "paydelay": "30J", + "date": "2026-02-20" +} +``` + +--- + +#### `Document_GetAttachListThumbnail` -- Miniatures des annexes + +Retourne les miniatures des fichiers images attachés à un document. Seuls les fichiers de type image sont concernés ; les autres types de fichiers ne sont pas retournés. + +| | | +|---|---| +| **URL** | `POST /{dossier}/Document_GetAttachListThumbnail` | +| **Méthode service** | `LogisticsService::documentGetAttachListThumbnail(string $jnl, string $number)` | + +**Paramètres** : + +| Paramètre | Type | Obligatoire | Description | +|-----------|------|:-----------:|-------------| +| `JNL` | `string` | Oui | Code du journal du document. | +| `NUMBER` | `string` | Oui | Identifiant du document. | + +**Exemple de requête** : + +```json +{ + "JNL": "VEN", + "NUMBER": "2026/0001" +} +``` + +--- + +### 5.5 Tiers + +Les tiers (clients, fournisseurs) sont les entités commerciales avec lesquelles l'entreprise interagit. Ils sont stockés dans la table `cust`. + +#### `third_list` -- Recherche de tiers + +Retourne une liste de tiers correspondant au filtre de recherche. Permet de trouver un client ou fournisseur par son nom, son identifiant ou d'autres critères. + +| | | +|---|---| +| **URL** | `POST /{dossier}/third_list` | +| **Méthode service** | `LogisticsService::thirdList(array $params)` | + +**Paramètres** : + +| Paramètre | Type | Obligatoire | Description | +|-----------|------|:-----------:|-------------| +| `search` | `string` | Oui | Filtre de recherche. **Ce paramètre est obligatoire** : un appel sans filtre retourne une erreur. | +| `select` | `string` | Non | Colonnes à retourner, séparées par des virgules (colonnes de la table `cust`). | +| `results` | `int` | Non | Nombre maximum de résultats. | + +**Exemple de requête** : + +```json +{ + "search": "Dupont", + "select": "custid,custname,city", + "results": 10 +} +``` + +--- + +#### `third_GetArtHistory` -- Historique des articles d'un tiers + +Retourne l'historique complet des articles présents dans les documents associés à un tiers. Permet d'analyser les achats ou ventes passés d'un client/fournisseur. + +| | | +|---|---| +| **URL** | `POST /{dossier}/third_GetArtHistory` | +| **Méthode service** | `LogisticsService::thirdGetArtHistory(string $thirdId)` | + +**Paramètres** : + +| Paramètre | Type | Obligatoire | Description | +|-----------|------|:-----------:|-------------| +| `thirdid` | `string` | Oui | Identifiant du tiers (champ `custid` de la table `cust`). | + +**Exemple de requête** : + +```json +{ + "thirdid": "CUST001" +} +``` + +--- + +### 5.6 Divers + +#### `getserialnumber` -- Numéro de série du dossier + +Retourne le numéro de série du dossier comptable. Identifie de manière unique l'installation du logiciel de gestion. + +| | | +|---|---| +| **URL** | `POST /{dossier}/getserialnumber` | +| **Méthode service** | `LogisticsService::getSerialNumber()` | + +**Paramètres** : aucun. + +**Exemple de requête** : + +```json +{} +``` + +--- + +#### `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.). + +| | | +|---|---| +| **URL** | `POST /{dossier}/codes_list` | +| **Méthode service** | `LogisticsService::codesList(array $params)` | + +**Paramètres** : + +| 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. | + +**Exemple de requête** : + +```json +{ + "code": "PAY" +} +``` + +**Remarque** : les valeurs retournées contiennent des champs `vala1`, `vala2`, etc. dont la signification précise dépend du code recherché. + +--- + +## 6. Envoi de données + +Les endpoints de cette section permettent de créer ou modifier des données dans le système de gestion via l'API. + +### 6.1 Ajout d'un document + +#### `document_add` -- Création d'un document + +Crée un nouveau document commercial (devis, commande, facture, etc.) dans un journal. Le document est composé d'un en-tête (tiers, date, journal) et d'une ou plusieurs lignes d'articles. + +| | | +|---|---| +| **URL** | `POST /{dossier}/document_add` | +| **Méthode service** | `LogisticsService::documentAdd(array $params)` | + +**Paramètres** : + +| Paramètre | Type | Obligatoire | Description | +|-----------|------|:-----------:|-------------| +| `ThirdId` | `string` | Oui | Identifiant du tiers (champ `custid` de la table `cust`). Détermine le client ou fournisseur associé au document. | +| `Date` | `string` | Oui | Date d'encodage du document (ex : `"2026-02-20"`). | +| `Artid` | `array` | Oui | Tableau d'identifiants d'articles (champ `artid` de la table `art`). Chaque élément correspond à une ligne du document. | +| `Qty` | `array` | Oui | Tableau de quantités. Correspond position par position au tableau `Artid`. Chaque élément est un `string`. | +| `Saleprice` | `array` | Oui | Tableau des prix de vente unitaires. Correspond position par position au tableau `Artid`. Chaque élément est un `string`. | +| `JNL` | `string` | Oui | Code du journal dans lequel créer le document (ex : `"VEN"` pour ventes). | +| `Discount` | `array` | Non | Tableau des réductions de prix (en pourcentage ou montant). Correspond position par position au tableau `Artid`. | +| `Vatid` | `array` | Non | Tableau des identifiants de code TVA. Correspond position par position au tableau `Artid`. | +| `Vatpc` | `array` | Non | Tableau des pourcentages de TVA. Correspond position par position au tableau `Artid`. | +| `Attachments` | `array` | Non | Liste de fichiers joints au document. Voir la structure ci-dessous. | + +**Structure d'un élément `Attachments`** : + +| Clé | Type | Description | |-----|------|-------------| -| `FileName` | string | Nom du fichier avec extension (ex: `facture.pdf`) | -| `FileDesc` | string | Description du fichier | -| `FileContentBase64` | string | Contenu du fichier encode en base64 | +| `FileName` | `string` | Nom du fichier avec extension (ex : `"facture.pdf"`). | +| `FileDesc` | `string` | Description du fichier (ex : `"Bon de commande signé"`). | +| `FileContentBase64` | `string` | Contenu du fichier encodé en base64. | -Exemple de body : +**Correspondance des tableaux** : les tableaux `Artid`, `Qty`, `Saleprice`, `Discount`, `Vatid` et `Vatpc` fonctionnent par correspondance positionnelle. L'élément à l'index 0 de chaque tableau concerne la première ligne du document, l'élément à l'index 1 la deuxième ligne, etc. + +**Exemple de requête** : ```json { @@ -272,6 +760,9 @@ Exemple de body : "Qty": ["2", "5"], "Saleprice": ["10.00", "25.50"], "JNL": "VEN", + "Discount": ["0", "10"], + "Vatid": ["TVA21", "TVA21"], + "Vatpc": ["21", "21"], "Attachments": [ { "FileName": "bon.pdf", @@ -284,234 +775,145 @@ Exemple de body : --- -#### `document_mod` -- Modification d'un document +### 6.2 Modification d'un document -Modifie un document existant. Le parametre `number` identifie le document a modifier. +#### `document_mod` -- Modification d'un document existant + +Modifie un document existant identifié par son numéro et son journal. Permet de mettre à jour les lignes d'articles, les prix, le tiers, ou d'ajouter des fichiers joints. | | | |---|---| -| **URL** | `POST //document_mod` | +| **URL** | `POST /{dossier}/document_mod` | +| **Méthode service** | `LogisticsService::documentMod(array $params)` | -| Parametre | Type | Obligatoire | Description | +**Paramètres** : + +| Paramètre | Type | Obligatoire | Description | |-----------|------|:-----------:|-------------| -| `number` | string | Oui | Identifiant du document a modifier | -| `JNL` | string | Oui | Code du journal lie au document | -| `Thirdid` | string | Non | Identifiant du tiers | -| `Artid` | array | Non | Tableau d'identifiants d'articles | -| `Qty` | array | Non | Tableau de quantites | -| `Saleprice` | array | Non | Tableau des prix de vente | -| `Attachments` | array | Non | Liste de fichiers joints (meme structure que `document_add`) | +| `number` | `string` | Oui | Identifiant du document à modifier. | +| `JNL` | `string` | Oui | Code du journal lié au document. | +| `Thirdid` | `string` | Non | Nouvel identifiant du tiers (si modification du tiers associé). | +| `Artid` | `array` | Non | Tableau d'identifiants d'articles (remplace les lignes existantes). | +| `Qty` | `array` | Non | Tableau de quantités (correspond position par position à `Artid`). | +| `Saleprice` | `array` | Non | Tableau des prix de vente unitaires (correspond position par position à `Artid`). | +| `Attachments` | `array` | Non | Liste de fichiers joints (même structure que `document_add`). | + +**Exemple de requête** : + +```json +{ + "number": "2026/0001", + "JNL": "VEN", + "Artid": ["ART001", "ART003"], + "Qty": ["3", "1"], + "Saleprice": ["10.00", "50.00"] +} +``` --- -#### `Document_GetStatusList` -- Statuts d'un journal +## 7. Endpoints non fonctionnels -Retourne la liste des statuts disponibles pour les documents d'un journal. +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. + +### `Document_GetPDF` -- Génération de PDF | | | |---|---| -| **URL** | `POST //Document_GetStatusList` | - -| Parametre | Type | Obligatoire | Description | -|-----------|------|:-----------:|-------------| -| `jnl` | string | Oui | Code du journal | - ---- - -#### `Document_GetUnitPriceAndVat` -- Prix unitaire et TVA - -Retourne le prix unitaire et la TVA pour un article dans un contexte donne (journal, tiers, date). - -| | | -|---|---| -| **URL** | `POST //Document_GetUnitPriceAndVat` | - -| Parametre | Type | Obligatoire | Description | -|-----------|------|:-----------:|-------------| -| `ARTID` | string | Oui | Identifiant de l'article | -| `QTY` | string | Oui | Quantite (format string obligatoire) | -| `JNL` | string | Oui | Code du journal | -| `THIRDID` | string | Oui | Identifiant du tiers (`custid` de la table `cust`) | -| `DATE` | string | Oui | Date | - ---- - -#### `Document_GetDueDate` -- Echeance de paiement - -Calcule la date d'echeance a partir d'un type de delai de paiement et d'une date de depart. - -| | | -|---|---| -| **URL** | `POST //Document_GetDueDate` | - -| Parametre | Type | Obligatoire | Description | -|-----------|------|:-----------:|-------------| -| `paydelay` | string | Oui | Type de delai de paiement | -| `date` | string | Oui | Date de depart | - ---- - -#### `Document_GetAttachListThumbnail` -- Miniatures des annexes - -Retourne les miniatures des fichiers attaches a un document. Seuls les fichiers de type image sont concernes. - -| | | -|---|---| -| **URL** | `POST //Document_GetAttachListThumbnail` | - -| Parametre | Type | Obligatoire | Description | -|-----------|------|:-----------:|-------------| -| `JNL` | string | Oui | Code du journal | -| `NUMBER` | string | Oui | Identifiant du document | - ---- - -### Tiers - -Un tiers (client) possede un ou plusieurs documents. Les tiers sont stockes dans la table `cust`. - -#### `third_list` -- Liste des tiers - -Retourne une liste de tiers correspondant au filtre de recherche. - -| | | -|---|---| -| **URL** | `POST //third_list` | - -| Parametre | Type | Obligatoire | Description | -|-----------|------|:-----------:|-------------| -| `select` | string | Non | Colonnes a retourner (colonnes de la table `cust`) | -| `results` | int | Non | Nombre de resultats a retourner | -| `search` | string | Oui | Filtre de recherche | - ---- - -#### `third_GetArtHistory` -- Historique articles d'un tiers - -Retourne l'historique des articles des documents associes a un tiers. - -| | | -|---|---| -| **URL** | `POST //third_GetArtHistory` | - -| Parametre | Type | Obligatoire | Description | -|-----------|------|:-----------:|-------------| -| `thirdid` | string | Oui | Identifiant du tiers | - ---- - -### Divers - -#### `getserialnumber` -- Numero de serie - -Retourne le numero de serie du dossier. - -| | | -|---|---| -| **URL** | `POST //getserialnumber` | -| **Parametres** | Aucun | - ---- - -#### `codes_list` -- Donnees par code - -Retourne des donnees associees a un code interne. Les codes proviennent de la table `incodes`. - -| | | -|---|---| -| **URL** | `POST //codes_list` | - -| Parametre | Type | Obligatoire | Description | -|-----------|------|:-----------:|-------------| -| `code` | string | Oui | Debut de code (de la table `incodes`) | - -Remarque : les valeurs retournees contiennent des champs `vala1`, `vala2`, etc. dont la signification precise reste a documenter. - ---- - -## Endpoints non fonctionnels - -Les endpoints suivants ont ete testes mais ne fonctionnent pas ou necessitent des parametres inconnus. - -#### `Document_GetPDF` -- Generation de PDF - -| | | -|---|---| -| **URL** | `POST //Document_GetPDF` | +| **URL** | `POST /{dossier}/Document_GetPDF` | | **Statut** | Non fonctionnel | -| Parametre | Type | Description | -|-----------|------|-------------| -| `JNL` | string | Code du journal | -| `NUMBER` | string | Identifiant du document | -| `LAYOUT` | string | Inconnu -- parametre requis mais valeur non documentee | +**Paramètres connus** : -Probleme : la valeur attendue pour le parametre `LAYOUT` est inconnue. L'endpoint retourne une erreur sans ce parametre. +| Paramètre | Type | Description | +|-----------|------|-------------| +| `JNL` | `string` | Code du journal. | +| `NUMBER` | `string` | Identifiant du document. | +| `LAYOUT` | `string` | Mise en page du PDF. **Valeur attendue inconnue**. | + +**Problème** : le paramètre `LAYOUT` est requis mais sa valeur attendue n'est pas documentée par le fournisseur de l'API. L'endpoint retourne une erreur sans ce paramètre. --- -#### `custom_geninv_updatestock` -- Mise a jour de l'inventaire +### `custom_geninv_updatestock` -- Mise à jour de l'inventaire | | | |---|---| -| **URL** | `POST //custom_geninv_updatestock` | +| **URL** | `POST /{dossier}/custom_geninv_updatestock` | | **Statut** | Non fonctionnel | -| Parametre | Type | Description | -|-----------|------|-------------| -| `ARTID` | string | Identifiant de l'article | -| `STKID` | string | Identifiant du stock -- valeur inconnue | -| `QTY` | string | Quantite a mettre a jour | -| `TOCHECK` | string | Signification inconnue (prix ?) | -| `TOCHECKDETAIL` | string | Signification inconnue (remarques ?) | -| `MODE` | string | Signification inconnue | +**Paramètres connus** : -Probleme : la valeur attendue pour `STKID` est inconnue, et la signification de plusieurs parametres reste a clarifier. +| 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. --- -## Relations entre entites +## 8. Relations entre entités + +Les entités du système de gestion sont liées entre elles selon le schéma suivant : ``` Tiers (cust) | - +-- possede un ou plusieurs --> Documents (dochead / docdet) + +-- possède un ou plusieurs --> Documents (dochead / docdet) | - +-- appartient a un --> Journal (jnl) + +-- appartient à un --> Journal (jnl) | +-- contient un ou plusieurs --> Articles (art) | - +-- peut avoir des --> Fichiers attaches (attach) + +-- peut avoir des --> Fichiers attachés (attach) + | + +-- peut avoir des --> Paiements (docpay) ``` -- Un **tiers** (`cust`) est un client qui peut avoir plusieurs documents. -- Un **journal** (`jnl`) regroupe plusieurs documents du meme type. -- Un **document** (`dochead` pour l'en-tete, `docdet` pour les lignes) appartient a un journal et est associe a un tiers. -- Un **article** (`art`) est une reference produit. Chaque ligne de document fait reference a un article avec une quantite et un prix. -- Le **stock** (`stk`) contient les quantites en stock par article. +**Description des relations** : + +- Un **tiers** (`cust`) est un client ou fournisseur. Il peut être associé à plusieurs documents commerciaux. +- Un **journal** (`jnl`) regroupe plusieurs documents du même type (ventes, achats, retours, etc.). Chaque document appartient à un seul journal. +- Un **document** est composé d'un en-tête (`dochead`) contenant les informations générales (tiers, date, journal, statut, totaux) et de lignes de détail (`docdet`) contenant les articles. +- Un **article** (`art`) est une référence produit du catalogue. Chaque ligne de document fait référence à un article avec une quantité, un prix unitaire et une TVA. +- Le **stock** (`stk`) contient les quantités en stock par article. Il est consultable via l'endpoint `art_getstk`. +- Les **fichiers attachés** (`attach`) sont des pièces jointes associées aux documents (factures PDF, bons de commande scannés, etc.). +- Les **paiements** (`docpay`) enregistrent les règlements associés aux documents. +- Les **codes internes** (`incodes`) sont des tables de référence paramétrables utilisées pour les listes déroulantes, les types, les catégories, etc. --- -## Remarques et points d'attention +## 9. Remarques et points d'attention -1. **Dossier en minuscules** : le nom du dossier dans les URLs doit toujours etre en minuscules. Exemple : `esigescom`, pas `EsiGescom`. +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. -2. **Methode POST uniquement** : tous les endpoints utilisent la methode POST, meme pour les operations de lecture. +2. **Méthode POST uniquement** : tous les endpoints utilisent la méthode POST, y compris pour les opérations de lecture. N'utilisez pas GET, PUT ou DELETE. -3. **Parametre `QTY`** : dans l'endpoint `Document_GetUnitPriceAndVat`, le parametre `QTY` doit etre au format string, pas numerique. +3. **Paramètre `QTY` en string** : dans l'endpoint `Document_GetUnitPriceAndVat`, le paramètre `QTY` doit impérativement être au format string (`"2"`), pas numérique (`2`). Le non-respect de ce format provoque un comportement inattendu. -4. **Parametre `search` obligatoire** : pour `third_list`, le parametre `search` est obligatoire. Un appel sans filtre retournera une erreur. +4. **Paramètre `search` obligatoire pour `third_list`** : l'endpoint `third_list` exige le paramètre `search`. Un appel sans ce paramètre retourne une erreur. -5. **Parametre `results`** : limite le nombre de resultats retournes. Par defaut, l'API retourne un nombre reduit de resultats (environ 5 a 10). +5. **Paramètre `results`** : limite le nombre de résultats retournés. Par défaut, l'API retourne un nombre réduit de résultats (environ 5 à 10). Augmentez cette valeur si vous avez besoin de plus de résultats. -6. **Parametre `select`** : permet de specifier les colonnes a retourner. Les noms de colonnes disponibles pour chaque table peuvent etre obtenus via `column_list/{tablename}`. +6. **Paramètre `select`** : permet de choisir les colonnes à retourner. Les noms de colonnes disponibles pour chaque table s'obtiennent via `column_list/{tablename}`. Si omis, un jeu de colonnes par défaut est retourné. -7. **Fichiers attaches** : lors de l'ajout ou la modification de documents, les fichiers doivent etre encodes en base64 dans le champ `FileContentBase64`. +7. **Casse des paramètres** : la casse des noms de paramètres varie selon les endpoints. Par exemple, l'identifiant du tiers peut être `thirdid`, `Thirdid` ou `THIRDID` selon l'endpoint. Respectez la casse documentée pour chaque endpoint. -8. **Identifiant tiers** : les parametres `thirdid`, `Thirdid` et `THIRDID` font tous reference au champ `custid` de la table `cust`, mais la casse varie selon l'endpoint. +8. **Fichiers attachés en base64** : lors de l'ajout ou la modification de documents, les fichiers joints doivent être encodés en base64 dans le champ `FileContentBase64`. Seul le contenu du fichier est encodé, pas le nom ni la description. + +9. **Déduplication des colonnes** : l'endpoint `column_list` retourne chaque colonne en double. L'application effectue une déduplication automatique, mais si vous interrogez l'API directement, vous devez gérer ce doublon. + +10. **Correspondance positionnelle des tableaux** : dans `document_add` et `document_mod`, les tableaux `Artid`, `Qty`, `Saleprice`, `Discount`, `Vatid` et `Vatpc` fonctionnent par correspondance positionnelle. Assurez-vous que tous les tableaux ont la même longueur. + +11. **Timeout** : certaines requêtes peuvent être lentes selon le volume de données. Le timeout par défaut est configuré à 300 secondes. En cas de timeout, vérifiez la configuration `LOGISTICS_API_TIMEOUT`. --- -## Ressources externes +## 10. Ressources externes - [Documentation Postman](https://documenter.getpostman.com/view/40440561/2sB2qaj2Pz) diff --git a/memory-bank/README.md b/memory-bank/README.md index 44879ff..2751ad1 100644 --- a/memory-bank/README.md +++ b/memory-bank/README.md @@ -1,24 +1,28 @@ # Memory Bank -Derniere mise a jour : 2026-02-20 +Dernière mise à jour : 2026-02-20 -## Presentation +## Présentation -Ce dossier contient le Memory Bank du projet API Logistics. Il sert de source de verite pour que l'IA (Cursor) conserve le contexte du projet entre les sessions. +Ce dossier contient le Memory Bank du projet API Logistics. Il sert de source de vérité pour que l'IA (Cursor) conserve le contexte du projet entre les sessions. ## Structure | Fichier | Description | |---------|-------------| -| `projectbrief.md` | Vision, objectifs et perimetre du projet | -| `productContext.md` | Contexte produit, problemes resolus, experience utilisateur | -| `techContext.md` | Stack technique, API Logistics, dependances, configuration | -| `systemPatterns.md` | Architecture, patterns, structure des repertoires, conventions | -| `activeContext.md` | Travail en cours, decisions recentes, prochaines etapes | -| `progress.md` | Avancement, ce qui fonctionne, ce qui reste a faire, metriques | +| `projectbrief.md` | Vision, objectifs et périmètre du projet | +| `productContext.md` | Contexte produit, problèmes résolus, expérience utilisateur | +| `techContext.md` | Stack technique, API Logistics, dépendances, configuration | +| `systemPatterns.md` | Architecture, patterns, structure des répertoires, conventions, système de design | +| `activeContext.md` | Travail en cours, décisions récentes, prochaines étapes | +| `progress.md` | Avancement, ce qui fonctionne, ce qui reste à faire, métriques | ## Utilisation -- **Lecture automatique** : La regle Cursor `.cursor/rules/memory-bank.mdc` est configuree avec `alwaysApply: true`. L'IA lit ces fichiers a chaque session. -- **Mise a jour** : Dire **"update memory bank"** dans le chat pour que l'IA relise le code source et mette a jour tous les fichiers. -- **Quand mettre a jour** : Apres chaque changement significatif (nouvelle fonctionnalite, changement d'architecture, correction de bug, nouvelle dependance). +- **Lecture automatique** : La règle Cursor `.cursor/rules/memory-bank.mdc` est configurée avec `alwaysApply: true`. L'IA lit ces fichiers à chaque session. +- **Mise à jour** : Dire **"update memory bank"** dans le chat pour que l'IA relise le code source et mette à jour tous les fichiers. +- **Quand mettre à jour** : Après chaque changement significatif (nouvelle fonctionnalité, changement d'architecture, correction de bug, nouvelle dépendance). + +## Convention d'écriture + +Tous les fichiers du projet (documentation, memory bank, règles Cursor) doivent être rédigés en français avec les accents appropriés. diff --git a/memory-bank/activeContext.md b/memory-bank/activeContext.md index dc01c2f..bdee980 100644 --- a/memory-bank/activeContext.md +++ b/memory-bank/activeContext.md @@ -1,44 +1,79 @@ # Active Context -Derniere mise a jour : 2026-02-20 +Dernière mise à jour : 2026-02-20 ## Travail en cours -Aucun travail en cours. Les ameliorations de robustesse du service API sont terminees. +Aucun travail en cours. -## Decisions recentes +## Décisions récentes -- **Filament v5 sans authentification** : Le `AdminPanelProvider` a ete configure sans `->login()` et sans `authMiddleware` pour permettre un acces libre au dashboard. -- **Pages personnalisees plutot que Resources** : L'application interroge une API externe, il n'y a pas de modeles Eloquent a gerer en CRUD. Les pages Filament utilisent des vues Blade avec des formulaires Livewire. -- **MySQL au lieu de SQLite** : Choix de l'utilisateur pour la base de donnees. -- **LogisticsService** : Toutes les interactions avec l'API sont centralisees dans un seul service pour faciliter la maintenance et le tracage. +- **Convention d'écriture avec accents** (2026-02-20) : Tous les contenus rédigés en français (documentation, memory bank, règles Cursor) doivent utiliser les accents appropriés. La documentation API et le memory bank ont été entièrement réécrits avec les accents. +- **Page Documentation ajoutée** (2026-02-20) : Nouvelle page Filament `Documentation` qui affiche le fichier markdown `documentation/documentation_api_logistics.md` converti en HTML via `Str::markdown()`. Actions d'en-tête : télécharger en PDF et ouvrir dans un nouvel onglet. +- **Styles prose personnalisés** (2026-02-20) : Le thème CSS Filament (`theme.css`) a été enrichi avec des styles `.documentation-prose` dédiés au rendu du markdown en dark mode : hiérarchie de titres avec bordures, tableaux avec bordures et en-têtes stylisés, blocs de code avec fond sombre, code inline coloré, liens bleus, listes à marqueurs, séparateurs visibles. +- **Plugin @tailwindcss/typography** (2026-02-20) : Ajout du plugin via `@plugin "@tailwindcss/typography"` dans le thème Filament pour activer les classes `prose`. +- **Export PDF de la documentation** (2026-02-20) : Route `documentation.download-pdf` dans `routes/web.php` utilisant `barryvdh/laravel-dompdf` pour générer un PDF téléchargeable de la documentation. +- **Règle update-documentation** (2026-02-20) : Nouvelle règle Cursor `.cursor/rules/update-documentation.mdc` définissant la procédure de mise à jour de la documentation quand l'utilisateur dit "update documentation". +- **Filament v5 sans authentification** : Le `AdminPanelProvider` a été configuré sans `->login()` et sans `authMiddleware` pour permettre un accès libre au dashboard. +- **Pages personnalisées plutôt que Resources** : L'application interroge une API externe, il n'y a pas de modèles Eloquent à gérer en CRUD. +- **MySQL au lieu de SQLite** : Choix de l'utilisateur pour la base de données. +- **LogisticsService** : Toutes les interactions avec l'API sont centralisées dans un seul service. - **Heroicon enum** : Filament v5 impose l'utilisation de `BackedEnum` pour `$navigationIcon` au lieu de strings. -- **$view non-static** : Filament v5 a change `$view` de static a instance property. -- **Timeout et retry configurables** (2026-02-20) : Les parametres `timeout`, `connect_timeout`, `retry.times` et `retry.sleep_ms` sont desormais dans `config/logistics.php` et pilotes par des variables `.env`. Le retry ne se declenche que sur les `ConnectionException`. -- **LogisticsApiException** (2026-02-20) : Exception dediee creee pour distinguer les erreurs de connexion (API injoignable) des erreurs de requete generiques. Messages en francais. -- **Logging des echecs** (2026-02-20) : Les requetes echouees sont desormais aussi enregistrees dans `api_request_logs` avec `response_status = 0`. -- **Contrainte reseau** (2026-02-20) : Le serveur API `tse-10-test.esiweb.pro` est sur un reseau prive, accessible uniquement via Bureau a distance (RDP). L'application locale ne peut pas joindre l'API sans tunnel ou deploiement sur le reseau distant. +- **$view non-static** : Filament v5 a changé `$view` de static à instance property. +- **Timeout et retry configurables** : Les paramètres sont dans `config/logistics.php` et pilotés par `.env`. +- **LogisticsApiException** : Exception dédiée créée pour distinguer les erreurs de connexion des erreurs de requête génériques. +- **Logging des échecs** : Les requêtes échouées sont aussi enregistrées dans `api_request_logs` avec `response_status = 0`. +- **Système de design unifié** (2026-02-20) : Création de 10 composants Blade réutilisables dans `resources/views/components/logistics/` et d'une convention documentée dans `.cursor/rules/design-system.mdc`. +- **Thème Filament personnalisé** (2026-02-20) : Création de `resources/css/filament/admin/theme.css` enregistré dans `AdminPanelProvider` via `->viteTheme()`. +- **TablesExplorer amélioré** (2026-02-20) : Remplacement de `wire:then` (invalide) par une méthode `selectTable()`. Ajout de la déduplication des colonnes, d'un filtre de tables, de la propriété computed `filteredTables`, des labels de type (`getDataTypeLabel`), et du stockage des métadonnées. +- **Connectivité API résolue** (2026-02-20) : Le serveur API est accessible via `http://tse-10-test.esi.local` (réseau interne). Le timeout a été augmenté à 300s dans `.env`. -## Changements importants (2026-02-20) +## Changements récents (2026-02-20, session documentation) -- `LogisticsService` mis a jour : timeout, connectTimeout, retry, gestion d'erreur avec `LogisticsApiException`. -- `LogisticsApiException` creee dans `app/Exceptions/`. -- `config/logistics.php` etendu avec timeout et retry. -- `.env` et `.env.example` completes avec les nouvelles variables. -- Les 5 pages Filament mises a jour pour attraper `LogisticsApiException`. -- Tests passes de 8 a 12 (4 nouveaux tests pour timeout, exception, logging, contexte). +- Page Filament `Documentation` créée (`app/Filament/Pages/Documentation.php`). +- Vue Blade `resources/views/filament/pages/documentation.blade.php` créée. +- Documentation markdown réécrite intégralement avec accents français. +- Styles CSS `.documentation-prose` ajoutés dans `theme.css` (titres, tableaux, code, liens, listes). +- Plugin `@tailwindcss/typography` activé dans le thème Filament. +- Route PDF (`documentation.download-pdf`) ajoutée dans `routes/web.php`. +- Template PDF (`resources/views/pdf/documentation.blade.php`) créé. +- 5 tests Pest créés pour la page Documentation (`tests/Feature/DocumentationTest.php`). +- Règle Cursor `update-documentation.mdc` créée. +- Memory bank entièrement réécrit avec accents français. +- Total : 61 tests passent (165 assertions). -## Historique (2026-02-19) +## Historique -- Installation de Filament v5.0.0 (31 packages ajoutes). -- 5 pages Filament creees : TablesExplorer, Articles, Documents, Journaux, Tiers. -- `LogisticsService` cree avec 17 endpoints. -- Migration `api_request_logs` creee. -- 8 tests Pest ecrits et valides. +### 2026-02-20 (session design) -## Prochaines etapes +- 10 composants Blade créés dans `resources/views/components/logistics/`. +- Convention de design documentée dans `.cursor/rules/design-system.mdc`. +- 5 pages Filament refactorisées pour utiliser les composants du système de design. +- `TablesExplorer.php` amélioré : `selectTable()`, déduplication, filtre, computed property, métadonnées, labels de types. +- Thème Filament personnalisé créé (`resources/css/filament/admin/theme.css`). +- `AdminPanelProvider.php` mis à jour avec `->viteTheme()`. +- 6 tests Pest créés pour `TablesExplorer` (Livewire). -- Deployer l'application sur le reseau distant (serveur accessible via RDP) ou mettre en place un tunnel SSH/VPN pour que l'application puisse joindre l'API. -- Tester le dashboard avec de vraies donnees API une fois la connectivite reseau resolue. -- Eventuellement : ajouter des pages pour les endpoints d'ecriture (document_add, document_mod). -- Eventuellement : ameliorer l'affichage des resultats (pagination, formatage). +### 2026-02-20 (session robustesse) + +- `LogisticsService` mis à jour : timeout, connectTimeout, retry, gestion d'erreur avec `LogisticsApiException`. +- `LogisticsApiException` créée dans `app/Exceptions/`. +- `config/logistics.php` étendu avec timeout et retry. +- `.env` et `.env.example` complétés avec les nouvelles variables. +- Les 5 pages Filament mises à jour pour attraper `LogisticsApiException`. +- Tests passés de 8 à 12. + +### 2026-02-19 + +- Installation de Filament v5.0.0 (31 packages ajoutés). +- 5 pages Filament créées : TablesExplorer, Articles, Documents, Journaux, Tiers. +- `LogisticsService` créé avec 17 endpoints. +- Migration `api_request_logs` créée. +- 8 tests Pest écrits et validés. + +## Prochaines étapes + +- Tester toutes les pages avec de vraies données API et vérifier le rendu visuel. +- Éventuellement : ajouter des pages pour les endpoints d'écriture (document_add, document_mod). +- Éventuellement : ajouter de la pagination ou du tri côté client pour les grands tableaux. +- Éventuellement : ajouter une page de consultation des logs API. diff --git a/memory-bank/productContext.md b/memory-bank/productContext.md index fc30190..a31f94c 100644 --- a/memory-bank/productContext.md +++ b/memory-bank/productContext.md @@ -1,30 +1,33 @@ # Product Context -Derniere mise a jour : 2026-02-20 +Dernière mise à jour : 2026-02-20 ## Pourquoi ce projet existe -L'API Logistics (Flex/ESI Gescom) est un systeme de gestion commerciale accessible via une API REST. La documentation officielle est limitee. Ce projet a ete cree pour : +L'API Logistics (Flex/ESI Gescom) est un système de gestion commerciale accessible via une API REST. La documentation officielle est limitée. Ce projet a été créé pour : -- Explorer les endpoints disponibles de maniere interactive. -- Comprendre les parametres attendus et les formats de reponse. -- Servir de base pour une documentation plus complete. +- Explorer les endpoints disponibles de manière interactive. +- Comprendre les paramètres attendus et les formats de réponse. +- Servir de base pour une documentation plus complète. -## Problemes resolus +## Problèmes résolus -- **Exploration de l'API** : Le dashboard permet de tester chaque endpoint avec des parametres personnalisables, sans avoir besoin de Postman. -- **Comprehension de la structure** : La page "Tables" permet de decouvrir les tables et colonnes disponibles dans l'API. -- **Tracabilite** : Chaque requete effectuee (reussie ou echouee) est enregistree dans `api_request_logs` pour pouvoir analyser les echanges. -- **Resilience** : Les erreurs de connexion sont gerees avec retry automatique et messages explicites en francais. +- **Exploration de l'API** : Le dashboard permet de tester chaque endpoint avec des paramètres personnalisables, sans avoir besoin de Postman. +- **Compréhension de la structure** : La page "Tables" permet de découvrir les tables et colonnes disponibles dans l'API, avec déduplication automatique des colonnes retournées en double par l'API. +- **Documentation intégrée** : La page "Documentation" affiche le markdown de la documentation API avec un rendu stylisé (typographie, tableaux, blocs de code) et propose un export PDF. +- **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. +- **Cohérence visuelle** : Un système de design unifié (composants `x-logistics.*`) garantit une présentation homogène sur toutes les pages. -## Experience utilisateur +## Expérience utilisateur -L'utilisateur accede au dashboard Filament sur `http://api-logistics.test/admin`. La navigation laterale propose 5 pages : +L'utilisateur accède au dashboard Filament sur `http://api-logistics.test/admin`. La navigation latérale propose 6 pages : -1. **Tables** : Cliquer sur une table pour voir ses colonnes. Utile pour connaitre les champs disponibles dans les parametres `select`. -2. **Articles** : Formulaire de recherche (search, select, results) + verification du stock d'un article par son ARTID. -3. **Documents** : Recherche par tiers (thirdid) + consultation du detail d'un document (jnl + number). -4. **Journaux** : Recherche par type de journal (TYPE). -5. **Tiers** : Recherche de tiers (search obligatoire) + historique des articles d'un tiers. +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. Rendu avec typographie soignée (titres hiérarchisés, tableaux bordés, blocs de code colorés, liens bleus). +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 (Caractère, Numérique, Date/Heure, Logique, Mémo). +3. **Articles** : Formulaire de recherche (search, select, results) + vérification du stock d'un article par son ARTID. Résultats en tableau structuré, stock en JSON formaté. +4. **Documents** : Recherche par tiers (thirdid) + consultation du détail d'un document (jnl + number). Détail en JSON formaté. +5. **Journaux** : Recherche par type de journal (TYPE). Résultats en tableau structuré. +6. **Tiers** : Recherche de tiers (search obligatoire) + historique des articles d'un tiers. Historique en JSON formaté. -Chaque page affiche les resultats sous forme de tableau dynamique et les metadonnees de la reponse (nombre de resultats, succes). En cas d'erreur de connexion a l'API, un message clair en francais est affiche a l'utilisateur. +Toutes les pages utilisent le même système de design : cartes à en-tête séparé, badges de compteur, indicateurs de chargement sur les actions réseau, et états vides avec icônes explicatives. En cas d'erreur API, un bandeau rouge s'affiche avec le message en français. diff --git a/memory-bank/progress.md b/memory-bank/progress.md index 3fb0665..232cdae 100644 --- a/memory-bank/progress.md +++ b/memory-bank/progress.md @@ -1,43 +1,55 @@ # Progress -Derniere mise a jour : 2026-02-20 +Dernière mise à jour : 2026-02-20 ## Ce qui fonctionne -- [x] Projet Laravel 12 initialise (livewire-starter-kit) -- [x] Livewire 4 + Flux UI Free v2 installes -- [x] Fortify installe (authentification existante, non utilisee par Filament) -- [x] Documentation API redigee (`documentation/WEB-A-1 (3).md`, `documentation/result.pdf`) -- [x] Memory bank cree et structure (`memory-bank/`, `.cursor/rules/memory-bank.mdc`) +- [x] Projet Laravel 12 initialisé (livewire-starter-kit) +- [x] Livewire 4 + Flux UI Free v2 installés +- [x] Fortify installé (authentification existante, non utilisée par Filament) +- [x] Documentation API rédigée avec accents (`documentation/documentation_api_logistics.md`) +- [x] Memory bank créé et structuré (`memory-bank/`, `.cursor/rules/memory-bank.mdc`) - [x] Configuration API Logistics (`.env`, `config/logistics.php`) avec timeout et retry -- [x] `LogisticsService` cree (`app/Services/LogisticsService.php`) avec 17 methodes, timeout, retry, gestion d'erreur -- [x] `LogisticsApiException` creee (`app/Exceptions/LogisticsApiException.php`) avec messages francais -- [x] Migration `api_request_logs` creee -- [x] Filament v5.0.0 installe et configure sans authentification -- [x] 5 pages Filament creees : TablesExplorer, Articles, Documents, Journaux, Tiers -- [x] 5 vues Blade associees dans `resources/views/filament/pages/` +- [x] `LogisticsService` créé (`app/Services/LogisticsService.php`) avec 17 méthodes, timeout, retry, gestion d'erreur +- [x] `LogisticsApiException` créée (`app/Exceptions/LogisticsApiException.php`) avec messages français +- [x] Migration `api_request_logs` créée +- [x] Filament v5.0.0 installé et configuré sans authentification +- [x] 6 pages Filament créées : Documentation, TablesExplorer, Articles, Documents, Journaux, Tiers +- [x] 6 vues Blade associées dans `resources/views/filament/pages/` - [x] Gestion d'erreur dans toutes les pages Filament (LogisticsApiException + Throwable) -- [x] Logging des requetes API reussies et echouees dans `api_request_logs` -- [x] 12 tests Pest pour LogisticsService (tous passent) -- [x] `README.md` cree -- [x] Formatage Pint valide +- [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] Convention de design documentée dans `.cursor/rules/design-system.mdc` +- [x] Toutes les pages Filament refactorisées avec les composants `x-logistics.*` +- [x] Thème Filament personnalisé (`resources/css/filament/admin/theme.css`) +- [x] Plugin `@tailwindcss/typography` activé pour le rendu prose +- [x] Styles `.documentation-prose` personnalisés pour le dark mode (titres, tableaux, code, liens) +- [x] TablesExplorer amélioré : selectTable, déduplication colonnes, filtre, badges de types +- [x] Page Documentation avec rendu markdown stylisé et export PDF +- [x] Connectivité API fonctionnelle (serveur `tse-10-test.esi.local`) +- [x] Convention d'écriture avec accents français appliquée +- [x] 61 tests Pest (tous passent) +- [x] `README.md` créé +- [x] Formatage Pint validé - [x] CI GitHub Actions (lint + tests) -## Ce qui reste a faire +## Ce qui reste à faire -- [ ] Resoudre la connectivite reseau : deployer sur le reseau distant ou mettre en place un tunnel -- [ ] Tester le dashboard avec de vraies donnees API -- [ ] Eventuellement : pages d'ecriture (document_add, document_mod) -- [ ] Eventuellement : ameliorer l'affichage des resultats (pagination, formatage) +- [ ] Vérifier le rendu visuel de toutes les pages avec de vraies données API +- [ ] Éventuellement : pages d'écriture (document_add, document_mod) +- [ ] Éventuellement : pagination / tri côté client pour les grands tableaux +- [ ] Éventuellement : page de consultation des logs API -## Problemes connus +## Problèmes connus -- **API injoignable depuis la machine locale** : Le serveur `tse-10-test.esiweb.pro` est sur un reseau prive accessible uniquement via Bureau a distance (RDP). L'application locale recoit `cURL error 28: Connection timed out`. Solution : deployer sur le reseau distant ou creer un tunnel SSH/VPN. -- L'erreur `SQLSTATE[HY000] [1049] Unknown database` peut apparaitre lors de `composer update` si la base n'est pas encore creee (script `boost:update`). Sans impact une fois la base creee. +- 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. -## Metriques +## Métriques -- Tests : 12 (tous passent, 18 assertions) -- Pages Filament : 5 +- Tests : 61 (tous passent, 165 assertions) +- Pages Filament : 6 (Documentation, TablesExplorer, Articles, Documents, Journaux, Tiers) +- Composants Blade design system : 10 - Endpoints API couverts par LogisticsService : 17 - Migrations : 5 (users, cache, jobs, two_factor, api_request_logs) +- Règles Cursor : 4 (laravel-boost, memory-bank, design-system, update-documentation) diff --git a/memory-bank/projectbrief.md b/memory-bank/projectbrief.md index 038f761..34417ee 100644 --- a/memory-bank/projectbrief.md +++ b/memory-bank/projectbrief.md @@ -1,36 +1,42 @@ # Project Brief -Derniere mise a jour : 2026-02-20 +Dernière mise à jour : 2026-02-20 ## Vision -Application Laravel de test dont l'objectif est de comprendre le fonctionnement de l'API Logistics (Flex/ESI Gescom) et d'en produire une documentation complete et comprehensible. +Application Laravel de test dont l'objectif est de comprendre le fonctionnement de l'API Logistics (Flex/ESI Gescom) et d'en produire une documentation complète et compréhensible. ## Objectifs 1. Comprendre le fonctionnement de l'API Logistics. -2. Creer une application simple permettant d'envoyer et de recuperer des donnees vers/depuis l'API. -3. Produire une documentation complete et comprehensible de l'API. +2. Créer une application simple permettant d'envoyer et de récupérer des données vers/depuis l'API. +3. Produire une documentation complète et compréhensible de l'API. -## Perimetre fonctionnel +## Périmètre fonctionnel - Dashboard Filament v5 accessible sans authentification sur `/admin`. -- Pages de consultation pour les principales entites de l'API : tables, articles, documents, journaux, tiers. -- Formulaires de recherche parametrables pour chaque endpoint. -- Affichage des resultats bruts retournes par l'API. -- Tracage des requetes effectuees dans une table `api_request_logs`. -- Gestion robuste des erreurs API (timeout, retry, messages utilisateur en francais). +- Pages de consultation pour les principales entités de l'API : tables, articles, documents, journaux, tiers. +- Page de documentation intégrée avec rendu stylisé du markdown et export PDF. +- Formulaires de recherche paramétrables pour chaque endpoint. +- 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.*`). +- 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). ## Contraintes - Pas d'authentification sur le dashboard (projet de test interne). -- L'API Logistics est hebergee sur le serveur TSE-10-TEST (`http://tse-10-test.esiweb.pro`). -- Le serveur API est accessible uniquement via le reseau interne (connexion Bureau a distance / RDP requise). L'application doit etre deployee sur ce reseau ou un tunnel doit etre mis en place. -- Toutes les requetes API sont en POST et necessitent un header `X-API-KEY`. -- Le nom du dossier dans les URLs de l'API doit etre en minuscules. +- L'API Logistics est hébergée sur le serveur TSE-10-TEST (`http://tse-10-test.esi.local`). +- Le serveur API est accessible via le réseau interne. +- Toutes les requêtes API sont en POST et nécessitent un header `X-API-KEY`. +- Le nom du dossier dans les URLs de l'API doit être en minuscules. + +## Convention d'écriture + +Tous les contenus rédigés en français (documentation, memory bank, règles Cursor, commentaires) doivent utiliser les accents appropriés. ## Ressources - Documentation Postman : https://documenter.getpostman.com/view/40440561/2sB2qaj2Pz -- Documentation interne : `documentation/WEB-A-1 (3).md` et `documentation/result.pdf` +- Documentation interne : `documentation/documentation_api_logistics.md` - Fichier projet : `project.md` diff --git a/memory-bank/systemPatterns.md b/memory-bank/systemPatterns.md index dfa459e..bfa0473 100644 --- a/memory-bank/systemPatterns.md +++ b/memory-bank/systemPatterns.md @@ -1,6 +1,6 @@ # System Patterns -Derniere mise a jour : 2026-02-20 +Dernière mise à jour : 2026-02-20 ## Architecture applicative @@ -17,72 +17,131 @@ Utilisateur --> Filament Dashboard (/admin) | (retry automatique sur ConnectionException) | +---> api_request_logs (MySQL) - | (succes ET echecs) + | (succès ET échecs) | +---> LogisticsApiException (en cas d'erreur) ``` -## Patterns utilises +## Patterns utilisés -### Service centralise +### Service centralisé -`App\Services\LogisticsService` encapsule tous les appels HTTP vers l'API Logistics. Chaque methode publique correspond a un endpoint. Le service : +`App\Services\LogisticsService` encapsule tous les appels HTTP vers l'API Logistics. Chaque méthode publique correspond à un endpoint. Le service : -- Construit l'URL a partir de `config('logistics.base_url')`, `config('logistics.folder')` et le nom de l'endpoint. +- Construit l'URL à partir de `config('logistics.base_url')`, `config('logistics.folder')` et le nom de l'endpoint. - Ajoute automatiquement le header `X-API-KEY`. - Configure `timeout()` et `connectTimeout()` depuis la config. -- Effectue un retry automatique (nombre et delai configurables) uniquement sur les `ConnectionException`. -- Enregistre chaque requete dans la table `api_request_logs` (succes et echecs). -- Retourne un tableau PHP avec les cles `data`, `metadata`, `error`. -- Lance une `LogisticsApiException` en cas d'erreur de connexion ou de requete. +- Effectue un retry automatique (nombre et délai configurables) uniquement sur les `ConnectionException`. +- Enregistre chaque requête dans la table `api_request_logs` (succès et échecs). +- Retourne un tableau PHP avec les clés `data`, `metadata`, `error`. +- Lance une `LogisticsApiException` en cas d'erreur de connexion ou de requête. -### Exception dediee +### Exception dédiée -`App\Exceptions\LogisticsApiException` (etend `RuntimeException`) fournit : +`App\Exceptions\LogisticsApiException` (étend `RuntimeException`) fournit : -- Des messages d'erreur en francais lisibles par l'utilisateur. -- Des proprietes `endpoint` et `params` pour le contexte de l'erreur. -- Deux methodes statiques : `connectionTimeout()` (API injoignable) et `requestFailed()` (erreur de requete). +- Des messages d'erreur en français lisibles par l'utilisateur. +- Des propriétés `endpoint` et `params` pour le contexte de l'erreur. +- Deux méthodes statiques : `connectionTimeout()` (API injoignable) et `requestFailed()` (erreur de requête). -### Pages Filament personnalisees (pas de Resources) +### Pages Filament personnalisées (pas de Resources) L'application n'utilise pas de Resources Filament (pas de CRUD local). Chaque page Filament : -- Etend `Filament\Pages\Page`. -- Utilise des proprietes Livewire publiques pour les champs de formulaire. -- Appelle `LogisticsService` via `app(LogisticsService::class)` dans des methodes d'action (ex: `searchArticles()`). -- Attrape `LogisticsApiException` pour afficher un message clair, et `\Throwable` en fallback. -- Affiche les resultats dans des tableaux HTML dynamiques generes dans les vues Blade. +- Étend `Filament\Pages\Page`. +- Utilise des propriétés Livewire publiques pour les champs de formulaire. +- Appelle `LogisticsService` via `app(LogisticsService::class)` dans des méthodes d'action (ex: `searchArticles()`). +- Attrape `LogisticsApiException` en premier, puis `\Throwable` en fallback. +- Affiche les résultats via les composants du système de design `x-logistics.*`. -### Configuration externalisee +### Page Documentation -Les parametres de connexion a l'API (URL, cle, dossier, timeout, retry) sont dans `config/logistics.php` et lus depuis `.env`. +`App\Filament\Pages\Documentation` est une page spéciale qui : -## Structure des repertoires +- Lit le fichier `documentation/documentation_api_logistics.md` au montage. +- Convertit le markdown en HTML via `Str::markdown()`. +- Affiche le contenu dans une vue avec la classe CSS `.documentation-prose` pour un rendu stylisé. +- Propose deux actions d'en-tête : télécharger en PDF (via `barryvdh/laravel-dompdf`) et ouvrir dans un nouvel onglet. + +### Système de design (composants Blade) + +Convention documentée dans `.cursor/rules/design-system.mdc`. Tous les composants visuels réutilisables sont dans `resources/views/components/logistics/` : + +| Composant | Rôle | +|-----------|------| +| `` | Conteneur blanc arrondi avec ombre et anneau | +| `` | En-tête de section (titre, description, slot `actions`) | +| `` | Bandeau d'erreur API conditionnel | +| `` | Barre horizontale de métadonnées | +| `` | Élément individuel (icône + label + valeur) | +| `` | Tableau dynamique avec en-têtes auto-détectés et état vide | +| `` | État vide centré (icône + titre + description) | +| `` | Champ de recherche avec icône loupe intégrée | +| `` | Champ de formulaire (label + input) à espacement homogène | +| `` | Bloc JSON formaté avec bordure et fond adapté | + +Règles : +- Toujours utiliser les composants `x-logistics.*` au lieu de dupliquer les classes CSS. +- Un `` n'a pas de padding interne. Le padding est géré par les enfants (`
`). +- Le `` est le premier enfant d'une carte et crée une bordure de séparation. +- Toutes les actions réseau doivent avoir un indicateur de chargement (`wire:loading`). + +### Thème Filament personnalisé + +Le panel Filament utilise un thème CSS personnalisé (`resources/css/filament/admin/theme.css`) enregistré via `->viteTheme()` dans `AdminPanelProvider`. Ce thème : + +- Importe le CSS de base Filament. +- Active le plugin `@tailwindcss/typography` pour les classes `prose`. +- Scanne les fichiers `app/Filament/**/*`, `resources/views/filament/**/*`, et `resources/views/components/logistics/**/*` pour inclure les classes Tailwind utilisées dans les composants. +- Contient des styles CSS personnalisés pour la classe `.documentation-prose` : hiérarchie de titres (h1-h4 avec bordures), tableaux avec bordures et en-têtes stylisés, blocs de code avec fond sombre, code inline avec fond distinct, liens colorés, listes avec marqueurs, séparateurs horizontaux visibles. + +Après tout ajout de nouvelles classes Tailwind dans ces fichiers, il faut exécuter `npm run build`. + +### Configuration externalisée + +Les paramètres de connexion à l'API (URL, clé, dossier, timeout, retry) sont dans `config/logistics.php` et lus depuis `.env`. + +## Structure des répertoires ``` app/ Exceptions/ - LogisticsApiException.php # Exception dediee API + LogisticsApiException.php # Exception dédiée API Filament/ Pages/ Articles.php # Recherche articles + stock - Documents.php # Recherche documents + detail + Dashboard.php # Page d'accueil + Documentation.php # Documentation API (markdown -> HTML) + Documents.php # Recherche documents + détail Journaux.php # Recherche journaux - TablesExplorer.php # Exploration tables + colonnes + TablesExplorer.php # Exploration tables + colonnes (filtre, déduplication, types) Tiers.php # Recherche tiers + historique Models/ - User.php # Modele utilisateur (Fortify) + User.php # Modèle utilisateur (Fortify) Providers/ Filament/ - AdminPanelProvider.php # Configuration du panel (sans auth) + AdminPanelProvider.php # Configuration du panel (sans auth, viteTheme) FortifyServiceProvider.php # Authentification Fortify AppServiceProvider.php # Config globale (CarbonImmutable, DB safety) Services/ - LogisticsService.php # Service centralise API Logistics + LogisticsService.php # Service centralisé API Logistics config/ - logistics.php # Configuration API Logistics (URL, cle, timeout, retry) + logistics.php # Configuration API Logistics (URL, clé, timeout, retry) + +documentation/ + documentation_api_logistics.md # Documentation complète de l'API (avec accents) + +resources/ + css/ + app.css # CSS principal (Tailwind 4, Flux UI) + filament/admin/ + theme.css # Thème Filament personnalisé (Tailwind 4 + Typography + prose) + views/ + components/logistics/ # 10 composants du système de design + filament/pages/ # 6 vues de pages Filament + pdf/ + documentation.blade.php # Template PDF pour la documentation database/ migrations/ @@ -92,23 +151,32 @@ database/ ...add_two_factor_columns_to_users_table.php ...create_api_request_logs_table.php -resources/views/ - filament/pages/ - articles.blade.php - documents.blade.php - journaux.blade.php - tables-explorer.blade.php - tiers.blade.php - tests/Feature/ - LogisticsServiceTest.php # 12 tests avec mocks HTTP + DocumentationTest.php # 5 tests page Documentation (Livewire + PDF) + LogisticsServiceTest.php # 12 tests service API (mocks HTTP) + TablesExplorerTest.php # 6 tests page TablesExplorer (Livewire) + FilamentDashboardTest.php # Tests dashboard Filament + DashboardTest.php # Tests dashboard + ExampleTest.php # Test d'exemple Laravel + +routes/ + web.php # Routes web (home, dashboard, documentation PDF) + +.cursor/rules/ + design-system.mdc # Convention de design (composants, CSS, structure) + memory-bank.mdc # Gestion du memory bank + update-documentation.mdc # Procédure de mise à jour de la documentation + laravel-boost.mdc # Règles Laravel Boost ``` ## Conventions -- Filament v5 : les icones de navigation utilisent l'enum `Filament\Support\Icons\Heroicon` (pas de strings). -- Filament v5 : la propriete `$view` est non-static (`protected string $view`). -- Les proprietes statiques (`$navigationIcon`, `$navigationLabel`, `$title`, `$navigationSort`) restent static. +- Filament v5 : les icônes de navigation utilisent l'enum `Filament\Support\Icons\Heroicon` (pas de strings). +- Filament v5 : la propriété `$view` est non-static (`protected string $view`). +- Les propriétés statiques (`$navigationIcon`, `$navigationLabel`, `$title`, `$navigationSort`) restent static. - Les appels API passent toujours par `LogisticsService`, jamais directement par `Http::`. - Les pages Filament attrapent `LogisticsApiException` en premier, puis `\Throwable` en fallback. -- Les messages d'erreur affiches a l'utilisateur sont en francais. +- Les messages d'erreur affichés à l'utilisateur sont en français. +- 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. +- Tous les contenus rédigés en français doivent utiliser les accents appropriés. diff --git a/memory-bank/techContext.md b/memory-bank/techContext.md index ff49fa2..b790ef4 100644 --- a/memory-bank/techContext.md +++ b/memory-bank/techContext.md @@ -1,39 +1,51 @@ # Tech Context -Derniere mise a jour : 2026-02-20 +Dernière mise à jour : 2026-02-20 ## Stack technique -| Composant | Version | Role | +| Composant | Version | Rôle | |-----------|---------|------| | PHP | 8.4 | Langage serveur | | Laravel | 12 | Framework applicatif | | Filament | 5.0 | Panel admin / dashboard | -| Livewire | 4 | Composants reactifs | +| Livewire | 4 | Composants réactifs | | Flux UI Free | 2.9+ | Composants UI Livewire | -| Fortify | 1.30+ | Authentification (existant, non utilise par Filament) | +| Fortify | 1.30+ | Authentification (existant, non utilisé par Filament) | | Pest | 4.4+ | Framework de tests | -| MySQL | - | Base de donnees | -| Vite | - | Bundler frontend | -| Tailwind CSS | 4 | Framework CSS | +| MySQL | - | Base de données | +| Vite | 7.3 | Bundler frontend | +| Tailwind CSS | 4 | Framework CSS (via @tailwindcss/vite) | +| @tailwindcss/typography | 0.5.19 | Plugin prose pour le rendu markdown | +| barryvdh/laravel-dompdf | - | Génération PDF | -## Dependances principales (composer.json) +## Dépendances principales (composer.json) - `filament/filament: ^5.0` - `laravel/framework: ^12.0` - `livewire/livewire: ^4.0` - `livewire/flux: ^2.9.0` - `laravel/fortify: ^1.30` +- `barryvdh/laravel-dompdf` (export PDF de la documentation) + +## Frontend + +- Tailwind CSS 4 avec le plugin Vite `@tailwindcss/vite` +- Plugin `@tailwindcss/typography` (v0.5.19) pour le rendu prose du markdown +- Thème Filament personnalisé : `resources/css/filament/admin/theme.css` +- Le thème Filament scanne les sources : `app/Filament/**/*`, `resources/views/filament/**/*`, `resources/views/components/logistics/**/*` +- Le thème inclut des styles CSS personnalisés pour la classe `.documentation-prose` (titres, tableaux, blocs de code, liens, listes) optimisés pour le dark mode Filament +- Build : `npm run build` (recompile `app.css` et `theme.css`) ## Configuration -### Variables d'environnement specifiques +### Variables d'environnement spécifiques ``` -LOGISTICS_API_BASE_URL=http://tse-10-test.esiweb.pro -LOGISTICS_API_KEY= +LOGISTICS_API_BASE_URL=http://tse-10-test.esi.local +LOGISTICS_API_KEY= LOGISTICS_API_FOLDER=esigescom -LOGISTICS_API_TIMEOUT=30 +LOGISTICS_API_TIMEOUT=300 LOGISTICS_API_CONNECT_TIMEOUT=10 LOGISTICS_API_RETRY_TIMES=3 LOGISTICS_API_RETRY_SLEEP_MS=500 @@ -41,17 +53,17 @@ LOGISTICS_API_RETRY_SLEEP_MS=500 Fichier de config : `config/logistics.php` -| Cle de config | Variable .env | Defaut | Description | +| Clé de config | Variable .env | Défaut | Description | |---------------|---------------|--------|-------------| | `logistics.base_url` | `LOGISTICS_API_BASE_URL` | - | URL de base de l'API | -| `logistics.api_key` | `LOGISTICS_API_KEY` | - | Cle d'authentification | +| `logistics.api_key` | `LOGISTICS_API_KEY` | - | Clé d'authentification | | `logistics.folder` | `LOGISTICS_API_FOLDER` | - | Dossier dans l'URL | -| `logistics.timeout` | `LOGISTICS_API_TIMEOUT` | 30 | Timeout total de la requete (secondes) | +| `logistics.timeout` | `LOGISTICS_API_TIMEOUT` | 30 | Timeout total de la requête (secondes) | | `logistics.connect_timeout` | `LOGISTICS_API_CONNECT_TIMEOUT` | 10 | Timeout de connexion (secondes) | -| `logistics.retry.times` | `LOGISTICS_API_RETRY_TIMES` | 3 | Nombre de tentatives en cas d'echec de connexion | -| `logistics.retry.sleep_ms` | `LOGISTICS_API_RETRY_SLEEP_MS` | 500 | Delai entre les tentatives (ms) | +| `logistics.retry.times` | `LOGISTICS_API_RETRY_TIMES` | 3 | Nombre de tentatives en cas d'échec de connexion | +| `logistics.retry.sleep_ms` | `LOGISTICS_API_RETRY_SLEEP_MS` | 500 | Délai entre les tentatives (ms) | -### Base de donnees +### Base de données - Connexion : MySQL - Base : `logistics` @@ -61,26 +73,28 @@ Fichier de config : `config/logistics.php` ### Connexion -- Serveur : TSE-10-TEST (reseau prive, accessible uniquement via Bureau a distance / RDP) -- Base URL : `http://tse-10-test.esiweb.pro` +- Serveur : TSE-10-TEST (réseau privé) +- Base URL : `http://tse-10-test.esi.local` - Dossier : `esigescom` (minuscules obligatoires) - Authentification : Header `X-API-KEY` -- Methode : POST pour tous les endpoints -- Port HTTP : 5186 / Port HTTPS : 7126 +- Méthode : POST pour tous les endpoints -### Structure de reponse +### Structure de réponse ```json { - "data": "", + "data": "", "metadata": { "rowcount": 0, "issuccess": true }, "error": "" } ``` +Réponse `tables_list` : chaque table a `name` et `columnCount`. +Réponse `column_list` : chaque colonne a `name`, `dataType` (C/N/T/D/L/M), `length`, `precision`. Les colonnes sont retournées en double par l'API (dédupliquées côté client). + ### Endpoints -| Endpoint | Description | Parametres principaux | +| Endpoint | Description | Paramètres principaux | |----------|-------------|-----------------------| | `tables_list` | Liste des tables | - | | `column_list/{table}` | Colonnes d'une table | table (URL) | @@ -88,18 +102,29 @@ Fichier de config : `config/logistics.php` | `art_getstk` | Stock d'un article | ARTID | | `jnl_list` | Liste des journaux | select, results, TYPE | | `document_list` | Liste des documents | select, thirdid | -| `document_detail` | Detail d'un document | jnl, number | +| `document_detail` | Détail d'un document | jnl, number | | `document_add` | Ajout d'un document | ThirdId, Date, Artid[], Qty[], Saleprice[], JNL, ... | | `document_mod` | Modification d'un document | number, Thirdid, Artid[], Qty[], Saleprice[], JNL, ... | | `Document_GetStatusList` | Statuts d'un journal | jnl | | `Document_GetUnitPriceAndVat` | Prix et TVA | ARTID, QTY, JNL, THIRDID, DATE | -| `Document_GetDueDate` | Echeance | paydelay, date | +| `Document_GetDueDate` | Échéance | paydelay, date | | `Document_GetAttachListThumbnail` | Miniatures annexes | JNL, NUMBER | | `third_list` | Liste des tiers | select, results, search | | `third_GetArtHistory` | Historique articles tiers | thirdid | -| `getserialnumber` | Numero de serie | - | -| `codes_list` | Donnees par code | code | +| `getserialnumber` | Numéro de série | - | +| `codes_list` | Données par code | code | ### Tables accessibles -art, attach, barcode, category, codes, cust, docdet, dochead, docpay, file, hist, incodes, jnl, pers, price, stk +art (160 col.), attach (13), barcode (12), category (10), codes (50), cust (216), docdet (82), dochead (212), docpay (22), file (17), hist (50), incodes (24), jnl (155), pers (78), price (28), stk (20) + +### Types de colonnes (dataType) + +| Code | Label | Couleur badge | +|------|-------|---------------| +| C | Caractère | Bleu | +| N | Numérique | Vert (emerald) | +| T | Date/Heure | Violet | +| D | Date | Violet | +| L | Logique | Ambre | +| M | Mémo | Gris | diff --git a/package-lock.json b/package-lock.json index 258ca2a..35c0d3e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,14 +5,17 @@ "packages": { "": { "dependencies": { - "@tailwindcss/vite": "^4.1.11", + "@tailwindcss/typography": "^0.5.19", "autoprefixer": "^10.4.20", "axios": "^1.7.4", "concurrently": "^9.0.1", "laravel-vite-plugin": "^2.0", - "tailwindcss": "^4.0.7", "vite": "^7.0.4" }, + "devDependencies": { + "@tailwindcss/vite": "^4.2.0", + "tailwindcss": "^4.2.0" + }, "optionalDependencies": { "@rollup/rollup-linux-x64-gnu": "4.9.5", "@tailwindcss/oxide-linux-x64-gnu": "^4.0.1", @@ -439,6 +442,7 @@ "version": "0.3.13", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", @@ -449,6 +453,7 @@ "version": "2.3.5", "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, "license": "MIT", "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", @@ -459,6 +464,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, "license": "MIT", "engines": { "node": ">=6.0.0" @@ -468,12 +474,14 @@ "version": "1.5.5", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.31", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -809,6 +817,7 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.2.0.tgz", "integrity": "sha512-Yv+fn/o2OmL5fh/Ir62VXItdShnUxfpkMA4Y7jdeC8O81WPB8Kf6TT6GSHvnqgSwDzlB5iT7kDpeXxLsUS0T6Q==", + "dev": true, "license": "MIT", "dependencies": { "@jridgewell/remapping": "^2.3.5", @@ -824,6 +833,7 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.2.0.tgz", "integrity": "sha512-AZqQzADaj742oqn2xjl5JbIOzZB/DGCYF/7bpvhA8KvjUj9HJkag6bBuwZvH1ps6dfgxNHyuJVlzSr2VpMgdTQ==", + "dev": true, "license": "MIT", "engines": { "node": ">= 20" @@ -850,6 +860,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -866,6 +877,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -882,6 +894,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -898,6 +911,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -914,6 +928,7 @@ "cpu": [ "arm" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -930,6 +945,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -946,6 +962,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -978,6 +995,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1002,6 +1020,7 @@ "cpu": [ "wasm32" ], + "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -1023,6 +1042,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1039,6 +1059,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1048,10 +1069,23 @@ "node": ">= 20" } }, + "node_modules/@tailwindcss/typography": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.19.tgz", + "integrity": "sha512-w31dd8HOx3k9vPtcQh5QHP9GwKcgbMp87j58qi6xgiBnFFtKEAgCWnDw4qUT8aHwkCp8bKvb/KGKWWHedP0AAg==", + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "6.0.10" + }, + "peerDependencies": { + "tailwindcss": ">=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1" + } + }, "node_modules/@tailwindcss/vite": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.2.0.tgz", "integrity": "sha512-da9mFCaHpoOgtQiWtDGIikTrSpUFBtIZCG3jy/u2BGV+l/X1/pbxzmIUxNt6JWm19N3WtGi4KlJdSH/Si83WOA==", + "dev": true, "license": "MIT", "dependencies": { "@tailwindcss/node": "4.2.0", @@ -1319,6 +1353,18 @@ "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" } }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -1332,6 +1378,7 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "devOptional": true, "license": "Apache-2.0", "engines": { "node": ">=8" @@ -1367,6 +1414,7 @@ "version": "5.19.0", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.19.0.tgz", "integrity": "sha512-phv3E1Xl4tQOShqSte26C7Fl84EwUdZsyOuSSk9qtAGyyQs2s3jJzComh+Abf4g187lUUAvH+H26omrqia2aGg==", + "dev": true, "license": "MIT", "dependencies": { "graceful-fs": "^4.2.4", @@ -1622,6 +1670,7 @@ "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, "license": "ISC" }, "node_modules/has-flag": { @@ -1685,6 +1734,7 @@ "version": "2.6.1", "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", + "devOptional": true, "license": "MIT", "bin": { "jiti": "lib/jiti-cli.mjs" @@ -1713,6 +1763,7 @@ "version": "1.31.1", "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.31.1.tgz", "integrity": "sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ==", + "devOptional": true, "license": "MPL-2.0", "dependencies": { "detect-libc": "^2.0.3" @@ -1962,6 +2013,7 @@ "version": "0.30.21", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" @@ -2067,6 +2119,19 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/postcss-selector-parser": { + "version": "6.0.10", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", + "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", @@ -2226,6 +2291,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", + "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -2296,6 +2362,12 @@ "browserslist": ">= 4.21.0" } }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, "node_modules/vite": { "version": "7.3.1", "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz", diff --git a/package.json b/package.json index 688bea8..bc778da 100644 --- a/package.json +++ b/package.json @@ -7,17 +7,20 @@ "dev": "vite" }, "dependencies": { - "@tailwindcss/vite": "^4.1.11", + "@tailwindcss/typography": "^0.5.19", "autoprefixer": "^10.4.20", "axios": "^1.7.4", "concurrently": "^9.0.1", "laravel-vite-plugin": "^2.0", - "tailwindcss": "^4.0.7", "vite": "^7.0.4" }, "optionalDependencies": { "@rollup/rollup-linux-x64-gnu": "4.9.5", "@tailwindcss/oxide-linux-x64-gnu": "^4.0.1", "lightningcss-linux-x64-gnu": "^1.29.1" + }, + "devDependencies": { + "@tailwindcss/vite": "^4.2.0", + "tailwindcss": "^4.2.0" } } diff --git a/resources/css/filament/admin/theme.css b/resources/css/filament/admin/theme.css new file mode 100644 index 0000000..25c3a48 --- /dev/null +++ b/resources/css/filament/admin/theme.css @@ -0,0 +1,191 @@ +@import '../../../../vendor/filament/filament/resources/css/theme.css'; + +@plugin "@tailwindcss/typography"; + +@source '../../../../app/Filament/**/*'; +@source '../../../../resources/views/filament/**/*'; +@source '../../../../resources/views/components/logistics/**/*'; + +/* --- Documentation prose overrides (dark mode Filament) --- */ + +.documentation-prose { + --tw-prose-body: theme(--color-gray-300); + --tw-prose-headings: theme(--color-white); + --tw-prose-links: theme(--color-blue-400); + --tw-prose-bold: theme(--color-white); + --tw-prose-code: theme(--color-blue-300); + --tw-prose-hr: theme(--color-white/10); + --tw-prose-th-borders: theme(--color-white/10); + --tw-prose-td-borders: theme(--color-white/5); + line-height: 1.75; +} + +.documentation-prose h1 { + font-size: 1.75rem; + font-weight: 700; + letter-spacing: -0.025em; + padding-bottom: 0.75rem; + border-bottom: 1px solid oklch(from white l c h / 0.1); + margin-bottom: 1.5rem; +} + +.documentation-prose h2 { + font-size: 1.35rem; + font-weight: 600; + letter-spacing: -0.015em; + padding-bottom: 0.5rem; + border-bottom: 1px solid oklch(from white l c h / 0.07); + margin-top: 2.5rem; + margin-bottom: 1.25rem; +} + +.documentation-prose h3 { + font-size: 1.1rem; + font-weight: 600; + margin-top: 2rem; + margin-bottom: 0.75rem; +} + +.documentation-prose h4 { + font-size: 1rem; + font-weight: 600; + margin-top: 1.5rem; + margin-bottom: 0.5rem; + color: oklch(from white l c h / 0.85); +} + +.documentation-prose hr { + border-color: oklch(from white l c h / 0.1); + margin-top: 2rem; + margin-bottom: 2rem; +} + +.documentation-prose a { + color: oklch(0.7 0.15 250); + text-decoration: underline; + text-underline-offset: 2px; + transition: color 0.15s; +} + +.documentation-prose a:hover { + color: oklch(0.8 0.15 250); +} + +/* --- Tables --- */ + +.documentation-prose table { + width: 100%; + border-collapse: collapse; + font-size: 0.8125rem; + margin-top: 1rem; + margin-bottom: 1.5rem; + border: 1px solid oklch(from white l c h / 0.1); + border-radius: 0.5rem; + overflow: hidden; +} + +.documentation-prose thead { + background: oklch(from white l c h / 0.05); +} + +.documentation-prose thead tr { + border-bottom: 1px solid oklch(from white l c h / 0.1); +} + +.documentation-prose th { + padding: 0.625rem 0.75rem; + font-size: 0.75rem; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.05em; + color: oklch(from white l c h / 0.6); + text-align: left; + white-space: nowrap; +} + +.documentation-prose td { + padding: 0.5rem 0.75rem; + color: oklch(from white l c h / 0.75); + vertical-align: top; + border-top: 1px solid oklch(from white l c h / 0.05); +} + +.documentation-prose tbody tr:hover { + background: oklch(from white l c h / 0.03); +} + +/* --- Code blocks --- */ + +.documentation-prose pre { + background: oklch(0.15 0.005 260); + border: 1px solid oklch(from white l c h / 0.1); + border-radius: 0.5rem; + padding: 1rem 1.25rem; + overflow-x: auto; + font-size: 0.8125rem; + line-height: 1.6; + margin-top: 0.75rem; + margin-bottom: 1.25rem; +} + +.documentation-prose pre code { + background: transparent; + padding: 0; + border-radius: 0; + font-size: inherit; + color: oklch(0.75 0.05 200); +} + +.documentation-prose :not(pre) > code { + background: oklch(from white l c h / 0.08); + border: 1px solid oklch(from white l c h / 0.1); + border-radius: 0.25rem; + padding: 0.125rem 0.375rem; + font-size: 0.8125em; + color: oklch(0.78 0.1 250); + font-weight: 500; +} + +/* --- Lists --- */ + +.documentation-prose ol { + list-style-type: decimal; + padding-left: 1.5rem; +} + +.documentation-prose ul { + list-style-type: disc; + padding-left: 1.5rem; +} + +.documentation-prose li { + margin-top: 0.25rem; + margin-bottom: 0.25rem; +} + +.documentation-prose li::marker { + color: oklch(from white l c h / 0.4); +} + +/* --- Blockquotes --- */ + +.documentation-prose blockquote { + border-left: 3px solid oklch(0.6 0.15 250); + padding-left: 1rem; + color: oklch(from white l c h / 0.7); + font-style: italic; +} + +/* --- Strong / Bold --- */ + +.documentation-prose strong { + color: oklch(from white l c h / 0.95); + font-weight: 600; +} + +/* --- Paragraphs --- */ + +.documentation-prose p { + margin-top: 0.5rem; + margin-bottom: 0.75rem; +} diff --git a/resources/views/components/logistics/card.blade.php b/resources/views/components/logistics/card.blade.php new file mode 100644 index 0000000..0fc16d8 --- /dev/null +++ b/resources/views/components/logistics/card.blade.php @@ -0,0 +1,5 @@ +@props(['class' => '']) + +
class(['rounded-xl bg-white shadow-sm ring-1 ring-gray-950/5 dark:bg-gray-900 dark:ring-white/10', $class]) }}> + {{ $slot }} +
diff --git a/resources/views/components/logistics/data-table.blade.php b/resources/views/components/logistics/data-table.blade.php new file mode 100644 index 0000000..a97067f --- /dev/null +++ b/resources/views/components/logistics/data-table.blade.php @@ -0,0 +1,40 @@ +@props(['data', 'metadata' => null, 'emptyMessage' => 'Aucun resultat.', 'emptyIcon' => 'heroicon-o-inbox']) + +@if (count($data) > 0) + @php + $firstRow = reset($data); + $isAssociative = is_array($firstRow); + $headers = $isAssociative ? array_keys($firstRow) : []; + @endphp + +
+ + + + @if ($isAssociative) + @foreach ($headers as $key) + + @endforeach + @else + + @endif + + + + @foreach ($data as $row) + + @if ($isAssociative) + @foreach ($row as $value) + + @endforeach + @else + + @endif + + @endforeach + +
{{ $key }}Valeur
{{ is_array($value) ? json_encode($value) : $value }}{{ $row }}
+
+@else + +@endif diff --git a/resources/views/components/logistics/empty-state.blade.php b/resources/views/components/logistics/empty-state.blade.php new file mode 100644 index 0000000..0a97e26 --- /dev/null +++ b/resources/views/components/logistics/empty-state.blade.php @@ -0,0 +1,9 @@ +@props(['icon' => 'heroicon-o-inbox', 'title', 'description' => null]) + +
+ +

{{ $title }}

+ @if ($description) +

{{ $description }}

+ @endif +
diff --git a/resources/views/components/logistics/error-banner.blade.php b/resources/views/components/logistics/error-banner.blade.php new file mode 100644 index 0000000..f7599dc --- /dev/null +++ b/resources/views/components/logistics/error-banner.blade.php @@ -0,0 +1,7 @@ +@props(['message']) + +@if ($message) +
+ {{ $message }} +
+@endif diff --git a/resources/views/components/logistics/form-field.blade.php b/resources/views/components/logistics/form-field.blade.php new file mode 100644 index 0000000..6e79797 --- /dev/null +++ b/resources/views/components/logistics/form-field.blade.php @@ -0,0 +1,11 @@ +@props(['label', 'id', 'type' => 'text', 'placeholder' => '']) + +
+ + class(['mt-1.5 w-full rounded-lg border-gray-300 py-2 text-sm shadow-sm focus:border-primary-500 focus:ring-primary-500 dark:border-white/10 dark:bg-white/5 dark:text-white']) }} + type="{{ $type }}" + id="{{ $id }}" + placeholder="{{ $placeholder }}" + /> +
diff --git a/resources/views/components/logistics/json-block.blade.php b/resources/views/components/logistics/json-block.blade.php new file mode 100644 index 0000000..4232859 --- /dev/null +++ b/resources/views/components/logistics/json-block.blade.php @@ -0,0 +1,7 @@ +@props(['data']) + +@if (! empty($data)) +
+
{{ json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) }}
+
+@endif diff --git a/resources/views/components/logistics/search-input.blade.php b/resources/views/components/logistics/search-input.blade.php new file mode 100644 index 0000000..50d1629 --- /dev/null +++ b/resources/views/components/logistics/search-input.blade.php @@ -0,0 +1,10 @@ +@props(['placeholder' => 'Rechercher...']) + +
+ + class(['w-full rounded-lg border-gray-300 py-2 pl-9 pr-3 text-sm shadow-sm focus:border-primary-500 focus:ring-primary-500 dark:border-white/10 dark:bg-white/5 dark:text-white']) }} + type="text" + placeholder="{{ $placeholder }}" + /> +
diff --git a/resources/views/components/logistics/section-header.blade.php b/resources/views/components/logistics/section-header.blade.php new file mode 100644 index 0000000..f05ec7a --- /dev/null +++ b/resources/views/components/logistics/section-header.blade.php @@ -0,0 +1,15 @@ +@props(['title', 'description' => null]) + +
+
+
+

{{ $title }}

+ @if ($description) +

{{ $description }}

+ @endif +
+ @isset($actions) +
{{ $actions }}
+ @endisset +
+
diff --git a/resources/views/components/logistics/stat-bar.blade.php b/resources/views/components/logistics/stat-bar.blade.php new file mode 100644 index 0000000..e45db77 --- /dev/null +++ b/resources/views/components/logistics/stat-bar.blade.php @@ -0,0 +1,5 @@ + +
+ {{ $slot }} +
+
diff --git a/resources/views/components/logistics/stat-item.blade.php b/resources/views/components/logistics/stat-item.blade.php new file mode 100644 index 0000000..65a13bf --- /dev/null +++ b/resources/views/components/logistics/stat-item.blade.php @@ -0,0 +1,12 @@ +@props(['icon' => null, 'label' => null, 'value']) + +
+ @if ($icon) + + @endif + @if ($label) + {{ $label }} {{ $value }} + @else + {{ $value }} + @endif +
diff --git a/resources/views/filament/pages/articles.blade.php b/resources/views/filament/pages/articles.blade.php index a22aac3..fea8d2d 100644 --- a/resources/views/filament/pages/articles.blade.php +++ b/resources/views/filament/pages/articles.blade.php @@ -1,91 +1,89 @@ - @if ($errorMessage) -
- {{ $errorMessage }} -
- @endif + {{-- Formulaire de recherche --}} -
-

Rechercher des articles

+ + +
+
+ + + +
-
-
- - -
-
- - -
-
- - +
+ + Rechercher + +
+ + Recherche en cours... +
- -
- - Rechercher - -
-
+ {{-- Resultats --}} @if (count($data) > 0) -
-
-

Resultats

- @if ($metadata) - {{ $metadata['rowcount'] ?? 0 }} resultat(s) - @endif + + + + @if ($metadata) + + {{ $metadata['rowcount'] ?? 0 }} résultat(s) + + @endif + + +
+
- -
- - - - @foreach (array_keys(is_array(reset($data)) ? reset($data) : $data) as $key) - - @endforeach - - - - @foreach ($data as $row) - - @foreach ((is_array($row) ? $row : [$row]) as $value) - - @endforeach - - @endforeach - -
{{ $key }}
{{ is_array($value) ? json_encode($value) : $value }}
-
-
+ @endif {{-- Stock d'un article --}} -
-

Verifier le stock d'un article

- -
-
- - + + +
+
+
+ +
+ + Vérifier le stock + +
+ +
+ + Chargement... +
+ +
+
- - Verifier le stock -
- - @if (count($stockData) > 0) -
-
{{ json_encode($stockData, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) }}
-
- @endif -
+ diff --git a/resources/views/filament/pages/dashboard.blade.php b/resources/views/filament/pages/dashboard.blade.php new file mode 100644 index 0000000..8dda335 --- /dev/null +++ b/resources/views/filament/pages/dashboard.blade.php @@ -0,0 +1,170 @@ + + + {{-- En-tete de bienvenue --}} + +
+
+

+ Bienvenue sur API Logistics +

+

+ Application d'exploration de l'API Logistics (Flex/ESI Gescom). + Ce projet permet de tester les endpoints disponibles, comprendre les structures de données + et servir de base pour une documentation complète de l'API. +

+
+
+
+ + {{-- Navigation rapide --}} + + + + + + {{-- Informations techniques --}} + + +
+
+
+

Stack

+
+
+
Framework
+
Laravel 12
+
+
+
Panel admin
+
Filament 5
+
+
+
Composants réactifs
+
Livewire 4
+
+
+
CSS
+
Tailwind CSS 4
+
+
+
Tests
+
Pest 4
+
+
+
+
+

Connexion API

+
+
+
Serveur
+
tse-10-test.esi.local
+
+
+
Méthode
+
POST
+
+
+
Authentification
+
X-API-KEY
+
+
+
Timeout
+
{{ config('logistics.timeout', 30) }}s
+
+
+
Retry
+
{{ config('logistics.retry.times', 3) }} tentatives
+
+
+
+
+
+
+ +
diff --git a/resources/views/filament/pages/documentation.blade.php b/resources/views/filament/pages/documentation.blade.php new file mode 100644 index 0000000..93fa367 --- /dev/null +++ b/resources/views/filament/pages/documentation.blade.php @@ -0,0 +1,9 @@ + + +
+
+ {!! $htmlContent !!} +
+
+
+
diff --git a/resources/views/filament/pages/documents.blade.php b/resources/views/filament/pages/documents.blade.php index e036bab..b7272c5 100644 --- a/resources/views/filament/pages/documents.blade.php +++ b/resources/views/filament/pages/documents.blade.php @@ -1,93 +1,87 @@ - @if ($errorMessage) -
- {{ $errorMessage }} -
- @endif + {{-- Formulaire de recherche --}} -
-

Rechercher des documents

- -
-
- - + + +
+
+ +
-
- - + +
+ + Rechercher + +
+ + Recherche en cours... +
- -
- - Rechercher - -
-
+
{{-- Resultats --}} @if (count($data) > 0) -
-
-

Resultats

- @if ($metadata) - {{ $metadata['rowcount'] ?? 0 }} resultat(s) - @endif + + + + @if ($metadata) + + {{ $metadata['rowcount'] ?? 0 }} résultat(s) + + @endif + + +
+
- -
- - - - @foreach (array_keys(is_array(reset($data)) ? reset($data) : $data) as $key) - - @endforeach - - - - @foreach ($data as $row) - - @foreach ((is_array($row) ? $row : [$row]) as $value) - - @endforeach - - @endforeach - -
{{ $key }}
{{ is_array($value) ? json_encode($value) : $value }}
-
-
+ @endif {{-- Detail d'un document --}} -
-

Detail d'un document

+ + +
+
+ + +
+ + Voir le détail + +
+
-
-
- - +
+ + Chargement...
-
- - -
-
- - Voir le detail - + +
+
- - @if (count($detailData) > 0) -
-
{{ json_encode($detailData, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) }}
-
- @endif -
+ diff --git a/resources/views/filament/pages/journaux.blade.php b/resources/views/filament/pages/journaux.blade.php index e363431..fa243a3 100644 --- a/resources/views/filament/pages/journaux.blade.php +++ b/resources/views/filament/pages/journaux.blade.php @@ -1,69 +1,60 @@ - @if ($errorMessage) -
- {{ $errorMessage }} -
- @endif + {{-- Formulaire de recherche --}} -
-

Rechercher des journaux

+ + +
+
+ + + +
-
-
- - -
-
- - -
-
- - +
+ + Rechercher + +
+ + Recherche en cours... +
- -
- - Rechercher - -
-
+ {{-- Resultats --}} @if (count($data) > 0) -
-
-

Resultats

- @if ($metadata) - {{ $metadata['rowcount'] ?? 0 }} resultat(s) - @endif + + + + @if ($metadata) + + {{ $metadata['rowcount'] ?? 0 }} résultat(s) + + @endif + + +
+
- -
- - - - @foreach (array_keys(is_array(reset($data)) ? reset($data) : $data) as $key) - - @endforeach - - - - @foreach ($data as $row) - - @foreach ((is_array($row) ? $row : [$row]) as $value) - - @endforeach - - @endforeach - -
{{ $key }}
{{ is_array($value) ? json_encode($value) : $value }}
-
-
+ @endif diff --git a/resources/views/filament/pages/tables-explorer.blade.php b/resources/views/filament/pages/tables-explorer.blade.php index 731d0b5..49de53f 100644 --- a/resources/views/filament/pages/tables-explorer.blade.php +++ b/resources/views/filament/pages/tables-explorer.blade.php @@ -1,85 +1,148 @@ - @if ($errorMessage) -
- {{ $errorMessage }} -
+ + + @if ($tablesMetadata) + + + + + @endif -
- {{-- Liste des tables --}} -
-

Tables disponibles

-

Cliquez sur une table pour voir ses colonnes.

+
+ {{-- Panneau gauche : liste des tables --}} + + -
- @forelse ($tables as $table) + @if (count($tables) > 6) +
+ +
+ @endif + +
+ @forelse ($this->filteredTables as $table) + @php + $tableName = $table['name'] ?? ''; + $columnCount = $table['columnCount'] ?? 0; + $isSelected = $selectedTable === $tableName; + @endphp @empty -

Aucune table trouvee. Verifiez votre cle API.

+ @endforelse
-
+
- {{-- Colonnes de la table selectionnee --}} -
-

- Colonnes + {{-- Panneau droit : colonnes de la table selectionnee --}} + + + + @if ($columnsMetadata && $selectedTable) + + {{ $columnsMetadata['columnCount'] ?? count($columns) }} colonne(s) + + @endif + + + +
@if ($selectedTable) - : {{ $selectedTable }} - @endif -

- - @if ($selectedTable) -
-
- Chargement... +
+ + Chargement des colonnes...
-
+
@if (count($columns) > 0)
- - - @if (is_array(reset($columns))) - @foreach (array_keys(reset($columns)) as $key) - - @endforeach - @else - - @endif + + + + + + @foreach ($columns as $column) - - @if (is_array($column)) - @foreach ($column as $value) - - @endforeach - @else - - @endif + @php + $dataType = strtoupper($column['dataType'] ?? ''); + $typeLabel = \App\Filament\Pages\TablesExplorer::getDataTypeLabel($dataType); + @endphp + + + + + @endforeach
{{ $key }}Colonne
NomTypeLongueurPrécision
{{ is_array($value) ? json_encode($value) : $value }}{{ $column }}
+ {{ $column['name'] ?? '-' }} + + $dataType === 'C', + 'bg-emerald-50 text-emerald-700 ring-emerald-600/20 dark:bg-emerald-400/10 dark:text-emerald-400 dark:ring-emerald-400/30' => $dataType === 'N', + 'bg-violet-50 text-violet-700 ring-violet-600/20 dark:bg-violet-400/10 dark:text-violet-400 dark:ring-violet-400/30' => in_array($dataType, ['T', 'D']), + 'bg-amber-50 text-amber-700 ring-amber-600/20 dark:bg-amber-400/10 dark:text-amber-400 dark:ring-amber-400/30' => $dataType === 'L', + 'bg-gray-50 text-gray-700 ring-gray-600/20 dark:bg-gray-400/10 dark:text-gray-400 dark:ring-gray-400/30' => ! in_array($dataType, ['C', 'N', 'T', 'D', 'L']), + ])> + {{ $typeLabel }} + + {{ $column['length'] ?? '-' }}{{ $column['precision'] ?? '-' }}
@else -

Aucune colonne trouvee.

+ @endif
-
- @else -

Selectionnez une table pour afficher ses colonnes.

- @endif -
+ @else + + @endif +
+
diff --git a/resources/views/filament/pages/tiers.blade.php b/resources/views/filament/pages/tiers.blade.php index eb4cceb..7cbdd4a 100644 --- a/resources/views/filament/pages/tiers.blade.php +++ b/resources/views/filament/pages/tiers.blade.php @@ -1,91 +1,89 @@ - @if ($errorMessage) -
- {{ $errorMessage }} -
- @endif + {{-- Formulaire de recherche --}} -
-

Rechercher des tiers

+ + +
+
+ + + +
-
-
- - -
-
- - -
-
- - +
+ + Rechercher + +
+ + Recherche en cours... +
- -
- - Rechercher - -
-
+ {{-- Resultats --}} @if (count($data) > 0) -
-
-

Resultats

- @if ($metadata) - {{ $metadata['rowcount'] ?? 0 }} resultat(s) - @endif + + + + @if ($metadata) + + {{ $metadata['rowcount'] ?? 0 }} résultat(s) + + @endif + + +
+
- -
- - - - @foreach (array_keys(is_array(reset($data)) ? reset($data) : $data) as $key) - - @endforeach - - - - @foreach ($data as $row) - - @foreach ((is_array($row) ? $row : [$row]) as $value) - - @endforeach - - @endforeach - -
{{ $key }}
{{ is_array($value) ? json_encode($value) : $value }}
-
-
+ @endif {{-- Historique des articles d'un tiers --}} -
-

Historique des articles d'un tiers

- -
-
- - + + +
+
+
+ +
+ + Voir l'historique + +
+ +
+ + Chargement... +
+ +
+
- - Voir l'historique -
- - @if (count($historyData) > 0) -
-
{{ json_encode($historyData, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) }}
-
- @endif -
+ diff --git a/resources/views/pdf/documentation.blade.php b/resources/views/pdf/documentation.blade.php new file mode 100644 index 0000000..9223259 --- /dev/null +++ b/resources/views/pdf/documentation.blade.php @@ -0,0 +1,122 @@ + + + + + Documentation API Logistics + + + + {!! $content !!} + + diff --git a/routes/web.php b/routes/web.php index f755f11..569d2c9 100644 --- a/routes/web.php +++ b/routes/web.php @@ -1,6 +1,8 @@ middleware(['auth', 'verified']) ->name('dashboard'); +Route::get('/documentation/download-pdf', function () { + $markdown = file_get_contents(base_path('documentation/documentation_api_logistics.md')); + $htmlContent = Str::markdown($markdown); + + $html = view('pdf.documentation', ['content' => $htmlContent])->render(); + + return Pdf::loadHTML($html) + ->setPaper('a4') + ->download('documentation_api_logistics.pdf'); +})->name('documentation.download-pdf'); + require __DIR__.'/settings.php'; diff --git a/tests/Feature/DocumentationTest.php b/tests/Feature/DocumentationTest.php new file mode 100644 index 0000000..01792c5 --- /dev/null +++ b/tests/Feature/DocumentationTest.php @@ -0,0 +1,63 @@ +actingAs(User::factory()->create()); +}); + +it('renders the documentation page', function () { + Livewire::test(Documentation::class) + ->assertSuccessful() + ->assertSee('Documentation API Logistics'); +}); + +it('converts markdown to HTML content', function () { + $component = Livewire::test(Documentation::class); + + expect($component->get('htmlContent')) + ->toBeString() + ->not->toBeEmpty() + ->toContain('

') + ->toContain(''); +}); + +it('displays the main documentation sections', function () { + Livewire::test(Documentation::class) + ->assertSee('Pré-requis') + ->assertSee('Comment effectuer des requêtes') + ->assertSee('Structure de réponse') + ->assertSee('Tables et colonnes disponibles') + ->assertSee('Récupération de données') + ->assertSee('Envoi de données'); +}); + +it('downloads the documentation as PDF', function () { + $response = $this->get(route('documentation.download-pdf')); + + $response->assertSuccessful() + ->assertHeader('content-type', 'application/pdf'); +}); + +it('documents all service endpoints', function () { + Livewire::test(Documentation::class) + ->assertSee('tables_list') + ->assertSee('column_list') + ->assertSee('art_list') + ->assertSee('art_getstk') + ->assertSee('jnl_list') + ->assertSee('document_list') + ->assertSee('document_detail') + ->assertSee('document_add') + ->assertSee('document_mod') + ->assertSee('Document_GetStatusList') + ->assertSee('Document_GetUnitPriceAndVat') + ->assertSee('Document_GetDueDate') + ->assertSee('Document_GetAttachListThumbnail') + ->assertSee('third_list') + ->assertSee('third_GetArtHistory') + ->assertSee('getserialnumber') + ->assertSee('codes_list'); +}); diff --git a/tests/Feature/FilamentDashboardTest.php b/tests/Feature/FilamentDashboardTest.php new file mode 100644 index 0000000..9bd6e29 --- /dev/null +++ b/tests/Feature/FilamentDashboardTest.php @@ -0,0 +1,46 @@ +actingAs(User::factory()->create()); +}); + +it('renders the dashboard page', function () { + Livewire::test(Dashboard::class) + ->assertSuccessful(); +}); + +it('displays the project title and description', function () { + Livewire::test(Dashboard::class) + ->assertSee('Bienvenue sur API Logistics') + ->assertSee('Flex/ESI Gescom'); +}); + +it('shows navigation links to all pages', function () { + Livewire::test(Dashboard::class) + ->assertSee('Tables') + ->assertSee('Articles') + ->assertSee('Documents') + ->assertSee('Journaux') + ->assertSee('Tiers') + ->assertSee('Documentation'); +}); + +it('displays project statistics', function () { + Livewire::test(Dashboard::class) + ->assertSee('Endpoints API') + ->assertSee('Tables accessibles') + ->assertSee('Pages Filament') + ->assertSee('Tests Pest'); +}); + +it('shows technical information', function () { + Livewire::test(Dashboard::class) + ->assertSee('Informations techniques') + ->assertSee('Laravel 12') + ->assertSee('Filament 5') + ->assertSee('Livewire 4'); +}); diff --git a/tests/Feature/TablesExplorerTest.php b/tests/Feature/TablesExplorerTest.php new file mode 100644 index 0000000..9c6d960 --- /dev/null +++ b/tests/Feature/TablesExplorerTest.php @@ -0,0 +1,147 @@ + 'http://test-server.local', + 'logistics.api_key' => 'test-api-key', + 'logistics.folder' => 'testfolder', + 'logistics.timeout' => 30, + 'logistics.connect_timeout' => 10, + 'logistics.retry.times' => 1, + 'logistics.retry.sleep_ms' => 0, + ]); + + $this->actingAs(User::factory()->create()); +}); + +it('loads the tables list on mount', function () { + Http::fake([ + '*/tables_list' => Http::response([ + 'data' => [ + ['name' => 'art', 'columnCount' => 160], + ['name' => 'cust', 'columnCount' => 216], + ], + 'metadata' => ['tableCount' => 2, 'folderType' => 'DBF', 'endpoint' => 'test'], + 'error' => null, + ]), + ]); + + Livewire::test(TablesExplorer::class) + ->assertSet('tables', [ + ['name' => 'art', 'columnCount' => 160], + ['name' => 'cust', 'columnCount' => 216], + ]) + ->assertSee('art') + ->assertSee('cust') + ->assertSee('160') + ->assertSee('216'); +}); + +it('loads columns when a table is selected', function () { + Http::fake([ + '*/tables_list' => Http::response([ + 'data' => [['name' => 'stk', 'columnCount' => 10]], + 'metadata' => ['tableCount' => 1], + 'error' => null, + ]), + '*/column_list/stk' => Http::response([ + 'data' => [ + ['name' => 'ARTID', 'dataType' => 'C', 'length' => 20, 'precision' => 0], + ['name' => 'ARTID', 'dataType' => 'C', 'length' => 20, 'precision' => 0], + ['name' => 'STOCK', 'dataType' => 'N', 'length' => 10, 'precision' => 2], + ['name' => 'STOCK', 'dataType' => 'N', 'length' => 10, 'precision' => 2], + ], + 'metadata' => ['columnCount' => 4, 'tableName' => 'stk'], + 'error' => null, + ]), + ]); + + Livewire::test(TablesExplorer::class) + ->call('selectTable', 'stk') + ->assertSet('selectedTable', 'stk') + ->assertSee('ARTID') + ->assertSee('STOCK') + ->assertSee('Caractère') + ->assertSee('Numérique'); +}); + +it('deduplicates columns from the API response', function () { + Http::fake([ + '*/tables_list' => Http::response([ + 'data' => [['name' => 'stk', 'columnCount' => 4]], + 'metadata' => ['tableCount' => 1], + 'error' => null, + ]), + '*/column_list/stk' => Http::response([ + 'data' => [ + ['name' => 'ARTID', 'dataType' => 'C', 'length' => 20, 'precision' => 0], + ['name' => 'ARTID', 'dataType' => 'C', 'length' => 20, 'precision' => 0], + ['name' => 'STOCK', 'dataType' => 'N', 'length' => 10, 'precision' => 2], + ['name' => 'STOCK', 'dataType' => 'N', 'length' => 10, 'precision' => 2], + ], + 'metadata' => ['columnCount' => 4], + 'error' => null, + ]), + ]); + + Livewire::test(TablesExplorer::class) + ->call('selectTable', 'stk') + ->assertSet('columns', [ + ['name' => 'ARTID', 'dataType' => 'C', 'length' => 20, 'precision' => 0], + ['name' => 'STOCK', 'dataType' => 'N', 'length' => 10, 'precision' => 2], + ]); +}); + +it('filters tables by name', function () { + Http::fake([ + '*/tables_list' => Http::response([ + 'data' => [ + ['name' => 'art', 'columnCount' => 160], + ['name' => 'attach', 'columnCount' => 13], + ['name' => 'cust', 'columnCount' => 216], + ['name' => 'dochead', 'columnCount' => 212], + ['name' => 'docdet', 'columnCount' => 82], + ['name' => 'docpay', 'columnCount' => 22], + ['name' => 'stk', 'columnCount' => 20], + ], + 'metadata' => ['tableCount' => 7], + 'error' => null, + ]), + ]); + + $component = Livewire::test(TablesExplorer::class) + ->set('tableFilter', 'doc'); + + $filteredTables = $component->get('filteredTables'); + + expect($filteredTables)->toHaveCount(3) + ->and(array_column($filteredTables, 'name'))->toBe(['dochead', 'docdet', 'docpay']); +}); + +it('displays an error message when the API fails', function () { + Http::fake([ + '*/tables_list' => Http::response([ + 'data' => [], + 'metadata' => [], + 'error' => 'Invalid API key', + ]), + ]); + + Livewire::test(TablesExplorer::class) + ->assertSee('Invalid API key'); +}); + +it('shows data type labels correctly', function () { + expect(TablesExplorer::getDataTypeLabel('C'))->toBe('Caractère') + ->and(TablesExplorer::getDataTypeLabel('N'))->toBe('Numérique') + ->and(TablesExplorer::getDataTypeLabel('T'))->toBe('Date/Heure') + ->and(TablesExplorer::getDataTypeLabel('D'))->toBe('Date') + ->and(TablesExplorer::getDataTypeLabel('L'))->toBe('Logique') + ->and(TablesExplorer::getDataTypeLabel('M'))->toBe('Mémo') + ->and(TablesExplorer::getDataTypeLabel('X'))->toBe('X'); +}); diff --git a/vite.config.js b/vite.config.js index f65249e..a5a3e9b 100644 --- a/vite.config.js +++ b/vite.config.js @@ -7,7 +7,7 @@ import tailwindcss from "@tailwindcss/vite"; export default defineConfig({ plugins: [ laravel({ - input: ['resources/css/app.css', 'resources/js/app.js'], + input: ['resources/css/app.css', 'resources/js/app.js', 'resources/css/filament/admin/theme.css'], refresh: true, }), tailwindcss(),