# 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 :** `[x]`
- **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.
- **Sous-taches :**
  - [x] F1.3a Extraire `customFieldFormUtils.ts` (duplique dans 5 fichiers)
  - [x] F1.3b Extraire `documentDisplayUtils.ts` (duplique dans 3 pages edit)
  - [x] F1.3c Extraire `historyDisplayUtils.ts` (duplique dans 3 pages edit)
  - [x] F1.3d Rewire les 5 pages create/edit sur les modules extraits
  - [x] F1.3e Typecheck + commit F1.3 (erreurs F1.3 corrigees, 120 erreurs preexistantes documentees)

### 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<T>` (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 `<NuxtLayout>` 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
