# Piece Quantity — Design Spec ## Context L'application gère des machines composées de composants et de pièces. Une même pièce (catalogue) peut apparaître dans plusieurs contextes avec des quantités différentes. La quantité doit être portée par la **relation**, pas par l'entité catalogue. ## Scope - Quantité sur les **pièces directement liées à une machine** (`MachinePieceLink`) - Quantité sur les **pièces d'un composant** (JSON `structure.pieces` du `Composant`) - **Hors scope** : quantité sur `MachineComponentLink`, `MachineProductLink`, override de quantité composant au niveau machine ## Règles métier | Contexte | Stockage | Éditable depuis | Visible sur machine | |----------|----------|-----------------|---------------------| | Pièce directement sur machine | `MachinePieceLink.quantity` | Page machine | Oui, éditable | | Pièce d'un composant | `Composant.structure.pieces[].quantity` | Page composant (création + édition) | Oui, lecture seule | - Type : entier, valeur par défaut = 1 - Affichage : "×N" après le nom de la pièce, masqué si N = 1 ## Backend ### 1. MachinePieceLink — Nouvelle colonne Ajout d'un champ `quantity` sur l'entité `MachinePieceLink` : ```php #[ORM\Column(type: Types::INTEGER, options: ['default' => 1])] #[Groups(['machine_piece_link:read', 'machine_piece_link:write'])] private int $quantity = 1; ``` Getter/setter standard. ### 2. Migration SQL ```sql ALTER TABLE machine_piece_link ADD COLUMN IF NOT EXISTS quantity INTEGER NOT NULL DEFAULT 1; ``` Idempotente avec `IF NOT EXISTS`. ### 3. Composant.structure JSON Le tableau `pieces` dans le JSON `structure` du Composant accepte une nouvelle clé `quantity`. Pas de migration DB nécessaire — c'est un champ JSON libre. Avant : ```json { "typePieceId": "...", "role": "Filtration" } ``` Après : ```json { "typePieceId": "...", "role": "Filtration", "quantity": 4 } ``` Les entrées existantes sans `quantity` sont traitées comme `quantity = 1` (défaut côté frontend et backend). ### 4. MachineStructureController - `normalizePieceLinks()` : inclure `quantity` dans la réponse JSON - Pièce machine directe (parentLink = null) : `quantity` depuis `MachinePieceLink.quantity` - Pièce sous composant : `quantity` depuis le `structure.pieces` du composant source - **PATCH** : accepter `quantity` pour les pièces directement sur la machine uniquement ## Frontend ### 1. Types TypeScript Mise à jour de `ComponentModelPiece` : ```typescript interface ComponentModelPiece { typePieceId?: string typePieceLabel?: string reference?: string familyCode?: string role?: string quantity?: number // défaut 1 } ``` ### 2. Pages composant (création + édition) Dans l'éditeur de structure, chaque pièce du tableau `structure.pieces` affiche un champ input : - Type : `number`, min = 1, step = 1 - Valeur par défaut : 1 - Style : `input input-bordered input-sm md:input-md` (DaisyUI) - Position : à côté des champs existants (reference, role) ### 3. Page machine (détail/structure) - **Pièce directe** (parentLink = null) : affiche "×N" à côté du nom, quantité éditable (input entier) - **Pièce de composant** : affiche "×N" à côté du nom, lecture seule (pas d'input) - Si quantité = 1 : rien n'est affiché (pas de bruit visuel) - Style du label : texte secondaire (`text-base-content/60` ou classe équivalente)