From 5ccc3b30f04ccc35dbd888f483f4d458411a5844 Mon Sep 17 00:00:00 2001 From: Matthieu Date: Tue, 3 Feb 2026 17:34:43 +0100 Subject: [PATCH] docs : add comprehensive refactoring plan (backend + frontend) 14 phases, 39 tasks covering: - Backend: security, code duplication, controllers, storage, tests - Frontend: mega-component split, duplication, TypeScript migration, tests Includes agent tracking system with status, journal, and rules. Co-Authored-By: Claude Opus 4.5 --- REFACTORING_PLAN.md | 675 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 675 insertions(+) create mode 100644 REFACTORING_PLAN.md diff --git a/REFACTORING_PLAN.md b/REFACTORING_PLAN.md new file mode 100644 index 0000000..111d5d5 --- /dev/null +++ b/REFACTORING_PLAN.md @@ -0,0 +1,675 @@ +# Plan de Refactoring - Inventory v1.2.0 + +> **Date de creation :** 2026-02-03 +> **Branche de travail :** `refacto/v1.3.0` +> **Base :** `develop` (commit `8d83076`) + +--- + +## Legende des statuts + +| Statut | Signification | +|--------|--------------| +| `[ ]` | A faire | +| `[~]` | En cours | +| `[x]` | Termine | +| `[!]` | Bloque / besoin d'info | + +--- + +## Phase 1 - Securite (CRITIQUE) + +> **Priorite :** MAXIMALE - A traiter en premier + +### 1.1 Corriger la configuration de securite +- **Statut :** `[ ]` +- **Fichier :** `config/packages/security.yaml` +- **Probleme :** `PUBLIC_ACCESS` applique a toutes les routes `/api` avant la regle `IS_AUTHENTICATED_FULLY`. Le pattern matching "first match wins" rend potentiellement tout public. +- **Action :** Reordonner les regles `access_control` pour que les routes protegees soient listees AVANT les routes publiques. +- **Agent :** - +- **Notes :** - + +### 1.2 Ajouter les controles d'autorisation sur les controllers +- **Statut :** `[ ]` +- **Fichiers :** + - `src/Controller/MachineSkeletonController.php` + - `src/Controller/CustomFieldValueController.php` + - `src/Controller/DocumentQueryController.php` + - `src/Controller/SessionProfileController.php` + - `src/Controller/SessionProfilesController.php` + - Tous les `*HistoryController.php` +- **Probleme :** Aucun attribut `#[IsGranted]` sur les controllers custom. Pas de RBAC. +- **Action :** Ajouter `#[IsGranted('IS_AUTHENTICATED_FULLY')]` sur chaque controller (ou route). Definir des roles si necessaire. +- **Agent :** - +- **Notes :** - + +### 1.3 Securiser les secrets +- **Statut :** `[ ]` +- **Fichiers :** + - `.env` (JWT_PASSPHRASE en dur, APP_SECRET vide) + - `docker/.env.docker` (credentials `root:root`) +- **Action :** + 1. Deplacer `JWT_PASSPHRASE` dans `.env.local` (git-ignore) + 2. Generer un `APP_SECRET` valide + 3. Ajouter `.env.local` dans `.gitignore` si pas deja fait + 4. Documenter la configuration des secrets pour les devs +- **Agent :** - +- **Notes :** - + +--- + +## Phase 2 - Elimination de la duplication de code + +> **Priorite :** HAUTE - Impact direct sur la maintenabilite + +### 2.1 Refactorer les 3 Audit Subscribers en un seul generique +- **Statut :** `[ ]` +- **Fichiers concernes :** + - `src/EventSubscriber/ProductAuditSubscriber.php` (298 LOC) + - `src/EventSubscriber/PieceAuditSubscriber.php` (300 LOC) + - `src/EventSubscriber/ComposantAuditSubscriber.php` (300 LOC) +- **Probleme :** ~900 LOC dupliquees a ~95%. Les methodes `onFlush()`, `buildDiffFromChangeSet()`, `resolveActorProfileId()`, `mergeDiffs()`, `normalizeCollection()` sont identiques. Seules les methodes `snapshot*()` different legerement. +- **Action :** + 1. Creer un `AbstractAuditSubscriber` ou un `GenericAuditSubscriber` parametrable + 2. Extraire la logique commune (onFlush, buildDiff, resolveActor, mergeDiffs, normalizeCollection) + 3. Utiliser un systeme de configuration par entite (map `entityClass => entityType + snapshotMethod`) + 4. Supprimer les 3 fichiers redondants + 5. Verifier que l'audit fonctionne toujours sur Product, Piece et Composant +- **Agent :** - +- **Notes :** Tester manuellement les logs d'audit apres refacto. + +### 2.2 Extraire un CuidGenerator utilitaire +- **Statut :** `[ ]` +- **Fichiers concernes :** 18 entites contenant `generateCuid()` en prive +- **Probleme :** Methode `generateCuid()` dupliquee dans chaque entite. De plus, `AuditLog.php` utilise une variante differente (base_convert). +- **Action :** + 1. Creer `src/Util/CuidGenerator.php` avec une methode statique `generate(): string` + 2. Uniformiser l'implementation (choisir une seule methode) + 3. Remplacer tous les appels dans les 18 entites + 4. Supprimer les methodes privees devenues inutiles +- **Agent :** - +- **Notes :** Attention a l'inconsistance entre AuditLog et les autres entites. + +### 2.3 Factoriser la logique de liaison dans MachineSkeletonController +- **Statut :** `[ ]` +- **Fichier :** `src/Controller/MachineSkeletonController.php` (756 LOC) +- **Probleme :** Les methodes `applyComponentLinks()`, `applyPieceLinks()`, `applyProductLinks()` sont quasi identiques (~90 LOC chacune). +- **Action :** + 1. Extraire une methode generique `applyLinks(Machine $machine, array $links, string $type)` + 2. Parametrer par le type d'entite liee (Composant, Piece, Product) + 3. Reduire le controller a ~400 LOC max +- **Agent :** - +- **Notes :** - + +--- + +## Phase 3 - Restructuration des controllers + +> **Priorite :** MOYENNE - Amelioration de la lisibilite et maintenabilite + +### 3.1 Decouper MachineSkeletonController +- **Statut :** `[ ]` +- **Fichier :** `src/Controller/MachineSkeletonController.php` (756 LOC) +- **Action :** + 1. Extraire la logique metier dans un `MachineSkeletonService` + 2. Le controller ne doit gerer que la requete/reponse HTTP + 3. Le service gere la logique de skeleton (get, update, applyLinks) + 4. Extraire les helpers (`resolveIdentifier`, `indexLinksById`, `applyOverrides`, `normalizeMachineSkeletonResponse`) dans le service +- **Agent :** - +- **Notes :** Depend de la phase 2.3 (factorisation des liens). + +### 3.2 Ajouter un try-catch et du logging dans les controllers +- **Statut :** `[ ]` +- **Fichiers :** Tous les controllers dans `src/Controller/` +- **Probleme :** Aucun try-catch autour des `flush()` et `persist()`. Pas de logging d'erreurs. +- **Action :** + 1. Ajouter `try-catch` autour des operations Doctrine dans chaque controller + 2. Logger les erreurs avec le `LoggerInterface` de Symfony (Monolog) + 3. Retourner des reponses JSON coherentes en cas d'erreur serveur (500) +- **Agent :** - +- **Notes :** - + +### 3.3 Renforcer la validation des entrees +- **Statut :** `[ ]` +- **Fichiers :** + - `src/Controller/CustomFieldValueController.php` + - `src/Controller/MachineSkeletonController.php` +- **Probleme :** Pas de validation de longueur max, pas de regex sur les IDs, pas de controle de profondeur JSON. +- **Action :** + 1. Valider le format des IDs (regex CUID : `/^cl[a-f0-9]{24}$/`) + 2. Ajouter des limites de longueur sur les champs string + 3. Utiliser le composant Validator de Symfony pour les DTOs si pertinent +- **Agent :** - +- **Notes :** - + +--- + +## Phase 4 - Amelioration du stockage + +> **Priorite :** MOYENNE - Performance et scalabilite + +### 4.1 Migrer le stockage PDF de base64 vers le filesystem +- **Statut :** `[ ]` +- **Fichiers :** + - `src/Entity/Document.php` + - `src/Command/CompressPdfCommand.php` + - `src/Service/PdfCompressorService.php` +- **Probleme :** Les PDFs sont stockes en base64 dans la colonne `path` (TEXT) de la BDD. Risque de DoS et mauvaise perf sur des gros fichiers. +- **Action :** + 1. Utiliser `vich/uploader-bundle` (deja installe) pour le stockage fichier + 2. Configurer un repertoire de stockage (`var/uploads/documents/`) + 3. Migrer les documents existants (script de migration) + 4. Adapter `PdfCompressorService` pour lire/ecrire sur le filesystem + 5. Mettre a jour l'entite Document +- **Agent :** - +- **Notes :** Prevoir une migration de donnees pour les documents existants. + +### 4.2 Corriger les types de prix (string -> decimal) +- **Statut :** `[ ]` +- **Fichiers :** + - `src/Entity/Machine.php` (`$prix`) + - `src/Entity/Product.php` (`$supplierPrice`) +- **Probleme :** Les prix sont types `?string` en PHP alors que la colonne est `DECIMAL(10,2)` en BDD. +- **Action :** + 1. Changer le type PHP en `?float` ou utiliser `brick/money` + 2. Adapter les getters/setters + 3. Verifier la serialisation API Platform +- **Agent :** - +- **Notes :** Impact potentiel sur le frontend (format des nombres). + +--- + +## Phase 5 - Utilisation du Process Component + +> **Priorite :** BASSE - Bonne pratique + +### 5.1 Remplacer exec() par Symfony Process +- **Statut :** `[ ]` +- **Fichiers :** + - `src/Command/CompressPdfCommand.php` (lignes 42, 98-101) + - `src/Service/PdfCompressorService.php` (lignes 37-41) +- **Probleme :** Utilisation de `exec()` directe pour appeler `qpdf`. +- **Action :** + 1. Remplacer par `Symfony\Component\Process\Process` + 2. Gerer le timeout et les erreurs proprement + 3. Tester que la compression fonctionne toujours +- **Agent :** - +- **Notes :** `escapeshellarg()` est deja utilise, donc pas de faille de securite immediate. + +--- + +## Phase 6 - Tests + +> **Priorite :** HAUTE - Indispensable avant toute refacto majeure + +### 6.1 Mettre en place les tests unitaires +- **Statut :** `[ ]` +- **Fichiers a creer :** + - `tests/Unit/Util/CuidGeneratorTest.php` + - `tests/Unit/Entity/MachineTest.php` + - `tests/Unit/Entity/ProductTest.php` + - `tests/Unit/Service/PdfCompressorServiceTest.php` +- **Action :** + 1. Tester le CuidGenerator (format, unicite) + 2. Tester les entites (validation, lifecycle callbacks) + 3. Tester le PdfCompressorService +- **Agent :** - +- **Notes :** - + +### 6.2 Mettre en place les tests fonctionnels (API) +- **Statut :** `[ ]` +- **Fichiers a creer :** + - `tests/Functional/Api/MachineTest.php` + - `tests/Functional/Api/ProductTest.php` + - `tests/Functional/Api/AuthenticationTest.php` + - `tests/Functional/Api/MachineSkeletonTest.php` +- **Action :** + 1. Configurer une base de test (SQLite ou PostgreSQL de test) + 2. Creer des fixtures de test + 3. Tester les endpoints CRUD + 4. Tester l'authentification JWT + 5. Tester les endpoints custom (skeleton, custom fields) +- **Agent :** - +- **Notes :** Utiliser `ApiTestCase` de API Platform. + +### 6.3 Tests des Audit Subscribers +- **Statut :** `[ ]` +- **Fichiers a creer :** + - `tests/Unit/EventSubscriber/AuditSubscriberTest.php` +- **Action :** + 1. Tester la creation de logs sur insert/update/delete + 2. Tester le format des diffs et snapshots + 3. Tester la resolution de l'acteur +- **Agent :** - +- **Notes :** A faire APRES la phase 2.1 (refacto des subscribers). + +--- + +## Phase 7 - Nettoyage et conventions + +> **Priorite :** BASSE - Polish final + +### 7.1 Supprimer les fichiers inutiles +- **Statut :** `[ ]` +- **Fichiers a verifier :** + - `frontend/` (dossier legacy ? vs `Inventory_frontend/`) + - `src/ApiResource/` (repertoire vide) + - Fichiers SQL a la racine (`backup_v1.0.0.sql`, `data_norm.sql`, `fullasse.sql`, `fulldata.sql`) +- **Action :** Confirmer avec l'equipe quels fichiers sont obsoletes et les supprimer. +- **Agent :** - +- **Notes :** Ne pas supprimer sans validation. + +### 7.2 Uniformiser la gestion des null +- **Statut :** `[ ]` +- **Fichiers :** Toutes les entites dans `src/Entity/` +- **Action :** S'assurer que les types nullable sont coherents entre PHP et la BDD (colonnes NOT NULL vs nullable). +- **Agent :** - +- **Notes :** - + +--- + +--- + +# FRONTEND (`Inventory_frontend/`) + +--- + +## Phase F1 - Decoupage des mega-composants (CRITIQUE) + +> **Priorite :** MAXIMALE - Les fichiers actuels sont inmaintenables + +### F1.1 Decouper `machine/[id].vue` (4308 LOC) +- **Statut :** `[ ]` +- **Fichier :** `Inventory_frontend/app/pages/machine/[id].vue` +- **Probleme :** Page monolithique de 4308 lignes. Contient la vue detail, l'edition, la gestion du skeleton, les composants, les pieces, les produits, les documents, l'historique. +- **Action :** + 1. Identifier les sections logiques (header, detail, skeleton, composants, pieces, produits, documents, historique) + 2. Extraire chaque section en composant dedie : + - `components/machine/MachineHeader.vue` + - `components/machine/MachineDetail.vue` + - `components/machine/MachineSkeletonEditor.vue` + - `components/machine/MachineComponentsList.vue` + - `components/machine/MachinePiecesList.vue` + - `components/machine/MachineProductsList.vue` + - `components/machine/MachineDocuments.vue` + - `components/machine/MachineHistory.vue` + 3. La page `[id].vue` ne doit plus etre qu'un orchestrateur (<300 LOC) + 4. Utiliser `provide/inject` ou un composable partage pour l'etat machine +- **Agent :** - +- **Notes :** Tache la plus impactante du frontend. A faire en premier. + +### F1.2 Decouper `machines/new.vue` (2313 LOC) +- **Statut :** `[ ]` +- **Fichier :** `Inventory_frontend/app/pages/machines/new.vue` +- **Probleme :** Page de creation de machine avec selection de type et heritage de structure, trop volumineuse. +- **Action :** + 1. Extraire le formulaire de creation en composant `MachineCreateForm.vue` + 2. Extraire la selection de type en `MachineTypeSelector.vue` + 3. Extraire l'apercu de structure en composant separe + 4. Objectif : page <200 LOC +- **Agent :** - +- **Notes :** - + +### F1.3 Decouper les pages de creation/edition (Piece, Component, Product) +- **Statut :** `[ ]` +- **Fichiers :** + - `pages/component/create.vue` (1282 LOC) + - `pages/component/[id]/edit.vue` (1629 LOC) + - `pages/pieces/create.vue` (817 LOC) + - `pages/pieces/[id]/edit.vue` (1327 LOC) + - `pages/product/[id]/edit.vue` (936 LOC) +- **Probleme :** Formulaires monolithiques avec sections multiples (infos generales, fournisseurs, documents, custom fields, etc.). +- **Action :** + 1. Identifier les sections communes entre create/edit (factoriser) + 2. Extraire chaque section en composant reutilisable : + - `EntityFormGeneral.vue` (nom, reference, description) + - `EntityFormSuppliers.vue` (constructeurs) + - `EntityFormDocuments.vue` (documents) + - `EntityFormCustomFields.vue` (champs personnalises) + 3. Objectif par page : <400 LOC +- **Agent :** - +- **Notes :** Les formulaires create et edit partagent beaucoup de code. Factoriser. + +### F1.4 Reduire PieceItem.vue (1588 LOC) et ComponentItem.vue (1336 LOC) +- **Statut :** `[ ]` +- **Fichiers :** + - `Inventory_frontend/app/components/PieceItem.vue` (1588 LOC) + - `Inventory_frontend/app/components/ComponentItem.vue` (1336 LOC) +- **Probleme :** Composants d'affichage/edition inline tres volumineux. +- **Action :** + 1. Separer la vue lecture de la vue edition + 2. Extraire les sous-sections (details, documents, fournisseurs) en sous-composants + 3. Objectif : <400 LOC par composant +- **Agent :** - +- **Notes :** - + +--- + +## Phase F2 - Elimination de la duplication frontend + +> **Priorite :** HAUTE - DRY + +### F2.1 Extraire `extractCollection()` dans un utilitaire partage +- **Statut :** `[ ]` +- **Fichiers concernes :** + - `composables/useSites.js` + - `composables/useProducts.js` + - `composables/usePieces.js` + - `composables/useComposants.js` + - `composables/useMachineTypesApi.js` + - `composables/useConstructeurs.js` +- **Probleme :** La fonction `extractCollection()` (parsing `hydra:member` / `member` / array) est dupliquee dans 6+ fichiers. +- **Action :** + 1. Creer `shared/utils/apiHelpers.ts` + 2. Y placer `extractCollection()`, `extractRelationId()`, `normalizeRelationIds()` + 3. Remplacer les implementations locales par un import +- **Agent :** - +- **Notes :** - + +### F2.2 Fusionner les 3 composables d'historique +- **Statut :** `[ ]` +- **Fichiers concernes :** + - `composables/useComponentHistory.ts` (67 LOC) + - `composables/usePieceHistory.ts` (67 LOC) + - `composables/useProductHistory.ts` (67 LOC) +- **Probleme :** 3 fichiers quasi identiques (seul le endpoint differe). +- **Action :** + 1. Creer `composables/useEntityHistory.ts` parametrable par type d'entite + 2. Supprimer les 3 fichiers specifiques +- **Agent :** - +- **Notes :** - + +### F2.3 Factoriser les composables de types (Component/Piece/Product) +- **Statut :** `[ ]` +- **Fichiers concernes :** + - `composables/useComponentTypes.js` (140 LOC) + - `composables/usePieceTypes.js` (140 LOC) + - `composables/useProductTypes.js` (132 LOC) +- **Probleme :** 3 composables tres similaires pour gerer les categories/types. +- **Action :** + 1. Creer `composables/useEntityTypes.ts` generique + 2. Parametrer par type d'entite et endpoint +- **Agent :** - +- **Notes :** - + +--- + +## Phase F3 - Migration TypeScript + +> **Priorite :** HAUTE - Securite du typage + +### F3.1 Definir les types pour les reponses API +- **Statut :** `[ ]` +- **Fichier a creer :** `Inventory_frontend/app/shared/types/api.ts` +- **Probleme :** Aucun type pour les reponses API. Les composables travaillent avec `any` implicite. +- **Action :** + 1. Definir les interfaces pour chaque entite API : + - `ApiMachine`, `ApiProduct`, `ApiPiece`, `ApiComposant` + - `ApiSite`, `ApiDocument`, `ApiConstructeur` + - `ApiAuditLog`, `ApiProfile`, `ApiCustomField` + 2. Definir `ApiCollectionResponse` (hydra:member, totalItems, etc.) + 3. Definir `ApiErrorResponse` + 4. Typer les retours de `useApi()` +- **Agent :** - +- **Notes :** Partir de `shared/types/inventory.ts` (289 LOC) qui contient deja des types partiels. + +### F3.2 Convertir les composables JS en TS +- **Statut :** `[ ]` +- **Fichiers concernes (10 fichiers JS) :** + - `useApi.js` -> `useApi.ts` + - `useMachines.js` -> `useMachines.ts` + - `useProducts.js` -> `useProducts.ts` + - `usePieces.js` -> `usePieces.ts` + - `useComposants.js` -> `useComposants.ts` + - `useConstructeurs.js` -> `useConstructeurs.ts` + - `useSites.js` -> `useSites.ts` + - `useDocuments.js` -> `useDocuments.ts` + - `useMachineTypesApi.js` -> `useMachineTypesApi.ts` + - `useCustomFields.js` -> `useCustomFields.ts` +- **Action :** + 1. Renommer `.js` en `.ts` + 2. Ajouter les types de retour, parametres, et variables reactives + 3. Utiliser les types API definis en F3.1 + 4. Eliminer tous les `any` explicites et implicites +- **Agent :** - +- **Notes :** Depend de F3.1 (types API). + +### F3.3 Eliminer les `any` restants +- **Statut :** `[ ]` +- **Fichiers concernes :** + - `components/common/ProductSelect.vue` + - `components/common/ManagementView.vue` + - `components/ComponentStructureAssignmentNode.vue` + - `components/model-types/ComponentModelStructureEditor.vue` + - `components/model-types/ModelTypeForm.vue` +- **Probleme :** 20+ usages de `any` type identifies. +- **Action :** Remplacer chaque `any` par un type concret ou un type union. +- **Agent :** - +- **Notes :** - + +--- + +## Phase F4 - Qualite du code frontend + +> **Priorite :** MOYENNE + +### F4.1 Activer les regles ESLint critiques +- **Statut :** `[ ]` +- **Fichier :** `Inventory_frontend/eslint.config.mjs` +- **Probleme :** Presque toutes les regles sont desactivees (`no-console: off`, `no-unused-vars: off`, `no-explicit-any: off`). +- **Action :** + 1. Activer `@typescript-eslint/no-explicit-any: warn` + 2. Activer `no-console: warn` (ou `error` sauf pour `console.error`) + 3. Activer `no-unused-vars: warn` + 4. Fixer les violations progressivement +- **Agent :** - +- **Notes :** 94 appels `console.*` a nettoyer. + +### F4.2 Nettoyer les console.log/console.error +- **Statut :** `[ ]` +- **Fichiers :** ~94 occurrences dans le frontend +- **Probleme :** Appels de debug laisses dans le code de production. +- **Action :** + 1. Remplacer les `console.error` utiles par un logger centralise (ou `useToast`) + 2. Supprimer les `console.log` de debug + 3. Creer un utilitaire `logger.ts` si necessaire (qui respecte `enableDebug` du runtime config) +- **Agent :** - +- **Notes :** - + +### F4.3 Centraliser la gestion d'erreurs API +- **Statut :** `[ ]` +- **Fichier :** `Inventory_frontend/app/composables/useApi.js` (105 LOC) +- **Probleme :** Gestion d'erreur basique (juste un toast). Pas de retry, pas d'intercepteur, erreurs silencieuses dans certains composables. +- **Action :** + 1. Ajouter un systeme de retry configurable (1-3 tentatives) + 2. Centraliser la gestion des erreurs HTTP (401 -> redirect login, 500 -> message explicite) + 3. Ajouter des intercepteurs request/response + 4. Uniformiser le pattern dans tous les composables +- **Agent :** - +- **Notes :** - + +--- + +## Phase F5 - Reduire le fichier modelUtils.ts (1017 LOC) + +> **Priorite :** MOYENNE + +### F5.1 Decouper `shared/modelUtils.ts` +- **Statut :** `[ ]` +- **Fichier :** `Inventory_frontend/app/shared/modelUtils.ts` (1017 LOC) +- **Probleme :** Fichier utilitaire monolithique de 1017 lignes regroupant toute la logique de manipulation de modeles. +- **Action :** + 1. Identifier les groupes de fonctions (structure, custom fields, requirements, serialization) + 2. Decouper en modules : + - `shared/model/structureUtils.ts` + - `shared/model/customFieldUtils.ts` + - `shared/model/requirementUtils.ts` + - `shared/model/serializationUtils.ts` + 3. Re-exporter depuis un `shared/model/index.ts` pour ne pas casser les imports +- **Agent :** - +- **Notes :** - + +--- + +## Phase F6 - Tests frontend + +> **Priorite :** HAUTE - Aucun test actuellement + +### F6.1 Configurer Vitest +- **Statut :** `[ ]` +- **Fichier a creer :** `Inventory_frontend/vitest.config.ts` +- **Action :** + 1. Installer `vitest`, `@vue/test-utils`, `@nuxt/test-utils` + 2. Configurer Vitest avec support Vue/Nuxt + 3. Ajouter un script `test` dans `package.json` + 4. Creer un premier test smoke +- **Agent :** - +- **Notes :** - + +### F6.2 Tests unitaires des composables +- **Statut :** `[ ]` +- **Fichiers a creer :** + - `tests/composables/useApi.test.ts` + - `tests/composables/useProducts.test.ts` + - `tests/composables/useToast.test.ts` + - `tests/shared/apiHelpers.test.ts` (apres F2.1) +- **Action :** + 1. Tester `useApi` (requetes, timeout, erreurs) + 2. Tester `extractCollection()` (tous les formats de reponse) + 3. Tester les composables CRUD (mock des appels API) + 4. Tester le toast (ajout, suppression, max toasts) +- **Agent :** - +- **Notes :** - + +### F6.3 Tests de composants +- **Statut :** `[ ]` +- **Fichiers a creer :** + - `tests/components/Pagination.test.ts` + - `tests/components/SearchSelect.test.ts` + - `tests/components/MachineHeader.test.ts` (apres F1.1) +- **Action :** + 1. Tester les composants communs (Pagination, SearchSelect) + 2. Tester le rendu conditionnel et les events +- **Agent :** - +- **Notes :** - + +--- + +## Phase F7 - Ameliorations UX/DX + +> **Priorite :** BASSE - Polish + +### F7.1 Reduire le props drilling +- **Statut :** `[ ]` +- **Probleme :** Props passees sur 3+ niveaux (ex: machine data dans les sous-composants). +- **Action :** + 1. Identifier les cas de props drilling >2 niveaux + 2. Utiliser `provide/inject` ou des composables partages + 3. Documenter le pattern choisi +- **Agent :** - +- **Notes :** A traiter apres F1 (decoupage des composants). + +### F7.2 Remplacer `confirm()` natif par des modales DaisyUI +- **Statut :** `[ ]` +- **Probleme :** Les confirmations de suppression utilisent `window.confirm()` (UI native, non-stylee). +- **Action :** + 1. Creer un composant `ConfirmModal.vue` reutilisable + 2. Ou creer un composable `useConfirm()` qui affiche une modale DaisyUI + 3. Remplacer tous les `confirm()` dans les composants +- **Agent :** - +- **Notes :** - + +### F7.3 Nettoyer `app.vue` (861 LOC) +- **Statut :** `[ ]` +- **Fichier :** `Inventory_frontend/app/app.vue` (861 LOC) +- **Probleme :** Le fichier racine contient le layout principal, la navbar, la sidebar, et du state management. +- **Action :** + 1. Extraire la navbar en `components/layout/AppNavbar.vue` + 2. Extraire la sidebar en `components/layout/AppSidebar.vue` + 3. Utiliser un layout Nuxt (`layouts/default.vue`) + 4. `app.vue` ne doit contenir que `` et les providers globaux +- **Agent :** - +- **Notes :** - + +--- + +## Ordre d'execution recommande + +``` +=== BACKEND === === FRONTEND === + +Phase 6.1 (Tests unitaires) Phase F6.1 (Config Vitest) + | | + v v +Phase 1 (Securite) Phase F1 (Decoupage mega-composants) + | | + v v +Phase 2 (Duplication backend) Phase F2 (Duplication frontend) + | | + v v +Phase 3 (Controllers) Phase F3 (Migration TypeScript) + | | + v v +Phase 6.2 (Tests API) Phase F4 (Qualite code) + Phase F5 (modelUtils) + | | + v v +Phase 4 (Stockage) Phase F6.2-F6.3 (Tests frontend) + | | + v v +Phase 5 + Phase 7 (Nettoyage) Phase F7 (UX/DX polish) + | + v +Phase 6.3 (Tests audit) +``` + +> Les colonnes backend et frontend peuvent etre executees **en parallele** par des agents differents. + +--- + +## Journal des modifications + +| Date | Phase | Tache | Agent | Statut | Notes | +|------|-------|-------|-------|--------|-------| +| 2026-02-03 | - | Creation du plan backend | Claude Opus 4.5 | Termine | Analyse initiale backend (7 phases, 17 taches) | +| 2026-02-03 | - | Creation du plan frontend | Claude Opus 4.5 | Termine | Analyse frontend (7 phases, 22 taches) | +| | | | | | | + +--- + +## Regles pour les agents + +1. **Avant de commencer une tache :** + - Mettre le statut a `[~]` dans ce fichier + - Inscrire son nom/ID dans la colonne "Agent" + - Lire les fichiers concernes AVANT de modifier quoi que ce soit + +2. **Pendant le travail :** + - Ne modifier QUE les fichiers listes dans la tache + - Respecter les conventions existantes (PSR-12, strict_types) + - Ne pas introduire de nouvelles dependances sans justification + - Lancer `php-cs-fixer` apres les modifications + +3. **Apres avoir termine :** + - Mettre le statut a `[x]` + - Ajouter une entree dans le "Journal des modifications" + - Lancer les tests existants (`make test`) pour verifier la non-regression + - Decrire brievement les changements effectues dans "Notes" + +4. **En cas de blocage :** + - Mettre le statut a `[!]` + - Documenter le blocage dans "Notes" + - Ne PAS passer a une autre tache sans signaler le blocage + +5. **Regles specifiques au frontend :** + - Ecrire en TypeScript (pas de JS pour les nouveaux fichiers) + - Pas de `any` - utiliser des types concrets + - Pas de `console.log` - utiliser le logger ou `useToast` + - Composants Vue : max 400 LOC par fichier + - Utiliser les composants DaisyUI existants (pas de CSS custom) + - Tester avec Vitest quand la config est en place + +6. **Regles specifiques au backend :** + - `declare(strict_types=1)` obligatoire + - Respecter PSR-12 + regles Symfony (php-cs-fixer) + - Pas de `exec()` direct - utiliser Symfony Process + - Tester avec PHPUnit