682 lines
26 KiB
Markdown
682 lines
26 KiB
Markdown
# 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
|