formSharedData(), [ 'values' => $this->stockEntryRepository->listForIndex(), ])); } public function create(): View|RedirectResponse { if (! auth()->user()->isAdmin()) { return redirect()->route('home'); } return view('admin.inventory.stock-entries.create', array_merge($this->formSharedData(), [ 'model' => new StockEntry([ 'ordered_at' => now()->toDateString(), 'entry_type' => 'ingredient', ]), ])); } public function store(StoreStockEntryRequest $request): RedirectResponse { if (! $request->user()->isAdmin()) { return redirect()->route('home'); } $data = $request->validatedPayload(); $data['ordered_by'] = (int) auth()->id(); $this->stockEntryRepository->create($data); \Session::flash('alert-save', '1'); return redirect()->route('admin.inventory.stock-entries.index'); } public function show(StockEntry $stockEntry): View { $stockEntry->load([ 'ingredient', 'packagingItem.packagingMaterial', 'supplier', 'location', 'quality', 'orderedByUser.account', 'receivedByUser.account', ]); return view('admin.inventory.stock-entries.show', array_merge($this->formSharedData(), [ 'model' => $stockEntry, 'materialQualities' => MaterialQuality::query()->orderBy('pos')->orderBy('name')->get(), ])); } public function edit(StockEntry $stockEntry): View|RedirectResponse { if (! auth()->user()->isAdmin()) { return redirect()->route('home'); } if (! $stockEntry->isPending()) { \Session::flash('alert-error', __('Nur offene Bestellungen können bearbeitet werden.')); return redirect()->route('admin.inventory.stock-entries.show', $stockEntry); } $stockEntry->load(['ingredient', 'packagingItem']); return view('admin.inventory.stock-entries.edit', array_merge($this->formSharedData(), [ 'model' => $stockEntry, ])); } public function update(UpdateStockEntryRequest $request, StockEntry $stockEntry): RedirectResponse { if (! $request->user()->isAdmin()) { return redirect()->route('home'); } if (! $stockEntry->isPending()) { \Session::flash('alert-error', __('Nur offene Bestellungen können bearbeitet werden.')); return redirect()->route('admin.inventory.stock-entries.show', $stockEntry); } $this->stockEntryRepository->update($stockEntry, $request->validatedPayload()); \Session::flash('alert-save', '1'); return redirect()->route('admin.inventory.stock-entries.index'); } public function destroy(StockEntry $stockEntry): RedirectResponse { if (! auth()->user()->isAdmin()) { return redirect()->route('home'); } if (! $stockEntry->isPending()) { \Session::flash('alert-error', __('Nur offene Bestellungen können gelöscht werden.')); return redirect()->route('admin.inventory.stock-entries.index'); } $stockEntry->delete(); \Session::flash('alert-success', __('Eintrag gelöscht')); return redirect()->route('admin.inventory.stock-entries.index'); } public function receive(ReceiveStockEntryRequest $request, StockEntry $stockEntry): RedirectResponse { if (! $stockEntry->isPending()) { \Session::flash('alert-error', __('Eintrag nicht mehr offen.')); return redirect()->route('admin.inventory.stock-entries.show', $stockEntry); } $data = $request->validated(); if ($stockEntry->entry_type !== 'ingredient') { $data['quality_id'] = null; $data['best_before'] = null; } $this->stockEntryRepository->receive($stockEntry, $data); \Session::flash('alert-save', '1'); return redirect()->route('admin.inventory.stock-entries.show', $stockEntry->fresh()); } public function searchIngredients(Request $request): JsonResponse { $term = trim((string) $request->query('q', '')); if (mb_strlen($term) < 1) { return response()->json(['results' => []]); } $rows = Ingredient::query() ->where('active', true) ->where(function ($query) use ($term) { $query->where('name', 'like', '%'.$term.'%') ->orWhere('inci', 'like', '%'.$term.'%'); }) ->orderBy('name') ->limit(30) ->get(['id', 'name', 'inci']); $results = $rows->map(function (Ingredient $i) { $text = $i->name; if ($i->inci) { $text .= ' ('.$i->inci.')'; } return ['id' => $i->id, 'text' => $text]; })->values()->all(); return response()->json(['results' => $results]); } public function searchPackagingItems(Request $request): JsonResponse { $term = trim((string) $request->query('q', '')); $entryType = $request->query('entry_type'); $categoryMap = [ 'packaging' => 'packaging', 'label' => 'label', 'shipping_office' => 'shipping_office', ]; $query = PackagingItem::query() ->where('active', true); if ($entryType && isset($categoryMap[$entryType])) { $query->where('category', $categoryMap[$entryType]); } if (mb_strlen($term) >= 1) { $query->where('name', 'like', '%'.$term.'%'); } $rows = $query->orderBy('name')->limit(30)->get(['id', 'name']); $results = $rows->map(fn (PackagingItem $p) => [ 'id' => $p->id, 'text' => $p->name, ])->values()->all(); return response()->json(['results' => $results]); } /** * @return array */ protected function formSharedData(): array { return [ 'suppliers' => Supplier::query()->where('active', true)->orderBy('name')->get(), 'locations' => Location::query()->where('active', true)->orderBy('name')->get(), 'entryTypeLabels' => [ 'ingredient' => __('Rohstoff'), 'packaging' => __('Verpackung'), 'label' => __('Etikett'), 'shipping_office' => __('Versand & Büro'), ], ]; } }