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
|
|
@ -7,10 +7,14 @@ use App\Http\Requests\Inventory\StorePackagingItemRequest;
|
|||
use App\Http\Requests\Inventory\UpdatePackagingItemRequest;
|
||||
use App\Models\PackagingItem;
|
||||
use App\Models\PackagingMaterial;
|
||||
use App\Models\StorageRoom;
|
||||
use App\Models\StorageShelf;
|
||||
use App\Models\StorageSlot;
|
||||
use App\Models\Supplier;
|
||||
use App\Repositories\PackagingItemRepository;
|
||||
use App\Services\DeletionGuard;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
class PackagingItemController extends Controller
|
||||
{
|
||||
|
|
@ -24,7 +28,7 @@ class PackagingItemController extends Controller
|
|||
$isShipping = $category === 'shipping';
|
||||
|
||||
$query = PackagingItem::query()
|
||||
->with(['packagingMaterial', 'supplier'])
|
||||
->with(['packagingMaterial', 'supplier', 'storageRoom', 'storageShelf', 'storageSlot'])
|
||||
->orderBy('name');
|
||||
|
||||
if ($isShipping) {
|
||||
|
|
@ -52,9 +56,24 @@ class PackagingItemController extends Controller
|
|||
'packagingMaterials' => PackagingMaterial::query()->orderBy('pos')->orderBy('name')->get(),
|
||||
'suppliers' => Supplier::query()->orderBy('name')->get(),
|
||||
'category' => $category,
|
||||
...$this->storageOptions(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* AP-51: Lagerplatz-Bausteine (Raum/Regal/Fach) für das Formular.
|
||||
*
|
||||
* @return array<string, Collection<int, mixed>>
|
||||
*/
|
||||
private function storageOptions(): array
|
||||
{
|
||||
return [
|
||||
'storageRooms' => StorageRoom::query()->active()->orderBy('pos')->orderBy('label')->get(),
|
||||
'storageShelves' => StorageShelf::query()->active()->orderBy('pos')->orderBy('label')->get(),
|
||||
'storageSlots' => StorageSlot::query()->active()->orderBy('pos')->orderBy('label')->get(),
|
||||
];
|
||||
}
|
||||
|
||||
public function store(StorePackagingItemRequest $request)
|
||||
{
|
||||
$validated = $request->validated();
|
||||
|
|
@ -77,6 +96,7 @@ class PackagingItemController extends Controller
|
|||
'packagingMaterials' => PackagingMaterial::query()->orderBy('pos')->orderBy('name')->get(),
|
||||
'suppliers' => Supplier::query()->orderBy('name')->get(),
|
||||
'category' => $category,
|
||||
...$this->storageOptions(),
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ class ProductStockController extends Controller
|
|||
->where('is_set', false)
|
||||
->where('show_in_product_stock', true)
|
||||
->whereNull('main_product_id')
|
||||
->with('images')
|
||||
->with(['images', 'storageRoom', 'storageShelf', 'storageSlot'])
|
||||
->orderBy('pos')
|
||||
->orderBy('name')
|
||||
->get();
|
||||
|
|
|
|||
|
|
@ -8,6 +8,9 @@ use App\Models\PackagingItem;
|
|||
use App\Models\Product;
|
||||
use App\Models\ProductImage;
|
||||
use App\Models\ProductIngredient;
|
||||
use App\Models\StorageRoom;
|
||||
use App\Models\StorageShelf;
|
||||
use App\Models\StorageSlot;
|
||||
use App\Repositories\ProductRepository;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Request;
|
||||
|
|
@ -58,6 +61,9 @@ class ProductController extends Controller
|
|||
'ingredient_catalog' => Ingredient::query()->where('active', true)->with('materialQuality')->orderBy('name')->get(['id', 'name', 'inci', 'effect', 'default_factor', 'material_quality_id']),
|
||||
'packaging_catalog' => PackagingItem::query()->where('active', true)->with('packagingMaterial')->orderBy('name')->get(),
|
||||
'set_product_catalog' => $this->setProductCatalog($model),
|
||||
'storageRooms' => StorageRoom::query()->active()->orderBy('pos')->orderBy('label')->get(),
|
||||
'storageShelves' => StorageShelf::query()->active()->orderBy('pos')->orderBy('label')->get(),
|
||||
'storageSlots' => StorageSlot::query()->active()->orderBy('pos')->orderBy('label')->get(),
|
||||
];
|
||||
|
||||
return view('admin.product.edit', $data);
|
||||
|
|
@ -127,6 +133,9 @@ class ProductController extends Controller
|
|||
'ingredient_catalog' => Ingredient::query()->where('active', true)->with('materialQuality')->orderBy('name')->get(['id', 'name', 'inci', 'effect', 'default_factor', 'material_quality_id']),
|
||||
'packaging_catalog' => PackagingItem::query()->where('active', true)->with('packagingMaterial')->orderBy('name')->get(),
|
||||
'set_product_catalog' => $this->setProductCatalog($model),
|
||||
'storageRooms' => StorageRoom::query()->active()->orderBy('pos')->orderBy('label')->get(),
|
||||
'storageShelves' => StorageShelf::query()->active()->orderBy('pos')->orderBy('label')->get(),
|
||||
'storageSlots' => StorageSlot::query()->active()->orderBy('pos')->orderBy('label')->get(),
|
||||
];
|
||||
|
||||
if ($validator->fails()) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue