Files
2026-09-23 12:45:02 +07:00

180 lines
5.8 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Models\Food;
use App\Models\Category;
use App\Traits\LogsActivity;
use Illuminate\Http\Request;
use Illuminate\View\View;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Gate;
class FoodController extends Controller
{
use LogsActivity;
/**
* Tampilkan daftar stok makanan.
*/
public function index(Request $request): View
{
// Proteksi Akses
Gate::authorize('check-access', ['foods', 'read']);
$now = now();
$query = Food::with('category');
// 1. FILTER KHUSUS (SINKRONISASI DENGAN DASHBOARD)
if ($request->filled('filter')) {
$filter = $request->get('filter');
if ($filter === 'expired') {
// Menampilkan makanan 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);
}
}
// 2. SEARCH GLOBAL
if ($request->filled('search')) {
$search = $request->search;
$query->where(function($q) use ($search) {
$q->where('nama_makanan', 'like', "%{$search}%")
->orWhere('kategori', 'like', "%{$search}%")
->orWhere('unit', 'like', "%{$search}%");
});
}
// 3. SORTING DINAMIS (Menambahkan kembali expired_at)
$allowedSorts = ['nama_makanan', 'qty', 'expired_at', 'created_at'];
$sort = in_array($request->get('sort'), $allowedSorts) ? $request->get('sort') : 'nama_makanan';
$direction = strtolower($request->get('direction')) === 'desc' ? 'desc' : 'asc';
$foods = $query->orderBy($sort, $direction)
->paginate(15)
->withQueryString();
// 4. STATISTIK (Komprehensif)
$totalStock = Food::sum('qty');
$lowStockCount = Food::where('qty', '<=', 5)->count();
// Hitung item yang expired (Wajib ada kolom expired_at di database)
$expiredCount = Food::whereNotNull('expired_at')
->where('expired_at', '<', $now)
->count();
$totalItems = Food::count();
return view('pages.inventory.foods.index', compact(
'foods',
'totalStock',
'lowStockCount',
'expiredCount',
'totalItems'
));
}
/**
* Tampilkan form tambah.
*/
public function create(): View
{
return view('pages.inventory.foods.create');
}
/**
* Simpan data makanan baru.
*/
public function store(Request $request): RedirectResponse
{
$validated = $request->validate([
'nama_makanan' => 'required|string|max:255',
'qty' => 'required|numeric|min:0',
'unit' => 'required|string|max:50',
'expired_date' => 'nullable|date|after_or_equal:today',
'foto_produk' => 'nullable|image|max:1024',
]);
if ($request->hasFile('foto_produk')) {
$validated['foto_produk'] = $request->file('foto_produk')->store('foods', 'public');
}
// Simpan data & tangkap objeknya untuk logging
$food = Food::create($validated);
// Tambahkan Log Aktivitas (Sangat penting untuk audit stok)
$this->logAction('CREATED_FOOD', $food, "Menambah stok pakan baru: {$food->nama_makanan}");
// FIX: Tambahkan .index agar tidak error RouteNotFound
return redirect()->route('inventory.foods.index')->with('success', 'Stok pakan berhasil ditambahkan.');
}
/**
* Tampilkan form edit.
*/
public function edit(Food $food): View
{
$categories = Category::all();
return view('pages.inventory.foods.edit', compact('food', 'categories'));
}
/**
* Update data makanan.
*/
public function update(Request $request, Food $food): RedirectResponse
{
$validated = $request->validate([
'nama_makanan' => 'required|string|max:255',
'qty' => 'required|numeric|min:0',
'unit' => 'required|string|max:50',
'category_id' => 'nullable|exists:categories,id',
'expired_date' => 'nullable|date|after_or_equal:today',
'foto_produk' => 'nullable|image|max:1024',
]);
if ($request->hasFile('foto_produk')) {
if ($food->foto_produk) {
Storage::disk('public')->delete($food->foto_produk);
}
$validated['foto_produk'] = $request->file('foto_produk')->store('foods', 'public');
}
$food->update($validated);
$this->logAction('UPDATED_FOOD', $food, "Memperbarui stok pakan: {$food->nama_makanan}");
// FIX: Tambahkan .index
return redirect()->route('inventory.foods.index')->with('success', 'Data stok pakan berhasil diperbarui.');
}
/**
* Hapus data makanan.
*/
public function destroy(Food $food): RedirectResponse
{
if (auth()->user()->role !== 'admin') {
abort(403, 'Hanya Admin yang dapat menghapus data stok pakan.');
}
$foodName = $food->nama_makanan;
if ($food->foto_produk) {
Storage::disk('public')->delete($food->foto_produk);
}
// Log dilakukan SEBELUM delete
$this->logAction('DELETED_FOOD', $food, "Menghapus data pakan: {$foodName}");
$food->delete();
// FIX: Tambahkan .index
return redirect()->route('inventory.foods.index')->with('success', 'Stok pakan berhasil dihapus.');
}
}