From 122d28bc4f9fe401f06a7539aa3baa037eb30a02 Mon Sep 17 00:00:00 2001 From: Kevin Adametz Date: Tue, 8 Sep 2026 10:57:07 +0000 Subject: [PATCH] =?UTF-8?q?Warenwirtschaft:=20F-06=20=E2=80=94=20Chargenze?= =?UTF-8?q?ilen=20nach=20Validierungsfehler=20aus=20old()=20wiederherstell?= =?UTF-8?q?en?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Vorbelegung der Chargen-Zeilen zentral in ProductionController::existingLines(); old('ingredient_lines') hat Vorrang vor dem gespeicherten Stand. Co-Authored-By: Claude Fable 5.1 --- .../Admin/Inventory/ProductionController.php | 41 +++++++++++++++++++ .../inventory/productions/_scripts.blade.php | 2 +- .../inventory/productions/create.blade.php | 15 +------ .../inventory/productions/edit.blade.php | 13 +----- tests/Feature/ProductionDraftTest.php | 32 +++++++++++++++ 5 files changed, 78 insertions(+), 25 deletions(-) diff --git a/app/Http/Controllers/Admin/Inventory/ProductionController.php b/app/Http/Controllers/Admin/Inventory/ProductionController.php index 76c4f94..3c3564a 100644 --- a/app/Http/Controllers/Admin/Inventory/ProductionController.php +++ b/app/Http/Controllers/Admin/Inventory/ProductionController.php @@ -52,6 +52,7 @@ class ProductionController extends Controller 'defaultLocationId' => $defaultLocationId, 'defaultProductId' => $defaultProductId, 'model' => null, + 'existingLines' => $this->existingLines(null), ]); } @@ -160,6 +161,7 @@ class ProductionController extends Controller ...$this->productCatalogs($production), 'locations' => Location::query()->where('active', true)->orderBy('name')->get(), 'defaultLocationId' => $defaultLocationId, + 'existingLines' => $this->existingLines($production), ]); } @@ -217,9 +219,48 @@ class ProductionController extends Controller ...$this->productCatalogs($production), 'locations' => Location::query()->where('active', true)->orderBy('name')->get(), 'defaultLocationId' => $defaultLocationId, + 'existingLines' => $this->existingLines($production), ]); } + /** + * Vorbelegung der Chargen-Zeilen im Formular, Schlüssel „Rohstoff|Phase“ (F-04). + * Prüfung 08.09.2026 F-06: Nach einem Validierungsfehler haben die zuletzt + * eingegebenen Zeilen (old()) Vorrang vor dem gespeicherten Stand — wie bei + * Kopfdaten und Ergebniszeilen. Sonst AP-27: Zeilen je Charge (batch_key) + * zusammenfassen, mehrere Einkäufe derselben Charge = eine Formularzeile. + * + * @return array> + */ + private function existingLines(?Production $production): array + { + $old = old('ingredient_lines'); + if (is_array($old) && $old !== []) { + return collect($old) + ->filter(fn ($l) => is_array($l) + && (int) ($l['ingredient_id'] ?? 0) > 0 + && (trim((string) ($l['batch_key'] ?? '')) !== '' || trim((string) ($l['quantity_used'] ?? '')) !== '')) + ->groupBy(fn ($l) => (int) $l['ingredient_id'].'|'.(! empty($l['recipe_phase_id']) ? (int) $l['recipe_phase_id'] : '')) + ->map(fn ($group) => $group->map(fn ($l) => [ + 'batch_key' => trim((string) ($l['batch_key'] ?? '')), + 'quantity_used' => (string) ($l['quantity_used'] ?? ''), + ])->values()->all()) + ->all(); + } + + if ($production === null) { + return []; + } + + return $production->productionIngredients + ->groupBy(fn ($l) => $l->formGroupKey()) + ->map(fn ($lines) => $lines + ->groupBy(fn ($l) => $l->formBatchKey()) + ->map(fn ($group, $key) => ['batch_key' => (string) $key, 'quantity_used' => (float) $group->sum('quantity_used')]) + ->values()->all()) + ->all(); + } + /** * Prüfung 08.09.2026 F-02: Zwei getrennte Kataloge. * - `products`: Planungsprodukt oben — nur produktionsrelevante Produkte (AP-47), diff --git a/resources/views/admin/inventory/productions/_scripts.blade.php b/resources/views/admin/inventory/productions/_scripts.blade.php index 45324a9..4da8bad 100644 --- a/resources/views/admin/inventory/productions/_scripts.blade.php +++ b/resources/views/admin/inventory/productions/_scripts.blade.php @@ -1,7 +1,7 @@