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>
Vorbereitung AP-13: Versand-Statuswechsel validiert Eingaben (Status aus
shippedTypes, Action-Whitelist), läuft in DB::transaction mit lockForUpdate
gegen Doppelklick/parallele Tabs. Verhalten sonst unverändert.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Chargennummern kommen von extern und können kollidieren. Der Lieferant
gehört jetzt zum Gruppenschlüssel (batchGroupKey b:<supplier>:<lot>) —
gleiche Lot-Nummern verschiedener Lieferanten verschmelzen nicht mehr
(kein gemeinsames min-MHD/Summen-Rest). Batch-Check (AP-27) prüft
zusätzlich den Lieferanten des zu buchenden Eingangs.
Tests: +1 (getrennte Optionen je Lieferant); Chargen-Tests auf neues
Schlüsselformat umgestellt.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- H-2: quantity_used muss > 0 sein (FormRequest-Regel + Service-Guard) —
negative Zeilen konnten sich in der Summenprüfung aufheben und
Chargen-Restbestände aufblähen.
- H-3: expandBatchLines() dekrementiert die gecachten Restmengen —
zwei Zeilen derselben Charge belasten nicht mehr denselben Einkauf
doppelt (FEFO korrekt über beide Zeilen).
- M-1: Ausschuss validiert Chargen-Konsistenz (gehört zum Rohstoff,
received) und Restbestand (je Charge bzw. gesamt).
- M-9: lockForUpdate auf die Produktionszeile bei Update und Löschen.
Tests: neuer ProductionHardeningTest (4). Suite: 223 grün, 806 Assertions.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- consumedByStockEntry(): chargen-bezogener Ausschuss zählt jetzt als
Verbrauch — entsorgte Chargen verschwinden aus Rohstoff-Detail,
Produktions-FEFO/Dropdown und AP-27-Batch-Check.
- Rohstoff-Detail: Kopfwert aus remainingByIngredient() (identisch zur
Index-Seite, inkl. Ausschuss ohne Chargenbezug).
- Aggregationen iterieren über die Key-Vereinigung (received ∪ consumed
∪ disposed) — negative Bestände werden nicht mehr als 0 maskiert.
- Standort-Aggregation: Chargen-Ausschuss zählt am Standort der Charge
(COALESCE), nicht am frei gewählten Formular-Standort.
Tests: neuer ChargeDisposalConsistencyTest (5). Suite: 219 grün, 795 Assertions.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Anforderung 15.07.2026: Nahezu alle WaWi-Einträge sind jetzt löschbar
(Soft-Delete, deleted_at), mit Abhängigkeitsprüfung und Bestätigungs-
warnung vor jeder Löschung.
- Migration: deleted_at auf 14 WaWi-Tabellen (Stammdaten, ingredients,
stock_entries, stock_disposals, productions); SoftDeletes-Trait in
den Models (suppliers/packaging_items hatten es bereits).
- Neuer App\Services\DeletionGuard: zentrale Abhängigkeitsprüfung je
Entität — referenzierte Einträge sind nicht löschbar, Fehlermeldung
nennt die Verwendungen (behebt auch Audit M-4: kein 500er/stiller
Cascade-Verlust mehr beim Löschen verwendeter Stammdaten).
- SettingCrudController::destroy() prüft Blocker; Supplier-,
PackagingItem-, Ingredient-destroy ebenso (Ingredient: vollständige
Prüfung inkl. Produktion/Ausschuss, Route GET→DELETE, Audit M-6).
- Wareneingänge: auch gebuchte Eingänge löschbar, sofern kein
Produktions-Verbrauch/Ausschuss darauf gebucht ist.
- Ausschuss: löschbar (Menge steht dem Bestand wieder zur Verfügung).
- Produktionen: löschbar (admin >= 7); Produktbestand wird per
Gegenbuchung zurückgeführt (reverseProductionStock, append-only,
withTrashed), Rohstoffverbrauch zählt nicht mehr (Bestandsqueries
schließen gelöschte Produktionen aus).
- lastNetPricePerSupplier: DB::query statt Model-Query (Global Scope
auf Sub-Select-Alias).
- Debug-Log-Reste im PackagingItemController entfernt (Audit N-16).
- Views: Lösch-Buttons mit deutschen Bestätigungswarnungen (Ausschuss,
Produktionen, gebuchte Wareneingänge, INCI als DELETE-Formular).
Tests: neuer InventoryDeletionTest (10 Tests), StorageSettingsTest an
neue Löschregel angepasst. Volle Suite: 214 grün, 783 Assertions.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Chargen-Existenz-Check beim Buchen (JSON-Endpoint batch-check): Hinweis
„Charge bereits im Haus" + Vorbelegung MHD/Qualität aus dem letzten Eingang
- Rohstoffbestand-Detail: Chargen je batch_number summiert
(InventoryService::chargeGroupsForIngredient), Einkäufe als Unterzeilen
- Produktion: Charge-Dropdown je Charge mit Summen-Rest (batches im
Recipe-Payload), Verbrauch wird per expandBatchLines FEFO auf die
Einzel-Einkäufe der Charge verteilt; Service-API bleibt je stock_entry
- Jeder Einkauf bleibt eigener stock_entry (Preis/Datum/Audit)
- Hinweise-Doku + Plan V6.0 §6 fortgeschrieben
Tests: StockEntryChargeMergeTest (7 neu); Suite 193 grün, 698 Assertions
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- ingredients.exclude_from_stock (Checkbox im INCI-Formular, z. B. Allergene):
erscheint nie im Rohstoffbestand und nicht im Kritisch-Badge
- Rohstoffbestand-Uebersicht: Umschalter "Alle" / "Nur aus Herstellerrezepturen"
(?scope=recipe, nutzt scopeUsedInActiveRecipes aus AP-21)
- Fix: AP-21-Migrationen hatten identischen Timestamp (add_storage lief vor
create_storage und scheiterte auf MySQL am FK) - umbenannt auf 120753,
Teilreste bereinigt, Migrationen sauber ausgefuehrt
- Hinweise-Doku fortgeschrieben
Tests: RawMaterialStockTest +2 (volle Suite 172 gruen, 624 Assertions)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Abstrakte SettingCrudController-Basis für die kleinen Stammdaten-CRUDs
- TaxRate/DeliveryTime/DisposalReason/MaterialQuality/Location/SupplierCategory/PackagingMaterial auf ~25-Zeilen-Konfiguration reduziert
- Identische Update*Request-Klassen entfernt (Update nutzt Store-Request, via updateRequestClass() überschreibbar)
- Bilanz -441/+73 Zeilen; Grundlage für die Lagerort-CRUDs in AP-21
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>