13-05-2026 Waren Wirtschaft

This commit is contained in:
Kevin Adametz 2026-05-13 18:09:20 +02:00
parent 9ce711d6b2
commit ca3eb663fe
40 changed files with 1000 additions and 189 deletions

View file

@ -15,7 +15,7 @@
@method('PUT')
@endif
<input type="hidden" name="category" value="{{ old('category', $model->category) }}">
<input type="hidden" name="category" value="{{ old('category', $category ?? 'packaging') }}">
<div class="form-group">
<label for="name">{{ __('Name') }}</label>

View file

@ -4,38 +4,56 @@
@endphp
<div class="form-group">
<label for="entry_type">{{ __('Art') }}</label>
<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)
@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>
<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') }}</label>
<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)
<option value="{{ $model->ingredient_id }}" selected>{{ $model->ingredient->name }}@if($model->ingredient->inci) ({{ $model->ingredient->inci }})@endif</option>
<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)
<option value="{{ $model->ingredient_id }}" 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>
<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') }}</label>
<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)
<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>
@ -43,69 +61,76 @@
</select>
</div>
@error('packaging_item_id')
<div class="text-danger small">{{ $message }}</div>
<div class="text-danger small">{{ $message }}</div>
@enderror
</div>
<div class="form-group">
<label for="supplier_id">{{ __('Lieferant') }}</label>
<select name="supplier_id" id="supplier_id" class="form-control @error('supplier_id') is-invalid @enderror" required>
<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>
@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>
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div class="form-group">
<label for="location_id">{{ __('Lagerort') }}</label>
<select name="location_id" id="location_id" class="form-control @error('location_id') is-invalid @enderror" required>
<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>
@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>
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div class="form-group">
<label for="ordered_at">{{ __('Bestelldatum') }}</label>
<input type="date" name="ordered_at" id="ordered_at" class="form-control @error('ordered_at') is-invalid @enderror"
value="{{ old('ordered_at', $model->ordered_at ? $model->ordered_at->format('Y-m-d') : '') }}" required>
<label for="ordered_at">{{ __('Bestelldatum') }} <span class="text-danger">*</span></label>
<input type="date" name="ordered_at" id="ordered_at"
class="form-control @error('ordered_at') is-invalid @enderror"
value="{{ old('ordered_at', $model->ordered_at ? $model->ordered_at->format('Y-m-d') : '') }}" required>
@error('ordered_at')
<div class="invalid-feedback">{{ $message }}</div>
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div class="form-group">
<label for="ordered_quantity">{{ __('Bestellte Menge') }}</label>
<input type="text" name="ordered_quantity" id="ordered_quantity" class="form-control @error('ordered_quantity') is-invalid @enderror"
value="{{ old('ordered_quantity', $model->ordered_quantity !== null ? \App\Services\Util::formatNumber($model->ordered_quantity) : '') }}" required>
<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', $model->ordered_quantity !== null ? \App\Services\Util::formatNumber($model->ordered_quantity) : '') }}"
required>
<small class="text-muted">{{ __('Bei Rohstoff in Gramm, bei Verpackung in Stück.') }}</small>
@error('ordered_quantity')
<div class="invalid-feedback">{{ $message }}</div>
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div id="price-per-kg-block" class="form-group" style="display:none;">
<label for="price_per_kg">{{ __('Netto-Preis pro kg') }}</label>
<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) : '') }}">
<label for="price_per_kg">{{ __('Netto-Preis pro kg') }} <span class="text-danger">*</span></label>
<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) : '') }}">
@error('price_per_kg')
<div class="invalid-feedback">{{ $message }}</div>
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div id="price-total-block" class="form-group" style="display:none;">
<label for="price_total">{{ __('Gesamtpreis netto') }}</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) : '') }}">
<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>
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>

View file

@ -4,6 +4,7 @@
var t = $('#entry_type').val();
var isIng = t === 'ingredient';
$('#stock-entry-ingredient-block').toggle(isIng);
$('#stock-entry-quality-block').toggle(isIng);
$('#stock-entry-packaging-block').toggle(!isIng);
$('#price-per-kg-block').toggle(isIng);
$('#price-total-block').toggle(!isIng);

View file

@ -42,6 +42,11 @@
@endif
</dd>
@if($model->entry_type === 'ingredient' && $model->quality)
<dt class="col-sm-3">{{ __('Rohstoffqualität') }}</dt>
<dd class="col-sm-9">{{ $model->quality->name }}</dd>
@endif
<dt class="col-sm-3">{{ __('Lieferant') }}</dt>
<dd class="col-sm-9">{{ $model->supplier?->name ?? '—' }}</dd>
@ -122,7 +127,7 @@
@method('PUT')
<div class="form-group">
<label for="received_at">{{ __('Eingangsdatum') }}</label>
<label for="received_at">{{ __('Eingangsdatum') }} <span class="text-danger">*</span></label>
<input type="date" name="received_at" id="received_at" required
class="form-control @error('received_at') is-invalid @enderror"
value="{{ old('received_at', now()->toDateString()) }}">
@ -132,7 +137,7 @@
</div>
<div class="form-group">
<label for="received_quantity">{{ __('Eingegangene Menge') }}</label>
<label for="received_quantity">{{ __('Eingegangene Menge') }} <span class="text-danger">*</span></label>
<input type="text" name="received_quantity" id="received_quantity" required
class="form-control @error('received_quantity') is-invalid @enderror"
value="{{ old('received_quantity', \App\Services\Util::formatNumber($model->ordered_quantity)) }}">
@ -150,7 +155,7 @@
@if($model->entry_type === 'ingredient')
<div class="form-group">
<label for="batch_number">{{ __('Chargennummer') }}</label>
<label for="batch_number">{{ __('Chargennummer') }} <span class="text-danger">*</span></label>
<input type="text" name="batch_number" id="batch_number" maxlength="100"
class="form-control @error('batch_number') is-invalid @enderror"
value="{{ old('batch_number') }}">
@ -160,7 +165,7 @@
</div>
<div class="form-group">
<label for="best_before">{{ __('Mindesthaltbarkeit') }}</label>
<label for="best_before">{{ __('Mindesthaltbarkeit') }} <span class="text-danger">*</span></label>
<input type="date" name="best_before" id="best_before"
class="form-control @error('best_before') is-invalid @enderror"
value="{{ old('best_before') }}">
@ -170,11 +175,11 @@
</div>
<div class="form-group">
<label for="quality_id">{{ __('Materialqualität') }}</label>
<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') === (string)$mq->id)>{{ $mq->name }}</option>
<option value="{{ $mq->id }}" @selected((string)old('quality_id', $model->quality_id) === (string)$mq->id)>{{ $mq->name }}</option>
@endforeach
</select>
@error('quality_id')

View file

@ -82,7 +82,7 @@
var $out = $row.find('.pi-effective');
if (!isNaN(g) && !isNaN(f)) {
var eff = g * f;
$out.text(eff.toLocaleString('de-DE', { minimumFractionDigits: 3, maximumFractionDigits: 3 }));
$out.text(eff.toLocaleString('de-DE', { minimumFractionDigits: 6, maximumFractionDigits: 6 }));
} else {
$out.text('—');
}
@ -100,10 +100,10 @@
$cell.text('—').removeClass('text-danger text-success');
return;
}
var formatted = total.toLocaleString('de-DE', { minimumFractionDigits: 3, maximumFractionDigits: 3 }) + ' %';
var formatted = total.toLocaleString('de-DE', { minimumFractionDigits: 6, maximumFractionDigits: 6 }) + ' %';
$cell.text(formatted);
var diff = Math.abs(total - 100);
if (diff < 0.001) {
if (diff < 0.000001) {
$cell.removeClass('text-danger').addClass('text-success');
$cell.attr('title', '');
} else {
@ -135,7 +135,7 @@
'<td class="text-muted align-middle ingredient-drag-handle" style="cursor:grab">&#9776;</td>' +
'<td class="align-middle"></td><td class="align-middle small text-muted"></td><td class="align-middle"></td>' +
'<td><input type="hidden" name="pi_ingredient_id[]" value="' + id + '">' +
'<input type="text" name="pi_gram[]" class="form-control form-control-sm pi-gram" value="" autocomplete="off" step="0.001"></td>' +
'<input type="text" name="pi_gram[]" class="form-control form-control-sm pi-gram" value="" autocomplete="off" step="0.000001"></td>' +
'<td><input type="text" name="pi_factor[]" class="form-control form-control-sm pi-factor" value="' + factor + '" autocomplete="off"></td>' +
'<td class="align-middle pi-effective text-right small text-muted">—</td>' +
'<td class="align-middle"><a class="text-danger ingredient-row-remove" href="#" title="Entfernen"><i class="far fa-trash-alt"></i></a></td></tr>');
@ -332,11 +332,11 @@
var f = parseDeNumber($row.find('.mfg-factor').val());
var $out = $row.find('.mfg-effective');
if (!isNaN(g) && !isNaN(f)) {
$out.text((g * f).toLocaleString('de-DE', { minimumFractionDigits: 3, maximumFractionDigits: 3 }));
} else {
$out.text('—');
}
$out.text((g * f).toLocaleString('de-DE', { minimumFractionDigits: 6, maximumFractionDigits: 6 }));
} else {
$out.text('—');
}
}
function updateMfgRecipeTotal() {
var total = 0, hasValue = false;
@ -346,8 +346,8 @@
});
var $cell = $('#mfg-recipe-total-percent');
if (!hasValue) { $cell.text('—').removeClass('text-danger text-success'); return; }
$cell.text(total.toLocaleString('de-DE', { minimumFractionDigits: 3, maximumFractionDigits: 3 }) + ' %');
if (Math.abs(total - 100) < 0.001) {
$cell.text(total.toLocaleString('de-DE', { minimumFractionDigits: 6, maximumFractionDigits: 6 }) + ' %');
if (Math.abs(total - 100) < 0.000001) {
$cell.removeClass('text-danger').addClass('text-success').attr('title', '');
} else {
$cell.removeClass('text-success').addClass('text-danger').attr('title', 'Die Gesamtrezeptur ergibt nicht 100 %!');
@ -368,7 +368,7 @@
'<td class="text-muted align-middle mfg-ingredient-drag-handle" style="cursor:grab">&#9776;</td>' +
'<td class="align-middle"></td><td class="align-middle small text-muted"></td><td class="align-middle"></td>' +
'<td><input type="hidden" name="mfg_ingredient_id[]" value="' + id + '">' +
'<input type="text" name="mfg_gram[]" class="form-control form-control-sm mfg-gram" value="" autocomplete="off" step="0.001"></td>' +
'<input type="text" name="mfg_gram[]" class="form-control form-control-sm mfg-gram" value="" autocomplete="off" step="0.000001"></td>' +
'<td><input type="text" name="mfg_factor[]" class="form-control form-control-sm mfg-factor" value="' + factor + '" autocomplete="off"></td>' +
'<td class="align-middle mfg-effective text-right small text-muted">—</td>' +
'<td class="align-middle"><a class="text-danger mfg-ingredient-row-remove" href="#" title="Entfernen"><i class="far fa-trash-alt"></i></a></td></tr>');

View file

@ -445,8 +445,8 @@
<td>
<input type="hidden" name="pi_ingredient_id[]" value="{{ $ingredient->id }}">
<input type="text" name="pi_gram[]" class="form-control form-control-sm pi-gram"
value="{{ $ingredient->pivot->gram !== null ? formatNumber($ingredient->pivot->gram, 3) : '' }}"
autocomplete="off" step="0.001">
value="{{ $ingredient->pivot->gram !== null ? formatNumber($ingredient->pivot->gram, 6) : '' }}"
autocomplete="off" step="0.000001">
</td>
<td>
<input type="text" name="pi_factor[]"
@ -594,8 +594,8 @@
<td>
<input type="hidden" name="mfg_ingredient_id[]" value="{{ $ingredient->id }}">
<input type="text" name="mfg_gram[]" class="form-control form-control-sm mfg-gram"
value="{{ $ingredient->pivot->gram !== null ? formatNumber($ingredient->pivot->gram, 3) : '' }}"
autocomplete="off" step="0.001">
value="{{ $ingredient->pivot->gram !== null ? formatNumber($ingredient->pivot->gram, 6) : '' }}"
autocomplete="off" step="0.000001">
</td>
<td>
<input type="text" name="mfg_factor[]"

View file

@ -214,7 +214,7 @@
<li class="sidenav-item{{ Request::is('admin/inventory/stock-entries*') ? ' active' : '' }}">
<a href="{{ route('admin.inventory.stock-entries.index') }}" class="sidenav-link"><i
class="sidenav-icon ion ion-md-download"></i>
<div>{{ __('Wareneingang') }}</div>
<div>{{ __('Einkauf & Wareneingang') }}</div>
</a>
</li>
<li class="sidenav-item{{ Request::is('admin/inventory/productions*') ? ' active' : '' }}">
@ -225,9 +225,7 @@
</li>
@endif
@if (Auth::user()->isAdmin())
<li class="sidenav-item @if (Request::is(
'admin/inventory/supplier-categories*',
'admin/inventory/suppliers*')) open @endif">
<li class="sidenav-item @if (Request::is('admin/inventory/supplier-categories*', 'admin/inventory/suppliers*')) open @endif">
<a href="javascript:void(0)" class="sidenav-link sidenav-toggle">
<i class="sidenav-icon ion ion-md-bus"></i>
<div>Lieferanten</div>
@ -248,15 +246,17 @@
</li>
</ul>
</li>
<li class="sidenav-item{{ Request::is('admin/inventory/packaging-items*') && request('category', 'packaging') === 'packaging' ? ' active' : '' }}">
<a href="{{ route('admin.inventory.packaging-items.index', ['category' => 'packaging']) }}" class="sidenav-link"><i
class="sidenav-icon ion ion-md-basket"></i>
<li
class="sidenav-item{{ Request::is('admin/inventory/packaging-items*') && request('category', 'packaging') === 'packaging' ? ' active' : '' }}">
<a href="{{ route('admin.inventory.packaging-items.index', ['category' => 'packaging']) }}"
class="sidenav-link"><i class="sidenav-icon ion ion-md-basket"></i>
<div>{{ __('Produktverpackung') }}</div>
</a>
</li>
<li class="sidenav-item{{ Request::is('admin/inventory/packaging-items*') && request('category') === 'shipping' ? ' active' : '' }}">
<a href="{{ route('admin.inventory.packaging-items.index', ['category' => 'shipping']) }}" class="sidenav-link"><i
class="sidenav-icon ion ion-md-mail"></i>
<li
class="sidenav-item{{ Request::is('admin/inventory/packaging-items*') && request('category') === 'shipping' ? ' active' : '' }}">
<a href="{{ route('admin.inventory.packaging-items.index', ['category' => 'shipping']) }}"
class="sidenav-link"><i class="sidenav-icon ion ion-md-mail"></i>
<div>{{ __('Versandverpackung') }}</div>
</a>
</li>

View file

@ -24,14 +24,14 @@
<div class="text-left mt-0 mb-2">
<button type="submit" class="btn btn-submit" name="action" value="save-user-promotion">Promotion {{ __('save') }}</button>&nbsp;
<a href="{{ route('user_promotions') }}" class="btn btn-default">{{ __('back') }}</a>
<a href="{{ route('user_promotion') }}" class="btn btn-default">{{ __('back') }}</a>
</div>
@include('user.promotion.form')
<div class="text-left mt-0 mb-2">
<button type="submit" class="btn btn-submit" name="action" value="save-user-promotion">Promotion {{ __('save') }}</button>&nbsp;
<a href="{{ route('user_promotions') }}" class="btn btn-default">{{ __('back') }}</a>
<a href="{{ route('user_promotion') }}" class="btn btn-default">{{ __('back') }}</a>
</div>
{!! Form::close() !!}