Warenwirtschaft: ml→g-Live-Vorschau direkt am Wareneingang

Ergänzt die selbsterklärende Dichte um eine fette Live-Vorschau direkt am
Mengenfeld — in beiden Stufen des Wareneingangs:

- Einkauf erfassen (Stufe 1): bei Einheit „ml" zeigt sich beim Tippen
  „<ml> ml × <Dichte> g/ml = <g> g"; der Hinweistext bleibt Führung.
- Wareneingang buchen (Stufe 2): gleiche Vorschau am Feld „Eingegangene
  Menge", wenn in ml eingekauft wurde.

So ist an jeder Eingabestelle sofort sichtbar, wie und wann die Dichte
rechnet. Kein Mechanik-Wechsel; Speicherung bleibt in Gramm.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Kevin Adametz 2026-09-14 11:47:51 +00:00
parent 2859b4339c
commit 23381a37f5
3 changed files with 35 additions and 4 deletions

View file

@ -126,7 +126,8 @@
</select>
</div>
</div>
<small class="text-muted" id="ordered-quantity-hint">{{ __('Bei Rohstoff in Gramm, bei Verpackung in Stück.') }}</small>
<small class="text-muted d-block" id="ordered-quantity-hint">{{ __('Bei Rohstoff in Gramm, bei Verpackung in Stück.') }}</small>
<small class="d-block font-weight-bold text-body mt-1" id="ordered-quantity-preview" style="display:none;"></small>
@error('ordered_quantity')
<div class="invalid-feedback d-block">{{ $message }}</div>
@enderror

View file

@ -88,14 +88,19 @@
}
var $hint = $('#ordered-quantity-hint');
var $preview = $('#ordered-quantity-preview');
$preview.hide().text('');
if (!isIng) {
$hint.text('{{ __('Bei Verpackung in Stück.') }}');
return;
}
if ($('#ordered_unit').val() === 'ml' && hasDensity) {
$hint.text('{{ __('Erfassung in ml — der Bestand wird über die Dichte in Gramm gebucht.') }}');
var ml = parseNumber($('#ordered_quantity').val());
var g = ml != null ? formatQuantity(ml * density) : '?';
$hint.text('{{ __('Erfassung in ml — entspricht ca.') }} ' + g + ' {{ __('g (Dichte') }} ' + formatDensity(density) + ' g/ml).');
if (ml != null && ml > 0) {
// AP-42: Live-Vorschau der ml→g-Umrechnung direkt am Mengenfeld.
$preview.text(formatQuantity(ml) + ' ml × ' + formatDensity(density) + ' g/ml = ' + formatQuantity(ml * density) + ' g').show();
}
} else if (hasDensity) {
$hint.text('{{ __('In Gramm — oder Einheit auf ml stellen (Dichte hinterlegt).') }}');
} else {

View file

@ -203,7 +203,7 @@
<input type="text" name="received_quantity" id="received_quantity" required
class="form-control @error('received_quantity') is-invalid @enderror"
value="{{ old('received_quantity', $receiveDefault) }}">
<small class="text-muted">
<small class="text-muted d-block">
@if($receiveIsMl)
{{ __('Angabe in ml — Umrechnung in Gramm über die Dichte') }} ({{ \App\Services\Util::formatNumber($model->density_used) }} g/ml)
@elseif($model->unit === 'gram')
@ -212,6 +212,9 @@
{{ __('Angabe in Stück') }}
@endif
</small>
@if($receiveIsMl)
<small class="d-block font-weight-bold text-body mt-1" id="received-quantity-preview" style="display:none;"></small>
@endif
@error('received_quantity')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
@ -266,6 +269,28 @@
@section('scripts')
<script>
(function ($) {
// AP-42: Live-Vorschau der ml→g-Umrechnung auch beim Buchen des Eingangs.
var receiveDensity = @json($model->purchase_unit === 'ml' && $model->density_used ? (float) $model->density_used : null);
if (receiveDensity) {
var $rq = $('#received_quantity');
var $rqPreview = $('#received-quantity-preview');
var fmtQ = function (v) {
return Number(v).toLocaleString('de-DE', {minimumFractionDigits: 2, maximumFractionDigits: 3, useGrouping: false});
};
var renderReceivePreview = function () {
var raw = String($rq.val() || '').trim();
var norm = /^-?(\d+\.\d{1,2}|0\.\d{3})$/.test(raw) ? raw : raw.replace(/\./g, '').replace(',', '.');
var ml = parseFloat(norm);
if (!raw || isNaN(ml) || ml <= 0) {
$rqPreview.hide().text('');
return;
}
$rqPreview.text(fmtQ(ml) + ' ml × ' + receiveDensity.toLocaleString('de-DE', {minimumFractionDigits: 2, maximumFractionDigits: 4, useGrouping: false}) + ' g/ml = ' + fmtQ(ml * receiveDensity) + ' g').show();
};
$rq.on('input change', renderReceivePreview);
renderReceivePreview();
}
// AP-27: Beim Eintippen der Chargennummer prüfen, ob die Charge schon im Haus ist.
var checkUrl = @json(route('admin.inventory.api.stock-entries.batch-check'));
var ingredientId = @json($model->ingredient_id);