gruene-seele/resources/views/admin/inventory/productions/create.blade.php
Kevin Adametz abd202a02e Warenwirtschaft: AP-43 — Produktion zwischenspeichern (Entwurf) + „abschließen"
Der Speicher-Button heißt jetzt „Produktion abschließen"; daneben gibt es
„Zwischenspeichern (Entwurf)". Ein Entwurf sichert den Stand ohne Pflichtfeld-
und ohne Bestandsprüfung und bucht KEINEN Bestand (Roh-/Produkt-/Verpackung).
Erst „abschließen" prüft vollständig und bucht.

- Migration: productions.status (default 'completed'; Bestand ist bereits gebucht).
- Production-Model: STATUS_DRAFT/COMPLETED, isDraft(), scopeBooked().
- InventoryService: Entwürfe fallen aus allen Verbrauchs-/Bestandsjoins heraus
  (status != draft an den 4 productions-Joins).
- ProductionService store()/updateProduction() bekommen $draft: Entwurf
  überspringt Rezeptur-/Mengen-/Bestandsprüfung + Buchungen, sichert nur
  vollständige Chargen-Zeilen (filterCompleteLines) und die angegebenen Outputs.
  Ein abgeschlossene Produktion kann NICHT zurück in den Entwurf (sonst
  verwaisen die Buchungen) — Guard wirft ValidationException.
- StoreProductionRequest: save_mode=draft => nur Kopfdaten Pflicht, Chargen/
  Ergebnis optional; validatedPayload filtert unvollständige Zeilen/Outputs.
- Controller: Entwurf löst Chargen tolerant auf (nicht auflösbare Chargen werden
  übersprungen, Entwurf ist immer speicherbar) und leitet zur Bearbeitung zurück.
- Views: create/edit „abschließen" + „Zwischenspeichern"-Button (nur solange
  Entwurf); Entwurf-Badge in Liste + Bearbeiten-Kopf.

Tests: 5 neue (kein Produktbestand, kein Rohstoffverbrauch, Abschluss bucht,
Rück-Entwurf verboten, HTTP-Entwurf ohne Ergebnis ok / Abschluss erzwingt
Ergebnis). Migration auf Dev-/Live-DB. Suite 336 grün.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-28 09:59:42 +00:00

34 lines
1.8 KiB
PHP

@extends('layouts.layout-2')
@section('content')
<h4 class="font-weight-bold py-2 mb-2">{{ __('Neue Produktion') }}</h4>
<div class="card">
<div class="card-body">
<form method="post" action="{{ route('admin.inventory.productions.store') }}" id="form-production">
@csrf
@include('admin.inventory.productions._form_fields', ['isEdit' => false])
<button type="submit" name="save_mode" value="complete" class="btn btn-primary" id="btn-submit-production">{{ __('Produktion abschließen') }}</button>
{{-- AP-43: Zwischenspeichern als Entwurf — ohne Pflichtfeld-/Bestandsprüfung, bucht keinen Bestand. --}}
<button type="submit" name="save_mode" value="draft" class="btn btn-outline-primary" id="btn-save-draft" formnovalidate>{{ __('Zwischenspeichern (Entwurf)') }}</button>
<a href="{{ route('admin.inventory.productions.index') }}" class="btn btn-outline-secondary">{{ __('Abbrechen') }}</a>
</form>
</div>
</div>
@endsection
@section('scripts')
@php
// AP-27: Zeilen je Charge (batch_key) zusammenfassen — mehrere Einkäufe derselben Charge = eine Formularzeile.
$existingLines = $model
? $model->productionIngredients->groupBy('ingredient_id')->map(function ($lines) {
return $lines
->groupBy(fn ($l) => $l->stockEntry?->batchGroupKey() ?? 'e:'.$l->stock_entry_id)
->map(fn ($group, $key) => ['batch_key' => $key, 'quantity_used' => (float) $group->sum('quantity_used')])
->values();
})
: [];
@endphp
@include('admin.inventory.productions._scripts', ['existingLines' => $existingLines, 'excludeProductionId' => null])
@endsection