Warenwirtschaft: OPT-3 Index-Limits + OPT-4 show()-Refactoring
- Wareneingang-/Produktions-Uebersicht: Eingegangene auf 500 gedeckelt (offene Bestellungen immer vollstaendig), ?all=1 + Hinweis-Link; ungenutzte User-Eager-Loads entfernt - RawMaterialStockController::show() entschlackt: Chargen-Restmengen (FEFO) und offene Bestellungen im InventoryService, letzter Netto-Preis je Lieferant als Window-Function-Query im StockEntryRepository Tests: RawMaterialStockTest +2, volle Suite 186 gruen, 663 Assertions Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
209ea467eb
commit
e47d848d3d
10 changed files with 165 additions and 75 deletions
|
|
@ -103,8 +103,8 @@ Alle Punkte dieser älteren Runde sind in V4.0 eingeflossen und umgesetzt (URL-F
|
|||
| 4 | ✅ AP-20 | Rohstoffbestand-Filter + „Kein Rohstoffbestand"-Flag — **erledigt 06.07.2026** | AP-21 | 1–2 Tage |
|
||||
| 5 | ✅ AP-23 | Rezeptur-Phasen (Hersteller-Rezeptur) — **erledigt 06.07.2026** | – | 3–5 Tage |
|
||||
| 6 | ✅ AP-24 | Chargen-Nr.-Präfix — **erledigt 06.07.2026** | – | 1 Tag |
|
||||
| 7 | ➡️ OPT-3 + OPT-4 | **NÄCHSTER SCHRITT:** Pagination + show()-Refactoring | – | 1,5–2,5 Tage |
|
||||
| 8 | AP-27 | Wareneingang: Chargen-Merge | OPT-4 | 1–2 Tage |
|
||||
| 7 | ✅ OPT-3 + OPT-4 | Pagination + show()-Refactoring — **erledigt 06.07.2026** | – | 1,5–2,5 Tage |
|
||||
| 8 | ➡️ AP-27 | **NÄCHSTER SCHRITT:** Wareneingang: Chargen-Merge | OPT-4 | 1–2 Tage |
|
||||
| 9 | AP-28 | Neue Produktions-Maske + Produktionsergebnis | AP-21, AP-23, AP-24, AP-27 | 5–8 Tage |
|
||||
| 10 | AP-13 | Shop-Bestandsabzug bei Versand (inkl. Sets; Konzept aus V4.0) | AP-28 (saubere Buchungslogik) | 3–5 Tage |
|
||||
| 11 | AP-14 | Audit-Trail | – | 2–3 Tage |
|
||||
|
|
@ -153,10 +153,10 @@ Die fachlichen Detailspezifikationen zu **AP-20, AP-21, AP-23, AP-24, AP-27, AP-
|
|||
| 06.07.2026 | **AP-20 (Rohstoffbestand-Filter + „Kein Rohstoffbestand")** | Migration `2026_07_06_133714_add_exclude_from_stock_to_ingredients_table` (`ingredients.exclude_from_stock` bool default 0); `Ingredient` fillable+cast; Checkbox „Kein Rohstoffbestand" (Hinweistext Allergen-Angaben) im INCI-Formular. `RawMaterialStockController@index`: grundsätzlich `exclude_from_stock=false`, neuer Umschalt-Modus `?scope=all\|recipe` (Default `all`; `recipe` nutzt `scopeUsedInActiveRecipes()` aus AP-21); Button-Gruppe „Alle / Nur aus Herstellerrezepturen" in der Toolbar. `InventoryService::criticalIngredientCount()` (Sidenav-Badge) respektiert das Flag. Hinweise-Doku fortgeschrieben. **Nebenbei behoben:** die beiden AP-21-Migrationen hatten denselben Timestamp, wodurch `add_storage…` alphabetisch **vor** `create_storage…` lief und auf MySQL am FK scheiterte (Teilreste `alt_name`/`storage_room_id`) — Migration auf `…120753` umbenannt, Teilreste bereinigt, alle drei Migrationen sauber ausgeführt. | `RawMaterialStockTest` +2 (Flag blendet aus Übersicht + Kritisch-Zähler aus; Modus `recipe` filtert, Default zeigt alle, Pills rendern). Volle Suite: **172 grün, 624 Assertions** |
|
||||
| 06.07.2026 | **AP-23 (Rezeptur-Phasen)** | **DB:** Migration `2026_07_06_134518_create_recipe_phases_table` — Tabelle `recipe_phases` (`product_id` FK cascade als `unsignedInteger` — `products.id` ist historisch int, kein `foreignId`!; `recipe_type` default `manufacturer`, `name`, `note` nullable, `pos`) + `product_ingredients.recipe_phase_id` (nullable FK, `nullOnDelete`); auf DB ausgeführt. **Abweichung zur V5.0-Spec:** kein Unique auf (`product_id`,`recipe_type`,`name`) — frei editierbare Namen sollen beim Speichern nicht crashen; Duplikate sind fachlich unkritisch. **Models:** `RecipePhase` (+ `Product::recipePhases()`, `ProductIngredient::phase()`, Pivot um `recipe_phase_id` erweitert). **Formular** (`admin/product/form.blade.php` + JS in `edit.blade.php`): Hersteller-Rezeptur-Card in **Phasen-Blöcke** umgebaut — je Block editierbarer Name (Platzhalter Phase A/B … aktualisiert sich), Rohstoff-Tabelle (Anteil %/Faktor/Effektiv wie bisher), Phasen-**Notiz**, „+ Rohstoffe hinzufügen" je Phase (gemeinsames Modal mit Ziel-Phase), „+ Neue Phase" (JS-Template), Phase entfernen (mit Warnung bei Zeilen); **Drag&Drop**: Phasen untereinander + Zeilen innerhalb und **zwischen** Phasen (Sortable `group`); 100-%-Summe global über alle Phasen (Anzeige grün/rot wie bisher); `mfg_row_phase[]`-Sync bei Drag/Add/Remove/Submit. **Repository:** `updateManufacturerIngredients()` persistiert Phasen (`persistRecipePhases()`: leerer Name ⇒ Auto „Phase A/B…", einzelner unbenannter Block ohne Notiz ⇒ **phasenlos wie bisher**, `recipe_phase_id=NULL`); `copy()` kopiert Phasen inkl. Zeilen-Zuordnung (ID-Mapping). Produktion (`requiredGramsByIngredient`) rechnet unverändert über alle Zeilen. **Blade-Falle behoben:** inline `@php(…)` (AP-25-Verfügbarkeits-Card) + neuer `@php…@endphp`-Block im selben Template ließen den Compiler beide falsch paaren (Raw-Block von Z. 106 bis 771) — inline-Variante auf Block-Form umgestellt. Hinweise-Doku fortgeschrieben. | Neuer `tests/Feature/RecipePhaseTest.php` (6 grün, 25 Assertions): Phasen+Zeilen+Notiz+Reihenfolge, Auto-Name, implizit phasenlos, Re-Save ersetzt vollständig, Kopie inkl. Zuordnung, Produktion phasenunabhängig. Volle Suite: **178 grün, 649 Assertions** |
|
||||
| 06.07.2026 | **AP-24 (Chargen-Nr.-Präfix)** | Migration `2026_07_06_140324_add_batch_prefix_to_products_table` (`products.batch_prefix` VARCHAR(20) nullable); auf DB ausgeführt. `Product` fillable + Helper `suggestedBatchNumber(?Carbon $date)` = Präfix + Datum `ttmmjj` (Beispiel `TP1` + 15.06.26 ⇒ `TP1150626`; ohne Präfix ⇒ null; Default-Datum heute). Eingabefeld „Chargen-Nr.-Präfix" in der Warenwirtschaft-Card des Produktformulars (Hilfetext mit Beispiel); `ProductRepository::update()` trimmt (leer ⇒ null). Vorbelegung des editierbaren Chargen-Nr.-Felds folgt in AP-28 (Produktionsergebnis). Chargen-Format war bereits in der Hinweise-Doku dokumentiert (AP-21-Lieferung). | Neuer `tests/Feature/BatchPrefixTest.php` (6 grün): Speichern/Trim, leer ⇒ null, `ttmmjj`-Zusammensetzung, Default heute, ohne Präfix null, Formular-Render. Volle Suite: **184 grün, 657 Assertions** |
|
||||
| _offen_ | OPT-3/OPT-4 | Pagination + show()-Refactoring | – |
|
||||
| 06.07.2026 | **OPT-3 + OPT-4** | **OPT-3 (Index-Limits):** `StockEntryRepository::listForIndex(?int $receivedLimit = 500)` — offene Bestellungen immer vollständig, Eingegangene auf 500 gedeckelt (neueste zuerst, stabile Sekundärsortierung nach `id`); ungenutzte Eager-Loads `orderedByUser`/`receivedByUser` entfernt (nur `show` braucht sie). `ProductionRepository::listForIndex(?int $limit = 500)` analog. Beide Controller unterstützen `?all=1`; die Views zeigen bei erreichtem Limit einen Hinweis mit „Alle anzeigen"-Link. **OPT-4 (show() entschlackt):** Chargen-Restmengen (`chargesWithRemainingForIngredient()`, FEFO) und offene Bestellungen (`openOrdersForIngredient()`) in den `InventoryService` verschoben (Konstruktor-Injection `ProductionService`, kein Zyklus); `lastNetPricePerSupplier()` in `StockEntryRepository` als **eine** Window-Function-Query (`ROW_NUMBER() OVER (PARTITION BY supplier_id …)`, läuft auf MySQL 8 + SQLite) statt In-Memory-Schleife über alle Einkäufe. `RawMaterialStockController::show()` ist nur noch Orchestrierung. | `RawMaterialStockTest` +2 (letzter Netto-Preis je Lieferant aus neuestem Einkauf; Liste deckelt Eingegangene, Offene vollständig, `null` = alle). Volle Suite: **186 grün, 663 Assertions** |
|
||||
| _offen_ | AP-27 | Chargen-Merge Wareneingang | – |
|
||||
| _offen_ | AP-28 | Neue Produktions-Maske + Produktionsergebnis | – |
|
||||
| _offen_ | AP-13 | Shop-Bestandsabzug | – |
|
||||
| _offen_ | AP-14/15/16/17 | Audit-Trail, Blockrechte, 2FA, WaWi-Einstellungen | – |
|
||||
|
||||
> **➡️ HIER GEHT ES WEITER: OPT-3 (Pagination der Index-Listen) + OPT-4 (`RawMaterialStockController::show` entschlacken)** gemäß §2. OPT-4 bewusst vor AP-27/AP-28, weil die Chargen-Gruppierung dieselben Stellen anfasst. Danach AP-27 (Wareneingang: Chargen-Merge) → AP-28 (neue Produktions-Maske + Produktionsergebnis; nutzt `suggestedBatchNumber()` aus AP-24, Phasen aus AP-23, Lagerort/Alternativname aus AP-21).
|
||||
> **➡️ HIER GEHT ES WEITER: AP-27 (Wareneingang: gleiche Charge zusammenführen)** gemäß V5.0-Spezifikation (§6 der V5.0-Datei): Existenz-Check per JSON-Endpoint beim Erfassen (`batch_number` + `ingredient_id` ⇒ Hinweis + Vorbelegung MHD/Lagerort), Chargen-Anzeige/Restbestand je `batch_number` summiert (Detailansicht nutzt jetzt `InventoryService::chargesWithRemainingForIngredient()` aus OPT-4 — dort gruppieren), Charge-Dropdown der Produktion nach `batch_number` gruppiert mit Summen-Rest. Jeder Einkauf bleibt eigener `stock_entry`. Danach AP-28 (neue Produktions-Maske + Produktionsergebnis; nutzt `suggestedBatchNumber()` aus AP-24, Phasen aus AP-23, Lagerort/Alternativname aus AP-21).
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue