Initial commit - Car Rental Management System

This commit is contained in:
Innovator committed 2026-02-19 22:05:20 +00:00
commit f72173377a
100 files changed
+15201

No files matched your search

+73
View File
@@ -0,0 +1,73 @@
<?php
namespace App\Http\Controllers;
use App\Models\Car;
use Illuminate\Http\Request;
class CarController extends Controller
{
public function index()
{
$cars = Car::all();
return view('cars.index', compact('cars'));
}
public function create()
{
return view('cars.create');
}
public function store(Request $request)
{
$request->validate([
'brand' => 'required',
'model' => 'required',
'year' => 'required',
'license_plate' => 'required|unique:cars',
'color' => 'required',
'daily_rate' => 'required|numeric'
]);
Car::create($request->all());
return redirect()->route('cars.index')->with('success', 'Car added successfully!');
}
public function show(Car $car)
{
$car->load('rentals', 'services');
return view('cars.show', compact('car'));
}
public function edit(Car $car)
{
return view('cars.edit', compact('car'));
}
public function update(Request $request, Car $car)
{
$request->validate([
'brand' => 'required',
'model' => 'required',
'year' => 'required',
'license_plate' => 'required|unique:cars,license_plate,' . $car->id,
'color' => 'required',
'daily_rate' => 'required|numeric'
]);
$car->update($request->all());
return redirect()->route('cars.index')->with('success', 'Car updated successfully!');
}
public function destroy(Car $car)
{
$car->delete();
return redirect()->route('cars.index')->with('success', 'Car deleted successfully!');
}
public function updateStatus(Request $request, Car $car, $status)
{
$car->update(['status' => $status]);
return redirect()->back()->with('success', 'Status updated!');
}
}
+8
View File
@@ -0,0 +1,8 @@
<?php
namespace App\Http\Controllers;
abstract class Controller
{
//
}
@@ -0,0 +1,75 @@
<?php
namespace App\Http\Controllers;
use App\Models\Customer;
use Illuminate\Http\Request;
class CustomerController extends Controller
{
public function index()
{
$customers = Customer::all();
return view('customers.index', compact('customers'));
}
public function create()
{
return view('customers.create');
}
public function store(Request $request)
{
$request->validate([
'name' => 'required',
'email' => 'required|email|unique:customers',
'phone' => 'required',
'address' => 'required',
'license_number' => 'required',
'license_expiry' => 'required|date',
'dob' => 'required|date'
]);
$customer = Customer::create($request->all());
// If AJAX request, return JSON
if ($request->expectsJson()) {
return response()->json(['id' => $customer->id, 'name' => $customer->name]);
}
return redirect()->route('customers.index')->with('success', 'Customer added successfully!');
}
public function show(Customer $customer)
{
$customer->load('rentals');
return view('customers.show', compact('customer'));
}
public function edit(Customer $customer)
{
return view('customers.edit', compact('customer'));
}
public function update(Request $request, Customer $customer)
{
$request->validate([
'name' => 'required',
'email' => 'required|email|unique:customers,email,' . $customer->id,
'phone' => 'required',
'address' => 'required',
'license_number' => 'required',
'license_expiry' => 'required|date',
'dob' => 'required|date'
]);
$customer->update($request->all());
return redirect()->route('customers.index')->with('success', 'Customer updated successfully!');
}
public function destroy(Customer $customer)
{
$customer->delete();
return redirect()->route('customers.index')->with('success', 'Customer deleted successfully!');
}
}
@@ -0,0 +1,97 @@
<?php
namespace App\Http\Controllers;
use App\Models\Car;
use App\Models\Customer;
use App\Models\Rental;
use App\Models\Service;
use App\Models\Payment;
use Carbon\Carbon;
class DashboardController extends Controller
{
public function index()
{
// Basic stats
$totalCars = Car::count();
$availableCars = Car::where('status', 'available')->count();
$rentedCars = Car::where('status', 'rented')->count();
$maintenanceCars = Car::where('status', 'maintenance')->count();
$totalCustomers = Customer::count();
$activeCustomers = Customer::where('status', 'active')->count();
$totalRentals = Rental::count();
$activeRentals = Rental::where('status', 'active')->count();
$pendingRentals = Rental::where('status', 'pending')->count();
// Revenue stats
$totalRevenue = Payment::where('status', 'completed')->sum('amount');
$monthlyRevenue = Payment::where('status', 'completed')
->whereMonth('created_at', Carbon::now()->month)
->sum('amount');
// Service stats
$totalServices = Service::count();
$totalServiceCost = Service::sum('cost');
$pendingServices = Service::where('status', '!=', 'completed')->count();
// Recent data
$recentRentals = Rental::with(['car', 'customer'])->latest()->take(5)->get();
$recentServices = Service::with('car')->latest()->take(5)->get();
// Chart data - rentals per month (last 6 months)
$monthlyRentals = [];
$monthlyRevenueChart = [];
for ($i = 5; $i >= 0; $i--) {
$month = Carbon::now()->subMonths($i);
$monthlyRentals[] = Rental::whereMonth('created_at', $month->month)
->whereYear('created_at', $month->year)
->count();
$monthlyRevenueChart[] = Payment::where('status', 'completed')
->whereMonth('created_at', $month->month)
->whereYear('created_at', $month->year)
->sum('amount');
}
// Car status distribution for pie chart
$carStatusData = [
'available' => Car::where('status', 'available')->count(),
'rented' => Car::where('status', 'rented')->count(),
'maintenance' => Car::where('status', 'maintenance')->count(),
];
// Cars grouped by status for modal
$carsByStatus = [
'available' => Car::where('status', 'available')->get(),
'rented' => Car::where('status', 'rented')->get(),
'maintenance' => Car::where('status', 'maintenance')->get(),
];
// Top rented cars
$topCars = Rental::select('car_id')
->groupBy('car_id')
->orderByRaw('COUNT(*) DESC')
->take(5)
->get()
->map(function ($rental) {
$car = Car::find($rental->car_id);
$count = Rental::where('car_id', $rental->car_id)->count();
return [
'car' => $car,
'rentals_count' => $count
];
});
return view('dashboard', compact(
'totalCars', 'availableCars', 'rentedCars', 'maintenanceCars',
'totalCustomers', 'activeCustomers',
'totalRentals', 'activeRentals', 'pendingRentals',
'totalRevenue', 'monthlyRevenue',
'totalServices', 'totalServiceCost', 'pendingServices',
'recentRentals', 'recentServices',
'monthlyRentals', 'monthlyRevenueChart', 'carStatusData', 'carsByStatus', 'topCars'
));
}
}
@@ -0,0 +1,66 @@
<?php
namespace App\Http\Controllers;
use App\Models\Payment;
use App\Models\Rental;
use Illuminate\Http\Request;
class PaymentController extends Controller
{
public function index()
{
$payments = Payment::with('rental')->get();
return view('payments.index', compact('payments'));
}
public function create()
{
$rentals = Rental::all();
return view('payments.create', compact('rentals'));
}
public function store(Request $request)
{
$request->validate([
'rental_id' => 'required',
'amount' => 'required|numeric',
'method' => 'required',
'status' => 'required'
]);
Payment::create($request->all());
return redirect()->route('payments.index')->with('success', 'Payment recorded successfully!');
}
public function show(Payment $payment)
{
$payment->load('rental');
return view('payments.show', compact('payment'));
}
public function edit(Payment $payment)
{
$rentals = Rental::all();
return view('payments.edit', compact('payment', 'rentals'));
}
public function update(Request $request, Payment $payment)
{
$request->validate([
'rental_id' => 'required',
'amount' => 'required|numeric',
'method' => 'required',
'status' => 'required'
]);
$payment->update($request->all());
return redirect()->route('payments.index')->with('success', 'Payment updated successfully!');
}
public function destroy(Payment $payment)
{
$payment->delete();
return redirect()->route('payments.index')->with('success', 'Payment deleted successfully!');
}
}
@@ -0,0 +1,91 @@
<?php
namespace App\Http\Controllers;
use App\Models\Car;
use App\Models\Customer;
use App\Models\Rental;
use App\Models\Payment;
use Illuminate\Http\Request;
use PDF;
use Carbon\Carbon;
class QuickRentalController extends Controller
{
public function getCustomers()
{
$customers = Customer::where('status', 'active')->get(['id', 'name', 'email', 'phone', 'license_number']);
return response()->json($customers);
}
public function getCars()
{
$cars = Car::where('status', 'available')->get();
return response()->json($cars);
}
public function store(Request $request)
{
// Validate the request
$request->validate([
'customer_id' => 'required',
'car_id' => 'required',
'rental_type' => 'required',
'start_date' => 'required|date',
'end_date' => 'required|date|after:start_date',
'total_amount' => 'required|numeric',
'advance_payment' => 'nullable|numeric',
]);
// Create rental
$rental = Rental::create([
'customer_id' => $request->customer_id,
'car_id' => $request->car_id,
'rental_type' => $request->rental_type,
'start_date' => $request->start_date,
'pickup_time' => $request->pickup_time,
'end_date' => $request->end_date,
'return_time' => $request->return_time,
'total_amount' => $request->total_amount,
'advance_payment' => $request->advance_payment ?? 0,
'status' => 'active',
'notes' => $request->notes,
'customer_signature' => $request->customer_signature,
]);
// Update car status
Car::find($request->car_id)->update(['status' => 'rented']);
// Create advance payment if paid
if ($request->advance_payment > 0) {
Payment::create([
'rental_id' => $rental->id,
'amount' => $request->advance_payment,
'method' => $request->payment_method ?? 'cash',
'status' => 'completed',
]);
}
return response()->json([
'success' => true,
'rental_id' => $rental->id,
]);
}
public function generateContract($rentalId)
{
$rental = Rental::with(['car', 'customer', 'payments'])->findOrFail($rentalId);
$pdf = PDF::loadView('contracts.rental', [
'rental' => $rental,
'company' => [
'name' => 'On The Road',
'address' => 'Manama, Bahrain',
'phone' => '+973-00000000',
'email' => '[email protected]',
]
]);
return $pdf->download('rental-contract-' . $rental->id . '.pdf');
}
}
+121
View File
@@ -0,0 +1,121 @@
<?php
namespace App\Http\Controllers;
use App\Models\Car;
use App\Models\Customer;
use App\Models\Rental;
use App\Models\Payment;
use Illuminate\Http\Request;
use Carbon\Carbon;
class RentalController extends Controller
{
public function index()
{
$rentals = Rental::with(['car', 'customer'])->get();
return view('rentals.index', compact('rentals'));
}
public function create()
{
$cars = Car::where('status', 'available')->get();
$customers = Customer::where('status', 'active')->get();
return view('rentals.create', compact('cars', 'customers'));
}
public function store(Request $request)
{
$request->validate([
'car_id' => 'required',
'customer_id' => 'required',
'rental_type' => 'required',
'start_date' => 'required|date',
'pickup_time' => 'nullable',
'end_date' => 'required|date|after:start_date',
'return_time' => 'nullable',
'total_amount' => 'required|numeric',
'advance_payment' => 'nullable|numeric'
]);
$rental = Rental::create($request->all());
// Update car status
Car::find($request->car_id)->update(['status' => 'rented']);
// Create payment if advance is paid
if ($request->advance_payment > 0) {
Payment::create([
'rental_id' => $rental->id,
'amount' => $request->advance_payment,
'method' => 'cash',
'status' => 'completed'
]);
}
return redirect()->route('rentals.index')->with('success', 'Rental created successfully!');
}
public function show(Rental $rental)
{
$rental->load(['car', 'customer', 'payments']);
return view('rentals.show', compact('rental'));
}
public function edit(Rental $rental)
{
$cars = Car::all();
$customers = Customer::all();
return view('rentals.edit', compact('rental', 'cars', 'customers'));
}
public function update(Request $request, Rental $rental)
{
$request->validate([
'car_id' => 'required',
'customer_id' => 'required',
'rental_type' => 'required',
'start_date' => 'required|date',
'end_date' => 'required|date|after:start_date',
'total_amount' => 'required|numeric'
]);
$rental->update($request->all());
return redirect()->route('rentals.index')->with('success', 'Rental updated successfully!');
}
public function destroy(Rental $rental)
{
// Reset car status
Car::find($rental->car_id)->update(['status' => 'available']);
$rental->delete();
return redirect()->route('rentals.index')->with('success', 'Rental deleted successfully!');
}
public function updateStatus(Request $request, Rental $rental, $status)
{
$rental->update(['status' => $status]);
if ($status == 'completed' || $status == 'cancelled') {
Car::find($rental->car_id)->update(['status' => 'available']);
} elseif ($status == 'active') {
Car::find($rental->car_id)->update(['status' => 'rented']);
}
return redirect()->back()->with('success', 'Status updated!');
}
public function contract(Rental $rental)
{
$rental->load(['car', 'customer']);
return view('contracts.rental', compact('rental'));
}
public function downloadContract(Rental $rental)
{
$rental->load(['car', 'customer']);
$pdf = \PDF::loadView('contracts.rental', compact('rental'));
return $pdf->download('contract-' . str_pad($rental->id, 6, '0', STR_PAD_LEFT) . '.pdf');
}
}
@@ -0,0 +1,74 @@
<?php
namespace App\Http\Controllers;
use App\Models\Car;
use App\Models\Service;
use Illuminate\Http\Request;
class ServiceController extends Controller
{
public function index()
{
$services = Service::with('car')->get();
return view('services.index', compact('services'));
}
public function create()
{
$cars = Car::all();
return view('services.create', compact('cars'));
}
public function store(Request $request)
{
$request->validate([
'car_id' => 'required',
'type' => 'required',
'description' => 'required',
'cost' => 'required|numeric',
'service_date' => 'required|date'
]);
Service::create($request->all());
// If it's a maintenance service, update car status
if ($request->type == 'repair') {
Car::find($request->car_id)->update(['status' => 'maintenance']);
}
return redirect()->route('services.index')->with('success', 'Service recorded successfully!');
}
public function show(Service $service)
{
$service->load('car');
return view('services.show', compact('service'));
}
public function edit(Service $service)
{
$cars = Car::all();
return view('services.edit', compact('service', 'cars'));
}
public function update(Request $request, Service $service)
{
$request->validate([
'car_id' => 'required',
'type' => 'required',
'description' => 'required',
'cost' => 'required|numeric',
'service_date' => 'required|date'
]);
$service->update($request->all());
return redirect()->route('services.index')->with('success', 'Service updated successfully!');
}
public function destroy(Service $service)
{
$service->delete();
return redirect()->route('services.index')->with('success', 'Service deleted successfully!');
}
}
@@ -0,0 +1,82 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Artisan;
class SettingsController extends Controller
{
public function index()
{
$settings = config('settings');
return view('settings.index', compact('settings'));
}
public function update(Request $request)
{
$request->validate([
'company_name' => 'required|string|max:100',
'company_tagline' => 'nullable|string|max:200',
'phone' => 'nullable|string|max:50',
'email' => 'nullable|email|max:100',
'address' => 'nullable|string|max:200',
]);
$config = [
'company_name' => $request->company_name,
'company_tagline' => $request->company_tagline ?? 'Car Rental Management System',
'logo' => config('settings.logo'),
'phone' => $request->phone ?? '',
'email' => $request->email ?? '',
'address' => $request->address ?? '',
];
$configContent = "<?php\n\nreturn [\n";
foreach ($config as $key => $value) {
$configContent .= " '$key' => " . var_export($value, true) . ",\n";
}
$configContent .= "];\n";
File::put(config_path('settings.php'), $configContent);
// Clear config cache
Artisan::call('config:clear');
return redirect()->route('settings.index')->with('success', 'Settings updated successfully!');
}
public function uploadLogo(Request $request)
{
$request->validate([
'logo' => 'required|image|mimes:png,jpg,jpeg,gif,svg|max:2048',
]);
$file = $request->file('logo');
$filename = 'logo.' . $file->getClientOriginalExtension();
// Delete old logo
$oldLogo = public_path(config('settings.logo'));
if (File::exists($oldLogo) && strpos(config('settings.logo'), 'logo.') !== false) {
File::delete($oldLogo);
}
$file->move(public_path('/uploads'), $filename);
// Update config
$config = config('settings');
$config['logo'] = '/uploads/' . $filename;
$configContent = "<?php\n\nreturn [\n";
foreach ($config as $key => $value) {
$configContent .= " '$key' => " . var_export($value, true) . ",\n";
}
$configContent .= "];\n";
File::put(config_path('settings.php'), $configContent);
Artisan::call('config:clear');
return redirect()->route('settings.index')->with('success', 'Logo uploaded successfully!');
}
}