{{-- Filial- und Zentrallagerbestellung sind derselbe Vorgang auf zwei Geltungsbereichen. Sie bleiben getrennte Seiten - dahinter liegen zwei Tabellen, zwei Rechenlaeufe und ganz andere Steuerelemente (Filter, Senden je Filiale, Skip, Riccardo-Weg gegen eine Liste mit einem Knopf). Eine Seite mit "wenn Zentrallager"-Abzweigungen waere unuebersichtlicher als zwei klare. Was fehlte, war nur der Weg dazwischen (07.09.2026). --}}
Filialen Zentrallager 94
@php $nf0 = fn ($v) => number_format((float) $v, 0, ',', '.'); // Ein einzelner Filial-Blick (Filter gesetzt oder nur eine Filiale) zeigt // die Positionstabellen sofort; die Gesamtsicht startet eingeklappt. $startOffen = request()->filled('branch_id') || $orders->count() === 1; // Farbwelt je Lieferant, damit die Belege auf einen Blick unterscheidbar sind. $lieferantenFarbe = fn ($id) => match ((int) $id) { 2 => ['border-blue-300', 'bg-blue-50', 'text-blue-800'], // ExTrade: taeglich 3 => ['border-purple-300', 'bg-purple-50', 'text-purple-800'], // Riccardo: woechentlich 1 => ['border-teal-300', 'bg-teal-50', 'text-teal-800'], // Nico: woechentlich default => ['border-red-400', 'bg-red-50', 'text-red-700'], // ohne Lieferant }; $rhythmus = fn ($id) => match ((int) $id) { 2 => 'Bestellung täglich 07:00', 1, 3 => 'Bestellung montags 07:00', default => 'nicht bestellbar', }; // ExTrade-Direktversand (Framework 02.09.2026, API-Definition folgt). $extradeBereit = app(\App\Services\ExTrade\ExTradeOrderService::class)->istKonfiguriert(); $extradeGesendet = fn ($branchId) => \App\Models\SupplierOrder::heuteGesendet( \App\Services\ExTrade\ExTradeOrderService::SUPPLIER_ID, 'branch', $branchId, ); // Riccardo (Vorgabe 07.09.2026): Auftrag in der Online-Wawi + Ameise-CSV // fuer die Offline-Wawi, beides ueber die Vorschauseite. $riccardoGesendet = fn ($branchId) => \App\Models\SupplierOrder::heuteGesendet( \App\Services\Riccardo\RiccardoOrderService::SUPPLIER_ID, 'branch', $branchId, ); // Niko (Vorgabe 08.09.2026): derselbe Weg ohne API - statt eines Auftrags // per REST entsteht eine Bestelldatei, dazu wie bei Riccardo die Ameise-CSV. $nikoGesendet = fn ($branchId) => \App\Models\SupplierOrder::heuteGesendet( \App\Services\Niko\NikoOrderService::SUPPLIER_ID, 'branch', $branchId, ); @endphp @unless($zeigePositionen)
{{ number_format($summary['positions'], 0, ',', '.') }} offene Positionen – mehr als {{ number_format($positionenGrenze, 0, ',', '.') }}. Die Belege stehen unten mit allen Zahlen und Knöpfen; die einzelnen Artikel blendet die Seite aus, weil sie sonst weder lädt noch zu bedienen wäre. Über den Filialfilter oben sind sie wie gewohnt zu sehen.
@endunless @if(session('success'))
{{ session('success') }}
@endif @if(session('error'))
{{ session('error') }}
@endif {{-- Altbestand-Warnung: darf im Normalbetrieb nie erscheinen, weil jeder Rechenlauf nicht bestellte Vorschlaege von Vortagen entfernt. --}} @if(($summary['stale'] ?? 0) > 0)

{{ $nf0($summary['stale']) }} Positionen ({{ $nf0($summary['stale_units']) }} Stück) stammen noch vom {{ \Illuminate\Support\Carbon::parse($summary['stale_oldest'])->format('d.m.Y') }} und nicht vom heutigen Lauf.

Ihre Mengen beruhen auf den Beständen von damals – nicht ungeprüft mitbestellen. Normalerweise räumt jeder Rechenlauf solche Positionen weg; dass sie hier stehen, heißt: der Lauf für diesen Lieferanten ist seitdem nicht mehr durchgelaufen. Bitte neu rechnen lassen.

@endif {{-- Kennzahlen. Fuenfte Kachel: was gebraucht wird und NICHT kommt - ohne sie sieht ein Tag gesund aus, an dem das halbe Sortiment fehlt. --}} @php $fehltPos = (int) ($fehlmenge->offen_pos ?? 0) + (int) ($fehlmenge->gekuerzt_pos ?? 0); $fehltStk = (float) ($fehlmenge->offen_stk ?? 0) + (float) ($fehlmenge->gekuerzt_stk ?? 0); @endphp

Filialen mit Bestellung

{{ $nf0($summary['branches']) }}

Positionen

{{ $nf0($summary['positions']) }}

Stück gesamt

{{ $nf0($summary['units']) }}

Ohne Lieferant

{{ $nf0($summary['no_supplier']) }}

Bedarf ohne Deckung

{{ $nf0($fehltPos) }}

{{ $nf0($fehltStk) }} Stück

{{-- Aufschluesselung: die Kachel nennt nur die Summe, hier steht das WARUM. Bewusst neben den Kennzahlen und nicht in einer Fussnote - ob 3.000 Positionen am leeren Zentrallager haengen oder an der Verteilung, sind zwei ganz verschiedene Probleme. --}} @if($fehltPos > 0)

{{ $nf0($fehltPos) }} Positionen ({{ $nf0($fehltStk) }} Stück) sollten bestellt werden, gehen aber heute nicht raus:

Alle betroffenen Artikel anzeigen →

Nichts davon ist verloren: der nächste Lauf rechnet den Bedarf aus dem dann niedrigeren Bestand erneut – er kommt größer wieder, statt sich aufzuaddieren. Welche Artikel es je Filiale betrifft, steht auf der jeweiligen Bestellseite unter „Nicht bestellbar“.

@endif {{-- Werkzeugleiste: Filter links, Sammelexporte rechts --}}
Reset Zur Übersicht
@if($suppliers->isNotEmpty() || $summary['no_supplier'] > 0)
Sammelexport {{-- Intern zuerst: der Beleg fuer uns, mit Gliederung und Kennzahlen. Die daneben gehen an die Lieferanten. --}} Intern – CSV @foreach($suppliers as $s) {{ \Illuminate\Support\Str::before($s->supplier_name, ' GmbH') }} – CSV @endforeach @if($summary['no_supplier'] > 0) Ohne Lieferant – CSV @endif
@endif

Angezeigt wird nur, was tatsächlich bestellt wird (offene Positionen mit Menge > 0). Je Filiale und Lieferant entsteht ein eigener Beleg. Sammelexport = alle Filialen eines Lieferanten in einer Datei.

{{-- Sprungleiste zu den Filialen --}} @if($orders->count() > 1)
@foreach($orders as $branchId => $bySupplier) @php $b = $bySupplier->first()->first()->branch; @endphp {{ $b->name }} {{ $bySupplier->flatten(1)->count() }} @if($bySupplier->has(0)) @endif @endforeach
@endif {{-- Bestellungen je Filiale und Lieferant --}} @forelse($orders as $branchId => $bySupplier) @php $branch = $bySupplier->first()->first()->branch; @endphp

{{ $branch->name }}

JTL-Lager {{ $branch->jtl_branch_id ?: '–' }} · {{ $bySupplier->flatten(1)->count() }} Positionen · {{ $nf0($bySupplier->flatten(1)->sum('order_quantity')) }} Stück · {{ $bySupplier->count() }} {{ $bySupplier->count() === 1 ? 'Beleg' : 'Belege' }}
@foreach($bySupplier as $supplierId => $items) @php $ohneLieferant = (int) $supplierId === 0; [$rand, $kopfBg, $kopfText] = $lieferantenFarbe($supplierId); @endphp
{{-- Belegkopf: klickbar zum Auf-/Zuklappen (div statt button, damit Export-Link und Senden-Formular gueltig darin liegen) --}}

{{ $ohneLieferant ? 'Ohne hinterlegten Lieferanten' : $items->first()->supplier_name }}

@if($ohneLieferant) Nicht bestellbar – in JTL ist für diese Artikel kein Lieferant gepflegt @else {{ $rhythmus($supplierId) }} @endif

{{ $items->count() }} Positionen · {{ $nf0($items->sum('order_quantity')) }} Stück

CSV @if((int) $supplierId === 2) @php $sendung = $extradeGesendet($branchId); @endphp @if($sendung) ✓ {{ $sendung->sent_at?->format('H:i') }} Uhr @elseif($extradeBereit)
@csrf
@else @endif @endif {{-- Riccardo laeuft ueber zwei Systeme (Auftrag Online-Wawi + Lieferantenbestellung Offline-Wawi), deshalb kein direkter Senden-Knopf, sondern der Weg ueber die Vorschau: dort wird die Lieferanschrift geprueft, bevor etwas angelegt wird. --}} Intern @if((int) $supplierId === 3) @php $ricSendung = $riccardoGesendet($branchId); @endphp @if($ricSendung) ✓ {{ $ricSendung->sent_at?->format('H:i') }} Uhr @else Bestellen … @endif @endif {{-- Niko genauso ueber die Vorschau: dort werden Anschrift und die Lieferantenartikelnummern geprueft, bevor etwas rausgeht. --}} @if((int) $supplierId === 1) @php $nikoSendung = $nikoGesendet($branchId); @endphp @if($nikoSendung) ✓ {{ $nikoSendung->sent_at?->format('H:i') }} Uhr @else Bestellen … @endif @endif
{{-- Positionen. Oberhalb der Grenze bleiben sie draussen - siehe StoreOrderController::index(). --}} @if(! $zeigePositionen)
{{ $items->count() }} Positionen – wegen der Menge hier nicht ausgeklappt. Positionen dieses Belegs anzeigen
@else
@include('partials.positionsliste', [ 'gruppen' => app(\App\Services\Replenishment\ArticleGrouping::class)->gruppiere($items), 'menge' => fn ($z) => (float) $z->order_quantity, 'spalten' => [ ['kopf' => 'Artikel', 'typ' => 'text', 'klasse' => 'text-left', 'wert' => fn ($z) => '

' . e($z->article_name) . '

' . '

' . e($z->article_sku ?: '–') . '

'], ['kopf' => 'Bestand', 'typ' => 'zahl', 'wert' => fn ($z) => '' . number_format((float) $z->current_stock, 0, ',', '.') . ''], ['kopf' => 'Dringlichkeit', 'typ' => 'text', 'wert' => fn ($z) => match ($z->severity()) { 'out' => 'Ausverkauft', 'critical' => 'Unter Sicherheitsbest.', default => 'Nachbestellen', }], ['kopf' => 'Meldebestand', 'typ' => 'zahl', 'wert' => fn ($z) => '' . number_format((float) $z->reorder_point, 0, ',', '.') . ''], ['kopf' => 'Bestellmenge', 'typ' => 'zahl', 'wert' => fn ($z) => '' . number_format((float) $z->order_quantity, 0, ',', '.') . ''], ['kopf' => 'Detail', 'typ' => 'text', 'wert' => fn ($z) => 'Detail'], ], ])
@endif
@endforeach @empty
Aktuell keine geplante Bestellung. Die Berechnung läuft automatisch – ExTrade täglich 04:30, Riccardo Online & Nico montags 01:00 (zur Übersicht).
@endforelse