Warenwirtschaft: AP-52 — Verpackungsvorschau mit Bestand, Differenz und Lagerort (Kundennachtrag 09.09.2026)
Je Verpackungsartikel Bestand (Stück), Differenz zu Bedarf (rot/grün wie bei Rohstoffen, AP-40) und Lagerplatz; Spalte einheitlich „Lagerort“ für Rohstoffe (INCI-Tabelle, vorher „Ablage“) und Verpackung. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
parent
22e218d570
commit
3abb9e644e
5 changed files with 103 additions and 16 deletions
|
|
@ -141,7 +141,8 @@
|
|||
<th>{{ __('Qualität') }}</th>
|
||||
<th class="text-right">{{ __('Anteil %') }}</th>
|
||||
<th class="text-right">{{ __('Gramm (gesamt)') }}</th>
|
||||
<th>{{ __('Ablage') }}</th>
|
||||
{{-- AP-52: „Lagerort" einheitlich für Rohstoffe und Verpackung (Kundenwunsch 09.09.2026) --}}
|
||||
<th>{{ __('Lagerort') }}</th>
|
||||
<th class="text-right">{{ __('Bestand') }}</th>
|
||||
<th class="text-right">{{ __('Differenz') }}</th>
|
||||
</tr>
|
||||
|
|
@ -157,9 +158,18 @@
|
|||
<h6>{{ __('Verpackung (Vorschau)') }} <small class="text-muted font-weight-normal">{{ __('aus dem Produktionsergebnis') }}</small></h6>
|
||||
<div class="table-responsive border rounded mb-3">
|
||||
<table class="table table-sm mb-0">
|
||||
<thead><tr><th>{{ __('Artikel') }}</th><th>{{ __('Stück gesamt') }}</th></tr></thead>
|
||||
{{-- AP-52: Bestand/Differenz/Lagerort je Verpackungsartikel — direkt bei der Planung sehen, ob alles da ist --}}
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{ __('Artikel') }}</th>
|
||||
<th class="text-right">{{ __('Stück gesamt') }}</th>
|
||||
<th>{{ __('Lagerort') }}</th>
|
||||
<th class="text-right">{{ __('Bestand') }}</th>
|
||||
<th class="text-right">{{ __('Differenz') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="recipe-packaging-preview"></tbody>
|
||||
<tfoot><tr><td colspan="2" class="text-muted small" id="recipe-packaging-hint"></td></tr></tfoot>
|
||||
<tfoot><tr><td colspan="5" class="text-muted small" id="recipe-packaging-hint"></td></tr></tfoot>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
|
|
@ -198,7 +208,7 @@
|
|||
<div class="col-sm-3">{{ __('Chargen-Nr.') }}</div>
|
||||
<div class="col-sm-1"></div>
|
||||
</div>
|
||||
<div id="production-outputs" data-initial='@json($initialOutputs)' data-packaging-bom='@json(($packagingBom ?? []) === [] ? (object) [] : $packagingBom)'
|
||||
<div id="production-outputs" data-initial='@json($initialOutputs)' data-packaging-bom='@json(($packagingBom ?? []) === [] ? (object) [] : $packagingBom)' data-packaging-info='@json(($packagingInfo ?? []) === [] ? (object) [] : $packagingInfo)'
|
||||
data-packaging-snapshot='@json($packagingSnapshot ?? [])' data-packaging-snapshot-applies='{{ ! empty($packagingSnapshotApplies) ? 1 : 0 }}' data-initial-output-totals='@json(($initialOutputTotals ?? []) === [] ? (object) [] : $initialOutputTotals)'></div>
|
||||
<button type="button" class="btn btn-sm btn-outline-secondary mb-3" id="btn-add-output">{{ __('+ weitere Ergebniszeile') }}</button>
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,11 @@
|
|||
return Number(value).toLocaleString('de-DE', {minimumFractionDigits: 2, maximumFractionDigits: 2});
|
||||
}
|
||||
|
||||
// AP-52: Stückzahlen (Verpackung) ohne Nachkommastellen.
|
||||
function fmtPieces(value) {
|
||||
return Number(value).toLocaleString('de-DE', {maximumFractionDigits: 0});
|
||||
}
|
||||
|
||||
function parseGerman(value) {
|
||||
value = String(value || '').trim();
|
||||
if (!value) {
|
||||
|
|
@ -395,17 +400,37 @@
|
|||
return true;
|
||||
}
|
||||
|
||||
// AP-52: Bestand + Lagerort je Verpackungsartikel (vom Server), Differenz = Bestand − Bedarf.
|
||||
var packagingInfo = $('#production-outputs').data('packaging-info') || {};
|
||||
|
||||
function packagingRow(id, name, pieces, withDiff) {
|
||||
var info = packagingInfo[String(id)] || {};
|
||||
var stock = info.stock != null ? Number(info.stock) : null;
|
||||
var $row = $('<tr></tr>')
|
||||
.append($('<td></td>').text(name))
|
||||
.append($('<td class="text-right"></td>').text(pieces))
|
||||
.append($('<td></td>').text(info.storage_label || '—'))
|
||||
.append($('<td class="text-right"></td>').text(stock != null ? fmtPieces(stock) : '—'));
|
||||
var $diff = $('<td class="text-right"></td>');
|
||||
if (withDiff && stock != null) {
|
||||
// Wie AP-40 bei den Rohstoffen: negativ rot = Fehlmenge, sonst grün.
|
||||
var d = stock - pieces;
|
||||
$diff.text((d >= 0 ? '+' : '') + fmtPieces(d)).css('color', d < 0 ? '#dc3545' : '#28a745');
|
||||
} else {
|
||||
$diff.text('—').attr('title', withDiff ? '' : '{{ __('Bereits gebucht — Bestand enthält den Abzug') }}');
|
||||
}
|
||||
return $row.append($diff);
|
||||
}
|
||||
|
||||
function renderPackagingPreview() {
|
||||
var $hint = $('#recipe-packaging-hint');
|
||||
if (packagingSnapshotApplies && sameTotals(currentOutputTotals(), initialOutputTotals)) {
|
||||
var $snap = $('#recipe-packaging-preview').empty();
|
||||
packagingSnapshot.forEach(function (pk) {
|
||||
$snap.append($('<tr></tr>')
|
||||
.append($('<td></td>').text(pk.name))
|
||||
.append($('<td></td>').text(pk.pieces)));
|
||||
$snap.append(packagingRow(pk.id, pk.name, pk.pieces, false));
|
||||
});
|
||||
if (!packagingSnapshot.length) {
|
||||
$snap.append('<tr><td colspan="2" class="text-muted">{{ __('Kein Verpackungsverbrauch gebucht.') }}</td></tr>');
|
||||
$snap.append('<tr><td colspan="5" class="text-muted">{{ __('Kein Verpackungsverbrauch gebucht.') }}</td></tr>');
|
||||
}
|
||||
$hint.text('{{ __('Gespeicherter Verpackungsverbrauch dieser Produktion — bleibt erhalten, solange Ergebnisprodukte und Stückzahlen unverändert sind.') }}');
|
||||
return;
|
||||
|
|
@ -429,12 +454,10 @@
|
|||
});
|
||||
var $pk = $('#recipe-packaging-preview').empty();
|
||||
order.forEach(function (id) {
|
||||
$pk.append($('<tr></tr>')
|
||||
.append($('<td></td>').text(totals[id].name))
|
||||
.append($('<td></td>').text(Math.round(totals[id].pieces))));
|
||||
$pk.append(packagingRow(id, totals[id].name, Math.round(totals[id].pieces), true));
|
||||
});
|
||||
if (!order.length) {
|
||||
$pk.append('<tr><td colspan="2" class="text-muted">{{ __('Keine Verpackung hinterlegt.') }}</td></tr>');
|
||||
$pk.append('<tr><td colspan="5" class="text-muted">{{ __('Keine Verpackung hinterlegt.') }}</td></tr>');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue