Files
Inventory/CLAUDE.md
T
2026-06-04 16:52:05 +02:00

9.1 KiB

CLAUDE.md — Inventory Project

Application de gestion d'inventaire industriel (machines, pièces, composants, produits). Monorepo : backend Symfony + frontend Nuxt (frontend/) dans le même dépôt git (plus de submodule). Un seul commit/push couvre backend + frontend.

Stack

Layer Tech Version
Backend Symfony + API Platform 8.0 / ^4.2
PHP PHP >=8.4
Database PostgreSQL 16
Frontend Nuxt (SPA, SSR off) 4
UI Vue 3 Composition API + TypeScript 3.5 / 5.7
CSS TailwindCSS 4 + DaisyUI 5
Auth Session-based (cookies, pas JWT)
Containers Docker Compose

Documentation détaillée (lire à la demande, ne pas dupliquer ici)

Vu la complexité du projet, le détail vit dans docs/ — y aller plutôt que de deviner :

  • docs/FONCTIONNEMENT.md — le métier : à quoi sert l'app, entités, ModelType/skeleton, cycle de vie, rôles, fonctionnalités clés.
  • docs/GLOSSAIRE_METIER.md — glossaire complet, correspondance métier ↔ code (le « pourquoi »).
  • docs/BACKEND.md — catalogue backend complet : toutes les entités, tous les controllers (routes), audit, services, migrations, auth, rôles.
  • docs/FRONTEND.md — catalogue frontend : composables, composants, useApi, IRIs, content-types, auth, style.
  • docs/REVIEW_ARCHITECTURE.md — top 10 des sources de complexité et effets de bord (God controllers, canaux cachés, doubles flush…). À consulter avant tout refacto.

Project Structure

Inventory/                      # Backend Symfony (repo principal)
├── src/Entity/ (+ Trait/)      # Entités Doctrine (attributs PHP 8), CuidEntityTrait
├── src/Controller/             # Controllers custom (session, comments, audit, structure…)
├── src/EventSubscriber/        # Audit (onFlush) + sync/contraintes
├── src/Service/ (+ Sync/)      # Services métier (sync, conversion, storage, versions…)
├── src/Enum/ src/DTO/ src/Filter/ src/Command/
├── config/ migrations/ docker/ scripts/ fixtures/ tests/
├── makefile  VERSION           # VERSION = source unique de version (semver)
└── frontend/                   # ← Frontend Nuxt (MÊME repo, pas un submodule)
    └── app/{pages,components,composables,shared,middleware,services}/

Key Commands

# Docker
make start / make stop          # Démarrer / arrêter les containers
make shell                      # Shell interactif (nécessite un TTY)
make install                    # Install complet (composer + npm + build)

# Backend
make test                       # PHPUnit (tous)
make test FILES=tests/Api/Entity/MachineTest.php   # Un test
make test-setup                 # Créer/MAJ le schéma de test
make php-cs-fixer-allow-risky   # Linter PHP
docker exec -u www-data php-inventory-apache php bin/console doctrine:migrations:migrate

# Frontend (dans frontend/)
npm run dev                     # Dev server (port 3001)
npm run lint:fix                # ESLint fix
npx nuxi typecheck              # TypeScript check (0 erreur attendu)

# Database / Fixtures
make db-reset                   # Reset DB (drop + recreate schema)
make fixtures-reset             # Reset DB + recharger fixtures SQL
make import-data                # Importer les dumps SQL normalisés
make cache-clear

# Import fournisseurs (non destructif : find-or-create par nom normalisé)
docker exec -u www-data php-inventory-apache php bin/console app:import-fournisseurs          # dry-run
docker exec -u www-data php-inventory-apache php bin/console app:import-fournisseurs --force  # applique

# Release
./scripts/release.sh patch      # Bump version (patch/minor/major)

Git Conventions

  • Branches : master (prod), develop (cible des PR), feat/* fix/* refactor/*.
  • Commit (enforced par hook) : <type>(<scope>) : <message>espace obligatoire autour du :. Types : build chore ci docs feat fix perf refactor revert style test wip.
    • Ex : feat(auth) : add login page, fix(machines) : prevent null crash
  • Pre-commit hook : php-cs-fixer + PHPUnit (bloque si échec).
  • Workflow commit : backend + frontend = un seul commit/push depuis la racine (pas de submodule). Le hook étant lent, committer avec git commit --no-verify. Push rejeté → git pull --rebase puis git push.
  • Sync master ↔ develop : git checkout master && git merge develop && git push puis revenir sur develop.

Pièges & patterns non-évidents

Le catalogue complet est dans docs/BACKEND.md / docs/FRONTEND.md. Ci-dessous uniquement ce qui n'est pas évident en lisant le code.

Backend

  • IDs CUID : strings 'cl' + bin2hex(random_bytes(12)), pas d'auto-increment.
  • Lifecycle : #[ORM\HasLifecycleCallbacks] + PrePersist/PreUpdate pour createdAt/updatedAt.
  • Sécurité : security: "is_granted('ROLE_...')" sur chaque opération API Platform. Hiérarchie : ROLE_ADMIN → ROLE_GESTIONNAIRE → ROLE_VIEWER → ROLE_USER.
  • Audit : subscribers Doctrine onFlush (diff + snapshot complet).
  • Migrations : raw SQL PostgreSQL avec IF NOT EXISTS/IF EXISTS (idempotence).
  • Constructeur (Fournisseur) : collection telephones (1-N, cascade/orphanRemoval) + categories (M2M, table constructeur_categories). ⚠️ L'adder M2M est addCategory()/removeCategory() (l'inflector singularise categoriescategory), pas addCategorie. Groupes API constructeur:read / constructeur:write.
  • Normalisation slots/skeleton : les anciennes colonnes JSON structure/productIds sont remplacées par des tables relationnelles — slots réels (ComposantPieceSlot, ComposantSubcomponentSlot, ComposantProductSlot, PieceProductSlot) vs définitions ModelType (SkeletonPieceRequirement, SkeletonProductRequirement, SkeletonSubcomponentRequirement).
  • Custom Fields : Composants/Pièces/Produits → définitions dans les Skeleton*Requirement du ModelType (clé customFields JSON) ; Machines → entités CustomField liées par machineId FK (pas de ModelType). Les deux partagent l'entité CustomFieldValue pour les valeurs.
  • MachineStructureController (/api/machines/{id}/structure, /clone) : source principale de données de la page détail machine (normalisation JSON manuelle). Cf. REVIEW_ARCHITECTURE.md (God controller).

PostgreSQL — ATTENTION

  • Noms de colonnes TOUJOURS EN MINUSCULES en PG. Doctrine camelCase (typePieceId) → PG typepieceid. Le SQL brut doit être lowercase.
  • Tables de jointure M2M : colonnes a et b (ex : _piececonstructeurs).

Frontend

  • Composables : interface Deps { ... } + export function useXxx(deps: Deps).
  • Communication composants : Props + Events uniquement (pas de provide/inject).
  • API : useApi.ts wrappe fetch avec credentials: 'include'. ⚠️ useApi() préfixe déjà /api → appeler sans /api au début. Ex : api.get('/custom-fields/names') et PAS '/api/custom-fields/names' (sinon 404 sur /api/api/...).
  • Content-Type : application/ld+json (POST/PUT), application/merge-patch+json (PATCH).
  • Auth : useProfileSession + middleware global profile.global.ts. Permissions : usePermissions.ts (miroir de la hiérarchie backend).
  • Classes DaisyUI : input input-bordered input-sm md:input-md (idem textarea/select/btn, btn-primary).

Règles Importantes

Avant de modifier du code

  1. Lire le fichier avant de l'éditer.
  2. Reproduire le pattern existant (noms, indentation, structure).
  3. Vérifier backend ET frontend — un changement peut impacter les deux (même repo).

Après chaque modification

  1. Backend PHP : make php-cs-fixer-allow-risky
  2. Frontend TS : npm run lint:fix puis npx nuxi typecheck

Ne jamais faire

  • Features non demandées, code mort, abstractions prématurées
  • provide/inject (le code utilise Props + Events) · JWT/tokens (auth session-based)
  • SQL en camelCase (PG = lowercase)
  • Committer sans demande explicite · force push sans confirmation · modifier la config git

Maintenir ce fichier

Mettre à jour quand une nouvelle convention/pattern/décision archi est établie. Source de vérité pour commandes, pièges et règles ; le détail descriptif va dans docs/.

Tests

  • PHPUnit 12 + API Platform Test (ApiTestCase), env test, même PG.
  • DAMA DoctrineTestBundle : chaque test wrappé en transaction + rollback auto → ne PAS faire de TRUNCATE/cleanup en tearDown.
  • Hériter de AbstractApiTestCase (helpers auth + factories create*()).
  • Auth : createViewerClient(), createGestionnaireClient(), createAdminClient(), createUnauthenticatedClient().

URLs Locales

  • API Symfony : http://localhost:8081/api · Nuxt dev : http://localhost:3001
  • Adminer : http://localhost:5050 · PG direct : localhost:5433 (user/pass root, db inventory)

Délégation Codex

Pour les tâches mécaniques (tests, boilerplate, renommages, refacto répétitif), déléguer à Codex via le plugin codex (junior rapide/pas cher). Garder Claude pour la réflexion, l'architecture et la vérification (senior). Meilleur ratio qualité/crédits.