Die Einheit hing bisher als Anhang rechts am Mengenfeld — auf breiten Monitoren außer Sicht, und „g" war stiller Default. Jetzt: - Eigenes Pflichtfeld „Einheit der bestellten Menge" direkt VOR der Menge mit „Bitte wählen"; beim Neuanlegen muss bewusst Gramm oder Milliliter gewählt werden, beim Bearbeiten ist die gespeicherte Einheit vorbelegt. - Hinweis unter der Einheit sagt, ob ml möglich ist (Dichte hinterlegt, Wert wird genannt) oder erst gepflegt werden muss; ml bleibt ohne Dichte gesperrt. Mengen-Hinweis und ml→g-Live-Vorschau folgen der Auswahl. - Server: Store-/UpdateStockEntryRequest weisen Rohstoff-Einkäufe ohne Einheit ab (Verpackung bleibt ohne Einheit). Bestehende Tests ergänzt, neuer Test für die Pflicht. - In-App-Doku (Hinweise, Testleitfaden) nachgezogen. Suite: 390 grün. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
202 lines
11 KiB
PHP
202 lines
11 KiB
PHP
@php
|
||
/** @var \App\Models\StockEntry $model */
|
||
$isEdit = $model->exists;
|
||
@endphp
|
||
|
||
<div class="form-group">
|
||
<label for="entry_type">{{ __('Art') }} <span class="text-danger">*</span></label>
|
||
<select name="entry_type" id="entry_type" class="form-control @error('entry_type') is-invalid @enderror" required>
|
||
@foreach ($entryTypeLabels as $value => $label)
|
||
<option value="{{ $value }}" @selected(old('entry_type', $model->entry_type ?? 'ingredient') === $value)>{{ $label }}</option>
|
||
@endforeach
|
||
</select>
|
||
@error('entry_type')
|
||
<div class="invalid-feedback">{{ $message }}</div>
|
||
@enderror
|
||
</div>
|
||
|
||
<div id="stock-entry-ingredient-block" class="form-group" style="display:none;">
|
||
<label for="ingredient_id">{{ __('Inhaltsstoff') }} <span class="text-danger">*</span></label>
|
||
<div class="light-style">
|
||
<select name="ingredient_id" id="ingredient_id" class="w-100"
|
||
data-search-url="{{ route('admin.inventory.api.ingredients.search') }}">
|
||
@if ($model->ingredient_id && $model->ingredient)
|
||
{{-- N-06: fehlt die Stammdaten-Dichte inzwischen, gilt der Dichte-Snapshot der Bestellung --}}
|
||
<option value="{{ $model->ingredient_id }}" data-density="{{ $model->ingredient->density ?? $model->density_used }}" selected>{{ $model->ingredient->name }}@if ($model->ingredient->inci)
|
||
({{ $model->ingredient->inci }})
|
||
@endif
|
||
</option>
|
||
@elseif(old('ingredient_id'))
|
||
<option value="{{ old('ingredient_id') }}" selected>{{ old('ingredient_id') }}</option>
|
||
@endif
|
||
</select>
|
||
</div>
|
||
@error('ingredient_id')
|
||
<div class="text-danger small">{{ $message }}</div>
|
||
@enderror
|
||
</div>
|
||
|
||
<div id="stock-entry-quality-block" class="form-group" style="display:none;">
|
||
<label for="quality_id">{{ __('Rohstoffqualität') }} <span class="text-danger">*</span></label>
|
||
<select name="quality_id" id="quality_id" class="form-control @error('quality_id') is-invalid @enderror">
|
||
<option value="">{{ __('Bitte wählen') }}</option>
|
||
@foreach ($materialQualities as $mq)
|
||
<option value="{{ $mq->id }}" @selected((string) old('quality_id', $model->quality_id) === (string) $mq->id)>{{ $mq->name }}</option>
|
||
@endforeach
|
||
</select>
|
||
@error('quality_id')
|
||
<div class="invalid-feedback">{{ $message }}</div>
|
||
@enderror
|
||
</div>
|
||
|
||
<div id="stock-entry-packaging-block" class="form-group" style="display:none;">
|
||
<label for="packaging_item_id">{{ __('Verpackungsartikel') }} <span class="text-danger">*</span></label>
|
||
<div class="light-style">
|
||
<select name="packaging_item_id" id="packaging_item_id" class="w-100"
|
||
data-search-url="{{ route('admin.inventory.api.packaging-items.search') }}">
|
||
@if ($model->packaging_item_id && $model->packagingItem)
|
||
<option value="{{ $model->packaging_item_id }}" selected>{{ $model->packagingItem->name }}</option>
|
||
@elseif(old('packaging_item_id'))
|
||
<option value="{{ old('packaging_item_id') }}" selected>{{ old('packaging_item_id') }}</option>
|
||
@endif
|
||
</select>
|
||
</div>
|
||
@error('packaging_item_id')
|
||
<div class="text-danger small">{{ $message }}</div>
|
||
@enderror
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="supplier_id">{{ __('Lieferant') }} <span class="text-danger">*</span></label>
|
||
<select name="supplier_id" id="supplier_id" class="form-control @error('supplier_id') is-invalid @enderror"
|
||
required>
|
||
<option value="">{{ __('Bitte wählen') }}</option>
|
||
@foreach ($suppliers as $sup)
|
||
<option value="{{ $sup->id }}" @selected((string) old('supplier_id', $model->supplier_id) === (string) $sup->id)>{{ $sup->name }}</option>
|
||
@endforeach
|
||
</select>
|
||
@error('supplier_id')
|
||
<div class="invalid-feedback">{{ $message }}</div>
|
||
@enderror
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="location_id">{{ __('Lagerort') }} <span class="text-danger">*</span></label>
|
||
<select name="location_id" id="location_id" class="form-control @error('location_id') is-invalid @enderror"
|
||
required>
|
||
<option value="">{{ __('Bitte wählen') }}</option>
|
||
@foreach ($locations as $loc)
|
||
<option value="{{ $loc->id }}" @selected((string) old('location_id', $model->location_id) === (string) $loc->id)>{{ $loc->name }}</option>
|
||
@endforeach
|
||
</select>
|
||
@error('location_id')
|
||
<div class="invalid-feedback">{{ $message }}</div>
|
||
@enderror
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="ordered_at">{{ __('Bestelldatum') }} <span class="text-danger">*</span></label>
|
||
<input type="text" name="ordered_at" id="ordered_at" autocomplete="off"
|
||
class="form-control datepicker-base @error('ordered_at') is-invalid @enderror"
|
||
value="{{ old('ordered_at', $model->ordered_at ? $model->ordered_at->format('d.m.Y') : '') }}" required>
|
||
@error('ordered_at')
|
||
<div class="invalid-feedback">{{ $message }}</div>
|
||
@enderror
|
||
</div>
|
||
|
||
@php
|
||
// AP-42: in ml erfasste Rohstoffe im Formular auch in ml anzeigen (Rückrechnung
|
||
// über die gespeicherte Dichte); Bestand bleibt intern in Gramm.
|
||
$orderedIsMl = $model->purchase_unit === 'ml' && $model->density_used;
|
||
$orderedDisplay = $model->ordered_quantity !== null
|
||
? formatWawiQuantity($orderedIsMl ? $model->ordered_quantity / $model->density_used : $model->ordered_quantity)
|
||
: '';
|
||
@endphp
|
||
@php
|
||
// Einheit steht als eigenes Pflichtfeld VOR der Menge (nicht mehr als Anhang
|
||
// rechts am Feld — auf breiten Monitoren lag es außer Sicht). Neu: bewusst
|
||
// wählen („Bitte wählen"); beim Bearbeiten ist die gespeicherte Einheit vorbelegt.
|
||
$orderedUnitValue = old('ordered_unit', $isEdit ? ($orderedIsMl ? 'ml' : 'gram') : '');
|
||
@endphp
|
||
<div class="form-group" id="ordered-unit-wrap" style="display:none;">
|
||
<label for="ordered_unit">{{ __('Einheit der bestellten Menge') }} <span class="text-danger">*</span></label>
|
||
<select name="ordered_unit" id="ordered_unit" class="form-control @error('ordered_unit') is-invalid @enderror">
|
||
<option value="" @selected($orderedUnitValue === '')>{{ __('Bitte wählen') }}</option>
|
||
<option value="gram" @selected($orderedUnitValue === 'gram')>{{ __('Gramm (g)') }}</option>
|
||
<option value="ml" @selected($orderedUnitValue === 'ml')>{{ __('Milliliter (ml) – wird über die Dichte in Gramm umgerechnet') }}</option>
|
||
</select>
|
||
<small class="text-muted d-block" id="ordered-unit-hint"></small>
|
||
@error('ordered_unit')
|
||
<div class="invalid-feedback d-block">{{ $message }}</div>
|
||
@enderror
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="ordered_quantity">{{ __('Bestellte Menge') }} <span class="text-danger">*</span></label>
|
||
<input type="text" name="ordered_quantity" id="ordered_quantity"
|
||
class="form-control @error('ordered_quantity') is-invalid @enderror"
|
||
value="{{ old('ordered_quantity', $orderedDisplay) }}"
|
||
required>
|
||
<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
|
||
</div>
|
||
|
||
<div id="price-per-kg-block" style="display:none;">
|
||
<div class="form-group">
|
||
<label for="tax_rate_id">{{ __('Umsatzsteuer') }}</label>
|
||
<select name="tax_rate_id" id="tax_rate_id" class="form-control @error('tax_rate_id') is-invalid @enderror">
|
||
<option value="" data-percent="0">{{ __('— keine Angabe —') }}</option>
|
||
@foreach ($taxRates as $taxRate)
|
||
<option value="{{ $taxRate->id }}" data-percent="{{ $taxRate->percent }}"
|
||
@selected((string) old('tax_rate_id', $model->tax_rate_id) === (string) $taxRate->id)>
|
||
{{ $taxRate->name }} ({{ \App\Services\Util::formatNumber($taxRate->percent) }} %)
|
||
</option>
|
||
@endforeach
|
||
</select>
|
||
<small class="text-muted">{{ __('Steuersatz zur Umrechnung zwischen Netto und Brutto.') }}</small>
|
||
@error('tax_rate_id')
|
||
<div class="invalid-feedback">{{ $message }}</div>
|
||
@enderror
|
||
</div>
|
||
|
||
<div class="form-row">
|
||
<div class="form-group col-md-6">
|
||
<label for="price_per_kg">{{ __('Netto-Preis pro kg') }} <span class="text-danger">*</span></label>
|
||
<div class="input-group">
|
||
<input type="text" name="price_per_kg" id="price_per_kg"
|
||
class="form-control @error('price_per_kg') is-invalid @enderror"
|
||
value="{{ old('price_per_kg', $model->price_per_kg !== null ? \App\Services\Util::formatNumber($model->price_per_kg) : '') }}">
|
||
<div class="input-group-append"><span class="input-group-text">€</span></div>
|
||
@error('price_per_kg')
|
||
<div class="invalid-feedback">{{ $message }}</div>
|
||
@enderror
|
||
</div>
|
||
</div>
|
||
<div class="form-group col-md-6">
|
||
<label for="price_per_kg_gross">{{ __('Brutto-Preis pro kg') }}</label>
|
||
<div class="input-group">
|
||
<input type="text" name="price_per_kg_gross" id="price_per_kg_gross"
|
||
class="form-control @error('price_per_kg_gross') is-invalid @enderror"
|
||
value="{{ old('price_per_kg_gross', $model->price_per_kg_gross !== null ? \App\Services\Util::formatNumber($model->price_per_kg_gross) : '') }}">
|
||
<div class="input-group-append"><span class="input-group-text">€</span></div>
|
||
@error('price_per_kg_gross')
|
||
<div class="invalid-feedback">{{ $message }}</div>
|
||
@enderror
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<small class="text-muted d-block mb-2">{{ __('Netto oder Brutto genügt – der jeweils andere Wert wird automatisch berechnet.') }}</small>
|
||
</div>
|
||
|
||
<div id="price-total-block" class="form-group" style="display:none;">
|
||
<label for="price_total">{{ __('Gesamtpreis netto') }} <span class="text-danger">*</span></label>
|
||
<input type="text" name="price_total" id="price_total"
|
||
class="form-control @error('price_total') is-invalid @enderror"
|
||
value="{{ old('price_total', $model->price_total !== null ? \App\Services\Util::formatNumber($model->price_total) : '') }}">
|
||
@error('price_total')
|
||
<div class="invalid-feedback">{{ $message }}</div>
|
||
@enderror
|
||
</div>
|