|
|
|
|
@@ -0,0 +1,786 @@
|
|
|
|
|
# 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 - Nett oyage 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` (2989 LOC → 219 LOC)
|
|
|
|
|
|
|
|
|
|
- **Statut :** `[x]`
|
|
|
|
|
- **Fichier :** `Inventory_frontend/app/pages/machine/[id].vue`
|
|
|
|
|
- **Resultat :** Page decomposee en 2 composables + 7 composants. Orchestrateur = 219 LOC.
|
|
|
|
|
- **Fichiers crees :**
|
|
|
|
|
- `composables/useMachineDetailData.ts` (1404 LOC) — state + logique metier
|
|
|
|
|
- `composables/useMachineSkeletonEditor.ts` (843 LOC) — logique skeleton
|
|
|
|
|
- `components/machine/MachineDetailHeader.vue` (76 LOC)
|
|
|
|
|
- `components/machine/MachineInfoCard.vue` (185 LOC)
|
|
|
|
|
- `components/machine/MachineDocumentsCard.vue` (116 LOC)
|
|
|
|
|
- `components/machine/MachineProductsCard.vue` (62 LOC)
|
|
|
|
|
- `components/machine/MachineComponentsCard.vue` (53 LOC)
|
|
|
|
|
- `components/machine/MachinePiecesCard.vue` (34 LOC)
|
|
|
|
|
- `components/machine/MachineSkeletonSummary.vue` (199 LOC)
|
|
|
|
|
- **Pattern :** Props + Events (pas de provide/inject). Composables avec injection de dependances (interface Deps).
|
|
|
|
|
- **Notes :** Typecheck 0 erreurs. Lint OK.
|
|
|
|
|
|
|
|
|
|
### F1.2 Decouper `machines/new.vue` (1231 LOC → 196 LOC)
|
|
|
|
|
|
|
|
|
|
- **Statut :** `[x]`
|
|
|
|
|
- **Fichier :** `Inventory_frontend/app/pages/machines/new.vue`
|
|
|
|
|
- **Resultat :** Page decomposee en 1 composable + 5 composants. Orchestrateur = 196 LOC.
|
|
|
|
|
- **Fichiers crees :**
|
|
|
|
|
- `composables/useMachineCreatePage.ts` (460 LOC) — state, entity lookups, options, creation
|
|
|
|
|
- `components/machine/create/RequirementComponentSelector.vue` (126 LOC)
|
|
|
|
|
- `components/machine/create/RequirementPieceSelector.vue` (130 LOC)
|
|
|
|
|
- `components/machine/create/RequirementProductSelector.vue` (142 LOC)
|
|
|
|
|
- `components/machine/create/MachineCreatePreview.vue` (205 LOC)
|
|
|
|
|
- `components/machine/create/PreviewRequirementGroup.vue` (59 LOC)
|
|
|
|
|
- **Pattern :** Props + Events. Composable consolide entity lookups, options, label helpers, creation.
|
|
|
|
|
- **Notes :** Typecheck 0 erreurs. Lint OK. Corrige aussi un bug F1.1 (defineProps dans mauvais script block de MachineSkeletonSummary.vue).
|
|
|
|
|
|
|
|
|
|
### 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 :** `[x]`
|
|
|
|
|
- **Fichiers :**
|
|
|
|
|
- `Inventory_frontend/app/components/PieceItem.vue` (1588 → 740 LOC)
|
|
|
|
|
- `Inventory_frontend/app/components/ComponentItem.vue` (1336 → 585 LOC)
|
|
|
|
|
- **Probleme :** ~700 LOC de logique dupliquee entre les deux composants (champs personnalises, documents, affichage produit).
|
|
|
|
|
- **Action realisee :**
|
|
|
|
|
1. Extraction de la logique pure custom fields dans `shared/utils/entityCustomFieldLogic.ts` (~350 LOC)
|
|
|
|
|
2. Creation de `composables/useEntityCustomFields.ts` (composable reactif, ~180 LOC)
|
|
|
|
|
3. Creation de `composables/useEntityDocuments.ts` (CRUD documents + preview, ~120 LOC)
|
|
|
|
|
4. Creation de `composables/useEntityProductDisplay.ts` (affichage produit, ~100 LOC)
|
|
|
|
|
5. Import des helpers document depuis `shared/utils/documentDisplayUtils.ts` (existant)
|
|
|
|
|
6. Rewrite des deux composants pour utiliser les modules partages
|
|
|
|
|
7. Typecheck 0 erreurs, lint 0 erreurs
|
|
|
|
|
- **Sous-taches :**
|
|
|
|
|
- [x] F1.4a Extraire `entityCustomFieldLogic.ts` (fonctions pures)
|
|
|
|
|
- [x] F1.4b Creer `useEntityCustomFields.ts` (composable reactif)
|
|
|
|
|
- [x] F1.4c Creer `useEntityDocuments.ts` (composable documents)
|
|
|
|
|
- [x] F1.4d Creer `useEntityProductDisplay.ts` (composable produit)
|
|
|
|
|
- [x] F1.4e Rewrite ComponentItem.vue (1336 → 585 LOC, script 900 → 150 LOC)
|
|
|
|
|
- [x] F1.4f Rewrite PieceItem.vue (1588 → 740 LOC, script 1100 → 255 LOC)
|
|
|
|
|
- [x] F1.4g Typecheck + lint (0 erreurs)
|
|
|
|
|
- **Notes :** Les templates restent volumineux (~430-480 LOC) car le contenu UI est dense. Une extraction en sous-composants (DocumentList, ProductDisplay, CustomFieldForm) serait une etape future optionnelle.
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Phase F2 - Elimination de la duplication frontend
|
|
|
|
|
|
|
|
|
|
> **Priorite :** HAUTE - DRY
|
|
|
|
|
|
|
|
|
|
### F2.1 Extraire `extractCollection()` dans un utilitaire partage
|
|
|
|
|
|
|
|
|
|
- **Statut :** `[x]`
|
|
|
|
|
- **Fichiers concernes :**
|
|
|
|
|
- `composables/useSites.ts`
|
|
|
|
|
- `composables/useProducts.ts`
|
|
|
|
|
- `composables/usePieces.ts`
|
|
|
|
|
- `composables/useComposants.ts`
|
|
|
|
|
- `composables/useMachineTypesApi.js`
|
|
|
|
|
- `composables/useConstructeurs.ts`
|
|
|
|
|
- `composables/useDocuments.ts`
|
|
|
|
|
- `composables/useMachineCreateSelections.ts`
|
|
|
|
|
- `components/ComponentStructureAssignmentNode.vue`
|
|
|
|
|
- `components/model-types/ManagementView.vue`
|
|
|
|
|
- **Probleme :** La fonction `extractCollection()` (parsing `hydra:member` / `member` / `items` / `data` / array) etait dupliquee dans 10 fichiers.
|
|
|
|
|
- **Action :**
|
|
|
|
|
1. [x] Creer `shared/utils/apiHelpers.ts` avec `extractCollection<T>()` generique
|
|
|
|
|
2. [x] Remplacer les 10 implementations locales par un import
|
|
|
|
|
- **Agent :** -
|
|
|
|
|
- **Notes :** Gere aussi `items` (utilise par ManagementView.vue). `extractRelationId()` et `normalizeRelationIds()` restent dans `shared/apiRelations.ts` (deja partages).
|
|
|
|
|
|
|
|
|
|
### F2.2 Fusionner les 3 composables d'historique
|
|
|
|
|
|
|
|
|
|
- **Statut :** `[x]`
|
|
|
|
|
- **Fichiers concernes :**
|
|
|
|
|
- `composables/useComponentHistory.ts` (67 → 13 LOC, thin wrapper)
|
|
|
|
|
- `composables/usePieceHistory.ts` (67 → 13 LOC, thin wrapper)
|
|
|
|
|
- `composables/useProductHistory.ts` (67 → 13 LOC, thin wrapper)
|
|
|
|
|
- `composables/useEntityHistory.ts` (NEW, 65 LOC, logique generique)
|
|
|
|
|
- **Probleme :** 3 fichiers quasi identiques (seul le endpoint differait).
|
|
|
|
|
- **Action :**
|
|
|
|
|
1. [x] Creer `composables/useEntityHistory.ts` parametrable par type d'entite
|
|
|
|
|
2. [x] Reecrire les 3 fichiers specifiques en wrappers backward-compatible
|
|
|
|
|
- **Agent :** -
|
|
|
|
|
- **Notes :** Les wrappers preservent l'API existante (types + fonction), aucun consommateur a modifier.
|
|
|
|
|
|
|
|
|
|
### F2.3 Factoriser les composables de types (Component/Piece/Product)
|
|
|
|
|
|
|
|
|
|
- **Statut :** `[x]`
|
|
|
|
|
- **Fichiers concernes :**
|
|
|
|
|
- `composables/useComponentTypes.ts` (165 → 30 LOC, thin wrapper)
|
|
|
|
|
- `composables/usePieceTypes.ts` (165 → 30 LOC, thin wrapper)
|
|
|
|
|
- `composables/useProductTypes.ts` (160 → 28 LOC, thin wrapper)
|
|
|
|
|
- `composables/useEntityTypes.ts` (NEW, 172 LOC, logique generique)
|
|
|
|
|
- **Probleme :** 3 composables tres similaires pour gerer les categories/types.
|
|
|
|
|
- **Action :**
|
|
|
|
|
1. [x] Creer `composables/useEntityTypes.ts` generique (CRUD + singleton state par categorie)
|
|
|
|
|
2. [x] Reecrire les 3 fichiers specifiques en wrappers avec renommage des champs
|
|
|
|
|
- **Agent :** -
|
|
|
|
|
- **Notes :** Les wrappers renomment `types` → `componentTypes`/`pieceTypes`/`productTypes`, preservent `getXxxTypes()` et `isXxxTypeLoading()`. Etat partage via `stateByCategory` map module-level.
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Phase F3 - Migration TypeScript
|
|
|
|
|
|
|
|
|
|
> **Priorite :** HAUTE - Securite du typage
|
|
|
|
|
|
|
|
|
|
### F3.1 Definir les types pour les reponses API
|
|
|
|
|
|
|
|
|
|
- **Statut :** `[x]` (partiellement — types definis dans chaque composable + `ApiResponse<T>` dans useApi.ts)
|
|
|
|
|
- **Fichiers :**
|
|
|
|
|
- `composables/useApi.ts` — `ApiResponse<T>` generique (success/data/error/status)
|
|
|
|
|
- `composables/useMachines.ts` — `Machine` interface
|
|
|
|
|
- `composables/useMachineTypesApi.ts` — `MachineType`, `MachineTypeRequirement` interfaces
|
|
|
|
|
- `composables/useToast.ts` — `Toast`, `ToastType` types
|
|
|
|
|
- `composables/useProfiles.ts` — `Profile` interface
|
|
|
|
|
- `composables/useCustomFields.ts` — `CustomFieldValue` interface
|
|
|
|
|
- **Notes :** Les types sont definis dans chaque composable (colocation). Types entite existants : `Product`, `Piece`, `Composant`, `Constructeur`, `Site`, `Document` dans leurs composables respectifs (.ts). `shared/types/inventory.ts` contient les types de structure de modele.
|
|
|
|
|
|
|
|
|
|
### F3.2 Convertir les composables JS en TS
|
|
|
|
|
|
|
|
|
|
- **Statut :** `[x]`
|
|
|
|
|
- **Fichiers convertis (7 fichiers JS → TS) :**
|
|
|
|
|
- [x] `useToast.js` → `useToast.ts` (72 LOC, types: `Toast`, `ToastType`)
|
|
|
|
|
- [x] `useProfiles.js` → `useProfiles.ts` (68 LOC, type: `Profile`)
|
|
|
|
|
- [x] `useProfileSession.js` → `useProfileSession.ts` (85 LOC, importe `Profile`)
|
|
|
|
|
- [x] `useApi.js` → `useApi.ts` (106 LOC → 120 LOC, types: `ApiResponse<T>`, `ApiCallOptions`, ajout `put()`)
|
|
|
|
|
- [x] `useCustomFields.js` → `useCustomFields.ts` (105 LOC, type: `CustomFieldValue`)
|
|
|
|
|
- [x] `useMachineTypesApi.js` → `useMachineTypesApi.ts` (173 → 188 LOC, types: `MachineType`, `MachineTypeRequirement`)
|
|
|
|
|
- [x] `useMachines.js` → `useMachines.ts` (267 LOC, type: `Machine`, utilise `extractCollection`)
|
|
|
|
|
- **Fichiers deja TS :** `useProducts.ts`, `usePieces.ts`, `useComposants.ts`, `useConstructeurs.ts`, `useSites.ts`, `useDocuments.ts`
|
|
|
|
|
- **Fichiers JS restants (deprecated) :** `useComponentModels.js`, `usePieceModels.js` (stubs deprecated, a supprimer)
|
|
|
|
|
- **Notes :** `ApiResponse<T = any>` par defaut `any` pour backward-compat. Les callers existants fonctionnent sans changement ; le nouveau code peut opt-in strict via `get<MyType>()`.
|
|
|
|
|
|
|
|
|
|
### F3.3 Eliminer les `any` restants
|
|
|
|
|
|
|
|
|
|
- **Statut :** `[x]`
|
|
|
|
|
- **Fichiers concernes :**
|
|
|
|
|
- `components/ProductSelect.vue` — 1 `any` restant (slot template, incompressible)
|
|
|
|
|
- `components/model-types/ManagementView.vue` — remplace `data?: any` → `Record<string, unknown>`, `error: any` → `error: unknown`, `item: any` → `item: unknown`
|
|
|
|
|
- `components/ComponentStructureAssignmentNode.vue` — 12 casts `(definition as any).typePiece/typeProduct` elimines grace a l'extension des types
|
|
|
|
|
- `components/ComponentModelStructureEditor.vue` — `Promise<any>` → `Promise<unknown>`
|
|
|
|
|
- `components/model-types/ModelTypeForm.vue` — `(incoming as any).description` → cast `Record<string, unknown>`
|
|
|
|
|
- `shared/types/inventory.ts` — `ComponentModelPiece.typePiece?` et `ComponentModelProduct.typeProduct?` ajoutes, 3 casts `(value as any)` supprimes
|
|
|
|
|
- **Probleme :** 20+ usages de `any` type identifies.
|
|
|
|
|
- **Action :** Etendre les interfaces de types pour supporter les formes alternatives de l'API. Remplacer les `any` par `unknown` ou `Record<string, unknown>` la ou possible.
|
|
|
|
|
- **Agent :** Claude
|
|
|
|
|
- **Notes :** ~15 casts `any` elimines. Les `Record<string, any>` restants dans ComponentModelStructureEditor sont justifies (manipulation dynamique interne de custom fields). Typecheck 0 erreurs.
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Phase F4 - Qualite du code frontend
|
|
|
|
|
|
|
|
|
|
> **Priorite :** MOYENNE
|
|
|
|
|
|
|
|
|
|
### F4.1 Activer les regles ESLint critiques
|
|
|
|
|
|
|
|
|
|
- **Statut :** `[x]` DONE
|
|
|
|
|
- **Fichier :** `Inventory_frontend/eslint.config.mjs`
|
|
|
|
|
- **Probleme :** Presque toutes les regles etaient desactivees (`no-console: off`, `no-unused-vars: off`, `no-explicit-any: off`).
|
|
|
|
|
- **Action realisee :**
|
|
|
|
|
1. [x] Active `@typescript-eslint/no-explicit-any: warn` (526 warnings — amelioration progressive)
|
|
|
|
|
2. [x] Active `no-console: warn` avec `allow: ['error']` — 0 violations (deja nettoye en F4.2)
|
|
|
|
|
3. [x] Active `@typescript-eslint/no-unused-vars: warn` avec ignore `^_` — 0 violations (26 corrigees)
|
|
|
|
|
4. [x] Corrige les 26 violations `no-unused-vars` : imports inutilises supprimes, variables prefixees `_`, destructurations nettoyees
|
|
|
|
|
- **Agent :** Claude
|
|
|
|
|
- **Notes :** 16 fichiers modifies. Regles organisees par categorie (vue, console, typescript, formatting). 0 erreurs, 526 warnings `no-explicit-any` restants (warn, pas bloquant).
|
|
|
|
|
|
|
|
|
|
### F4.2 Nettoyer les console.log/console.error
|
|
|
|
|
|
|
|
|
|
- **Statut :** `[x]` (console.log supprime, console.error conserve)
|
|
|
|
|
- **Fichiers modifies :** 8 fichiers (useMachineTypesApi.ts, useSites.ts, type/[id].vue, type/edit/[id].vue, TypeEditPieceRequirementsSection.vue, SearchSelect.vue, app.vue)
|
|
|
|
|
- **Probleme :** 19 appels `console.log` de debug laisses dans le code de production.
|
|
|
|
|
- **Action :**
|
|
|
|
|
1. [x] Supprimer les 19 `console.log` de debug (normalizeRequirementList, page loading, route params, etc.)
|
|
|
|
|
2. [ ] Les 72 `console.error` restants sont conserves (gestion d'erreur legitime). Migration vers un logger centralise a faire en F4.3.
|
|
|
|
|
- **Agent :** Claude
|
|
|
|
|
- **Notes :** 0 `console.log/warn/debug/info` restants dans le frontend.
|
|
|
|
|
|
|
|
|
|
### 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 :** `[x]`
|
|
|
|
|
- **Fichier :** `Inventory_frontend/app/shared/modelUtils.ts` (1017 LOC → 37 LOC barrel)
|
|
|
|
|
- **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 3 modules thematiques :
|
|
|
|
|
- `shared/model/componentStructure.ts` (~590 LOC) — helpers, sanitize, hydrate, normalize, extract, format pour composants
|
|
|
|
|
- `shared/model/pieceProductStructure.ts` (~155 LOC) — structure piece/produit (clone, sanitize, hydrate, format)
|
|
|
|
|
- `shared/model/definitionOverrides.ts` (~50 LOC) — sanitization des overrides de definition
|
|
|
|
|
3. Re-exporter depuis `shared/modelUtils.ts` (barrel) pour ne pas casser les imports
|
|
|
|
|
- **Agent :** Claude
|
|
|
|
|
- **Notes :** 11 fichiers consommateurs inchanges (barrel preserve la retro-compat). Typecheck 0 erreurs.
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Phase F6 - Tests frontend
|
|
|
|
|
|
|
|
|
|
> **Priorite :** HAUTE - Aucun test actuellement
|
|
|
|
|
|
|
|
|
|
### F6.1 Configurer Vitest
|
|
|
|
|
|
|
|
|
|
- **Statut :** `[x]` DONE
|
|
|
|
|
- **Fichiers crees :**
|
|
|
|
|
- `vitest.config.ts` — config Vitest avec happy-dom, alias `~` et `#imports`
|
|
|
|
|
- `tests/__mocks__/imports.ts` — mock des auto-imports Nuxt (useRuntimeConfig, useRoute, etc.)
|
|
|
|
|
- `tests/shared/inventory-types.test.ts` — 9 tests smoke (validator, empty structures)
|
|
|
|
|
- **Action realisee :**
|
|
|
|
|
1. [x] Installe `vitest`, `@vue/test-utils`, `happy-dom`
|
|
|
|
|
2. [x] Configure Vitest avec environment happy-dom et resolution d'alias
|
|
|
|
|
3. [x] Ajoute scripts `test` et `test:watch` dans `package.json`
|
|
|
|
|
4. [x] Premier test suite : `componentModelStructureValidator` (9 tests, 100% pass)
|
|
|
|
|
- **Agent :** Claude
|
|
|
|
|
- **Notes :** `npm test` → 9 tests, 0 failures, <1s. Alias `#imports` pointe vers un mock minimal extensible.
|
|
|
|
|
|
|
|
|
|
### F6.2 Tests unitaires des composables
|
|
|
|
|
|
|
|
|
|
- **Statut :** `[x]` DONE (base)
|
|
|
|
|
- **Fichiers crees :**
|
|
|
|
|
- `tests/shared/apiHelpers.test.ts` — 10 tests (extractCollection, tous formats API)
|
|
|
|
|
- `tests/shared/modelUtils.test.ts` — 18 tests (isPlainObject, clone, stats, format, piece/product)
|
|
|
|
|
- `tests/shared/inventory-types.test.ts` — 9 tests (validator, empty structures)
|
|
|
|
|
- `tests/composables/useToast.test.ts` — 9 tests (add, types, max limit, clear, singleton)
|
|
|
|
|
- `tests/composables/useConfirm.test.ts` — 8 tests (open, confirm, cancel, options, singleton)
|
|
|
|
|
- **Action realisee :**
|
|
|
|
|
1. [x] Teste `extractCollection()` : array, hydra:member, member, items, data, null, undefined
|
|
|
|
|
2. [x] Teste `useToast` : ajout, types, max 3 toasts, clearAll, removeToast, singleton
|
|
|
|
|
3. [x] Teste `useConfirm` : open/close, resolve true/false, custom options, singleton state
|
|
|
|
|
4. [x] Teste `modelUtils` : clone, stats, preview, isPlainObject, piece/product variants
|
|
|
|
|
5. [x] Teste `componentModelStructureValidator` : valid/invalid, custom fields, subcomponents
|
|
|
|
|
- **Agent :** Claude
|
|
|
|
|
- **Notes :** 54 tests, 5 fichiers, 100% pass, <2s. Tests `useApi` et CRUD composables necessitent mock fetch (phase ulterieure).
|
|
|
|
|
|
|
|
|
|
### 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 :** `[x]` DONE
|
|
|
|
|
- **Probleme :** Les confirmations de suppression utilisaient `window.confirm()` (UI native, non-stylee).
|
|
|
|
|
- **Action realisee :**
|
|
|
|
|
1. [x] Cree `composables/useConfirm.ts` — composable promise-based avec etat reactif partage
|
|
|
|
|
2. [x] Cree `components/common/ConfirmModal.vue` — modale DaisyUI teleportee (backdrop blur, btn-error)
|
|
|
|
|
3. [x] Monte `ConfirmModal` globalement dans `app.vue`
|
|
|
|
|
4. [x] Remplace les 10 `confirm()` natifs dans 10 fichiers :
|
|
|
|
|
- `constructeurs.vue`, `profiles/manage.vue`, `ManagementView.vue`
|
|
|
|
|
- `product-catalog.vue`, `index.vue`, `machines/index.vue`
|
|
|
|
|
- `machine-skeleton/index.vue`, `pieces-catalog.vue`, `component-catalog.vue`
|
|
|
|
|
- `useSiteManagement.ts` (composable — import explicite)
|
|
|
|
|
- **Agent :** Claude
|
|
|
|
|
- **Notes :** API : `const { confirm } = useConfirm(); const ok = await confirm({ message: '...' })`. Auto-import Nuxt pour les SFC, import explicite pour les composables.
|
|
|
|
|
|
|
|
|
|
### F7.3 Nettoyer `app.vue` (861 LOC)
|
|
|
|
|
|
|
|
|
|
- **Statut :** `[x]` DONE
|
|
|
|
|
- **Fichier :** `Inventory_frontend/app/app.vue` (861 → 49 LOC)
|
|
|
|
|
- **Probleme :** Le fichier racine contenait le layout principal, la navbar (~676 LOC dupliquee mobile/desktop), et du state management.
|
|
|
|
|
- **Action realisee :**
|
|
|
|
|
1. Cree `composables/useNavDropdown.ts` (~65 LOC) — gestion etat dropdowns navbar
|
|
|
|
|
2. Cree `components/layout/AppNavbar.vue` (~310 LOC) — navbar data-driven avec `v-for` eliminant duplication mobile/desktop
|
|
|
|
|
3. `app.vue` reecrit en orchestrateur minimal (49 LOC) + converti en TypeScript
|
|
|
|
|
4. Supprime 4 imports d'icones inutilises
|
|
|
|
|
- **Agent :** Claude
|
|
|
|
|
- **Notes :** Approche data-driven : liens et groupes definis comme tableaux types (`NavLink[]`, `NavGroup[]`), rendus par `v-for` pour mobile et desktop
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 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) |
|
|
|
|
|
| | | | | | |
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Commandes de verification
|
|
|
|
|
|
|
|
|
|
> **Contexte :** Le backend tourne dans Docker (`docker compose`), le frontend est en local.
|
|
|
|
|
> Les commandes ci-dessous sont executees **depuis la racine du projet** (`/home/matthieu/dev_malio/Inventory/`).
|
|
|
|
|
|
|
|
|
|
### Frontend (Nuxt 3 / Vue 3 / TypeScript)
|
|
|
|
|
|
|
|
|
|
| Commande | Description | Quand l'utiliser |
|
|
|
|
|
| -------------------- | ----------------------------------------------- | ------------------------------------------------------------------------------------------------- |
|
|
|
|
|
| `npx nuxi typecheck` | Verification des types TypeScript via `vue-tsc` | Apres chaque modification de fichier `.vue` ou `.ts`. C'est la commande principale de validation. |
|
|
|
|
|
| `npm run lint` | ESLint (config dans `eslint.config.mjs`) | Apres chaque modification pour verifier le style et les erreurs statiques. |
|
|
|
|
|
| `npm run lint:fix` | ESLint avec auto-fix | Pour corriger automatiquement les erreurs de formatage. |
|
|
|
|
|
| `npm run build` | Build de production Nuxt (inclut le typecheck) | Avant un commit pour s'assurer que tout compile. Plus lent que `typecheck` seul. |
|
|
|
|
|
| `npx nuxi prepare` | Regenerer les types auto-generes (`.nuxt/`) | Si les imports auto (composables, components) ne sont pas reconnus par le typecheck. |
|
|
|
|
|
|
|
|
|
|
> **Toutes les commandes frontend** sont executees depuis `Inventory_frontend/` :
|
|
|
|
|
>
|
|
|
|
|
> ```bash
|
|
|
|
|
> cd Inventory_frontend && npx nuxi typecheck
|
|
|
|
|
> ```
|
|
|
|
|
|
|
|
|
|
> **Note sur les erreurs pre-existantes :** Il y a ~120 erreurs TypeScript pre-existantes documentees
|
|
|
|
|
> (anterieures a la refacto). L'objectif est de ne pas en ajouter de nouvelles.
|
|
|
|
|
> Pour verifier : comparer le nombre d'erreurs avant/apres modification.
|
|
|
|
|
|
|
|
|
|
### Backend (Symfony 8 / PHP 8.4)
|
|
|
|
|
|
|
|
|
|
| Commande | Description | Quand l'utiliser |
|
|
|
|
|
| ---------------------------------------------- | ----------------------------------------------------- | ------------------------------------------------------------------- |
|
|
|
|
|
| `vendor/bin/php-cs-fixer fix --dry-run --diff` | Verifie le style PHP (PSR-12 + Symfony) sans modifier | Apres chaque modification PHP. |
|
|
|
|
|
| `vendor/bin/php-cs-fixer fix` | Corrige automatiquement le style PHP | Avant chaque commit. |
|
|
|
|
|
| `bin/phpunit` | Lance les tests PHPUnit | Apres chaque modification backend. |
|
|
|
|
|
| `php bin/console cache:clear` | Vide le cache Symfony | Si des erreurs bizarres apparaissent apres un changement de config. |
|
|
|
|
|
|
|
|
|
|
> **Les commandes backend** sont executees **dans le conteneur Docker** :
|
|
|
|
|
>
|
|
|
|
|
> ```bash
|
|
|
|
|
> docker compose exec web vendor/bin/php-cs-fixer fix --dry-run --diff
|
|
|
|
|
> docker compose exec web bin/phpunit
|
|
|
|
|
> ```
|
|
|
|
|
|
|
|
|
|
### Workflow de verification (checklist par tache)
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
1. Lire les fichiers concernes (AVANT toute modification)
|
|
|
|
|
2. Effectuer les modifications
|
|
|
|
|
3. Frontend : npx nuxi typecheck → verifier pas de nouvelles erreurs
|
|
|
|
|
4. Frontend : npm run lint:fix → corriger le formatage
|
|
|
|
|
5. Backend : php-cs-fixer fix → corriger le style PHP
|
|
|
|
|
6. Backend : bin/phpunit → verifier la non-regression
|
|
|
|
|
7. Commit si tout est OK
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 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
|