# 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

```bash
# 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 `categories` → `category`), **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.
