docs : update piece quantity spec after review

Address review findings: drop Groups attribute, add clone logic,
specify PATCH payload format, list frontend functions to update,
add validation and test cases.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Matthieu
2026-03-12 11:48:01 +01:00
parent 7a7af58074
commit b8edf1ea95

View File

@@ -8,7 +8,7 @@ L'application gère des machines composées de composants et de pièces. Une mê
- 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
- **Hors scope** : quantité sur `MachineComponentLink`, `MachineProductLink`, override de quantité composant au niveau machine, audit logging
## Règles métier
@@ -17,8 +17,9 @@ L'application gère des machines composées de composants et de pièces. Une mê
| 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
- Type : entier, valeur par défaut = 1, minimum = 1
- Affichage : "×N" après le nom de la pièce, masqué si N = 1
- Quantité = 0 n'est pas valide (utiliser la suppression du lien à la place)
## Backend
@@ -28,11 +29,12 @@ 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.
Getter/setter standard. **Pas de `#[Groups]`** — cohérent avec les autres champs de l'entité qui n'en déclarent pas (l'entité n'a pas de `normalizationContext`).
Validation : `#[Assert\GreaterThanOrEqual(1)]`
### 2. Migration SQL
@@ -60,29 +62,69 @@ Les entrées existantes sans `quantity` sont traitées comme `quantity = 1` (dé
### 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
#### Normalisation (GET)
`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. Résolution :
1. Naviguer `MachinePieceLink``parentLink` (MachineComponentLink) → `composant``structure['pieces']`
2. Matcher par index de position dans le tableau `pieces` (l'ordre des pièces dans la structure correspond à l'ordre de création des liens)
3. Fallback : `quantity = 1` si non trouvé
#### PATCH structure
Dans `applyPieceLinks()`, accepter `quantity` au même niveau que `pieceId` dans le payload :
```json
{
"pieceLinks": [
{ "pieceId": "cl...", "quantity": 4, "overrides": { "nameOverride": "..." } }
]
}
```
- `quantity` est appliqué uniquement pour les pièces directement sur la machine (pas de `parentComponentLinkId`)
- Si `parentComponentLinkId` est présent, `quantity` est **ignoré silencieusement** (la valeur vient du composant)
#### Clone
`clonePieceLinks()` doit copier `quantity` depuis le lien source :
```php
$newLink->setQuantity($link->getQuantity());
```
Sans cela, les machines clonées perdraient les quantités (reset à 1).
### 5. Tests
Ajouter dans `MachinePieceLinkTest.php` :
- POST avec `quantity` explicite → vérifier la valeur
- POST sans `quantity` → vérifier défaut = 1
- PATCH `quantity` sur pièce directe → vérifier mise à jour
- GET structure → vérifier `quantity` dans la réponse normalisée
- Clone → vérifier que `quantity` est préservé
## Frontend
### 1. Types TypeScript
Mise à jour de `ComponentModelPiece` :
Mise à jour de `ComponentModelPiece` dans `shared/types/inventory.ts` — ajout du champ `quantity` :
```typescript
interface ComponentModelPiece {
typePieceId?: string
typePieceLabel?: string
reference?: string
familyCode?: string
role?: string
quantity?: number // défaut 1
}
quantity?: number // défaut 1
```
### 2. Pages composant (création + édition)
### 2. Fonctions de sanitization/normalisation à mettre à jour
Ces fonctions énumèrent explicitement les champs à conserver et doivent inclure `quantity` :
- `normalizeStructureForSave()` dans `shared/model/componentStructure.ts` — inclure `quantity` dans le payload backend des pièces
- `sanitizePieceDefinition()` dans `shared/utils/structureAssignmentHelpers.ts` — préserver `quantity`
- `sanitizePieces()` dans `shared/model/componentStructureSanitize.ts` — préserver `quantity` dans la sortie
- `hydratePieces()` / `mapComponentPieces()` — préserver `quantity` lors de l'hydratation
### 3. 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
@@ -90,7 +132,7 @@ Dans l'éditeur de structure, chaque pièce du tableau `structure.pieces` affich
- Style : `input input-bordered input-sm md:input-md` (DaisyUI)
- Position : à côté des champs existants (reference, role)
### 3. Page machine (détail/structure)
### 4. 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)