get(); return view('pages.inventory.categories.index', compact('categories')); } /** * Menyimpan kategori baru. */ public function store(Request $request): RedirectResponse { $validated = $request->validate([ 'name' => 'required|string|max:255|unique:categories,name', 'keywords' => 'required|string' ]); $category = Category::create($validated); $this->logAction('CREATED_CATEGORY', $category, "Menambah kategori master: {$category->name}"); return back()->with('success', 'Kategori baru berhasil ditambahkan.'); } /** * Menampilkan halaman edit (Hanya Admin). */ public function edit(Category $category): View { if (auth()->user()->role !== 'admin') { abort(403, 'Akses Ditolak.'); } return view('pages.inventory.categories.edit', compact('category')); } /** * Memperbarui data kategori. */ public function update(Request $request, Category $category): RedirectResponse { $validated = $request->validate([ 'name' => 'required|string|max:255|unique:categories,name,' . $category->id, 'keywords' => 'required|string', ]); $category->update($validated); $this->logAction('UPDATED_CATEGORY', $category, "Memperbarui data kategori: {$category->name}"); return redirect()->route('categories.index') ->with('success', "Kategori {$category->name} berhasil diperbarui."); } /** * Sinkronisasi massal seluruh inventori berdasarkan kata kunci. */ public function recategorizeAll(): RedirectResponse { if (auth()->user()->role !== 'admin') { abort(403, 'Hanya Admin yang dapat melakukan sinkronisasi ulang.'); } try { $categories = Category::all(); $updatedCount = 0; // 1. Ambil semua data dari 3 modul inventori $inventories = [ 'Medicine' => Medicine::all(), 'Food' => Food::all(), 'Supply' => Supply::all(), ]; foreach ($inventories as $type => $items) { foreach ($items as $item) { // Tentukan field nama berdasarkan model (nama_obat, nama_makanan, nama_perlengkapan) $fieldName = $this->getFieldName($type); $name = strtolower($item->$fieldName); $found = false; foreach ($categories as $cat) { $keywords = explode(',', strtolower($cat->keywords)); foreach ($keywords as $keyword) { $trimmed = trim($keyword); if (!empty($trimmed) && str_contains($name, $trimmed)) { $item->category_id = $cat->id; // Sinkronisasi kolom teks kategori jika ada if (isset($item->kategori)) { $item->kategori = $cat->name; } $item->save(); $updatedCount++; $found = true; break 2; } } } // Jika tidak cocok, arahkan ke kategori 'Umum' if (!$found) { $umum = Category::where('name', 'Umum')->first(); $item->category_id = $umum ? $umum->id : null; if (isset($item->kategori)) { $item->kategori = 'Umum'; } $item->save(); } } } $this->logAction('RECATEGORIZE_ALL', null, "Melakukan sinkronisasi massal kategori pada seluruh inventori"); return back()->with('success', "Sinkronisasi selesai! {$updatedCount} item berhasil diperbarui kategorinya."); } catch (\Exception $e) { return back()->with('error', 'Gagal sinkronisasi: ' . $e->getMessage()); } } /** * Helper untuk menentukan field nama produk */ private function getFieldName($type) { return match($type) { 'Medicine' => 'nama_obat', 'Food' => 'nama_makanan', 'Supply' => 'nama_perlengkapan', }; } /** * Menghapus kategori (Hanya Admin). */ public function destroy(Category $category): RedirectResponse { if (auth()->user()->role !== 'admin') { abort(403, 'Akses Ditolak.'); } $categoryName = $category->name; // Cek apakah masih ada item yang menggunakan kategori ini if ($category->medicines()->exists() || $category->foods()->exists() || $category->supplies()->exists()) { return back()->with('error', "Kategori '{$categoryName}' tidak bisa dihapus karena masih digunakan oleh beberapa item."); } $this->logAction('DELETED_CATEGORY', null, "Menghapus kategori: {$categoryName}"); $category->delete(); return back()->with('success', 'Kategori berhasil dihapus.'); } }