Warenwirtschaft: Bestandsrechnung auf der Rohstoff-Detailseite nachvollziehbar
Neuer Klappbereich „Bestandsrechnung nachvollziehen" zeigt alle gebuchten Eingänge – auch aufgebrauchte mit Rest 0 – mit Produktionsverbrauch, Ausschuss mit Chargenbezug und dem nach FEFO zugerechneten Ausschuss ohne Chargenbezug; Summenzeile bis zum Gesamtbestand identisch zur Kopfzahl. Alt-Ausschuss ohne Chargenbezug wird einzeln mit Grund/Notiz/Bearbeiter gelistet. Anlass: Live-Fall Sonnenblumenöl (doppelte Korrektur vom 28.07.). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
79bec0ff0b
commit
761ea35047
7 changed files with 417 additions and 2 deletions
|
|
@ -306,5 +306,160 @@
|
|||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- 17.09.2026: Bestandsrechnung zum Nachvollziehen — alle Eingänge (auch Rest 0), Verbrauch, Ausschuss --}}
|
||||
@php
|
||||
$bd = $breakdown;
|
||||
$unboundCount = $bd['unbound_disposals']->count();
|
||||
$zeroCount = $bd['entries']->filter(fn ($e) => (float) $e->getAttribute('remaining_quantity') <= 0)->count();
|
||||
$summaryParts = [trans_choice(':count Eingang|:count Eingänge', $bd['entries']->count(), ['count' => $bd['entries']->count()])];
|
||||
if ($zeroCount > 0) {
|
||||
$summaryParts[] = $zeroCount . ' ' . __('davon aufgebraucht');
|
||||
}
|
||||
if ($unboundCount > 0) {
|
||||
$summaryParts[] = $unboundCount . ' ' . __('Ausschuss ohne Chargenbezug');
|
||||
}
|
||||
@endphp
|
||||
<div class="wawi-card">
|
||||
<a class="wawi-card__header d-flex justify-content-between align-items-center text-reset text-decoration-none collapsed"
|
||||
data-toggle="collapse" href="#stock-breakdown" role="button" aria-expanded="false" aria-controls="stock-breakdown">
|
||||
<span>
|
||||
{{ __('Bestandsrechnung nachvollziehen') }}
|
||||
<span class="text-muted small font-weight-normal ml-2">
|
||||
{{ implode(', ', $summaryParts) }}
|
||||
</span>
|
||||
</span>
|
||||
<span class="fas fa-chevron-down small text-muted"></span>
|
||||
</a>
|
||||
<div class="collapse" id="stock-breakdown">
|
||||
<div class="table-responsive">
|
||||
<table class="table wawi-table mb-0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{ __('Eingang') }}</th>
|
||||
<th>{{ __('Charge') }}</th>
|
||||
<th>{{ __('Lagerort') }}</th>
|
||||
<th>{{ __('MHD') }}</th>
|
||||
<th class="text-right">{{ __('Eingang') }}</th>
|
||||
<th class="text-right">{{ __('Produktion') }}</th>
|
||||
<th class="text-right" title="{{ __('Ausschuss, der beim Erfassen dieser Charge zugeordnet wurde') }}">{{ __('Ausschuss (Charge)') }}</th>
|
||||
<th class="text-right" title="{{ __('Ausschuss ohne Chargenbezug — wird rechnerisch nach MHD (FEFO) auf die Eingänge verteilt') }}">{{ __('Ausschuss (o. Charge)') }}</th>
|
||||
<th class="text-right">{{ __('Rest') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@forelse($bd['entries'] as $entry)
|
||||
@php $isEmpty = (float) $entry->getAttribute('remaining_quantity') <= 0; @endphp
|
||||
<tr class="{{ $isEmpty ? 'text-muted' : '' }}">
|
||||
<td>
|
||||
<a href="{{ route('admin.inventory.stock-entries.show', $entry) }}" class="text-reset">
|
||||
{{ $entry->received_at?->format('d.m.Y') ?? '—' }}
|
||||
</a>
|
||||
<span class="text-muted small">#{{ $entry->id }}</span>
|
||||
@if($entry->supplier)
|
||||
<div class="wawi-item-sub">{{ $entry->supplier->name }}</div>
|
||||
@endif
|
||||
</td>
|
||||
<td>{{ $entry->batch_number ?: '—' }}</td>
|
||||
<td>{{ $entry->location?->name ?? '—' }}</td>
|
||||
<td>{{ $entry->best_before?->format('d.m.Y') ?? '—' }}</td>
|
||||
<td class="text-right">{{ formatWawiQuantity($entry->received_quantity) }} g</td>
|
||||
<td class="text-right">{{ (float) $entry->getAttribute('production_quantity') > 0 ? '− ' . formatWawiQuantity($entry->getAttribute('production_quantity')) . ' g' : '—' }}</td>
|
||||
<td class="text-right">{{ (float) $entry->getAttribute('bound_disposal_quantity') > 0 ? '− ' . formatWawiQuantity($entry->getAttribute('bound_disposal_quantity')) . ' g' : '—' }}</td>
|
||||
<td class="text-right">{{ (float) $entry->getAttribute('unbound_disposal_quantity') > 0 ? '− ' . formatWawiQuantity($entry->getAttribute('unbound_disposal_quantity')) . ' g' : '—' }}</td>
|
||||
<td class="text-right">
|
||||
<strong>{{ formatWawiQuantity($entry->getAttribute('remaining_quantity')) }} g</strong>
|
||||
@if($isEmpty)
|
||||
<span class="badge badge-light border ml-1">{{ __('aufgebraucht') }}</span>
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="9"><div class="wawi-empty">{{ __('Noch kein gebuchter Wareneingang.') }}</div></td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="4" class="text-right text-muted">{{ __('Summe Wareneingänge') }}</td>
|
||||
<td class="text-right">{{ formatWawiQuantity($bd['received_total']) }} g</td>
|
||||
<td colspan="4"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="4" class="text-right text-muted">{{ __('− Produktionsverbrauch') }}</td>
|
||||
<td class="text-right">− {{ formatWawiQuantity($bd['production_total']) }} g</td>
|
||||
<td colspan="4" class="text-muted small">
|
||||
@if($bd['production_other'] > 0)
|
||||
{{ __('davon :qty g ohne zuordenbaren Eingang (z. B. Eingang nachträglich gelöscht)', ['qty' => formatWawiQuantity($bd['production_other'])]) }}
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="4" class="text-right text-muted">{{ __('− Ausschuss mit Chargenbezug') }}</td>
|
||||
<td class="text-right">− {{ formatWawiQuantity($bd['disposed_bound_total'] + $bd['disposed_other']) }} g</td>
|
||||
<td colspan="4" class="text-muted small">
|
||||
@if($bd['disposed_other'] > 0)
|
||||
{{ __('davon :qty g ohne zuordenbaren Eingang (Eingang nachträglich gelöscht)', ['qty' => formatWawiQuantity($bd['disposed_other'])]) }}
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="4" class="text-right text-muted">{{ __('− Ausschuss ohne Chargenbezug') }}</td>
|
||||
<td class="text-right">− {{ formatWawiQuantity($bd['disposed_unbound_total']) }} g</td>
|
||||
<td colspan="4" class="text-muted small">
|
||||
@if($bd['disposed_unbound_unallocated'] > 0)
|
||||
{{ __('davon :qty g keinem Eingang zurechenbar (mehr Ausschuss als Eingang am Lagerort)', ['qty' => formatWawiQuantity($bd['disposed_unbound_unallocated'])]) }}
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="4" class="text-right"><strong>{{ __('= Gesamtbestand') }}</strong></td>
|
||||
<td class="text-right"><strong>{{ formatWawiQuantity($bd['remaining_total']) }} g</strong></td>
|
||||
<td colspan="4"></td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
@if($bd['unbound_disposals']->isNotEmpty())
|
||||
<div class="wawi-card__footer" style="display:block;">
|
||||
<div class="font-weight-bold mb-2">{{ __('Ausschuss ohne Chargenbezug') }}</div>
|
||||
<p class="text-muted small mb-2">
|
||||
{{ __('Diese Buchungen wurden ohne Zuordnung zu einem Eingang erfasst (Altbestand vor Einführung der Chargenwahl). Sie mindern den Gesamtbestand und werden in der Chargenansicht rechnerisch nach MHD (ältestes zuerst) von den Eingängen abgezogen — deshalb können auch neuere Eingänge als „aufgebraucht" erscheinen. Ist so eine Buchung überholt (z. B. doppelte Korrektur), lässt sie sich in der Ausschuss-Liste löschen.') }}
|
||||
</p>
|
||||
<div class="table-responsive">
|
||||
<table class="table wawi-table table-sm mb-0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{ __('Datum') }}</th>
|
||||
<th>{{ __('Lagerort') }}</th>
|
||||
<th>{{ __('Grund') }}</th>
|
||||
<th>{{ __('Notiz') }}</th>
|
||||
<th>{{ __('Erfasst von') }}</th>
|
||||
<th class="text-right">{{ __('Menge') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($bd['unbound_disposals'] as $disposal)
|
||||
<tr>
|
||||
<td>{{ $disposal->disposed_at?->format('d.m.Y') ?? $disposal->created_at?->format('d.m.Y') }} <span class="text-muted small">#{{ $disposal->id }}</span></td>
|
||||
<td>{{ $disposal->location?->name ?? '—' }}</td>
|
||||
<td>{{ $disposal->reason ?: '—' }}</td>
|
||||
<td>{{ $disposal->note ?: '—' }}</td>
|
||||
<td>{{ $disposal->user?->name ?? '—' }}</td>
|
||||
<td class="text-right">− {{ formatWawiQuantity($disposal->quantity) }} g</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@if(Auth::user()->isAdmin())
|
||||
<a href="{{ route('admin.inventory.stock-disposals.index') }}" class="btn btn-sm btn-outline-secondary mt-2">{{ __('Zur Ausschuss-Liste') }}</a>
|
||||
@endif
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue