173 lines
6.5 KiB
PHP
173 lines
6.5 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\AdminRental;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Models\Booking;
|
|
use App\Models\RentalCompany;
|
|
use App\Models\Review;
|
|
use App\Models\User;
|
|
use App\Services\PromoService;
|
|
use Illuminate\Database\Eloquent\Builder;
|
|
use Illuminate\Http\RedirectResponse;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Auth;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\View\View;
|
|
|
|
class CustomerController extends Controller
|
|
{
|
|
public function index(Request $request): View|RedirectResponse
|
|
{
|
|
$rentalCompany = $this->getRentalCompany();
|
|
|
|
if (!$rentalCompany) {
|
|
return redirect()->route('admin-rental.dashboard')->with('error', 'Akun admin rental ini belum memiliki rental company.');
|
|
}
|
|
|
|
$this->authorize('viewAny', User::class);
|
|
|
|
$request->validate([
|
|
'search' => ['nullable', 'string', 'max:100'],
|
|
'loyal' => ['nullable', 'in:loyal,non_loyal'],
|
|
]);
|
|
|
|
$threshold = PromoService::LOYAL_COMPLETED_THRESHOLD;
|
|
$loyalCustomerIdSubQuery = Booking::query()
|
|
->select('customer_id')
|
|
->where('rental_company_id', $rentalCompany->id)
|
|
->where('booking_status', Booking::BOOKING_COMPLETED)
|
|
->groupBy('customer_id')
|
|
->havingRaw('COUNT(*) >= ?', [$threshold]);
|
|
|
|
$customers = User::query()
|
|
->whereHas('bookings', function (Builder $query) use ($rentalCompany): void {
|
|
$query->where('rental_company_id', $rentalCompany->id);
|
|
})
|
|
->withCount([
|
|
'bookings as booking_count' => function (Builder $query) use ($rentalCompany): void {
|
|
$query->where('rental_company_id', $rentalCompany->id);
|
|
},
|
|
'bookings as completed_booking_count' => function (Builder $query) use ($rentalCompany): void {
|
|
$query->where('rental_company_id', $rentalCompany->id)
|
|
->where('booking_status', Booking::BOOKING_COMPLETED);
|
|
},
|
|
])
|
|
->withSum([
|
|
'bookings as total_transaction_amount' => function (Builder $query) use ($rentalCompany): void {
|
|
$query->where('rental_company_id', $rentalCompany->id);
|
|
},
|
|
], 'total_amount')
|
|
->withMax([
|
|
'bookings as last_booking_at' => function (Builder $query) use ($rentalCompany): void {
|
|
$query->where('rental_company_id', $rentalCompany->id);
|
|
},
|
|
], 'created_at')
|
|
->withAvg([
|
|
'reviews as average_rating_given' => function (Builder $query) use ($rentalCompany): void {
|
|
$query->where('rental_company_id', $rentalCompany->id);
|
|
},
|
|
], 'rating')
|
|
->when($request->filled('search'), function (Builder $query) use ($request): void {
|
|
$search = $request->string('search')->toString();
|
|
$query->where(function (Builder $subQuery) use ($search): void {
|
|
$subQuery->where('name', 'like', '%' . $search . '%')
|
|
->orWhere('email', 'like', '%' . $search . '%');
|
|
});
|
|
})
|
|
->when($request->string('loyal')->toString() === 'loyal', function (Builder $query) use ($loyalCustomerIdSubQuery): void {
|
|
$query->whereIn('id', $loyalCustomerIdSubQuery);
|
|
})
|
|
->when($request->string('loyal')->toString() === 'non_loyal', function (Builder $query) use ($loyalCustomerIdSubQuery): void {
|
|
$query->whereNotIn('id', $loyalCustomerIdSubQuery);
|
|
})
|
|
->orderByDesc('last_booking_at')
|
|
->paginate(10)
|
|
->withQueryString();
|
|
|
|
$summary = [
|
|
'total_customers' => Booking::query()
|
|
->where('rental_company_id', $rentalCompany->id)
|
|
->distinct('customer_id')
|
|
->count('customer_id'),
|
|
'loyal_customers' => DB::query()->fromSub($loyalCustomerIdSubQuery, 'loyal_customers')->count(),
|
|
'completed_bookings' => Booking::query()
|
|
->where('rental_company_id', $rentalCompany->id)
|
|
->where('booking_status', Booking::BOOKING_COMPLETED)
|
|
->count(),
|
|
];
|
|
|
|
return view('admin-rental.customers.index', compact('customers', 'rentalCompany', 'summary', 'threshold'));
|
|
}
|
|
|
|
public function show(User $customer): View
|
|
{
|
|
$rentalCompany = $this->getRentalCompanyOrAbort();
|
|
|
|
$bookingsQuery = Booking::query()
|
|
->with(['vehicle', 'payment', 'review', 'promo'])
|
|
->where('rental_company_id', $rentalCompany->id)
|
|
->where('customer_id', $customer->id)
|
|
->latest('id');
|
|
|
|
if (!(clone $bookingsQuery)->exists()) {
|
|
abort(404);
|
|
}
|
|
|
|
$threshold = PromoService::LOYAL_COMPLETED_THRESHOLD;
|
|
$bookingCount = (clone $bookingsQuery)->count();
|
|
$completedCount = (clone $bookingsQuery)->where('booking_status', Booking::BOOKING_COMPLETED)->count();
|
|
$totalTransactionAmount = (float) ((clone $bookingsQuery)->sum('total_amount') ?? 0);
|
|
$lastBooking = (clone $bookingsQuery)->first();
|
|
$lastBookingDate = $lastBooking?->created_at;
|
|
|
|
$vehicles = (clone $bookingsQuery)
|
|
->with('vehicle')
|
|
->distinct('vehicle_id')
|
|
->get()
|
|
->pluck('vehicle')
|
|
->unique('id')
|
|
->sortBy('name');
|
|
|
|
$reviews = Review::query()
|
|
->with(['vehicle', 'booking'])
|
|
->where('rental_company_id', $rentalCompany->id)
|
|
->where('customer_id', $customer->id)
|
|
->latest('id')
|
|
->get();
|
|
|
|
$bookings = $bookingsQuery->paginate(8);
|
|
$isLoyal = $completedCount >= $threshold;
|
|
|
|
return view('admin-rental.customers.show', compact(
|
|
'customer',
|
|
'rentalCompany',
|
|
'bookings',
|
|
'bookingCount',
|
|
'completedCount',
|
|
'totalTransactionAmount',
|
|
'lastBookingDate',
|
|
'vehicles',
|
|
'reviews',
|
|
'threshold',
|
|
'isLoyal'
|
|
));
|
|
}
|
|
|
|
private function getRentalCompany(): ?RentalCompany
|
|
{
|
|
return Auth::user()?->rentalCompany;
|
|
}
|
|
|
|
private function getRentalCompanyOrAbort(): RentalCompany
|
|
{
|
|
$rentalCompany = $this->getRentalCompany();
|
|
|
|
if (!$rentalCompany) {
|
|
abort(404);
|
|
}
|
|
|
|
return $rentalCompany;
|
|
}
|
|
}
|