# ADR-0007 — La vente n'est jamais bloquée par le stock

> Date : 2026-08-20
> Statut : `accepted`

## Contexte

`SaleService::createSale` refusait la vente entière dès qu'un produit du panier n'avait pas le stock demandé, en levant une `InsufficientStockException`. La spec `vente.md` allait dans le même sens : un produit à stock 0 était grisé et non ajoutable.

Cette règle part du principe que le stock enregistré dit la vérité. Sur un stand, c'est faux. Le stock informatique est une estimation qui décroche en permanence — une entrée oubliée, un carton ouvert à la va-vite, un produit offert. Le stock réel, c'est ce qu'il y a dans le carton.

Conséquence : un élève tient le paquet de chips en main, le client tend la monnaie, et la caisse refuse la vente parce qu'une ligne de base dit zéro. On fait payer au client une erreur de saisie, devant une file d'attente, pendant une récré de quinze minutes.

## Décision

**Une vente n'est jamais refusée pour un motif de stock.** Le stock d'un produit peut devenir négatif, et un stock négatif est traité comme un **signal de décrochage** entre l'informatique et le réel, pas comme une erreur à empêcher.

Ce qui disparaît : le refus de vente et l'`InsufficientStockException` sur le chemin de vente, ainsi que le blocage des produits à stock 0.

Ce qui reste : la transaction explicite et le verrou en écriture sur les produits. Ils ne servaient pas seulement à refuser — ils garantissent que deux ventes simultanées ne perdent pas un décrément. Cette garantie-là vaut toujours.

Ce qui répare le décrochage relève de deux autres chantiers : les alertes le signalent (`docs/specs/alertes.md`), l'inventaire le corrige (`docs/specs/inventaire.md`).

## Conséquences

- **+** La caisse ne bloque jamais une vente qui a réellement eu lieu. C'est la règle d'or d'un point de vente.
- **+** Le vendeur n'a aucune décision à prendre sous pression : il encaisse, on corrige plus tard.
- **+** Le stock négatif devient une information exploitable — il pointe exactement les produits dont le suivi décroche.
- **−** `Product.stock` ne peut plus être lu comme une quantité physique. C'est un compteur d'écritures, qui peut mentir tant qu'un inventaire ne l'a pas recalé.
- **−** Sans alertes ni inventaire, le décrochage passe inaperçu. Ces deux features deviennent nécessaires, plus seulement souhaitables.
- **−** Renverse une partie du travail livré : `InsufficientStockException` sur le chemin de vente, cinq tests, et le critère « produit à stock 0 grisé » de `vente.md`.
