Warenwirtschaft: AP-09 bis AP-13 (Produktbestand, Set-Produkte, Ausschuss, Konzepte)

- AP-09 Produktbestand inkl. Bewegungshistorie (product_stock_movements, ProductStockService)
- AP-10 Rohstoffbestand-Ansicht je Lager (RawMaterialStockController)
- AP-11 Bestandsschwellen / Out-of-Stock-Handling fuer Produkte und Shop
- AP-12 Ausgang/Ausschuss (stock_disposals, StockDisposalController, InventoryService)
- Set-Produkte (product_set_items) inkl. Aufloesung
- Produktentwicklung & Hinweise-Verwaltung (Notices)
- AP-13 Entwicklungskonzept Shop-Bestandsabzug im Plan dokumentiert
- Feature-Tests fuer neue Module + aktualisierter Entwicklungsplan

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Kevin Adametz 2026-06-03 11:04:22 +00:00
parent 78679e0c55
commit 3ee2d756e9
63 changed files with 5968 additions and 901 deletions

View file

@ -4,9 +4,14 @@ use App\Http\Controllers\Admin\Inventory\DeliveryTimeController as InventoryDeli
use App\Http\Controllers\Admin\Inventory\GeneralSettingController as InventoryGeneralSettingController;
use App\Http\Controllers\Admin\Inventory\LocationController as InventoryLocationController;
use App\Http\Controllers\Admin\Inventory\MaterialQualityController as InventoryMaterialQualityController;
use App\Http\Controllers\Admin\Inventory\NoticeController as InventoryNoticeController;
use App\Http\Controllers\Admin\Inventory\PackagingItemController as InventoryPackagingItemController;
use App\Http\Controllers\Admin\Inventory\PackagingMaterialController as InventoryPackagingMaterialController;
use App\Http\Controllers\Admin\Inventory\ProductDevelopmentController as InventoryProductDevelopmentController;
use App\Http\Controllers\Admin\Inventory\ProductionController as InventoryProductionController;
use App\Http\Controllers\Admin\Inventory\ProductStockController as InventoryProductStockController;
use App\Http\Controllers\Admin\Inventory\RawMaterialStockController as InventoryRawMaterialStockController;
use App\Http\Controllers\Admin\Inventory\StockDisposalController as InventoryStockDisposalController;
use App\Http\Controllers\Admin\Inventory\StockEntryController as InventoryStockEntryController;
use App\Http\Controllers\Admin\Inventory\SupplierCategoryController as InventorySupplierCategoryController;
use App\Http\Controllers\Admin\Inventory\SupplierController as InventorySupplierController;
@ -278,6 +283,7 @@ Route::domain(config('app.domain'))->group(function () {
Route::resource('material-qualities', InventoryMaterialQualityController::class)->except(['show']);
Route::resource('packaging-materials', InventoryPackagingMaterialController::class)->except(['show']);
Route::get('general', [InventoryGeneralSettingController::class, 'index'])->name('general');
Route::get('notices', [InventoryNoticeController::class, 'index'])->name('notices');
Route::resource('tax-rates', InventoryTaxRateController::class)->except(['index', 'show']);
Route::resource('delivery-times', InventoryDeliveryTimeController::class)->except(['index', 'show']);
});
@ -293,14 +299,24 @@ Route::domain(config('app.domain'))->group(function () {
});
Route::middleware(['copyreader'])->prefix('admin/inventory')->name('admin.inventory.')->group(function () {
Route::get('product-stock', [InventoryProductStockController::class, 'index'])->name('product-stock.index');
Route::get('product-stock/history', [InventoryProductStockController::class, 'history'])->name('product-stock.history');
Route::post('product-stock/{product}/movement', [InventoryProductStockController::class, 'storeMovement'])->name('product-stock.movement');
Route::get('raw-material-stock', [InventoryRawMaterialStockController::class, 'index'])->name('raw-material-stock.index');
Route::get('raw-material-stock/{ingredient}', [InventoryRawMaterialStockController::class, 'show'])->name('raw-material-stock.show');
Route::get('api/ingredients/search', [InventoryStockEntryController::class, 'searchIngredients'])->name('api.ingredients.search');
Route::get('api/packaging-items/search', [InventoryStockEntryController::class, 'searchPackagingItems'])->name('api.packaging-items.search');
Route::get('api/products/{product}/recipe', [InventoryProductionController::class, 'recipeJson'])->name('api.products.recipe');
Route::get('api/disposals/ingredient-charges/{ingredient}', [InventoryStockDisposalController::class, 'ingredientCharges'])->name('api.disposals.ingredient-charges');
Route::get('stock-disposals', [InventoryStockDisposalController::class, 'index'])->name('stock-disposals.index');
Route::get('stock-disposals/create', [InventoryStockDisposalController::class, 'create'])->name('stock-disposals.create');
Route::post('stock-disposals', [InventoryStockDisposalController::class, 'store'])->name('stock-disposals.store');
Route::put('stock-entries/{stock_entry}/receive', [InventoryStockEntryController::class, 'receive'])->name('stock-entries.receive');
Route::get('stock-entries/{stock_entry}/copy', [InventoryStockEntryController::class, 'copy'])->name('stock-entries.copy');
Route::resource('stock-entries', InventoryStockEntryController::class);
Route::resource('productions', InventoryProductionController::class)->only(['index', 'create', 'store', 'show', 'edit', 'update']);
Route::get('productions/{production}/copy', [InventoryProductionController::class, 'copy'])->name('productions.copy');
Route::get('product-development', [InventoryProductDevelopmentController::class, 'index'])->name('product-development');
});
});