Warenwirtschaft: AP-45 + AP-47 — Verpackung aus Produktionsergebnis, Produktionsrelevant-Flag

AP-45: Verpackungsverbrauch (Etikett/Tiegel) wird jetzt aus dem tatsächlichen
Produktionsergebnis gebucht — je Ergebnisprodukt dessen eigene Stückliste ×
Ergebnismenge, über alle Outputs summiert — statt aus der geplanten Stückzahl.
syncPackagingSnapshot liest die production_outputs und läuft daher nach
persistOutputs (store + update umgestellt).

AP-47: Neues Produkt-Kennzeichen „produktionsrelevant" (Boolean, Default true).
Nur so markierte Produkte erscheinen in der Produktions-Auswahl
(ProductionController create/edit/copy) und in der „Enthalten in"-Box des
Rohstoffbestands (blendet z. B. Aloe-Handelsware und Zweitgrößen aus).
Checkbox im Produktformular (mit Hidden-Fallback 0). Migration Default true,
damit Bestandsdaten unverändert bleiben.

Migrationen add_production_relevant auf Dev-/Live-DB ausgeführt. 4 Tests, Suite 314 grün.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Kevin Adametz 2026-08-28 08:38:59 +00:00
parent e6007efc41
commit d51860af39
7 changed files with 132 additions and 17 deletions

View file

@ -46,7 +46,7 @@ class ProductionController extends Controller
$defaultProductId = (int) $request->query('product_id') ?: null;
return view('admin.inventory.productions.create', [
'products' => Product::query()->where('active', 1)->where('is_set', false)->orderBy('name')->get(['id', 'name', 'batch_prefix']),
'products' => Product::query()->where('active', 1)->where('is_set', false)->where('production_relevant', true)->orderBy('name')->get(['id', 'name', 'batch_prefix']),
'locations' => Location::query()->where('active', true)->orderBy('name')->get(),
'defaultLocationId' => $defaultLocationId,
'defaultProductId' => $defaultProductId,
@ -124,7 +124,7 @@ class ProductionController extends Controller
return view('admin.inventory.productions.edit', [
'model' => $production,
'products' => Product::query()
->where(fn ($q) => $q->where('active', 1)->where('is_set', false))
->where(fn ($q) => $q->where('active', 1)->where('is_set', false)->where('production_relevant', true))
->orWhere('id', $production->product_id)
->orderBy('name')->get(['id', 'name', 'batch_prefix']),
'locations' => Location::query()->where('active', true)->orderBy('name')->get(),
@ -190,7 +190,7 @@ class ProductionController extends Controller
return view('admin.inventory.productions.create', [
'model' => $production,
'products' => Product::query()->where('active', 1)->where('is_set', false)->orderBy('name')->get(['id', 'name', 'batch_prefix']),
'products' => Product::query()->where('active', 1)->where('is_set', false)->where('production_relevant', true)->orderBy('name')->get(['id', 'name', 'batch_prefix']),
'locations' => Location::query()->where('active', true)->orderBy('name')->get(),
'defaultLocationId' => $defaultLocationId,
]);

View file

@ -85,7 +85,9 @@ class RawMaterialStockController extends Controller
'materialQuality',
'taxRate',
'suppliers' => fn ($q) => $q->orderByPivot('preferred', 'desc')->orderBy('name'),
'products' => fn ($q) => $q->where('active', true),
// AP-47: nur produktionsrelevante Produkte in „Enthalten in" (blendet z. B.
// Aloe-Handelsware und Zweitgrößen aus).
'products' => fn ($q) => $q->where('active', true)->where('production_relevant', true),
]);
// AP-37: Jedes Produkt hat i. d. R. zwei product_ingredients-Zeilen