# Spec — Stock

> Statut : `done`

## Intention

Suivre le niveau de stock de chaque produit avec un historique des mouvements (entrées, ajustements manuels, sorties par vente).

## Contraintes

- Le stock courant est stocké directement sur `Product.stock` pour performance.
- Chaque modification de stock crée un `StockMovement` pour traçabilité.
- Les mouvements de type SALE sont créés automatiquement par le processus de vente.
- Les entrées et ajustements sont saisis manuellement par l'admin (back-office).

## Comportement attendu

### Entrée de stock (back-office)
1. L'admin sélectionne un produit.
2. Il saisit la quantité reçue et un motif optionnel.
3. Un `StockMovement` de type ENTRY est créé, le stock courant est incrémenté.

### Ajustement (back-office)
1. L'admin saisit la quantité d'ajustement (positive ou négative) et un motif obligatoire.
2. Un `StockMovement` de type ADJUSTMENT est créé, le stock est mis à jour.

### Vente (automatique)
- À chaque validation de vente, un `StockMovement` de type SALE est créé par ligne de vente.
- Le stock est décrémenté de la quantité vendue.

### Consultation
- L'admin voit le stock courant de chaque produit.
- Il peut consulter l'historique des mouvements (filtrable par produit, type, date).

## Critères de « fait »

- [x] Entité `StockMovement` avec produit, type, quantité, motif, date.
- [x] Enum `StockMovementType` (ENTRY, ADJUSTMENT, SALE).
- [x] CRUD EasyAdmin pour les entrées de stock.
- [x] Formulaire d'ajustement avec motif obligatoire.
- [x] Mouvements SALE créés automatiquement à la vente.
- [x] Stock courant mis à jour sur `Product` à chaque mouvement.
- [x] Historique des mouvements consultable et filtrable.

## Un produit hors suivi de stock — ajouté le 2026-09-10

Un sweat du lycée commandé une fois, un lot de gâteaux pour une kermesse : ces ventes sont des
**coups uniques**, pas un flux. Elles n'ont pas de rythme, donc pas de couverture, et « douze jours
de rupture » n'y veut rien dire — l'article n'était pas censé être réapprovisionné, il est épuisé,
ce qui est la fin prévue de son histoire.

`Product.suiviDeStock`, une case décochable sur la fiche produit. Ce qu'elle coupe :

- les **ruptures** et les **ventes perdues** des statistiques ;
- la **couverture** du cadencier ;
- les **alertes de stock** et les pastilles du tableau de bord ;
- la **proposition de quantité** à la commande.

Ce qu'elle **ne touche pas** : le stock continue d'être décrémenté et le journal des mouvements
reste tenu. On coupe des interprétations, pas la trace — sans quoi on ne saurait plus combien il
reste de sweats sur les quarante.

Le défaut est `true`, et la migration le pose sur tous les produits existants : c'est l'exception
qui se déclare, pas la règle.

## Notes

Le stock peut devenir négatif (l'admin ajuste après coup). Pas de réassort automatique en v1.
