gruene-seele/dev/product management /entwicklungsplan-aktualisiert-02-06-2026.md
Kevin Adametz 78679e0c55 Warenwirtschaft: AP-00 bis AP-08 + aktualisierter Entwicklungsplan
Umsetzung der Warenwirtschafts-/Produktmanagement-Erweiterung gemaess
Entwicklungsplan V4.0:

- AP-00: Regressionsbasis fuer 5.1-Features (ProductPhase51Test)
- AP-01: URL-Bugfixes B1/B2 (suppliers/packaging-items, breitere url-Spalten)
- AP-04/04.1: iPad-taugliche, vereinheitlichte Tabellen-Aktionen
- AP-05: Einstellungen "Allgemein" mit UST-Saetzen (tax_rates) und
  Lieferzeit-Vorlagen (delivery_times, inkl. Tage-Feld)
- AP-06: Lieferanten um Bestellweg, Bestell-Mail/-URL und Lieferzeit erweitert
- AP-07/07.1: INCI um Lieferanten-Mehrfachwahl, UST und Lieferzeit erweitert;
  Lieferanten-Detailansicht im Modal mit pflegbaren INCI-/Verpackungslisten
- AP-08: Einkauf um UST-Snapshot, Netto/Brutto-Automatik und Duplizieren erweitert

Entwicklungsplan aktualisiert: alle Klaerungspunkte (§5) vom Kunden beantwortet
und in die jeweiligen APs eingearbeitet (AP-02/03/09/13/15), neues AP-18
(Hinweise-Doku unter Einstellungen) ergaenzt. Naechster Schritt eindeutig
markiert: AP-09 (Produktion auf Hersteller-Rezeptur, kein Fallback, Warnung).
2026-06-02 16:30:42 +00:00

42 KiB
Raw Blame History

Aktualisierter Entwicklungsplan: Warenwirtschaft, Produktion & Produktbestand

Version: 4.0 - Stand 02.06.2026 Ersetzt: entwicklungsplan-aktualisiert-27-04-2026.md (V3.0) als operative Arbeitsgrundlage Referenzen: entwicklungsplan.md (V2.0), briefing-anpassungen-27-04-2026.md, feedback.md, konzept-final.md, docs/Todos.md Methodik: Backlog aus kleinen, sequenziell abarbeitbaren Arbeitspaketen (AP). Jedes AP hat Ziel, konkrete Schritte mit Dateipfaden, DB-Änderungen, Akzeptanzkriterien und Tests. Reihenfolge ist so gewählt, dass jedes AP einzeln deploybar ist.


0. Was dieses Dokument neu macht

Gegenüber V3.0 wurde der reale Code-Stand verifiziert (nicht nur die Protokolltabelle übernommen). Daraus ergeben sich Korrekturen, neu entdeckte Bugs und eine feinere Zerlegung in einzeln umsetzbare Schritte.

Geprüfte Dateien u. a.: routes/web.php, app/Http/Controllers/Admin/Inventory/*, app/Services/ProductionService.php, app/Http/Requests/Inventory/*, resources/views/admin/inventory/*, Migrationen unter database/migrations/.


0a. Umsetzungsprotokoll V4.0 (laufend)

Jede abgeschlossene Teil-Lieferung wird hier mit Datum, betroffenen Dateien und Test-Status protokolliert.

Datum AP Kurzbeschreibung Tests
02.06.2026 AP-01 URL-Bugfixes B1/B2 umgesetzt: suppliers/form.blade.php und packaging-items/form.blade.php von type="url" auf type="text" (placeholder https://); Store/UpdatePackagingItemRequest URL-Regel url|max:500string|max:2048; Migration 2026_06_02_145358_widen_url_columns_in_inventory_tables (suppliers.url + packaging_items.url → varchar(2048)). tests/Feature/InventoryUrlFieldsTest.php (3 grün); Regression Phase 2+3 grün (17)
02.06.2026 AP-04 iPad-taugliche Tabellen-Aktionen (B5): neue Partial resources/views/admin/inventory/partials/table-actions-style.blade.php (@once-Style für .wawi-table td .btn, min. 42px Touch-Target, mehr Abstand); Klasse wawi-table + Partial-Include in allen 8 Index-Views (locations, material-qualities, packaging-materials, supplier-categories, suppliers, packaging-items, stock-entries, productions). Render-Regression Phase 2+3+5 grün (21)
02.06.2026 AP-00 Regressionsbasis für umgesetzte 5.1-Features als Pest-Tests nachgezogen: INCI-Rohstoffqualität-Relation, Hersteller-Rezeptur getrennt von Produkt-Rezeptur, Produkt-Kopie inkl. beider Rezepturen, „nur aktive Produkte" im Produktions-Formular, Produktion edit/copy rendern. tests/Feature/ProductPhase51Test.php (5 grün)
02.06.2026 AP-04.1 Aktionsspalten vereinheitlicht (Kunden-Feedback): einheitliches Schema Spalte 1 = Ansicht + Bearbeiten (+ Kopieren bei Produktion), letzte Spalte = Löschen. Umgebaut: stock-entries/index (Ansicht/Bearbeiten nach vorn, Löschen ans Ende, DataTables order/columnDefs an verschobene Spalten angepasst) und productions/index (Ansicht/Bearbeiten/Kopieren nach vorn). Stammdaten-Tabellen waren bereits konform (kein show-Route → keine Ansicht). CSS-Feinjustierung der Button-Abstände durch Kunden in partials/table-actions-style.blade.php übernommen. Produktions-Index-Render + Aktionslinks geprüft; stock-entries Index-Render grün (13)
02.06.2026 AP-05 (Teil 1: UST) Neuer Unterpunkt Warenwirtschaft → Einstellungen → „Allgemein" als erweiterbarer Container für kleinteilige Einstellungen (erstes Modul = Umsatzsteuersätze). Tabelle tax_rates (name, percent DECIMAL(5,2), active, pos) via Migration 2026_06_02_152721_create_tax_rates_table; Model TaxRate (casts percent/active, scopeActive), TaxRateFactory, Seeder-Erweiterung InventoryStammdatenSeeder (19/7/0, idempotent per firstOrCreate). CRUD: GeneralSettingController@index (Allgemein-Seite), TaxRateController (create/store/edit/update/destroy, Redirect zurück auf general), Store/UpdateTaxRateRequest. Views admin/inventory/general/index.blade.php (Karte „Umsatzsteuersätze" mit Tabelle + Neu/Bearbeiten/Löschen) und admin/inventory/tax-rates/form.blade.php. Routen in superadmin-Gruppe (admin.inventory.general, Resource tax-rates ohne index/show). Sidenav-Eintrag „Allgemein" inkl. open/active-Logik. Migration + Seed auf DB ausgeführt (3 Default-Sätze vorhanden). tests/Feature/TaxRateSettingsTest.php (7 grün, 24 Assertions): Render, CRUD, Validierung Pflicht/Bereich, active-Scope, Zugriffsschutz Nicht-SuperAdmin
02.06.2026 AP-05 (Teil 2: Lieferzeiten) Zweite Karte „Lieferzeit-Vorlagen" auf der Allgemein-Seite. Tabelle delivery_times (label, active, pos) via Migration 2026_06_02_153243_create_delivery_times_table; Model DeliveryTime (cast active, scopeActive), DeliveryTimeFactory, Seeder-Erweiterung (13 / 35 Werktage / 12 Wochen, idempotent). CRUD: DeliveryTimeController (create/store/edit/update/destroy → Redirect general), Store/UpdateDeliveryTimeRequest. GeneralSettingController um deliveryTimes erweitert. View admin/inventory/delivery-times/form.blade.php + zweite Karte in general/index. Route Resource delivery-times (ohne index/show) in superadmin-Gruppe. Sidenav open/active um delivery-times ergänzt. Migration + Seed auf DB ausgeführt. tests/Feature/DeliveryTimeSettingsTest.php (7 grün, 21 Assertions): Render, CRUD, Validierung, active-Scope, Zugriffsschutz
02.06.2026 AP-06 (Lieferanten erweitern) Felder order_method ENUM(email,online_shop), order_email, order_url, delivery_time (Freitext) an suppliers via Migration 2026_06_02_154755_add_order_fields_to_suppliers_table. Supplier fillable erweitert; Store/UpdateSupplierRequest Regeln (order_method in:email,online_shop; order_email email; order_url string max 2048; delivery_time string). SupplierRepository::extractSupplierAttributes erweitert. SupplierController create/edit übergeben aktive deliveryTimes als Vorlagen. suppliers/form.blade.php: Bestellweg-Select + bedingte Felder (Bestell-E-Mail / Bestell-URL via JS-Toggle) + Lieferzeit-Textfeld mit <datalist> aus aktiven Lieferzeit-Vorlagen. Migration auf DB ausgeführt. tests/Feature/SupplierOrderFieldsTest.php (6 grün): Formular zeigt nur aktive Vorlagen, Speichern E-Mail-/Shop-Bestellweg, Update, Validierung Bestellweg/Bestell-E-Mail. Regression InventoryPhase2Test (9 grün)
02.06.2026 AP-06 (Nachtrag: Lieferzeit in Tagen) Lieferzeit-Vorlagen erhalten festes Feld days (ganze Tage bis Wareneingang, Basis für spätere „rechtzeitig bestellen"-Ableitung). Migration 2026_06_02_160411_add_days_to_delivery_times_table (delivery_times.days unsignedSmallInt nullable) + 2026_06_02_160411_add_delivery_time_days_to_suppliers_table (suppliers.delivery_time_days). DeliveryTime (fillable+cast days), Factory/Seeder (3/5/14 Tage, Bestandsdaten nachgepflegt). Store/UpdateDeliveryTimeRequest + Store/UpdateSupplierRequest um days/delivery_time_days (nullable int) erweitert; SupplierRepository + Supplier cast. Views: Tage-Feld in delivery-times/form, Spalte „Tage" in general/index, Tage-Feld im suppliers/form + JS-Autofill (data-days an Datalist-Optionen setzt Tage bei Vorlagenauswahl, manuell überschreibbar). Migrationen auf DB ausgeführt, Default-Vorlagen mit Tagen befüllt. DeliveryTimeSettingsTest (10 grün): days speichern/optional/Integer-Validierung; SupplierOrderFieldsTest (9 grün): delivery_time_days speichern, Integer-Validierung, data-days-Ausgabe
02.06.2026 AP-08 (Einkauf erweitern) Einkauf um UST-Satz + Netto/Brutto-Automatik + Duplizieren erweitert. Migration 2026_06_02_181548_add_price_fields_to_stock_entries_table (price_per_kg_gross DECIMAL(10,4), tax_rate_id FK→tax_rates nullOnDelete, tax_rate_percent DECIMAL(5,2) als Snapshot). price_per_kg bleibt das bestehende Netto-Feld (kein Rename → keine Migration der Bestandsdaten/Tests). StockEntry: fillable + casts (price_per_kg_gross/tax_rate_percent) + taxRate() belongsTo. Store/UpdateStockEntryRequest: Regeln tax_rate_id (exists) + price_per_kg_gross (numeric), Reformat dt. Zahl, neue Regel „bei Rohstoff genau eines von Netto/Brutto verpflichtend". Berechnung zentral im StockEntryRepository::resolvePrices(): UST-Prozent als Snapshot, fehlender Netto-/Brutto-Wert wird aus dem Faktor (1+%/100) berechnet (Netto↔Brutto), bei Verpackung Preisfelder/UST genullt (Netto-Gesamt bleibt). View _form: UST-Dropdown (aktive tax_rates, data-percent) + Netto-/Brutto-Felder nebeneinander; _scripts: JS rechnet live Netto↔Brutto bei Eingabe und UST-Wechsel (dt. Zahlenformat). show: Anzeige Netto/Brutto/USt. Duplizieren: Route stock-entries/{stock_entry}/copy + StockEntryController@copy legt direkt eine pending-Kopie der Stufe-1-Felder an (Charge/MHD/Eingangsdaten leer, ordered_at=heute, ordered_by=aktueller User) und leitet zur Bearbeitung; Kopieren-Button in index (Aktionsspalte) + show-Header. Migration auf DB ausgeführt. tests/Feature/StockEntryPriceTest.php (6 grün): Netto→Brutto, Brutto→Netto, ohne UST Netto=Brutto, Netto/Brutto-Pflicht, Duplizieren erzeugt pending-Kopie ohne Chargendaten, Copy-Zugriffsschutz. Regression InventoryPhase3Test (8 grün)
02.06.2026 AP-07.1 (Lieferanten-Detailansicht/Modal) Zwischenschritt (Kunde): Lieferanten-Zuordnungen auch von der Lieferantenseite aus sichtbar/pflegbar. Supplier::ingredients() belongsToMany (Gegenstück zu Ingredient::suppliers()). Resource suppliers show reaktiviert + neue Routen suppliers.ingredients.attach/detach und suppliers.packaging-items.attach/detach (admin-Gruppe). SupplierController: show() + attach/detachIngredient() + attach/detachPackagingItem() rendern gemeinsames Partial suppliers/_details.blade.php (Stammdaten + zwei kleine Listen „Zugeordnete INCIs" / „Zugeordnete Verpackungsartikel" mit Entfernen-Button und Hinzufügen-Auswahl der noch nicht zugeordneten Einträge). Index: Augen-Button (Spalte 1) öffnet Bootstrap-Modal, lädt Details per AJAX; Hinzufügen/Entfernen via delegiertem jQuery-AJAX (X-CSRF-TOKEN-Header) und ersetzt den Modal-Body mit dem neu gerenderten Partial. Verpackungsartikel-Zuordnung = packaging_items.supplier_id setzen/leeren. tests/Feature/SupplierDetailsTest.php (7 grün): show zeigt zugeordnete INCIs/Verpackung, INCI attach/detach, Verpackung attach/detach, Validierung, Zugriffsschutz Nicht-Admin
02.06.2026 AP-07 (INCI erweitern) INCI/Rohstoffe um Lieferanten-Mehrfachwahl, UST-Satz und eigene Lieferzeit (inkl. Tage-Autofill) erweitert. Migration 2026_06_02_161237_add_order_fields_to_ingredients_table (ingredients.tax_rate_id FK→tax_rates nullOnDelete, delivery_time VARCHAR, delivery_time_days unsignedSmallInt) + 2026_06_02_161237_create_ingredient_supplier_table (Pivot ingredient_id (unsignedInt, passend zu altem increments) / supplier_id, preferred bool, supplier_sku, url(2048), unique-Paar, cascadeOnDelete). Ingredient: fillable + cast delivery_time_days, Relationen taxRate() belongsTo + suppliers() belongsToMany (Pivot preferred/supplier_sku/url). O1 erledigt: IngredientController::store() von Request::all() auf neuen App\Http\Requests\StoreIngredientRequest umgestellt (validiert + normalisiert deutsche Dezimalzahlen default_factor/min_stock_alert, leere FKs→null). edit() lädt aktive taxRates, aktive deliveryTimes, aktive suppliers + eager-load suppliers; nach Speichern suppliers()->sync(). Single-Endpoint-Schema (admin_product_ingredient_store für Neu+Update) beibehalten → ein FormRequest genügt. View admin/ingredient/form.blade.php: UST-Dropdown (aktive tax_rates), Select2-Mehrfachwahl Lieferanten, Lieferzeit-Textfeld mit <datalist> (data-days) + Tage-Feld; edit.blade.php @section('scripts') mit Select2-Init + Tage-Autofill (manuell überschreibbar). Lieferzeit-Logik: INCI-Lieferzeit hat Vorrang vor Lieferanten-Lieferzeit (Auswertung erst in AP-10). Migrationen auf DB ausgeführt. tests/Feature/IngredientOrderFieldsTest.php (6 grün): Formular zeigt Lieferanten/UST/aktive Vorlagen+data-days, Speichern mit UST/Lieferzeit/Tagen/Lieferanten, Lieferanten-Sync bei Update, Validierung Tage-Integer/UST-Existenz/Name-Pflicht. Regression SupplierOrderFieldsTest (8) + ProductPhase51Test (5) grün

Status Roadmap: AP-00, AP-01, AP-04, AP-05, AP-06 (inkl. Nachtrag) erledigt; AP-07 erledigt (INCI: Lieferanten-Mehrfachwahl, UST-Satz, eigene Lieferzeit inkl. Tage-Autofill, ingredient_supplier-Pivot; O1 IngredientController auf FormRequest umgestellt) inkl. AP-07.1 (Lieferanten-Detailansicht im Modal mit pflegbaren INCI-/Verpackungs-Listen); AP-08 erledigt (Einkauf: UST-Snapshot, Netto/Brutto-Automatik, Duplizieren).

Alle Klärungspunkte aus §5 sind beantwortet (Kunde, 02.06.2026) und in die jeweiligen APs eingearbeitet — keine Blocker mehr offen.

➡️ NÄCHSTER SCHRITT: AP-09 (Produktion korrigieren). Konkret: (1) Produktion ausschließlich auf Hersteller-Rezeptur umstellen + Warnung, wenn keine gepflegt ist (kein Fallback); (2) Chargen-Dropdown-Label + nur Chargen mit Restbestand; (3) B3 „Weitere Charge"-JS-Fix (genau eine Zeile); (4) Soll-Neuberechnung ohne Überschreiben manueller Eingaben; (5) B4 iPad-Layout der Kopfdaten; (6) Produktentwicklung-Platzhalterseite („Briefing ausstehend"). Danach AP-02/AP-03, dann die großen Übersichten. Neu: AP-18 (Hinweise-Doku unter Einstellungen) kann jederzeit dazwischengezogen werden.


1. Verifizierter Ist-Stand (02.06.2026)

Umgesetzt und im Code vorhanden

Bereich Status Belegt durch
Produktmanagement (Produkte, INCIs, Kategorien, Attribute) vorhanden app/Http/Controllers/ProductController.php, IngredientController.php
Rezeptur + Hersteller-Rezeptur (Prozent, Faktor, 100%-Summe) vorhanden product_ingredients.recipe_type, Product::p_ingredients() / manufacturer_ingredients()
Haltbarkeit am Produkt (PAO / festes MHD) vorhanden products.shelf_life_type, shelf_life_months
Stammdaten (Lagerorte, Lieferanten, Kategorien, Rohstoffqualität, Verpackungsmaterial, Produkt-/Versandverpackung) vorhanden app/Http/Controllers/Admin/Inventory/*, Migrationen 2026_03_27_*
INCI mit Rohstoffqualität vorhanden ingredients.material_quality_id
Verpackung & Material am Produkt (BOM) vorhanden product_packagings, Product::packagings()
Einkauf & Wareneingang (zweistufig pending → received, Charge, MHD) vorhanden stock_entries, StockEntryController, ReceiveStockEntryRequest
Produktion (Chargen-Zuordnung, Soll-Verbrauch, MHD-Warnung, Packaging-Snapshot, edit/copy) vorhanden ProductionService, ProductionController, production_*-Tabellen
Tests Phase 05 vorhanden tests/Feature/ProductPhase0/1/4Test.php, InventoryPhase2/3Test.php, ProductionPhase5Test.php

Noch NICHT im Code vorhanden (entgegen Eindruck aus V3.0-Lesart)

  • Phase 5.2 ist vollständig offen — keine der dort beschriebenen DB-Strukturen existiert:
    • kein tax_rates / tax_rate_id / tax_rate_percent
    • kein is_set, main_product_id, product_set_items
    • kein order_method / order_email / order_url / delivery_time an suppliers
    • kein ingredient_supplier-Pivot, kein tax_rate/delivery_time an ingredients
    • kein price_per_kg_net / price_per_kg_gross an stock_entries
    • kein out_of_stock_until an products
    • kein product_stock_movements, kein InventoryService, keine Bestandsseiten
  • Produktion basiert noch auf p_ingredients (Produkt-Rezeptur), nicht auf der Hersteller-Rezeptur (ProductionService::store() und buildRecipePayload() laden p_ingredients). Briefing fordert Hersteller-Rezeptur als Basis → offen.
  • Kein Rohstoffbestand / Produktbestand / Historie, kein Ausgang/Ausschuss, kein Audit-Trail, kein 2FA, keine blockbasierten Rechte, keine Warenwirtschafts-Einstellungen.

2. Gefundene Bugs & Optimierungen (sofort vor Feature-Arbeit)

Diese Punkte sind klein, konkret und blockieren teils die tägliche Nutzung. Sie werden als Phase 5.1.x Nachzügler vorgezogen.

B1 — Lieferanten-URL: Speichern schlägt fehl, wenn URL ausgefüllt ist (umgekehrtes Verhalten)

  • Symptom (Kunde): „Neuer Lieferant: sagt URL eingeben, obwohl eine drinsteht. Nehme ich sie raus, geht das Abspeichern."
  • Ursache: resources/views/admin/inventory/suppliers/form.blade.php Zeile 56 nutzt <input type="url">. Die native Browser-Validierung lehnt eine ausgefüllte, aber nicht streng schema-konforme URL (z. B. ohne https:// oder mit kodierten Parametern) ab; ein leeres Feld ist gültig → exakt das gemeldete „umgekehrte" Verhalten. Die Server-Validierung ist bereits korrekt (nullable|string|max:2048).
  • Fix: type="url"type="text" (Server validiert ohnehin als String). Damit werden auch Konfigurator-URLs mit Parametern akzeptiert (siehe B2).
  • Aufwand: ~15 Min.

B2 — URL-Felder müssen Konfigurator-URLs mit Parametern akzeptieren

  • Anforderung (Todos Z. 12): URLs wie https://www.kartonsaufmass.de/bestellen?bom_configuration=%7B%2522length%2522:125,...%7D müssen gespeichert werden können (Versandverpackungs-Konfiguratoren).
  • Status (verifiziert): Lieferanten-URL ist bereits nullable|string|max:2048 (ok, mit B1-Fix vollständig). PackagingItem ist NICHT ok: Store/UpdatePackagingItemRequest haben ['nullable','url','max:500'] — die url-Regel lehnt kodierte Konfigurator-URLs ab und max:500 ist für lange Konfigurator-Links zu kurz. → auf ['nullable','string','max:2048'] ändern und Blade-Input auf type="text". Konsistent für alle URL-Felder im Warenwirtschaftsmodul.
  • Aufwand: ~30 Min.

B3 — „Weitere Charge": es erscheinen zwei Felder statt einem

  • Anforderung (Todos Z. 14, Briefing 5.2.6): Klick auf „Weitere Charge" soll genau eine neue Zeile/Dropdown hinzufügen.
  • Status: JS-Fehler in der Produktions-Create/Edit-View (Chargen-Splitting). Wird in AP-09 (Produktionskorrekturen) sauber behoben, da es mit der Soll-Neuberechnung zusammenhängt.

B4 — iPad: Produktionsdatum und Stückzahl überlappen grafisch

  • Anforderung (Todos Z. 86, Briefing 5.2.6 D): Responsive Grid der Kopfdaten in productions/create.blade.php / edit.blade.php reparieren. → Teil von AP-09.

B5 — Tabellen-Aktionsicons (Auge/Stift/Mülleimer) zu klein/zu eng (iPad)

  • Anforderung (Todos Z. 36, Briefing 5.2.3 C): Betrifft alle Tabellen im Modul. Eine gemeinsame CSS-Utility-Klasse (z. B. .wawi-actions mit größeren Touch-Targets + Abstand) einführen und in allen index.blade.php anwenden. → AP-04 (Querschnitt, früh, weil überall sichtbar).

Optimierungen (Konsistenz/Sauberkeit)

  • O1: IngredientController nutzt noch Request::all() statt FormRequest → bei INCI-Erweiterung (AP-07) auf StoreIngredientRequest/UpdateIngredientRequest umstellen.
  • O2: Offene Tests aus Phase 5.1 (Menü-Labels, INCI-Qualität, Prozent-Rezeptur, 100%-Summe, Hersteller-Rezeptur, Produktion edit/copy, nur aktive Produkte) sind im Plan als [ ] markiert, aber Features sind umgesetzt → AP-00 schreibt diese Tests nach, um eine grüne Regressionsbasis zu haben, bevor 5.2 beginnt.
  • O3: Steuerart als Enum, später änderbar gewünscht (feedback/Briefing INCI B). Lösung: konfigurierbare tax_rates-Stammdaten statt Hardcode-Enum (AP-05).

3. Priorisierte Roadmap (Phasenüberblick)

Reihenfolge AP Titel Abhängigkeit Aufwand
1 AP-00 Regressionsbasis: offene 5.1-Tests nachziehen 1 Tag
2 AP-01 Quick-Fixes B1/B2 (URL-Felder) 0,5 Tag
3 AP-04 Querschnitt: iPad-taugliche Tabellen-Aktionen (B5) 0,51 Tag
4 AP-05 Einstellungen: UST-Sätze & Lieferzeiten (Stammdaten) 12 Tage
5 AP-06 Lieferanten erweitern (Bestellweg, Lieferzeit) AP-05 12 Tage
6 AP-07 INCI erweitern (Lieferanten-Mehrfachwahl, UST, Lieferzeit) AP-05, AP-06 23 Tage
7 AP-08 Einkauf erweitern (UST, Netto/Brutto, Duplizieren) AP-05 23 Tage
8 AP-09 Produktion korrigieren (Hersteller-Rezeptur, Charge-JS, iPad, Produktentwicklung-Platzhalter) 24 Tage
9 AP-02 Produkt-Klassen: Einzelprodukt vs. Set + Hauptprodukt 35 Tage
10 AP-03 „Nicht vorrätig" mit Zeitangabe 12 Tage
11 AP-10 Rohstoffbestand (InventoryService + Übersicht) AP-06, AP-07, AP-09 46 Tage
12 AP-11 Produktbestand + Historie + manuelle Bewegungen AP-02, AP-10 58 Tage
13 AP-12 Ausgang/Ausschuss (Rohstoffe/Verpackung) AP-10 23 Tage
14 AP-13 Shop-Anbindung: Bestand bei Verkauf reduzieren (inkl. Sets) AP-02, AP-11 35 Tage
15 AP-14 Audit-Trail (inventory_logs) AP-1013 23 Tage
16 AP-15 Blockbasierte Rechte AP-05+ 58 Tage
17 AP-16 2FA Google Authenticator für Admins 35 Tage
18 AP-17 Warenwirtschafts-Einstellungen (Alarm-Mail, Default-Lager, Schwellwerte) AP-10/11 12 Tage
19 AP-18 Hinweise-/Doku-Seite (Einstellungen → Hinweise, MD-basiert) 0,5 Tag

Leitplanke: AP-00 bis AP-09 sind „Korrektur & Datenmodell-Vorbereitung". Erst danach werden die großen Übersichten (Rohstoff-/Produktbestand) gebaut, weil sie auf den neuen Stammdatenfeldern aufsetzen.


4. Arbeitspakete im Detail

AP-00 — Regressionsbasis: offene 5.1-Tests nachziehen

Ziel: Grüne Test-Suite als Sicherheitsnetz, bevor 5.2 beginnt.

Schritte

  • Pest-Feature-Tests ergänzen (php artisan make:test --pest <Name>):
    • Menü-Labels (Rohstoffqualität, Verpackungsmaterial, Produkt-/Versandverpackung).
    • INCI mit material_quality_id speichern + Anzeige im Produktformular-Katalog.
    • Rezeptur in Prozent (3 Nachkomma) speichern; 100%-Summen-Validierung (grün/rot).
    • Hersteller-Rezeptur getrennt speichern (recipe_type=manufacturer).
    • Produktion edit/update und copy.
    • Nur aktive Produkte im Produktions-Dropdown.

Akzeptanz: php artisan test läuft vollständig grün; neue Tests decken die genannten Features ab.


AP-01 — Quick-Fixes URL-Felder (B1 + B2)

Schritte

  • resources/views/admin/inventory/suppliers/form.blade.php: type="url"type="text" (Zeile ~56).
  • URL-Validierung aller Warenwirtschafts-FormRequests prüfen (Supplier ist ok). Store/UpdatePackagingItemRequest: falls url-Regel → auf ['nullable','string','max:2048'] ändern; zugehöriges Blade-Input auf type="text".
  • vendor/bin/pint --dirty.

Akzeptanz

  • Lieferant mit ausgefüllter URL (auch ohne https:// und mit kodierten Parametern) speichert ohne Fehler.
  • Konfigurator-URL aus Todos Z. 2 wird unverändert gespeichert.

Tests: Feature-Test „Supplier mit Parameter-URL speichern", „PackagingItem mit Parameter-URL speichern".


AP-04 — Querschnitt: iPad-taugliche Tabellen-Aktionen (B5)

Schritte

  • Gemeinsame CSS-Klasse .wawi-actions (größere Buttons, mehr Abstand, Touch-Target ≥ 44px) in vorhandenes Admin-CSS aufnehmen (Laravel Mix; danach npm run dev/prod).
  • In allen resources/views/admin/inventory/**/index.blade.php die Aktionsspalte (Auge/Stift/Mülleimer) auf die Klasse umstellen.

Akzeptanz: Aktionen sind auf dem iPad gut und einzeln klickbar; Optik in allen Modul-Tabellen konsistent.


AP-05 — Einstellungen: UST-Sätze & Lieferzeiten

Ziel: Konfigurierbare Steuersätze und Lieferzeit-Vorlagen als Stammdaten (Basis für AP-06/07/08).

DB

  • tax_rates: name (z. B. „Standard"), percent DECIMAL(5,2), active bool, pos. Seeder: 19,00 / 7,00 / 0,00.
  • delivery_times: label VARCHAR (Freitext, z. B. „35 Werktage"), days (ganze Tage bis Wareneingang, optional Basis für „rechtzeitig bestellen"-Ableitung), active, pos.

Code

  • Models TaxRate, DeliveryTime (make:model -mf), CRUD-Controller unter Admin/Inventory/, FormRequests, Views index+form, Routen unter admin/inventory (superadmin), Sidenav-Einträge.

Akzeptanz: SuperAdmin pflegt UST-Sätze und Lieferzeiten; nur aktive Sätze sind in Dropdowns wählbar; historische (deaktivierte) Sätze bleiben referenzierbar.

Entscheidung (O3): UST als Stammdaten-Tabelle statt PHP-Enum, weil „später änderbar" gefordert ist und historische Werte erhalten bleiben müssen.

Umgesetzte Struktur (Kunde, 02.06.2026): Unter Warenwirtschaft → Einstellungen neuer Unterpunkt „Allgemein" als Sammelseite für kleinteilige Einstellungen. Sektion 1 = Umsatzsteuersätze, Sektion 2 = Lieferzeit-Vorlagen (jeweils Tabelle, neue Einträge jederzeit ergänzbar). Weitere kleinteilige Einstellungen (Default-Werte etc.) werden später als zusätzliche Karten auf derselben „Allgemein"-Seite ergänzt.

Status: Erledigt — Teil 1 (tax_rates) und Teil 2 (delivery_times) als CRUD unter „Allgemein".


AP-06 — Lieferanten erweitern

DB (suppliers)

  • order_method ENUM(email,online_shop) nullable.
  • order_email nullable (falls abweichend von email).
  • order_url nullable (falls abweichend von url).
  • delivery_time VARCHAR nullable (Freitext; optional Verknüpfung mit delivery_times als Vorlage, aber Freitext bleibt führend).

Code

  • Migration + Supplier fillable/casts; Store/UpdateSupplierRequest erweitern; suppliers/form.blade.php: Radio/Select Bestellweg + bedingte Felder + Lieferzeit-Textfeld (mit Vorlagen-Datalist aus delivery_times).

Akzeptanz: Pro Lieferant ist Bestellweg + Ziel (Mail/Shop) + Lieferzeit hinterlegt und editierbar; Daten stehen später dem Rohstoffbestand für Bestell-Links zur Verfügung.

Status: Erledigt (02.06.2026). Migration 2026_06_02_154755_add_order_fields_to_suppliers_table (order_method, order_email, order_url, delivery_time). Formular mit Bestellweg-Select, JS-gesteuerten bedingten Feldern (E-Mail vs. URL) und Lieferzeit-Datalist aus aktiven delivery_times. Freitext bleibt führend, Vorlagen sind nur Eingabehilfe. Tests: tests/Feature/SupplierOrderFieldsTest.php.

Nachtrag (02.06.2026, Kunde): Lieferzeit ist jetzt zusätzlich als fester Tageswert auswertbar. Lieferzeit-Vorlagen haben Feld days (ganze Tage). Lieferant hat delivery_time_days (2026_06_02_160411_*). Beim Auswählen einer Vorlage im Lieferzeit-Feld setzt JS automatisch den Tageswert (manuell überschreibbar). Dieser Tageswert ist die Grundlage, um später Rohstoffe rechtzeitig vor MHD/Bedarf zu bestellen. Gleiche Auto-Befüllung wird in AP-07 (INCI) übernommen.


AP-07 — INCI erweitern

DB

  • Pivot ingredient_supplier: ingredient_id, supplier_id, optional preferred bool, supplier_sku, url.
  • ingredients: tax_rate_id nullable FK, delivery_time VARCHAR nullable.

Code

  • Ingredient: suppliers() belongsToMany, taxRate() belongsTo; fillable/casts.
  • O1: IngredientController auf StoreIngredientRequest/UpdateIngredientRequest umstellen (Ersatz für Request::all()).
  • admin/ingredient/form.blade.php: Select2-Mehrfachauswahl Lieferanten, UST-Dropdown (aktive tax_rates), Lieferzeit-Textfeld.

Lieferzeit-Logik: INCI-Lieferzeit überschreibt Lieferanten-Lieferzeit (Auswertung erst im Rohstoffbestand AP-10).

Akzeptanz: INCI kann mehrere Lieferanten, einen UST-Satz und eine eigene Lieferzeit haben; alles wird gespeichert und angezeigt.

Status: Erledigt (02.06.2026). Migrationen 2026_06_02_161237_add_order_fields_to_ingredients_table (tax_rate_id FK, delivery_time, delivery_time_days) + 2026_06_02_161237_create_ingredient_supplier_table (Pivot mit preferred/supplier_sku/url). Ingredient: taxRate() belongsTo, suppliers() belongsToMany (mit Pivot-Feldern), cast delivery_time_days. O1 umgesetzt: IngredientController nutzt jetzt StoreIngredientRequest (statt Request::all()) und synct Lieferanten via suppliers()->sync(). Formular: UST-Dropdown, Select2-Lieferanten-Mehrfachwahl, Lieferzeit-Textfeld mit data-days-Datalist + Tage-Feld inkl. JS-Autofill (manuell überschreibbar). Der bestehende Single-Endpoint (admin_product_ingredient_store für Neu+Update) wurde beibehalten, daher genügt ein FormRequest. Pivot-Zusatzfelder (preferred/supplier_sku/url) sind im Schema vorbereitet, das Formular synct vorerst nur die Lieferanten-Zuordnung. Tests: tests/Feature/IngredientOrderFieldsTest.php (6 grün).


AP-08 — Einkauf erweitern

DB (stock_entries)

  • tax_rate_id nullable FK + Snapshot tax_rate_percent DECIMAL(5,2) (für historische Korrektheit).
  • price_per_kg_net DECIMAL(10,4) nullable, price_per_kg_gross DECIMAL(10,4) nullable.

Code

  • Migration + StockEntry fillable/casts; Store/UpdateStockEntryRequest erweitern (genau eines von Netto/Brutto verpflichtend bei Rohstoff).
  • stock-entries/_form.blade.php + _scripts.blade.php: UST-Dropdown; JS berechnet Netto↔Brutto gegenseitig beim Eintragen/UST-Wechsel (einheitliche Rundung).
  • Duplizieren: Route GET stock-entries/{stock_entry}/copy + StockEntryController@copy: dupliziert Stufe-1-Felder, setzt status=pending, lässt Charge/MHD/Eingangsdaten leer.

Akzeptanz

  • Einkauf mit Netto oder Brutto anlegbar; Gegenfeld wird automatisch korrekt berechnet.
  • UST-Wechsel aktualisiert das Gegenfeld.
  • Ausgefüllter Einkauf für weitere Kanister/Chargen mit einem Klick duplizierbar.

Tests: Netto→Brutto-Berechnung, Brutto→Netto, Duplizieren erzeugt pending-Kopie ohne Chargendaten.

Status: Erledigt (02.06.2026). Migration 2026_06_02_181548_add_price_fields_to_stock_entries_table (price_per_kg_gross, tax_rate_id, tax_rate_percent). Das bereits vorhandene price_per_kg dient als Netto-Feld (price_per_kg_net), ergänzt um price_per_kg_gross; bewusst kein Rename, um Bestandsdaten/Factory/Tests stabil zu halten. Netto/Brutto-Umrechnung zentral in StockEntryRepository::resolvePrices() (UST-Prozent-Snapshot, fehlender Wert wird berechnet), live im Formular via JS. Duplizieren über stock-entries/{id}/copy legt direkt eine pending-Kopie der Stufe-1-Felder an. Verpackungspreis bleibt Netto-Gesamt ohne UST/Brutto (außerhalb des Plan-Scopes, kann später ergänzt werden). Tests: tests/Feature/StockEntryPriceTest.php (6 grün).


AP-09 — Produktion korrigieren

Ziel: Produktion auf Hersteller-Rezeptur stellen, JS-/iPad-Fehler beheben, Platzhalter Produktentwicklung.

Code

  • Basis Hersteller-Rezeptur: ProductionService::store(), updateProduction(), requiredGramsByIngredient(), buildRecipePayload() von p_ingredients auf manufacturer_ingredients umstellen (Pivot gram/factor analog). ProductionController::recipeJson() entsprechend.

    Entscheidung (§5.1, geklärt): Produktion nutzt ausschließlich die Hersteller-Rezeptur. Kein Fallback auf die Produkt-Rezeptur. Ist für das gewählte Produkt keine Hersteller-Rezeptur gepflegt, muss im Produktions-Formular direkt eine deutliche Warnung erscheinen (kein stilles Laden der Produkt-Rezeptur, Produktion ohne Hersteller-Rezeptur blockieren bzw. unmissverständlich warnen).

  • Chargen-Dropdown-Label: Lieferant - Chargennr. - dd.mm.yyyy (kein „MHD"-Text). Nur Chargen mit Restbestand > 0 anzeigen (Restbestand = received_quantity bereits in production_ingredients verbrauchte Menge dieser Charge). Erfordert Verbrauchsabfrage je stock_entry_id.
  • B3 JS-Fix: „Weitere Charge" fügt genau eine Zeile/ein Dropdown hinzu.
  • Soll-Neuberechnung stabil: Ändert sich oben die Stückzahl, bleiben bereits eingetragene Chargen/Ist-Mengen erhalten; nur Soll-Gramm werden neu berechnet (keine Überschreibung manueller Eingaben).
  • UI vereinfachen: Spaltenüberschriften „Charge"/„Menge" pro Rohstoffzeile entfernen; g hinter Mengen; weniger Linien.
  • B4 iPad-Fix: Bootstrap-Grid der Kopfdaten (Produktionsdatum / Stückzahl) responsive ohne Überlappung.
  • Produktentwicklung-Platzhalter (§5.5, geklärt): Sidenav-Unterpunkt unter „Produktion"; Route + simple View mit Hinweistext, dass hier noch ein genaues Briefing aussteht (keine Bestandsbuchung, keine Logik).

Akzeptanz: Produktion rechnet auf Basis Hersteller-Rezeptur; fehlt diese, erscheint eine Warnung (kein Fallback); Chargenliste zeigt nur verfügbare Chargen im geforderten Label; „Weitere Charge" erzeugt eine Zeile; Stückzahländerung zerstört keine Eingaben; iPad-Layout sauber; Menüpunkt Produktentwicklung mit „Briefing ausstehend"-Hinweis sichtbar.

Tests: Soll-Verbrauch aus Hersteller-Rezeptur; Warnung bei fehlender Hersteller-Rezeptur; Charge ohne Restbestand erscheint nicht; Service-Berechnung bei Stückzahländerung.


AP-02 — Produkt-Klassen: Einzelprodukt vs. Set + Hauptprodukt

Entscheidung (§5.6, geklärt): Echte Sets via Pivot (product_set_items) — mehrere Einzelprodukte bündelbar, nicht nur „genau ein Hauptprodukt".

DB (products)

  • is_set bool default 0.
  • main_product_id nullable FK auf products (Child→Hauptprodukt).
  • main_product_quantity UINT nullable (z. B. 50 für „50 × 15 ml").
  • Pivot product_set_items: set_product_id, component_product_id, quantity.

Code

  • Product: setItems(), mainProduct(), Scopes mainProducts() / singleProducts().
  • Produktformular: Checkbox „Ist Set"; bei aktiv Karten Rezeptur/Verpackung/Warenwirtschaft ausblenden, Karte „Set-Bestandteile" einblenden (Modal wie Rezeptur, nur Einzelprodukte wählbar, mit Menge).
  • Validierung: Set enthält nur Einzelprodukte (keine Sets), mind. 1 Bestandteil; Einzelprodukt darf Rezeptur/Packaging/Warenwirtschaft pflegen.

Akzeptanz: Sets bestehen aus Einzelprodukten mit Menge; Sets sind nicht produzierbar; Produktbestand (AP-11) zeigt nur Haupt-/Einzelprodukte; Set-Verkauf reduziert später die enthaltenen Einzelprodukte (AP-13).


AP-03 — „Nicht vorrätig" mit Zeitangabe

DB (products)

  • out_of_stock_until DATE nullable (Empfehlung: aus Tagen berechnet, sauber für Resttage).
  • out_of_stock_indefinite bool default 0 (zweites Kästchen „auf unbestimmte Zeit vergriffen", ohne Tagefeld).

Code

  • Produktformular: Checkbox „Nicht vorrätig" + Tagefeld → out_of_stock_until = now()->addDays($tage); zweite Checkbox „unbestimmt".
  • Shop-/Bestellansicht: bei out_of_stock_until in der Zukunft Hinweis „In ca. X Tagen wieder da!" (Resttage dynamisch); bei indefinite entsprechender Dauerhinweis.

Entscheidung (§5.3, geklärt): Vorerst nur Hinweis, der Kauf bleibt möglich. In der Hinweise-Doku (AP-18) ist zu dokumentieren, dass künftig optional eine Kauf-Sperre ergänzt werden kann/muss.

Akzeptanz: Produkt zeitweise/unbefristet als nicht vorrätig markierbar; Resttage zählen automatisch herunter; nach Ablauf verschwindet der Hinweis ohne manuelles Zutun.


AP-10 — Rohstoffbestand (InventoryService + Übersicht)

Code

  • app/Services/InventoryService.php: Restbestand je Rohstoff/Charge/Lagerort = SUM(received_quantity) SUM(production_ingredients.quantity_used) SUM(stock_disposals.quantity) (Ausgang ab AP-12).
  • Controller + View „Rohstoffbestand" (Sidenav-Menüpunkt). Spalten: INCI/Rohstoff, Qualität, Gesamtbestand, Bestand je Lagerort (dynamisch aus locations), verbraucht/Produktion, Meldebestand/Bedarf, Status, Lieferanten, Lieferzeit (INCI vor Lieferant), Bestellaktion (mailto:/Shop-Link je order_method).
  • Nur Chargen mit Restbestand > 0 einbeziehen; kritische Rohstoffe visuell markieren.

Akzeptanz: Reale Restbestände sichtbar; Bestellweg direkt aus der Übersicht erreichbar; kritische Rohstoffe hervorgehoben.


AP-11 — Produktbestand + Historie

DB

  • product_stock_movements: product_id, direction ENUM(in,out), quantity, reason, source (produktion/verkauf/manuell/set), user_id, created_at, reference_type/reference_id (polymorph, nullable).
  • Schwellwerte: Felder an products (min_product_stock, critical_product_stock) oder eigene Tabelle.
  • Initialisierung (Briefing): Lagerbestand einmalig einpflegbar (Anfangsbestand als in-Bewegung mit Grund „Initialbestand").

Code

  • Bestand = SUM(in) SUM(out). Manuelle Bewegung: Menge + Grund + Richtung Pflicht.
  • Hauptmenü „Produktbestand" (nur Hauptprodukte, Suche, Checkbox „nur kritische", Buttons +//Produzieren, rot/gelb-Markierung) + Untermenü „Historie" (filterbar Produkt/Quelle/Zeitraum/User; revisionssicher, Korrektur nur per Gegenbuchung).

Akzeptanz: Bestand schnell pflegbar; jede Bewegung in der Historie; nur Hauptprodukte sichtbar; Kritisch-Filter funktioniert.


AP-12 — Ausgang / Ausschuss (Rohstoffe/Verpackung)

  • stock_disposals (Typ, Artikel, Charge optional, Lagerort, Menge, Einheit, Grund Pflicht, User, Datum) + Controller/Views; Integration in InventoryService.
  • Akzeptanz: Ausgang reduziert Rohstoff-/Verpackungsbestand; Grund ist Pflicht.

AP-13 — Shop-Anbindung: Bestand bei Verkauf reduzieren

  • Entscheidung (§5.2, geklärt): Bestandsabzug erfolgt beim Versand (erst wenn der Versand gebucht ist, wurde das Produkt real „aus dem Regal" genommen). Dieser Hinweis ist auch in der Hinweise-Doku (AP-18) zu hinterlegen.
  • Beim Statuswechsel auf versendet product_stock_movements-out-Buchung; bei Sets die enthaltenen Einzelprodukte (× Menge) reduzieren. Stornos/Retouren als Gegenbuchung (Detailregel bei Umsetzung festzurren).
  • Akzeptanz: Versand reduziert Produktbestand; Set-Versand reduziert Einzelprodukte; jede Buchung in der Historie.

AP-14 — Audit-Trail

  • inventory_logs (polymorph) + Observer auf StockEntry/Production/StockDisposal/ProductStockMovement.
  • Akzeptanz: Jede Bestandsbewegung wird mit User/Zeit/Änderungen protokolliert.

AP-15 — Blockbasierte Rechte

  • Entscheidung (§5.4, geklärt): Blockrechte gelten nur für Warenwirtschaft und Produktmanagement, nicht für alle Admin-Bereiche. In der Hinweise-Doku (AP-18) dokumentieren, dass die Rechte bei Bedarf später ausgebaut werden können/müssen, falls sie nicht ausreichen.
  • admin_permission_blocks + admin_permission_user (view/edit pro Block: Produkte, Einkauf, Rohstoffbestand, Produktbestand, Produktion, Lieferanten, Einstellungen, Historie); Middleware/Gates; Sidenav zeigt nur erlaubte Blöcke.
  • Bestehende Level (copyreader/admin/superadmin) bleiben als Grundschutz.
  • Akzeptanz: SuperAdmin vergibt pro Mitarbeiter view/edit je Block (Warenwirtschaft + Produktmanagement); Leserecht ohne Schreibrecht greift; gesperrte Blöcke unsichtbar.

AP-16 — 2FA Google Authenticator (Admins)

  • TOTP-Secret am App\User (Guard user), Setup-Flow, Login-Zwischenschritt; Recovery-Codes.
  • Akzeptanz: Bei aktivem 2FA kein Zugriff auf geschützte Bereiche ohne Code.

AP-17 — Warenwirtschafts-Einstellungen

  • Über bestehendes Setting-Model: inventory_alert_email, inventory_alert_enabled, inventory_default_location, optional Produktbestands-Schwellwerte, Standardtexte „Nicht vorrätig". SuperAdmin-only.

AP-18 — Hinweise-/Doku-Seite (Einstellungen → Hinweise)

Anforderung (§5, Kunde): Eine als MD gepflegte Doku, die unter Warenwirtschaft → Einstellungen → „Hinweise" im Admin sichtbar ist, damit auch der Kunde Einsicht hat.

Code

  • Markdown-Datei im Repo (z. B. docs/hinweise.md oder resources/docs/hinweise.md) als Pflege-Quelle.
  • Route + View unter admin/inventory (Einstellungen-Gruppe), die das MD gerendert anzeigt (Parsedown o. Ä.); Sidenav-Eintrag „Hinweise".

Inhalt (laufend zu pflegen):

  • Kurzer Entwicklungsstand / Überblick (was fertig ist, was offen ist).
  • Wichtige Hinweise & noch nötige Schritte verständlich für den Kunden.
  • Festgehaltene offene/spätere Entscheidungen, u. a.:
    • „Nicht vorrätig" kann künftig optional zur Kauf-Sperre ausgebaut werden (§5.3).
    • Blockrechte ggf. später über Warenwirtschaft/Produktmanagement hinaus ausbauen (§5.4).
    • Shop-Bestandsabzug erfolgt bei Versand (§5.2).
  • Akzeptanz: Kunde sieht unter Einstellungen → Hinweise eine lesbare, gepflegte Statusseite.

Empfehlung: Früh als Platzhalter anlegen und mit jedem AP fortschreiben, damit der Kunde jederzeit den Stand sieht.


5. Klärungspunkte — ALLE GEKLÄRT (Kunde, 02.06.2026)

Alle Punkte sind beantwortet und in die jeweiligen Arbeitspakete eingearbeitet. Keine Blocker mehr offen.

  1. Produktion-BasisAusschließlich Hersteller-Rezeptur. Kein Fallback. Ist keine angelegt, erscheint direkt eine Warnung. → eingearbeitet in AP-09.

  2. Shop-BestandsabzugBeim Versand (erst mit gebuchtem Versand ist das Produkt real „aus dem Regal"). Als Hinweis dokumentieren. → eingearbeitet in AP-13 + Hinweis in AP-18.

  3. „Nicht vorrätig" → Vorerst nur Hinweis. Dokumentieren, dass künftig optional eine Kauf-Sperre ergänzt werden kann. → eingearbeitet in AP-03 + Hinweis in AP-18.

  4. Blockrechte-GeltungNur Warenwirtschaft und Produktmanagement. Dokumentieren, dass die Rechte bei Bedarf später ausgebaut werden können. → eingearbeitet in AP-15 + Hinweis in AP-18.

  5. ProduktentwicklungPlatzhalter-Seite mit Hinweis, dass ein genaues Briefing noch aussteht. → eingearbeitet in AP-09.

  6. Child-Produkt / SetsEchte Sets via Pivot (product_set_items). → eingearbeitet in AP-02.

  7. Hinweise-Doku (neu): MD-basierte Doku-Seite unter Einstellungen → Hinweise mit Entwicklungsstand, wichtigen Hinweisen und noch nötigen Schritten, einsehbar auch für den Kunden. → neues AP-18.


6. Empfohlene Sofort-Reihenfolge (nächste Schritte)

Erledigt: AP-00, AP-01, AP-04 (+ AP-04.1), AP-05, AP-06 (+ Nachtrag), AP-07 (+ AP-07.1), AP-08.

➡️ Hier geht es weiter:

  1. AP-09 Produktionskorrekturen: ausschließlich Hersteller-Rezeptur (+ Warnung bei fehlender Rezeptur, kein Fallback), Chargen-Label + Restbestandsfilter, B3 „Weitere Charge"-Fix, stabile Soll-Neuberechnung, B4 iPad-Layout, Produktentwicklung-Platzhalter.
  2. AP-18 Hinweise-Doku (Einstellungen → Hinweise) — kann parallel/früh als Platzhalter angelegt und laufend gepflegt werden.
  3. Datenmodell AP-02 (Sets via Pivot) / AP-03 („Nicht vorrätig", nur Hinweis).
  4. Große Übersichten AP-10/AP-11 und Folge-APs (AP-12AP-17).

7. Pflege dieses Dokuments

  • Jedes abgeschlossene AP hier mit Datum + Kurzbeschreibung + Test-Status protokollieren (analog Umsetzungsprotokoll in entwicklungsplan.md).
  • Bei DB-Änderungen: Migration-Dateinamen referenzieren; bei Modellen Casts in casts()-Methode pflegen (L11-Konvention).
  • Vor jedem Commit: vendor/bin/pint --dirty und betroffene Tests (php artisan test --filter=...).