Files
Inventory/CLAUDE.md
Matthieu b2aff0e414 feat(sync) : add slot selection controllers, custom field sync, and position fallbacks
- Add selectedPieceId support to ComposantPieceSlotController
- Create ComposantProductSlotController and ComposantSubcomponentSlotController
- Add updateCustomFields() to SkeletonStructureService for managing CustomField entities
- Fix position/orderIndex fallback to array index in all 3 sync strategies
- Fix type comparison in ProductSyncStrategy for dual format support
- Update CLAUDE.md with new entities, controllers, and fixtures documentation
- Update frontend submodule with interactive slot selectors

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 16:40:44 +01:00

12 KiB

CLAUDE.md — Inventory Project

Project Overview

Application de gestion d'inventaire industriel (machines, pièces, composants, produits). Mono-repo avec backend Symfony et frontend Nuxt en submodule git.

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

Project Structure

Inventory/                      # Backend Symfony (repo principal)
├── src/Entity/                 # Entités Doctrine (annotations PHP 8 attributes)
├── src/Controller/             # Controllers custom (session, comments, audit…)
├── src/EventSubscriber/        # Audit subscribers (onFlush)
├── config/                     # Config Symfony
├── migrations/                 # Migrations Doctrine (raw SQL PostgreSQL)
├── docker/                     # Dockerfile + .env.docker
├── scripts/                    # release.sh, normalize-dump.py
├── fixtures/                   # SQL fixtures
├── tests/                      # PHPUnit
├── pre-commit, commit-msg      # Git hooks
├── makefile                    # Commandes Docker/dev
├── VERSION                     # Source unique de version (semver)
├── Inventory_frontend/         # ← SUBMODULE GIT (repo séparé)
│   ├── app/pages/              # Pages Nuxt (file-based routing)
│   ├── app/components/         # Composants Vue (auto-imported)
│   ├── app/composables/        # Composables Vue
│   ├── app/shared/             # Types, utils, validation
│   ├── app/middleware/          # Auth middleware global
│   └── app/services/           # Service layer (wrappers useApi)

Key Commands

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

# Backend
make test                     # PHPUnit (tous les tests)
make test FILES=tests/Api/Entity/MachineTest.php   # Un test spécifique
make php-cs-fixer-allow-risky # Linter PHP (cs-fixer)
docker exec -u www-data php-inventory-apache php bin/console doctrine:migrations:migrate

# Frontend (dans Inventory_frontend/)
npm run dev                   # Dev server (port 3001)
npm run build                 # Build production
npm run lint:fix              # ESLint fix
npx nuxi typecheck            # TypeScript check (0 errors attendu)

# Database / Fixtures
make db-reset                 # Reset database (drop + recreate schema)
make fixtures-dump            # Dump la DB vers fixtures/data.sql
make fixtures-load            # Charger les fixtures SQL (désactive FK)
make fixtures-reset           # Reset DB + recharger fixtures
make import-data              # Importer les dumps SQL normalisés
make cache-clear              # Clear cache Symfony

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

Git Conventions

Branches

  • master — production
  • develop — branche principale de dev (cible des PR)
  • feat/xxx, fix/xxx, refactor/xxx — branches de travail

Commit Message Format (enforced by hook)

<type>(<scope optionnel>) : <message>

Espace obligatoire autour du :. Types autorisés (minuscules) : build, chore, ci, docs, feat, fix, perf, refactor, revert, style, test, wip

Exemples :

  • feat(auth) : add login page
  • fix(machines) : prevent null crash on skeleton creation

Pre-commit Hook

  1. php-cs-fixer sur les fichiers PHP stagés
  2. PHPUnit — bloque le commit si tests échouent

Submodule Workflow

Le frontend est un submodule git. Lors d'un commit frontend :

  1. Commit dans Inventory_frontend/ d'abord
  2. Commit dans le repo principal pour mettre à jour le pointeur submodule
  3. Push les deux repos

Architecture Backend

Entités Principales

Machine, Piece, Composant, Product, Constructeur, Site, ModelType, CustomField, CustomFieldValue, Document, AuditLog, Comment, Profile, MachineComponentLink, MachinePieceLink, MachineProductLink

Entités de normalisation (slots & skeleton requirements)

Remplacent les anciennes colonnes JSON structure et productIds par des tables relationnelles :

  • Slots (données réelles d'un composant) : ComposantPieceSlot, ComposantSubcomponentSlot, ComposantProductSlot
  • Skeleton Requirements (définitions du ModelType) : SkeletonPieceRequirement, SkeletonProductRequirement, SkeletonSubcomponentRequirement

Patterns

  • IDs : CUID-like strings ('cl' + bin2hex(random_bytes(12))), pas d'auto-increment
  • ORM : Attributs PHP 8 (#[ORM\Column(...)], #[Groups([...])])
  • Lifecycle : #[ORM\HasLifecycleCallbacks] avec PrePersist/PreUpdate pour createdAt/updatedAt
  • Sécurité : security: "is_granted('ROLE_...')" sur chaque opération API Platform
  • Audit : Subscribers Doctrine onFlush capturent diff + snapshot complet
  • Migrations : Raw SQL PostgreSQL avec IF NOT EXISTS/IF EXISTS pour idempotence

Custom Controllers (pas API Platform)

  • MachineStructureController/api/machines/{id}/structure (GET/PATCH), /api/machines/{id}/clone (POST) : hiérarchie complète machine avec normalisation JSON manuelle. Source principale de données pour la page détail machine.
  • MachineCustomFieldsController/api/machines/{id}/add-custom-fields (POST) : initialise les CustomFieldValue manquants pour une machine.
  • CustomFieldValueController/api/custom-fields/values/* : CRUD + upsert pour les valeurs de champs perso.
  • ComposantPieceSlotController/api/composant-piece-slots/{id} (PATCH) : mise à jour des slots pièce d'un composant.
  • SessionProfileController/api/session/profile (GET/POST/DELETE) : auth session (login/logout/current user).
  • SessionProfilesController/api/session/profiles (GET) : liste des profils disponibles pour la session.
  • AdminProfileController/api/admin/profiles : CRUD profils, gestion rôles et mots de passe (ROLE_ADMIN).
  • CommentController/api/comments : création, résolution, compteur non-résolus.
  • ActivityLogController/api/activity-logs (GET) : journal d'activité global.
  • EntityHistoryController/api/{entity}/{id}/history (GET) : historique audit par entité (machines, pièces, composants, produits).
  • DocumentQueryController/api/documents/{entity}/{id} (GET) : documents par site/machine/composant/pièce/produit.
  • DocumentServeController/api/documents/{id}/file|download (GET) : servir/télécharger fichiers.
  • ModelTypeConversionController/api/model_types/{id}/conversion-check|convert : vérification et conversion de ModelType.
  • HealthCheckController/api/health (GET) : health check.

Custom Fields — Architecture

  • Composants/Pièces/Produits : définitions dans les entités SkeletonPieceRequirement, SkeletonProductRequirement, SkeletonSubcomponentRequirement du ModelType (anciennement JSON structure, normalisé en tables relationnelles). Les custom fields de ces entités sont définis dans customFields JSON sur chaque Skeleton*Requirement.
  • Machines : définitions = entités CustomField liées directement via machineId FK (pas de ModelType)
  • Les deux partagent la même entité CustomFieldValue pour stocker les valeurs

Normalisation JSON → Tables (architecture slots)

Les anciennes colonnes JSON structure et productIds des Composants ont été remplacées par des tables relationnelles :

  • ModelType définit le squelette via SkeletonPieceRequirement, SkeletonProductRequirement, SkeletonSubcomponentRequirement
  • Composant stocke les données réelles via ComposantPieceSlot, ComposantProductSlot, ComposantSubcomponentSlot
  • Chaque slot référence son skeleton requirement (skeletonRequirement FK) + l'entité sélectionnée + position

Rôles (hiérarchie)

ROLE_ADMIN → ROLE_GESTIONNAIRE → ROLE_VIEWER → ROLE_USER

PostgreSQL — ATTENTION

  • Les noms de colonnes sont TOUJOURS EN MINUSCULES dans PG
  • Doctrine utilise camelCase (typePieceId) mais PG stocke typepieceid
  • Le SQL brut doit utiliser les noms lowercase
  • Tables de jointure many-to-many : colonnes a et b (ex: _piececonstructeurs)

Architecture Frontend

Patterns

  • Composables : interface Deps { ... } + export function useXxx(deps: Deps)
  • Communication composants : Props + Events uniquement (pas de provide/inject)
  • API : useApi.ts wraps fetch avec credentials: 'include' pour les cookies session
  • Content-Type : application/ld+json pour POST/PUT, application/merge-patch+json pour PATCH
  • Auth : useProfileSession + middleware global profile.global.ts
  • Permissions : usePermissions.ts miroir de la hiérarchie backend côté client
  • Auto-imports : Nuxt auto-importe composants (components/) et composables (composables/)

DaisyUI Classes

  • Input : input input-bordered input-sm md:input-md
  • Textarea : textarea textarea-bordered textarea-sm md:textarea-md
  • Select : select select-bordered select-sm md:select-md
  • Button : btn btn-sm md:btn-md btn-primary

Règles Importantes

CLAUDE.md — Maintenance obligatoire

  • Toujours consulter ce fichier en début de conversation pour respecter les conventions
  • Mettre à jour ce fichier quand une nouvelle convention, pattern ou décision architecturale est établie
  • Utiliser comme source de vérité pour les commandes, patterns et règles du projet

Toujours faire AVANT de modifier du code

  1. Lire le fichier avant de l'éditer — ne jamais proposer de changements sur du code non lu
  2. Comprendre le pattern existant — reproduire le style du fichier (noms, indentation, structure)
  3. Vérifier les deux repos — un changement peut impacter backend ET frontend

Après chaque modification

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

Ne jamais faire

  • Ajouter des features non demandées, du code mort, ou des abstractions prématurées
  • Utiliser provide/inject — le codebase utilise Props + Events
  • Utiliser JWT/tokens — l'auth est session-based
  • Écrire du SQL avec des noms camelCase — PostgreSQL = lowercase
  • Committer sans que l'utilisateur le demande explicitement
  • Force push sans confirmation explicite
  • Modifier la config git

Submodule — Synchronisation

Quand les branches master et develop divergent sur l'un des deux repos, toujours les synchroniser :

  • Main repo : git checkout master && git merge develop && git push
  • Frontend : git checkout develop && git merge master && git push (ou l'inverse selon le cas)

Tests

Stack de test

  • PHPUnit 12 + API Platform Test (ApiTestCase)
  • DAMA DoctrineTestBundle — wrappe chaque test dans une transaction avec rollback automatique (pas de TRUNCATE)
  • Base de test : même PG, env test

Commandes

Voir section "Key Commands". Commande additionnelle :

make test-setup               # Créer/mettre à jour le schéma test

Pattern de test

  • Hériter de AbstractApiTestCase (helpers auth + factories)
  • Ne PAS faire de TRUNCATE/cleanup dans tearDown — DAMA s'en occupe par rollback
  • Factories : createProfile(), createMachine(), createSite(), createComposant(), createPiece(), createProduct(), createConstructeur(), createCustomField(), createCustomFieldValue(), createModelType(), createMachineComponentLink(), createMachinePieceLink(), createMachineProductLink(), createComposantPieceSlot(), createComposantSubcomponentSlot(), createComposantProductSlot()
  • Auth : createViewerClient(), createGestionnaireClient(), createAdminClient(), createUnauthenticatedClient()

URLs Locales

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