Warenwirtschaft: AP-51 — Lagerplatz-Felder für Produkte & Verpackung
Lagerplatz-Zuordnung (Raum/Regal/Fach) gab es bisher nur bei Rohstoffen. Jetzt dieselbe Storage-Hierarchie (StorageRoom/Shelf/Slot) auch für Produkte und Verpackungsartikel, inkl. Anzeige an den passenden Stellen. - Migration: storage_room_id/shelf/slot an products + packaging_items (nullable, FK constrained, nullOnDelete). - Models Product + PackagingItem: fillable + storageRoom/Shelf/Slot-Relationen + storageLabel() („Raum 1 | Regal 3 | A"). - Produktformular (Inventar-Abschnitt) + Verpackungsformular: Auswahl-Zeile Raum/Regal/Fach; Optionen kommen aktiv/sortiert aus den zentral pflegbaren Bausteinen (Einstellungen → Allgemein). - Speichern: ProductRepository normalisiert leere Auswahl -> null (FK); PackagingItem-Requests + Repository um die drei Felder erweitert. - Anzeige: Produktbestand (Sub-Zeile mit Marker), Produktverpackung-Übersicht (neue Spalte „Lagerplatz"). - DeletionGuard: Lagerbaustein ist nicht löschbar, solange Produkte/Verpackung darauf verweisen (analog Rohstoffe). Tests: 4 neue (Produkt speichern + leer->null, Verpackung speichern + Anzeige, Löschsperre, freier Baustein löschbar). Migration auf Dev-/Live-DB gelaufen. Suite 331 grün. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
eb47c8a82d
commit
30d4e28696
16 changed files with 363 additions and 5 deletions
|
|
@ -84,6 +84,37 @@
|
|||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<div class="form-group col-sm-4">
|
||||
<label class="form-label" for="storage_room_id">{{ __('Lagerort: Raum') }}</label>
|
||||
<select name="storage_room_id" id="storage_room_id" class="form-control">
|
||||
<option value="">{{ __('— keine Angabe —') }}</option>
|
||||
@foreach($storageRooms as $room)
|
||||
<option value="{{ $room->id }}" @selected((string) old('storage_room_id', $model->storage_room_id) === (string) $room->id)>{{ $room->label }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group col-sm-4">
|
||||
<label class="form-label" for="storage_shelf_id">{{ __('Lagerort: Regal') }}</label>
|
||||
<select name="storage_shelf_id" id="storage_shelf_id" class="form-control">
|
||||
<option value="">{{ __('— keine Angabe —') }}</option>
|
||||
@foreach($storageShelves as $shelf)
|
||||
<option value="{{ $shelf->id }}" @selected((string) old('storage_shelf_id', $model->storage_shelf_id) === (string) $shelf->id)>{{ $shelf->label }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group col-sm-4">
|
||||
<label class="form-label" for="storage_slot_id">{{ __('Lagerort: Fach / Buchstabe') }}</label>
|
||||
<select name="storage_slot_id" id="storage_slot_id" class="form-control">
|
||||
<option value="">{{ __('— keine Angabe —') }}</option>
|
||||
@foreach($storageSlots as $slot)
|
||||
<option value="{{ $slot->id }}" @selected((string) old('storage_slot_id', $model->storage_slot_id) === (string) $slot->id)>{{ $slot->label }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<small class="text-muted">{{ __('Bausteine zentral pflegbar unter Einstellungen → Allgemein.') }}</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="custom-control custom-checkbox">
|
||||
<input type="checkbox" name="active" value="1" class="custom-control-input"
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
<th>{{ __('Material') }}</th>
|
||||
<th>{{ __('Gewicht (g)') }}</th>
|
||||
<th>{{ __('Lieferant') }}</th>
|
||||
<th>{{ __('Lagerplatz') }}</th>
|
||||
<th>{{ __('URL') }}</th>
|
||||
<th>{{ __('Status') }}</th>
|
||||
<th></th>
|
||||
|
|
@ -40,6 +41,7 @@
|
|||
<td>{{ $value->packagingMaterial?->name ?? '—' }}</td>
|
||||
<td>{{ $value->weight_grams }}</td>
|
||||
<td>{{ $value->supplier?->name ?? '—' }}</td>
|
||||
<td>{{ $value->storageLabel() ?? '—' }}</td>
|
||||
<td>
|
||||
@if($value->url)
|
||||
<a href="{{ $value->url }}" target="_blank" title="{{ $value->url }}"><i class="fa fa-external-link-alt"></i></a>
|
||||
|
|
|
|||
|
|
@ -103,6 +103,9 @@
|
|||
@if (!empty($product->number))
|
||||
<div class="wawi-item-sub">{{ $product->number }}</div>
|
||||
@endif
|
||||
@if ($product->storageLabel())
|
||||
<div class="wawi-item-sub text-muted"><span class="fas fa-map-marker-alt mr-1"></span>{{ $product->storageLabel() }}</div>
|
||||
@endif
|
||||
</td>
|
||||
<td class="text-right {{ $stockClass }}">
|
||||
{{ \App\Services\Util::formatNumber($row['stock'], 0) }} <span class="text-muted">{{ __('Stück') }}</span>
|
||||
|
|
|
|||
|
|
@ -1140,6 +1140,38 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
<p class="text-muted small mb-2">{{ __('Lagerplatz (Raum / Regal / Fach). Bausteine zentral pflegbar unter Einstellungen → Allgemein.') }}</p>
|
||||
<div class="form-row">
|
||||
<div class="form-group col-sm-4">
|
||||
<label class="form-label" for="storage_room_id">{{ __('Lagerort: Raum') }}</label>
|
||||
<select name="storage_room_id" id="storage_room_id" class="form-control">
|
||||
<option value="">{{ __('— keine Angabe —') }}</option>
|
||||
@foreach ($storageRooms as $room)
|
||||
<option value="{{ $room->id }}" @selected((string) old('storage_room_id', $product->storage_room_id) === (string) $room->id)>{{ $room->label }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group col-sm-4">
|
||||
<label class="form-label" for="storage_shelf_id">{{ __('Lagerort: Regal') }}</label>
|
||||
<select name="storage_shelf_id" id="storage_shelf_id" class="form-control">
|
||||
<option value="">{{ __('— keine Angabe —') }}</option>
|
||||
@foreach ($storageShelves as $shelf)
|
||||
<option value="{{ $shelf->id }}" @selected((string) old('storage_shelf_id', $product->storage_shelf_id) === (string) $shelf->id)>{{ $shelf->label }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group col-sm-4">
|
||||
<label class="form-label" for="storage_slot_id">{{ __('Lagerort: Fach / Buchstabe') }}</label>
|
||||
<select name="storage_slot_id" id="storage_slot_id" class="form-control">
|
||||
<option value="">{{ __('— keine Angabe —') }}</option>
|
||||
@foreach ($storageSlots as $slot)
|
||||
<option value="{{ $slot->id }}" @selected((string) old('storage_slot_id', $product->storage_slot_id) === (string) $slot->id)>{{ $slot->label }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
<p class="text-muted small mb-2">{{ __('Optional: dieses Einzelprodukt einem Hauptprodukt zuordnen (z. B. „50 × 15 ml"). Der Produktbestand führt nur Haupt-/Einzelprodukte.') }}</p>
|
||||
<div class="form-row">
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue