initial commit
This commit is contained in:
@@ -9,6 +9,8 @@ use Illuminate\Http\Request;
|
||||
use Illuminate\View\View;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class SupplyController extends Controller
|
||||
{
|
||||
@@ -17,18 +19,74 @@ class SupplyController extends Controller
|
||||
/**
|
||||
* Tampilkan daftar perlengkapan.
|
||||
*/
|
||||
public function index(Request $request): View
|
||||
{
|
||||
$query = Supply::with('category');
|
||||
public function index(Request $request): View
|
||||
{
|
||||
// 1. Proteksi Akses (Sesuai Matriks Role Management)
|
||||
Gate::authorize('check-access', ['supplies', 'read']);
|
||||
|
||||
if ($request->filled('search')) {
|
||||
$query->where('nama_perlengkapan', 'like', '%' . $request->search . '%');
|
||||
$now = now();
|
||||
$query = Supply::with('category');
|
||||
|
||||
// 2. FILTER KHUSUS (SINKRONISASI DENGAN DASHBOARD)
|
||||
if ($request->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);
|
||||
}
|
||||
|
||||
$supplies = $query->latest()->paginate(10);
|
||||
return view('pages.inventory.supplies.index', compact('supplies'));
|
||||
}
|
||||
|
||||
// 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.
|
||||
*/
|
||||
@@ -103,24 +161,41 @@ class SupplyController extends Controller
|
||||
/**
|
||||
* Hapus data perlengkapan.
|
||||
*/
|
||||
public function destroy(Supply $supply): RedirectResponse
|
||||
{
|
||||
if (auth()->user()->role !== 'admin') {
|
||||
abort(403, 'Akses Ditolak.');
|
||||
}
|
||||
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;
|
||||
|
||||
if ($supply->foto_produk) {
|
||||
// 2. PEMBERSIHAN FILE (STORAGE)
|
||||
if ($supply->foto_produk && Storage::disk('public')->exists($supply->foto_produk)) {
|
||||
Storage::disk('public')->delete($supply->foto_produk);
|
||||
}
|
||||
|
||||
// PENTING: Log dilakukan SEBELUM delete agar ID tidak null
|
||||
$this->logAction('DELETED_SUPPLY', $supply, "Menghapus perlengkapan: {$supplyName}");
|
||||
// 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();
|
||||
|
||||
// FIX: Menggunakan .index
|
||||
return redirect()->route('inventory.supplies.index')->with('success', 'Data perlengkapan berhasil dihapus.');
|
||||
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.');
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user