Update frontend submodule with 14 conventional commits covering: - F1.1-F1.4: Decompose mega-components (machine detail/create, ComponentItem/PieceItem) - F2.1-F2.3: Extract shared helpers (extractCollection, history, types) - F3.2-F3.3: Migrate composables to TypeScript, eliminate explicit any - F4.1-F4.2: Enable strict ESLint rules, remove debug console.logs - F5.1: Split modelUtils into thematic modules - F6.1-F6.2: Configure Vitest with 54 unit tests - F7.2-F7.3: DaisyUI confirm modal, extract AppNavbar Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
37 KiB
Plan de Refactoring - Inventory v1.2.0
Date de creation : 2026-02-03 Branche de travail :
refacto/v1.3.0Base :develop(commit8d83076)
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_ACCESSapplique a toutes les routes/apiavant la regleIS_AUTHENTICATED_FULLY. Le pattern matching "first match wins" rend potentiellement tout public. - Action : Reordonner les regles
access_controlpour 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.phpsrc/Controller/CustomFieldValueController.phpsrc/Controller/DocumentQueryController.phpsrc/Controller/SessionProfileController.phpsrc/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(credentialsroot:root)
- Action :
- Deplacer
JWT_PASSPHRASEdans.env.local(git-ignore) - Generer un
APP_SECRETvalide - Ajouter
.env.localdans.gitignoresi pas deja fait - Documenter la configuration des secrets pour les devs
- Deplacer
- 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 methodessnapshot*()different legerement. - Action :
- Creer un
AbstractAuditSubscriberou unGenericAuditSubscriberparametrable - Extraire la logique commune (onFlush, buildDiff, resolveActor, mergeDiffs, normalizeCollection)
- Utiliser un systeme de configuration par entite (map
entityClass => entityType + snapshotMethod) - Supprimer les 3 fichiers redondants
- Verifier que l'audit fonctionne toujours sur Product, Piece et Composant
- Creer un
- 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.phputilise une variante differente (base_convert). - Action :
- Creer
src/Util/CuidGenerator.phpavec une methode statiquegenerate(): string - Uniformiser l'implementation (choisir une seule methode)
- Remplacer tous les appels dans les 18 entites
- Supprimer les methodes privees devenues inutiles
- Creer
- 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 :
- Extraire une methode generique
applyLinks(Machine $machine, array $links, string $type) - Parametrer par le type d'entite liee (Composant, Piece, Product)
- Reduire le controller a ~400 LOC max
- Extraire une methode generique
- 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 :
- Extraire la logique metier dans un
MachineSkeletonService - Le controller ne doit gerer que la requete/reponse HTTP
- Le service gere la logique de skeleton (get, update, applyLinks)
- Extraire les helpers (
resolveIdentifier,indexLinksById,applyOverrides,normalizeMachineSkeletonResponse) dans le service
- Extraire la logique metier dans un
- 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()etpersist(). Pas de logging d'erreurs. - Action :
- Ajouter
try-catchautour des operations Doctrine dans chaque controller - Logger les erreurs avec le
LoggerInterfacede Symfony (Monolog) - Retourner des reponses JSON coherentes en cas d'erreur serveur (500)
- Ajouter
- Agent : -
- Notes : -
3.3 Renforcer la validation des entrees
- Statut :
[ ] - Fichiers :
src/Controller/CustomFieldValueController.phpsrc/Controller/MachineSkeletonController.php
- Probleme : Pas de validation de longueur max, pas de regex sur les IDs, pas de controle de profondeur JSON.
- Action :
- Valider le format des IDs (regex CUID :
/^cl[a-f0-9]{24}$/) - Ajouter des limites de longueur sur les champs string
- Utiliser le composant Validator de Symfony pour les DTOs si pertinent
- Valider le format des IDs (regex CUID :
- 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.phpsrc/Command/CompressPdfCommand.phpsrc/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 :
- Utiliser
vich/uploader-bundle(deja installe) pour le stockage fichier - Configurer un repertoire de stockage (
var/uploads/documents/) - Migrer les documents existants (script de migration)
- Adapter
PdfCompressorServicepour lire/ecrire sur le filesystem - Mettre a jour l'entite Document
- Utiliser
- 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
?stringen PHP alors que la colonne estDECIMAL(10,2)en BDD. - Action :
- Changer le type PHP en
?floatou utiliserbrick/money - Adapter les getters/setters
- Verifier la serialisation API Platform
- Changer le type PHP en
- 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 appelerqpdf. - Action :
- Remplacer par
Symfony\Component\Process\Process - Gerer le timeout et les erreurs proprement
- Tester que la compression fonctionne toujours
- Remplacer par
- 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.phptests/Unit/Entity/MachineTest.phptests/Unit/Entity/ProductTest.phptests/Unit/Service/PdfCompressorServiceTest.php
- Action :
- Tester le CuidGenerator (format, unicite)
- Tester les entites (validation, lifecycle callbacks)
- Tester le PdfCompressorService
- Agent : -
- Notes : -
6.2 Mettre en place les tests fonctionnels (API)
- Statut :
[ ] - Fichiers a creer :
tests/Functional/Api/MachineTest.phptests/Functional/Api/ProductTest.phptests/Functional/Api/AuthenticationTest.phptests/Functional/Api/MachineSkeletonTest.php
- Action :
- Configurer une base de test (SQLite ou PostgreSQL de test)
- Creer des fixtures de test
- Tester les endpoints CRUD
- Tester l'authentification JWT
- Tester les endpoints custom (skeleton, custom fields)
- Agent : -
- Notes : Utiliser
ApiTestCasede API Platform.
6.3 Tests des Audit Subscribers
- Statut :
[ ] - Fichiers a creer :
tests/Unit/EventSubscriber/AuditSubscriberTest.php
- Action :
- Tester la creation de logs sur insert/update/delete
- Tester le format des diffs et snapshots
- 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 ? vsInventory_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 metiercomposables/useMachineSkeletonEditor.ts(843 LOC) — logique skeletoncomponents/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, creationcomponents/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 :
- Identifier les sections communes entre create/edit (factoriser)
- Extraire chaque section en composant reutilisable :
EntityFormGeneral.vue(nom, reference, description)EntityFormSuppliers.vue(constructeurs)EntityFormDocuments.vue(documents)EntityFormCustomFields.vue(champs personnalises)
- Objectif par page : <400 LOC
- Agent : -
- Notes : Les formulaires create et edit partagent beaucoup de code. Factoriser.
- Sous-taches :
- F1.3a Extraire
customFieldFormUtils.ts(duplique dans 5 fichiers) - F1.3b Extraire
documentDisplayUtils.ts(duplique dans 3 pages edit) - F1.3c Extraire
historyDisplayUtils.ts(duplique dans 3 pages edit) - F1.3d Rewire les 5 pages create/edit sur les modules extraits
- F1.3e Typecheck + commit F1.3 (erreurs F1.3 corrigees, 120 erreurs preexistantes documentees)
- F1.3a Extraire
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 :
- Extraction de la logique pure custom fields dans
shared/utils/entityCustomFieldLogic.ts(~350 LOC) - Creation de
composables/useEntityCustomFields.ts(composable reactif, ~180 LOC) - Creation de
composables/useEntityDocuments.ts(CRUD documents + preview, ~120 LOC) - Creation de
composables/useEntityProductDisplay.ts(affichage produit, ~100 LOC) - Import des helpers document depuis
shared/utils/documentDisplayUtils.ts(existant) - Rewrite des deux composants pour utiliser les modules partages
- Typecheck 0 erreurs, lint 0 erreurs
- Extraction de la logique pure custom fields dans
- Sous-taches :
- F1.4a Extraire
entityCustomFieldLogic.ts(fonctions pures) - F1.4b Creer
useEntityCustomFields.ts(composable reactif) - F1.4c Creer
useEntityDocuments.ts(composable documents) - F1.4d Creer
useEntityProductDisplay.ts(composable produit) - F1.4e Rewrite ComponentItem.vue (1336 → 585 LOC, script 900 → 150 LOC)
- F1.4f Rewrite PieceItem.vue (1588 → 740 LOC, script 1100 → 255 LOC)
- F1.4g Typecheck + lint (0 erreurs)
- F1.4a Extraire
- 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.tscomposables/useProducts.tscomposables/usePieces.tscomposables/useComposants.tscomposables/useMachineTypesApi.jscomposables/useConstructeurs.tscomposables/useDocuments.tscomposables/useMachineCreateSelections.tscomponents/ComponentStructureAssignmentNode.vuecomponents/model-types/ManagementView.vue
- Probleme : La fonction
extractCollection()(parsinghydra:member/member/items/data/ array) etait dupliquee dans 10 fichiers. - Action :
- Creer
shared/utils/apiHelpers.tsavecextractCollection<T>()generique - Remplacer les 10 implementations locales par un import
- Creer
- Agent : -
- Notes : Gere aussi
items(utilise par ManagementView.vue).extractRelationId()etnormalizeRelationIds()restent dansshared/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 :
- Creer
composables/useEntityHistory.tsparametrable par type d'entite - Reecrire les 3 fichiers specifiques en wrappers backward-compatible
- Creer
- 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 :
- Creer
composables/useEntityTypes.tsgenerique (CRUD + singleton state par categorie) - Reecrire les 3 fichiers specifiques en wrappers avec renommage des champs
- Creer
- Agent : -
- Notes : Les wrappers renomment
types→componentTypes/pieceTypes/productTypes, preserventgetXxxTypes()etisXxxTypeLoading(). Etat partage viastateByCategorymap 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—Machineinterfacecomposables/useMachineTypesApi.ts—MachineType,MachineTypeRequirementinterfacescomposables/useToast.ts—Toast,ToastTypetypescomposables/useProfiles.ts—Profileinterfacecomposables/useCustomFields.ts—CustomFieldValueinterface
- Notes : Les types sont definis dans chaque composable (colocation). Types entite existants :
Product,Piece,Composant,Constructeur,Site,Documentdans leurs composables respectifs (.ts).shared/types/inventory.tscontient les types de structure de modele.
F3.2 Convertir les composables JS en TS
- Statut :
[x] - Fichiers convertis (7 fichiers JS → TS) :
useToast.js→useToast.ts(72 LOC, types:Toast,ToastType)useProfiles.js→useProfiles.ts(68 LOC, type:Profile)useProfileSession.js→useProfileSession.ts(85 LOC, importeProfile)useApi.js→useApi.ts(106 LOC → 120 LOC, types:ApiResponse<T>,ApiCallOptions, ajoutput())useCustomFields.js→useCustomFields.ts(105 LOC, type:CustomFieldValue)useMachineTypesApi.js→useMachineTypesApi.ts(173 → 188 LOC, types:MachineType,MachineTypeRequirement)useMachines.js→useMachines.ts(267 LOC, type:Machine, utiliseextractCollection)
- 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 defautanypour backward-compat. Les callers existants fonctionnent sans changement ; le nouveau code peut opt-in strict viaget<MyType>().
F3.3 Eliminer les any restants
- Statut :
[x] - Fichiers concernes :
components/ProductSelect.vue— 1anyrestant (slot template, incompressible)components/model-types/ManagementView.vue— remplacedata?: any→Record<string, unknown>,error: any→error: unknown,item: any→item: unknowncomponents/ComponentStructureAssignmentNode.vue— 12 casts(definition as any).typePiece/typeProductelimines grace a l'extension des typescomponents/ComponentModelStructureEditor.vue—Promise<any>→Promise<unknown>components/model-types/ModelTypeForm.vue—(incoming as any).description→ castRecord<string, unknown>shared/types/inventory.ts—ComponentModelPiece.typePiece?etComponentModelProduct.typeProduct?ajoutes, 3 casts(value as any)supprimes
- Probleme : 20+ usages de
anytype identifies. - Action : Etendre les interfaces de types pour supporter les formes alternatives de l'API. Remplacer les
anyparunknownouRecord<string, unknown>la ou possible. - Agent : Claude
- Notes : ~15 casts
anyelimines. LesRecord<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 :
- Active
@typescript-eslint/no-explicit-any: warn(526 warnings — amelioration progressive) - Active
no-console: warnavecallow: ['error']— 0 violations (deja nettoye en F4.2) - Active
@typescript-eslint/no-unused-vars: warnavec ignore^_— 0 violations (26 corrigees) - Corrige les 26 violations
no-unused-vars: imports inutilises supprimes, variables prefixees_, destructurations nettoyees
- Active
- Agent : Claude
- Notes : 16 fichiers modifies. Regles organisees par categorie (vue, console, typescript, formatting). 0 erreurs, 526 warnings
no-explicit-anyrestants (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.logde debug laisses dans le code de production. - Action :
- Supprimer les 19
console.logde debug (normalizeRequirementList, page loading, route params, etc.) - Les 72
console.errorrestants sont conserves (gestion d'erreur legitime). Migration vers un logger centralise a faire en F4.3.
- Supprimer les 19
- Agent : Claude
- Notes : 0
console.log/warn/debug/inforestants 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 :
- Ajouter un systeme de retry configurable (1-3 tentatives)
- Centraliser la gestion des erreurs HTTP (401 -> redirect login, 500 -> message explicite)
- Ajouter des intercepteurs request/response
- 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 :
- Identifier les groupes de fonctions (structure, custom fields, requirements, serialization)
- Decouper en 3 modules thematiques :
shared/model/componentStructure.ts(~590 LOC) — helpers, sanitize, hydrate, normalize, extract, format pour composantsshared/model/pieceProductStructure.ts(~155 LOC) — structure piece/produit (clone, sanitize, hydrate, format)shared/model/definitionOverrides.ts(~50 LOC) — sanitization des overrides de definition
- 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#importstests/__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 :
- Installe
vitest,@vue/test-utils,happy-dom - Configure Vitest avec environment happy-dom et resolution d'alias
- Ajoute scripts
testettest:watchdanspackage.json - Premier test suite :
componentModelStructureValidator(9 tests, 100% pass)
- Installe
- Agent : Claude
- Notes :
npm test→ 9 tests, 0 failures, <1s. Alias#importspointe 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 :
- Teste
extractCollection(): array, hydra:member, member, items, data, null, undefined - Teste
useToast: ajout, types, max 3 toasts, clearAll, removeToast, singleton - Teste
useConfirm: open/close, resolve true/false, custom options, singleton state - Teste
modelUtils: clone, stats, preview, isPlainObject, piece/product variants - Teste
componentModelStructureValidator: valid/invalid, custom fields, subcomponents
- Teste
- Agent : Claude
- Notes : 54 tests, 5 fichiers, 100% pass, <2s. Tests
useApiet CRUD composables necessitent mock fetch (phase ulterieure).
F6.3 Tests de composants
- Statut :
[ ] - Fichiers a creer :
tests/components/Pagination.test.tstests/components/SearchSelect.test.tstests/components/MachineHeader.test.ts(apres F1.1)
- Action :
- Tester les composants communs (Pagination, SearchSelect)
- 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 :
- Identifier les cas de props drilling >2 niveaux
- Utiliser
provide/injectou des composables partages - 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 :
- Cree
composables/useConfirm.ts— composable promise-based avec etat reactif partage - Cree
components/common/ConfirmModal.vue— modale DaisyUI teleportee (backdrop blur, btn-error) - Monte
ConfirmModalglobalement dansapp.vue - Remplace les 10
confirm()natifs dans 10 fichiers :constructeurs.vue,profiles/manage.vue,ManagementView.vueproduct-catalog.vue,index.vue,machines/index.vuemachine-skeleton/index.vue,pieces-catalog.vue,component-catalog.vueuseSiteManagement.ts(composable — import explicite)
- Cree
- 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 :
- Cree
composables/useNavDropdown.ts(~65 LOC) — gestion etat dropdowns navbar - Cree
components/layout/AppNavbar.vue(~310 LOC) — navbar data-driven avecv-foreliminant duplication mobile/desktop app.vuereecrit en orchestrateur minimal (49 LOC) + converti en TypeScript- Supprime 4 imports d'icones inutilises
- Cree
- Agent : Claude
- Notes : Approche data-driven : liens et groupes definis comme tableaux types (
NavLink[],NavGroup[]), rendus parv-forpour 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/: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 :
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
-
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
- Mettre le statut a
-
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-fixerapres les modifications
-
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"
- Mettre le statut a
-
En cas de blocage :
- Mettre le statut a
[!] - Documenter le blocage dans "Notes"
- Ne PAS passer a une autre tache sans signaler le blocage
- Mettre le statut a
-
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 ouuseToast - 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
-
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