getRentalCompany(); if (!$rentalCompany) { return redirect() ->route('admin-rental.dashboard') ->with('error', 'Akun admin rental ini belum memiliki rental company.'); } $bookings = Booking::query() ->with(['customer', 'vehicle', 'payment']) ->where('rental_company_id', $rentalCompany->id) ->whereHas('payment') // Exclude bookings that have been cancelled so payments won't show for cancelled bookings ->where('booking_status', '!=', Booking::BOOKING_CANCELLED) ->latest('id') ->paginate(10); return view('admin-rental.payments.index', compact('bookings', 'rentalCompany')); } public function show(Booking $booking): View|RedirectResponse { $rentalCompany = $this->getRentalCompany(); if (!$rentalCompany) { return redirect() ->route('admin-rental.dashboard') ->with('error', 'Akun admin rental ini belum memiliki rental company.'); } $this->ensureBookingBelongsToRental($booking, $rentalCompany->id); $booking->load(['customer', 'vehicle.rentalCompany', 'vehicle.primaryImage', 'payment']); return view('admin-rental.payments.show', compact('booking', 'rentalCompany')); } public function verify(Booking $booking): RedirectResponse { $rentalCompany = $this->getRentalCompany(); if (!$rentalCompany) { return redirect() ->route('admin-rental.dashboard') ->with('error', 'Akun admin rental ini belum memiliki rental company.'); } $this->ensureBookingBelongsToRental($booking, $rentalCompany->id); $booking->load('payment'); if (!$booking->payment || $booking->payment->payment_status !== Payment::STATUS_UPLOADED) { return back()->with('error', 'Pembayaran harus berstatus uploaded sebelum diverifikasi.'); } DB::transaction(function () use ($booking): void { $booking->payment->update([ 'payment_status' => Payment::STATUS_VERIFIED, 'verified_by' => Auth::id(), 'verified_at' => now(), 'rejection_note' => null, ]); $booking->update([ 'payment_status' => Booking::PAYMENT_VERIFIED, 'booking_status' => Booking::BOOKING_CONFIRMED, ]); $this->notificationService->notifyUser( userId: (int) $booking->customer_id, title: 'Pembayaran Diverifikasi', message: 'Bukti pembayaran untuk booking ' . $booking->booking_code . ' telah diverifikasi. Booking Anda dikonfirmasi.', type: 'success', url: route('customer.bookings.show', $booking), referenceType: 'booking', referenceId: $booking->id, ); $this->activityLogService->log( action: 'payment.verified', description: 'Admin rental memverifikasi pembayaran booking: ' . $booking->booking_code, targetType: 'payment', targetId: $booking->payment->id, meta: ['booking_id' => $booking->id, 'amount' => $booking->payment->amount] ); }); return back()->with('success', 'Pembayaran berhasil diverifikasi.'); } public function reject(RejectPaymentRequest $request, Booking $booking): RedirectResponse { $rentalCompany = $this->getRentalCompany(); if (!$rentalCompany) { return redirect() ->route('admin-rental.dashboard') ->with('error', 'Akun admin rental ini belum memiliki rental company.'); } $this->ensureBookingBelongsToRental($booking, $rentalCompany->id); $booking->load('payment'); if (!$booking->payment || $booking->payment->payment_status !== Payment::STATUS_UPLOADED) { return back()->with('error', 'Pembayaran harus berstatus uploaded sebelum ditolak.'); } $validated = $request->validated(); DB::transaction(function () use ($booking, $validated): void { $booking->payment->update([ 'payment_status' => Payment::STATUS_REJECTED, 'rejection_note' => $validated['rejection_note'], ]); $booking->update([ 'payment_status' => Booking::PAYMENT_REJECTED, 'booking_status' => Booking::BOOKING_WAITING_PAYMENT, ]); $this->notificationService->notifyUser( userId: (int) $booking->customer_id, title: 'Pembayaran Ditolak', message: 'Bukti pembayaran untuk booking ' . $booking->booking_code . ' ditolak. Alasan: ' . $validated['rejection_note'], type: 'error', url: route('customer.bookings.show', $booking), referenceType: 'booking', referenceId: $booking->id, ); $this->activityLogService->log( action: 'payment.rejected', description: 'Admin rental menolak pembayaran booking: ' . $booking->booking_code, targetType: 'payment', targetId: $booking->payment->id, meta: ['booking_id' => $booking->id, 'rejection_note' => $validated['rejection_note']] ); }); return back()->with('success', 'Pembayaran berhasil ditolak. Customer dapat upload ulang bukti pembayaran.'); } private function getRentalCompany(): ?RentalCompany { return Auth::user()?->rentalCompany; } private function ensureBookingBelongsToRental(Booking $booking, int $rentalCompanyId): void { if ((int) $booking->rental_company_id !== $rentalCompanyId) { abort(404); } } }