anggota; if (!$anggota) { return redirect()->route('user.member.create') ->with('error', 'Silakan daftar anggota terlebih dahulu sebelum meminjam buku.'); } $dipinjam = BorrowTransaction::where('anggota_id', $anggota->id) ->where('status', 'dipinjam') ->get(); 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; } 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(); } } $peminjaman = BorrowTransaction::with(['koleksi']) ->where('anggota_id', $anggota->id) ->orderBy('tanggal_pinjam', 'desc') ->get() ->map(function ($item) { if ($item->pickup_date) { $item->pickup_date = Carbon::parse($item->pickup_date)->setTimezone('Asia/Jakarta'); } if ($item->tanggal_pinjam) { $item->tanggal_pinjam = Carbon::parse($item->tanggal_pinjam)->setTimezone('Asia/Jakarta'); } if ($item->tanggal_kembali) { $item->tanggal_kembali = Carbon::parse($item->tanggal_kembali)->setTimezone('Asia/Jakarta'); } return $item; }); return view('user.peminjaman.index', compact('peminjaman', 'anggota')); } public function create() { $anggota = Auth::user()->anggota; if (!$anggota) { return redirect()->route('user.member.create') ->with('error', 'Silakan daftar anggota terlebih dahulu sebelum meminjam buku.'); } $koleksi = Koleksi::whereDoesntHave('borrowTransactions', function ($q) { $q->whereIn('status', ['dipinjam', 'menunggu', 'disetujui']); })->get(); $lastTransaction = $anggota->borrowTransactions()->latest()->first(); return view('user.peminjaman.create', compact('anggota', 'koleksi', 'lastTransaction')); } public function store(Request $request) { $anggota = Auth::user()->anggota; if (!$anggota) { return redirect()->route('user.member.create') ->with('error', 'Silakan daftar anggota terlebih dahulu sebelum meminjam buku.'); } if ($anggota->status !== 'disetujui') { return redirect()->route('user.peminjaman.create') ->with('error', 'Anda belum dapat meminjam buku sebelum disetujui oleh admin.'); } $request->validate([ 'koleksi_id' => 'required|exists:koleksis,biblio_id', 'tanggal_pinjam' => 'required|date', 'surat_pengantar' => 'nullable|file|mimes:pdf|max:2048', ]); $alreadyBorrowed = BorrowTransaction::where('koleksi_id', $request->koleksi_id) ->whereIn('status', ['menunggu', 'disetujui', 'dipinjam']) ->exists(); if ($alreadyBorrowed) { return back()->withErrors(['koleksi_id' => 'Buku ini sedang dalam proses peminjaman.']); } $pdfFilename = null; if ($request->hasFile('surat_pengantar')) { $file = $request->file('surat_pengantar'); if (!Storage::exists('public/surat_pengantar')) { Storage::makeDirectory('public/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, ]); if (env('MAIL_USERNAME')) { try { Mail::send('emails.peminjaman_baru', [ 'anggota' => $anggota, 'transaction' => $transaction, ], function ($message) { $message->to(config('mail.from.address')) ->subject('📚 Pengajuan Peminjaman Buku Baru'); }); } catch (\Exception $e) { \Log::error('Gagal mengirim email peminjaman ke admin: ' . $e->getMessage()); } } return redirect()->route('user.peminjaman.index') ->with('success', 'Pengajuan peminjaman berhasil dikirim! Menunggu persetujuan admin.'); } public function kembalikan($id) { $transaction = BorrowTransaction::findOrFail($id); if ($transaction->status != 'dipinjam') { return redirect()->route('user.peminjaman.index') ->with('error', 'Buku belum dapat dikembalikan atau sudah dikembalikan.'); } $transaction->markAsPengembalianMenunggu(); if (env('MAIL_USERNAME')) { try { Mail::to(config('mail.from.address')) ->send(new PengembalianMenungguApproval($transaction)); } catch (\Exception $e) { return back()->with('error', 'Gagal mengirim email ke admin: ' . $e->getMessage()); } } return redirect()->route('user.peminjaman.index') ->with('success', 'Permintaan pengembalian dikirim! Menunggu persetujuan admin.'); } public function ajukanPerpanjangan($id) { $transaction = BorrowTransaction::findOrFail($id); if ($transaction->status !== 'dipinjam') { return redirect()->route('user.peminjaman.index') ->with('error', 'Hanya buku yang sedang dipinjam yang bisa diperpanjang.'); } if ($transaction->perpanjangan_diajukan) { return back()->with('error', 'Anda sudah pernah mengajukan perpanjangan untuk buku ini.'); } $transaction->status = 'perpanjangan_menunggu'; $transaction->perpanjangan_diajukan = true; $transaction->save(); if (env('MAIL_USERNAME')) { try { Mail::to(config('mail.from.address')) ->send(new PerpanjanganMenungguApproval($transaction)); } catch (\Exception $e) { return back()->with('error', 'Gagal mengirim email perpanjangan: ' . $e->getMessage()); } } return redirect()->route('user.peminjaman.index') ->with('success', 'Permintaan perpanjangan telah dikirim! Menunggu persetujuan admin.'); } public function setujuiPerpanjangan($id) { $transaction = BorrowTransaction::findOrFail($id); if ($transaction->status !== 'perpanjangan_menunggu') { return back()->with('error', 'Status transaksi tidak valid.'); } $transaction->tanggal_kembali = Carbon::parse($transaction->tanggal_kembali)->addDays(7); $transaction->status = 'dipinjam'; $transaction->perpanjangan_disetujui = true; $transaction->save(); return back()->with('success', 'Perpanjangan berhasil disetujui (7 hari).'); } public function tolakPerpanjangan($id) { $transaction = BorrowTransaction::findOrFail($id); if ($transaction->status !== 'perpanjangan_menunggu') { return back()->with('error', 'Status transaksi tidak valid.'); } $transaction->status = 'dipinjam'; $transaction->perpanjangan_disetujui = false; $transaction->save(); return back()->with('success', 'Permintaan perpanjangan ditolak.'); } public function penilaian($id) { $transaction = BorrowTransaction::findOrFail($id); if ($transaction->status !== 'dikembalikan') { return redirect()->route('user.peminjaman.index') ->with('error', 'Pengembalian belum disetujui admin.'); } return view('user.rating.form', compact('transaction')); } public function simpanPenilaian(Request $request, $id) { $transaction = BorrowTransaction::findOrFail($id); $request->validate([ 'rating' => 'required|integer|min:1|max:5', 'feedback' => 'nullable|string|max:500', ]); Rating::create([ 'user_id' => Auth::id(), 'borrow_transaction_id' => $transaction->id, 'rating' => $request->rating, 'feedback' => $request->feedback, ]); return redirect()->route('user.peminjaman.index') ->with('success', 'Terima kasih atas penilaian Anda!'); } public function downloadSuratPengantar($id) { $transaction = BorrowTransaction::findOrFail($id); if (!$transaction->surat_pengantar) { return back()->with('error', 'Surat pengantar tidak ditemukan.'); } $path = 'public/surat_pengantar/' . $transaction->surat_pengantar; if (!Storage::exists($path)) { return back()->with('error', 'File surat pengantar tidak ditemukan di server.'); } return Storage::download($path); } }