anggota; // 🔥 1. PROTEKSI UTAMA: Cek pendaftaran dan status persetujuan admin if (!$anggota) { return redirect()->route('user.member.create') ->with('error', 'Silakan daftar anggota terlebih dahulu sebelum meminjam buku.'); } // Jika statusnya bukan 'disetujui' (misal: 'menunggu' atau 'ditolak'), tendang ke halaman pending if ($anggota->status !== 'disetujui') { return redirect()->route('user.member.pending') ->with('error', 'Akses ditolak! Anda harus berstatus sebagai Anggota Aktif (Disetujui) untuk mengakses halaman transaksi.'); } // 2. Ambil transaksi dipinjam untuk cek keterlambatan (Kode Asli Anda) $dipinjam = BorrowTransaction::where('anggota_id', $anggota->id) ->where('status', 'dipinjam') ->get(); $blokir = false; foreach ($dipinjam as $trx) { if ($trx->tanggal_kembali && Carbon::now()->gt(Carbon::parse($trx->tanggal_kembali))) { if ($trx->is_late == 0) { $trx->is_late = 1; } $blokir = true; if ($trx->late_notified == 0 && env('MAIL_USERNAME')) { try { Mail::to($trx->anggota->email) ->send(new PeringatanKeterlambatanMail($trx)); $trx->late_notified = 1; } catch (\Exception $e) { \Log::error('Gagal mengirim email keterlambatan: ' . $e->getMessage()); } } $trx->save(); } } // 3. Ambil semua transaksi termasuk kolom admin_feedback (Kode Asli Anda) $peminjaman = BorrowTransaction::with(['koleksi']) ->where('anggota_id', $anggota->id) ->latest() ->get() ->map(function ($item) { // Konversi timezone untuk view $fields = ['pickup_date', 'tanggal_pinjam', 'tanggal_kembali']; foreach ($fields as $field) { if ($item->$field) { $item->$field = Carbon::parse($item->$field)->setTimezone('Asia/Jakarta'); } } return $item; }); return view('user.peminjaman.index', compact('peminjaman', 'anggota', 'blokir')); } /** * MENAMPILKAN FORM PERPANJANGAN (GET) */ public function showPerpanjangForm($id) { $peminjaman = BorrowTransaction::with(['koleksi', 'anggota'])->findOrFail($id); // Proteksi: Cek apakah benar milik user yang login if ($peminjaman->anggota_id !== Auth::user()->anggota->id) { abort(403); } // Proteksi: Cek status & keterlambatan if ($peminjaman->status !== 'dipinjam') { return redirect()->route('user.peminjaman.index')->with('error', 'Status buku tidak valid untuk diperpanjang.'); } if ($peminjaman->tanggal_kembali && Carbon::now()->gt(Carbon::parse($peminjaman->tanggal_kembali))) { return redirect()->route('user.peminjaman.index')->with('error', 'Buku terlambat tidak bisa diperpanjang secara mandiri.'); } if ($peminjaman->perpanjangan_diajukan) { return redirect()->route('user.peminjaman.index')->with('error', 'Perpanjangan sudah pernah diajukan.'); } return view('user.peminjaman.perpanjang', compact('peminjaman')); } /** * MEMPROSES PENGAJUAN PERPANJANGAN (POST) */ public function processPerpanjang(Request $request, $id) { $transaction = BorrowTransaction::findOrFail($id); // Validasi input file $request->validate([ 'surat_pengantar' => 'required|file|mimes:pdf|max:2048', ]); // Cek keterlambatan lagi (security check) if ($transaction->tanggal_kembali && Carbon::now()->gt(Carbon::parse($transaction->tanggal_kembali))) { return redirect()->route('user.peminjaman.index')->with('error', 'Buku ini sudah terlambat.'); } // Simpan File PDF baru if ($request->hasFile('surat_pengantar')) { $file = $request->file('surat_pengantar'); $pdfFilename = 'perpanjang_' . time() . '_' . $file->getClientOriginalName(); $file->storeAs('public/surat_pengantar', $pdfFilename); // Update transaksi $transaction->status = 'perpanjangan_menunggu'; $transaction->perpanjangan_diajukan = true; $transaction->surat_pengantar = $pdfFilename; // Update dengan surat baru $transaction->save(); } // Kirim Email ke Admin if (env('MAIL_USERNAME')) { try { Mail::to(config('mail.from.address')) ->send(new PerpanjanganMenungguApproval($transaction)); } catch (\Exception $e) { \Log::error('Gagal kirim email perpanjangan: ' . $e->getMessage()); } } return redirect()->route('user.peminjaman.index') ->with('success', 'Permintaan perpanjangan dan dokumen berhasil dikirim!'); } public function store(Request $request) { $anggota = Auth::user()->anggota; if (!$anggota || $anggota->status !== 'disetujui') { return back()->with('error', 'Status keanggotaan Anda belum diizinkan meminjam.'); } $request->validate([ 'koleksi_id' => 'required|exists:koleksis,biblio_id', 'tanggal_pinjam' => 'required|date', 'surat_pengantar' => 'nullable|file|mimes:pdf|max:2048', ]); $pdfFilename = null; if ($request->hasFile('surat_pengantar')) { $file = $request->file('surat_pengantar'); $pdfFilename = time() . '_' . $file->getClientOriginalName(); $file->storeAs('public/surat_pengantar', $pdfFilename); } $transaction = BorrowTransaction::create([ 'anggota_id' => $anggota->id, 'koleksi_id' => $request->koleksi_id, 'tanggal_pinjam' => $request->tanggal_pinjam, 'status' => 'menunggu', 'surat_pengantar' => $pdfFilename, ]); return redirect()->route('user.peminjaman.index')->with('success', 'Pengajuan berhasil dikirim!'); } public function kembalikan($id) { $transaction = BorrowTransaction::findOrFail($id); if ($transaction->status != 'dipinjam') { return back()->with('error', 'Buku belum dapat dikembalikan.'); } $transaction->markAsPengembalianMenunggu(); if (env('MAIL_USERNAME')) { try { Mail::to(config('mail.from.address'))->send(new PengembalianMenungguApproval($transaction)); } catch (\Exception $e) {} } return redirect()->route('user.peminjaman.index')->with('success', 'Permintaan pengembalian dikirim!'); } // Fungsi Rating & Penilaian public function penilaian($id) { $transaction = BorrowTransaction::findOrFail($id); return view('user.rating.form', compact('transaction')); } public function simpanPenilaian(Request $request, $id) { $request->validate(['rating' => 'required|integer|min:1|max:5']); Rating::create([ 'user_id' => Auth::id(), 'borrow_transaction_id' => $id, 'rating' => $request->rating, 'feedback' => $request->feedback, ]); return redirect()->route('user.peminjaman.index')->with('success', 'Terima kasih!'); } public function downloadSuratPengantar($id) { $transaction = BorrowTransaction::findOrFail($id); $path = 'public/surat_pengantar/' . $transaction->surat_pengantar; if (!Storage::exists($path)) return back()->with('error', 'File tidak ditemukan.'); return Storage::download($path); } }