filled('filter')) { $filter = $request->get('filter'); if ($filter === 'expired') { // Menampilkan perlengkapan yang sudah kadaluwarsa $query->whereNotNull('expired_at')->where('expired_at', '<', $now); } elseif ($filter === 'expiring_soon') { // Menampilkan yang kadaluwarsa dalam 7 hari kedepan $query->whereNotNull('expired_at') ->whereBetween('expired_at', [$now, $now->copy()->addDays(7)]); } elseif ($filter === 'low_stock') { // Menampilkan stok kritis $query->where('qty', '<=', 5); } } // 3. SEARCH GLOBAL (Mencari di Nama, Kategori, dan Unit) if ($request->filled('search')) { $search = $request->search; $query->where(function($q) use ($search) { $q->where('nama_perlengkapan', 'like', "%{$search}%") ->orWhere('kategori', 'like', "%{$search}%") ->orWhere('unit', 'like', "%{$search}%") ->orWhereHas('category', function($sub) use ($search) { $sub->where('name', 'like', "%{$search}%"); }); }); } // 4. LOGIKA SORTING DINAMIS (Menambahkan expired_at dalam daftar sort) $allowedSorts = ['nama_perlengkapan', 'qty', 'kategori', 'expired_at', 'created_at']; $sort = in_array($request->get('sort'), $allowedSorts) ? $request->get('sort') : 'nama_perlengkapan'; $direction = strtolower($request->get('direction')) === 'desc' ? 'desc' : 'asc'; // Eksekusi Query dengan Pagination $supplies = $query->orderBy($sort, $direction) ->paginate(15) ->withQueryString(); // 5. STATISTIK RINGKAS (Komprehensif) $totalStock = Supply::sum('qty'); $lowStockCount = Supply::where('qty', '<=', 5)->count(); // Hitung item yang expired (Wajib ada kolom expired_at di database) $expiredCount = Supply::whereNotNull('expired_at') ->where('expired_at', '<', $now) ->count(); $totalItems = Supply::count(); return view('pages.inventory.supplies.index', compact( 'supplies', 'totalStock', 'lowStockCount', 'expiredCount', // Variabel statistik baru 'totalItems' )); } /** * Tampilkan form tambah. */ public function create(): View { // Category ditentukan otomatis oleh Model Supply return view('pages.inventory.supplies.create'); } /** * Simpan data perlengkapan baru. */ public function store(Request $request): RedirectResponse { $validated = $request->validate([ 'nama_perlengkapan' => 'required|string|max:255', 'qty' => 'required|numeric|min:0', 'unit' => 'required|string|max:50', 'category_id' => 'nullable|exists:categories,id', 'foto_produk' => 'nullable|image|max:1024', ]); if ($request->hasFile('foto_produk')) { $validated['foto_produk'] = $request->file('foto_produk')->store('supplies', 'public'); } $supply = Supply::create($validated); $this->logAction('CREATED_SUPPLY', $supply, "Menambah perlengkapan: {$supply->nama_perlengkapan}"); // FIX: Menggunakan .index agar tidak RouteNotFound return redirect()->route('inventory.supplies.index')->with('success', 'Perlengkapan berhasil ditambahkan.'); } /** * Tampilkan form edit. */ public function edit(Supply $supply): View { $categories = Category::all(); return view('pages.inventory.supplies.edit', compact('supply', 'categories')); } /** * Update data perlengkapan. */ public function update(Request $request, Supply $supply): RedirectResponse { $validated = $request->validate([ 'nama_perlengkapan' => 'required|string|max:255', 'qty' => 'required|numeric|min:0', 'unit' => 'required|string|max:50', 'category_id' => 'nullable|exists:categories,id', 'foto_produk' => 'nullable|image|max:1024', ]); if ($request->hasFile('foto_produk')) { if ($supply->foto_produk) { Storage::disk('public')->delete($supply->foto_produk); } $validated['foto_produk'] = $request->file('foto_produk')->store('supplies', 'public'); } $supply->update($validated); $this->logAction('UPDATED_SUPPLY', $supply, "Memperbarui data perlengkapan: {$supply->nama_perlengkapan}"); // FIX: Menggunakan .index return redirect()->route('inventory.supplies.index')->with('success', 'Data perlengkapan berhasil diperbarui.'); } /** * Hapus data perlengkapan. */ public function destroy(Supply $supply): RedirectResponse { // 1. OTORISASI DINAMIS (Inilah perbaikan untuk akses Supervisor) // Menggunakan Gate 'check-access' agar sinkron dengan Role Management Anda Gate::authorize('check-access', ['supplies', 'delete']); try { DB::beginTransaction(); $supplyName = $supply->nama_perlengkapan; // 2. PEMBERSIHAN FILE (STORAGE) if ($supply->foto_produk && Storage::disk('public')->exists($supply->foto_produk)) { Storage::disk('public')->delete($supply->foto_produk); } // 3. AUDIT TRAIL // Dicatat sebelum delete agar konteks data $supply masih tersedia secara lengkap if (method_exists($this, 'logAction')) { $this->logAction('DELETE', 'Inventory', "Menghapus perlengkapan: {$supplyName}"); } // 4. EKSEKUSI HAPUS $supply->delete(); DB::commit(); return redirect()->route('inventory.supplies.index') ->with('success', "Perlengkapan '{$supplyName}' berhasil dihapus dari sistem."); } catch (\Exception $e) { DB::rollBack(); // Reporting error jika terjadi kegagalan sistem return back()->with('error', 'Gagal menghapus data. Silakan coba lagi atau hubungi IT.'); } } }