Amisdelaferme fonctionne en flux tendu roulant : les clients commandent en continu, les commandes fournisseur partent selon un calendrier fixe (Baron : lundi + mercredi, livraison à J+2). Ci-dessous, une vraie semaine du ledger (Baron, 15/06 → 05/07) rejouée pas à pas. Faites défiler le temps : chaque chiffre est recalculé depuis le journal des mouvements de stock à l'instant T. Deux ledgers tournent en parallèle — l'actuel (ce que le système a réellement écrit) et le correct (réceptions − demande client) — et leur écart est le stock fantôme qui sous-commande l'envoi suivant.
La cadence roulante garantit la panne : un client dont la date de livraison tombeentre deux réceptions fournisseur est servi alors que Product.stock = 0. Le cron d'auto-validation décrémente alors max(0, 0 − 1) = 0 — la consommation est silencieusement perdue. La réception qui couvrait ce client arrive plus tard et ajoute +N de stock… sans rien à compenser.
stock += N, sans plafond, sans annuler le réservé-entrée.stock = max(0, stock − q) — bridée à 0, la sortie est perdue.stock == ledger == la valeur fantôme.sourceOrderIds).Σ réceptions − Σ livraisons = stock réel, toujours. Le fantôme devient impossible.La scène relie les flux réellement séparés dans le code :P1/P2 génération roulante des commandes fournisseur (cron 30 min + reconcile 07:15) → réservé-entrée ;P1 intake client (sync PrestaShop) → réservé-sortie ;P3 auto-validation réception (date prévue + 12 h) ;P4 auto-validation livraison client (date livraison + 12 h, avec le bridage) ;P5 le ledger (Product.stock + stockLedger). Le détail complet, les diagrammes Mermaid avant/après et la liste des correctifs + tests sont dans docs/stock/2886-rolling-stock-model.md.