170 lines
5.7 KiB
PHP
170 lines
5.7 KiB
PHP
|
|
<?php
|
||
|
|
|
||
|
|
namespace App\Http\Controllers;
|
||
|
|
|
||
|
|
use App\Models\Category;
|
||
|
|
use App\Models\Medicine;
|
||
|
|
use App\Models\Food;
|
||
|
|
use App\Models\Supply;
|
||
|
|
use App\Traits\LogsActivity;
|
||
|
|
use Illuminate\Http\Request;
|
||
|
|
use Illuminate\View\View;
|
||
|
|
use Illuminate\Http\RedirectResponse;
|
||
|
|
|
||
|
|
class CategoryController extends Controller
|
||
|
|
{
|
||
|
|
use LogsActivity;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Menampilkan daftar kategori.
|
||
|
|
*/
|
||
|
|
public function index(): View
|
||
|
|
{
|
||
|
|
// Mengambil kategori beserta hitungan item di dalamnya (optional untuk insight)
|
||
|
|
$categories = Category::latest()->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.');
|
||
|
|
}
|
||
|
|
}
|