Der Auto-Storno der Zahlungserinnerung schrieb shipped=10 direkt und rief
nur syncSaleStock() — Margen-Storno-Flag, pending_to/shipped_at-Reset und
Promotions-/Guthaben-Folgen fehlten. Die Partnerprovision einer
versendeten, nie bezahlten Bestellung wäre zahlbar geblieben.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Der Schutz historischer Bestellungen hing an shipped_at, das der
OrderStatusService beim Status-Toggle nullt und neu stempelt — Storno +
erneutes Versenden einer Alt-Bestellung hätte rückwirkend vom heutigen
Bestand abgezogen. Migration mit einmaligem Backfill (shipped_at vor
16.07.2026), Guard prüft nur noch das Flag.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Erneutes Speichern des Versandstatus einer Alt-Bestellung (shipped_at vor
16.07.2026) hätte rückwirkend vom heutigen Bestand abgezogen. syncSaleStock()
überspringt historische Bestellungen jetzt per Stichtag SALE_STOCK_SINCE.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
ProductStockService::syncSaleStock(): idempotenter Differenz-Abgleich der
Verkaufs-Abgänge (source='sale', Referenz = Bestellung) mit dem Versandstatus —
Abzug je Bestellposition bei versendet/abgeschlossen, Sets rekursiv über
product_set_items in Einzelprodukte aufgelöst; Zurücksetzen/Storno führt per
Gegenbuchung zurück (behebt auch das Doppelabzug-Risiko Versand→Zurücksetzen→
Versand). Andockpunkte: SalesController::store (in der Transaktion) und
PaymentReminderService (Auto-Storno per Cron). Verbrauch/Monat zählt
Verkaufs-Abgänge automatisch mit (source != production).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>