HEX
Server: Apache/2.4.58 (Ubuntu)
System: Linux ip-172-26-0-120 6.17.0-1009-aws #9~24.04.2-Ubuntu SMP Fri Mar 6 23:50:29 UTC 2026 x86_64
User: ubuntu (1000)
PHP: 8.3.6
Disabled: NONE
Upload Files
File: /var/www/html/dashboard.orbiwheels.com/app/Http/Controllers/Api/Customer/BookingController.php
<?php

namespace App\Http\Controllers\Api\Customer;

use App\Http\Controllers\Controller;
use App\Http\Resources\BookingResource;
use App\Mail\BookingEnquiryMail;
use App\Mail\UserBookingEnquiryMail;
use App\Models\Booking;
use App\Models\BookingEnquiry;
use App\Models\RideRequest;
use App\Models\Transporter;
use App\Models\Trip;
use App\Models\VehicleType;
use App\Services\FirebaseService;
use Illuminate\Http\Request;
use Illuminate\Validation\ValidationException;
use Kreait\Firebase\Factory;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\Mail;

class BookingController extends Controller
{

    public function oldcreateBooking(Request $request)
    {
        try {
            $validator = Validator::make($request->all(), [
                'ride_type'     => 'required|in:1,2,3,4,5',
                'booking_type'  => 'required|in:1,2',
                'dates.from_date' => 'required|date',
                'dates.to_date'   => 'required|date|after_or_equal:dates.from_date',
                'trips'                  => 'required|array|min:1',
                'trips.*.vehicle_type'   => 'required|integer',
                'trips.*.quantity'       => 'required|integer|min:1',
                'trips.*.pickup_location' => 'required|string|max:255',
                'trips.*.pickup_lat'     => 'required|numeric',
                'trips.*.pickup_lng'     => 'required|numeric',
                'trips.*.drop_location'  => 'required|string|max:255',
                'trips.*.drop_lat'       => 'required|numeric',
                'trips.*.drop_lng'       => 'required|numeric',
                'trips.*.pickup_time'    => 'required|date_format:H:i',
                'trips.*.return_time'    => 'nullable|date_format:H:i|required_if:booking_type,2',
            ]);
            if ($validator->fails()) {
                return response()->json([
                    'status' => false,
                    'errors' => $validator->errors()
                ], 422);
            }
            // dd($request->all());
            $booking = Booking::create([
                'customer_id'         => auth()->user()->id,
                'ride_type'           => $request->ride_type,
                'booking_type'        => $request->booking_type,
                'no_of_passengers'    => $request->no_of_passengers ?? 1,
                'dates'               => $request->dates,
                'times'               => $request->times,
                'status'              => Booking::PENDING,
                'total_customer_amount' => 0,
            ]);

            $fromDate = Carbon::parse($request->dates['from_date']);
            $toDate   = Carbon::parse($request->dates['to_date']);
            $total_customer_amount = 0;

            foreach ($request->trips as $trip) {
                $vehicle_type = VehicleType::findOrFail($trip['vehicle_type']);
                $distance_km = getDistance(
                    $trip['pickup_lat'],
                    $trip['pickup_lng'],
                    $trip['drop_lat'],
                    $trip['drop_lng']
                );

                $fare       = getFare($distance_km, $vehicle_type, "city");
                $commission = getCommission($distance_km);
                $gst        = get_gst_on_commission($commission);


                for ($date = $fromDate->copy(); $date->lte($toDate); $date->addDay()) {

                    for ($i = 1; $i <= $trip['quantity']; $i++) {
                        // Create onward ride
                        $booking->rides()->create([
                            'vehicle_type_id'       => $vehicle_type->id,
                            'locations'             => [
                                'pickup_location' => $trip['pickup_location'],
                                'pickup_lat'      => $trip['pickup_lat'],
                                'pickup_lng'      => $trip['pickup_lng'],
                                'drop_location'   => $trip['drop_location'],
                                'drop_lat'        => $trip['drop_lat'],
                                'drop_lng'        => $trip['drop_lng'],
                            ],
                            'ride_date'             => $date->format('Y-m-d'),
                            'pickup_time'           => $trip['pickup_time'],
                            'ride_slot'             => getTimeSlot($trip['pickup_time']),
                            'distance_km'           => $distance_km,
                            'fare'                  => $fare,
                            'ride_commission'       => $commission,
                            'gst_on_commission'     => $gst,
                            'total_customer_amount' => $fare + $commission + $gst,
                        ]);

                        $total_customer_amount += ($fare + $commission + $gst);

                        // Create return ride if booking_type = 2
                        if ($request->booking_type == 2) {
                            $booking->rides()->create([
                                'vehicle_type_id'       => $vehicle_type->id,
                                'locations'             => [
                                    'pickup_location' => $trip['drop_location'],
                                    'pickup_lat'      => $trip['drop_lat'],
                                    'pickup_lng'      => $trip['drop_lng'],
                                    'drop_location'   => $trip['pickup_location'],
                                    'drop_lat'        => $trip['pickup_lat'],
                                    'drop_lng'        => $trip['pickup_lng'],
                                ],
                                'ride_date'             => $date->format('Y-m-d'),
                                'pickup_time'           => $trip['return_time'],
                                'ride_slot'             => getTimeSlot($trip['return_time']),
                                'distance_km'           => $distance_km,
                                'fare'                  => $fare,
                                'ride_commission'       => $commission,
                                'gst_on_commission'     => $gst,
                                'total_customer_amount' => $fare + $commission + $gst,
                            ]);

                            $total_customer_amount += ($fare + $commission + $gst);
                        }
                    }
                }
            }
            $rides = $booking->rides;
            $booking->update([
                'base_rate_per_km'      => $rides->sum('fare'),              // total base fare
                'commission_per_km'     => $rides->sum('ride_commission'),   // total commission
                'gst_on_commission'     => $rides->sum('gst_on_commission'), // total gst
                'total_customer_amount' => $total_customer_amount,
            ]);

            return response()->json([
                'status' => true,
                'message' => 'Booking created successfully!',
                'booking' => new BookingResource($booking)
            ]);
        } catch (\Exception $e) {
            return response()->json(['status' => false, 'error' => $e->getMessage()], 500);
        }
    }
    public function createBooking(Request $request)
    {
        try {
            $validator = Validator::make($request->all(), [
                'ride_type'     => 'required|in:1,2,3,4,5',
                'booking_type'  => 'required|in:1,2',
                'trips'                  => 'required|array|min:1',
                'trips.*.vehicle_type'   => 'required|integer|exists:vehicle_types,id',
                'trips.*.pickup_location' => 'required|string|max:255',
                'trips.*.pickup_lat'     => 'required|numeric',
                'trips.*.pickup_lng'     => 'required|numeric',
                'trips.*.drop_location'  => 'required|string|max:255',
                'trips.*.drop_lat'       => 'required|numeric',
                'trips.*.drop_lng'       => 'required|numeric',
                'trips.*.pickup_time'    => 'required|date_format:H:i',
                'trips.*.return_time'    => 'nullable|date_format:H:i|required_if:booking_type,2',
                'trips.*.dates'          => 'required|array|min:1',
            ]);

            if ($validator->fails()) {
                return response()->json([
                    'status' => false,
                    'errors' => $validator->errors()
                ], 422);
            }

            // STEP 1: Create booking
            $booking = Booking::create([
                'customer_id'         => auth()->user()->id,
                'ride_type'           => $request->ride_type,
                'booking_type'        => $request->booking_type,
                'no_of_passengers'    => $request->no_of_passengers ?? 1,
                'status'              => Booking::PENDING,
                'total_customer_amount' => 0,
            ]);

            $total_customer_amount = 0;

            // STEP 2: Create trips under booking
            foreach ($request->trips as $tripData) {
                $vehicleType = VehicleType::findOrFail($tripData['vehicle_type']);
                $distance_km = getDistance(
                    $tripData['pickup_lat'],
                    $tripData['pickup_lng'],
                    $tripData['drop_lat'],
                    $tripData['drop_lng']
                );

                $fare       = getFare($distance_km, $vehicleType, "city");
                $commission = getCommission($distance_km);
                $gst        = get_gst_on_commission($commission);

                // Save trip
                $trip = Trip::create([
                    'booking_id'     => $booking->id,
                    'vehicle_type_id' => $vehicleType->id,
                    'ride_type'      => $request->ride_type,
                    'booking_type'   => $request->booking_type,
                    'dates'          => $tripData['dates'],
                    'times'          => [
                        'pickup_time' => $tripData['pickup_time'],
                        'return_time' => $tripData['return_time'] ?? null,
                    ],
                    'locations'      => [
                        'pickup_location' => $tripData['pickup_location'],
                        'pickup_lat'      => $tripData['pickup_lat'],
                        'pickup_lng'      => $tripData['pickup_lng'],
                        'drop_location'   => $tripData['drop_location'],
                        'drop_lat'        => $tripData['drop_lat'],
                        'drop_lng'        => $tripData['drop_lng'],
                    ],
                    'pricing_details' => [],
                    'distance_km'    => $distance_km,
                    'status'         => '0',
                ]);
                $totalFare = 0;
                $totalCommission = 0;
                $totalGst = 0;
                $totalAmount = 0;
                // STEP 3: Create rides for each date
                foreach ($tripData['dates'] as $date) {
                    $onward = $booking->rides()->create([
                        'trip_id'               => $trip->id,
                        'vehicle_type_id'       => $vehicleType->id,
                        'locations'             => [
                            'pickup_location' => $tripData['pickup_location'],
                            'pickup_lat'      => $tripData['pickup_lat'],
                            'pickup_lng'      => $tripData['pickup_lng'],
                            'drop_location'   => $tripData['drop_location'],
                            'drop_lat'        => $tripData['drop_lat'],
                            'drop_lng'        => $tripData['drop_lng'],
                        ],
                        'ride_date'             => $date,
                        'pickup_time'           => $tripData['pickup_time'],
                        'ride_slot'             => getTimeSlot($tripData['pickup_time']),
                        'distance_km'           => $distance_km,
                        'fare'                  => $fare,
                        'ride_commission'       => $commission,
                        'gst_on_commission'     => $gst,
                        'total_customer_amount' => $fare + $commission + $gst,
                    ]);

                    $totalFare       += $fare;
                    $totalCommission += $commission;
                    $totalGst        += $gst;
                    $totalAmount     += ($fare + $commission + $gst);

                    // Return ride (if booking_type = 2)
                    if ($request->booking_type == 2 && !empty($tripData['return_time'])) {
                        $return = $booking->rides()->create([
                            'trip_id'               => $trip->id,
                            'vehicle_type_id'       => $vehicleType->id,
                            'locations'             => [
                                'pickup_location' => $tripData['drop_location'],
                                'pickup_lat'      => $tripData['drop_lat'],
                                'pickup_lng'      => $tripData['drop_lng'],
                                'drop_location'   => $tripData['pickup_location'],
                                'drop_lat'        => $tripData['pickup_lat'],
                                'drop_lng'        => $tripData['pickup_lng'],
                            ],
                            'ride_date'             => $date,
                            'pickup_time'           => $tripData['return_time'],
                            'ride_slot'             => getTimeSlot($tripData['return_time']),
                            'distance_km'           => $distance_km,
                            'fare'                  => $fare,
                            'ride_commission'       => $commission,
                            'gst_on_commission'     => $gst,
                            'total_customer_amount' => $fare + $commission + $gst,
                        ]);

                        $totalFare       += $fare;
                        $totalCommission += $commission;
                        $totalGst        += $gst;
                        $totalAmount     += ($fare + $commission + $gst);
                    }
                }

                // rides ke totals Trip ke andar save karo
                $trip->update([
                    'pricing_details' => [
                        'fare'         => $totalFare,
                        'commission'   => $totalCommission,
                        'gst'          => $totalGst,
                        'total_amount' => $totalAmount,
                    ]
                ]);
            }
            // STEP 4: Update booking totals
            // $rides = $booking->rides;
            // $booking->update([
            //     'base_rate_per_km'      => $rides->sum('fare'),
            //     'commission_per_km'     => $rides->sum('ride_commission'),
            //     'gst_on_commission'     => $rides->sum('gst_on_commission'),
            //     'total_customer_amount' => $total_customer_amount,
            // ]);

            return response()->json([
                'status' => true,
                'message' => 'Booking created successfully!',
                'booking' => new BookingResource($booking)
            ]);
        } catch (\Exception $e) {
            return response()->json(['status' => false, 'error' => $e->getMessage()], 500);
        }
    }

    public function confirmBooking(Request $request, $id)
    {
        try {
            $booking = Booking::findOrFail($id);

            foreach ($booking->trips as $trip) {
                $transporters = Transporter::where('status', Transporter::APPROVED)
                    ->where('mode', 1)
                    ->whereJsonContains('ride_permissions', $booking->ride_type)
                    ->get();

                foreach ($transporters as $transporter) {
                    RideRequest::create([
                        'booking_id'    => $booking->id,
                        'trip_id'       => $trip->id,
                        'transporter_id' => $transporter->id,
                        'status'        => RideRequest::PENDING,
                    ]);

                    // Optional: Push request to Firebase
                    // $service->pushRequest($transporter, $booking, $ride);
                }
            }

            // Update booking status
            $booking->update(['status' => Booking::REQUESTED]);

            return response()->json([
                'status'  => true,
                'message' => 'Booking requested successfully! Ride requests sent to transporters.',
                'booking' => $booking
            ]);
        } catch (ModelNotFoundException $e) {
            return response()->json(['status' => false, 'error' => 'Booking not found'], 404);
        } catch (\Exception $e) {
            return response()->json(['status' => false, 'error' => $e->getMessage()], 500);
        }
    }
    public function draftBooking(Request $request, $id)
    {
        try {
            $booking = Booking::findOrFail($id);

            $validator = Validator::make($request->all(), [
                'is_draft' => 'required|boolean',
            ]);

            if ($validator->fails()) {
                return response()->json([
                    'status' => false,
                    'errors' => $validator->errors()
                ], 422);
            }

            $booking->update([
                'is_draft' => $request->is_draft,
            ]);

            return response()->json([
                'status'  => true,
                'message' => $request->is_draft
                    ? 'Booking saved as draft successfully!'
                    : 'Booking removed from draft!',
                'booking' => $booking
            ]);
        } catch (ModelNotFoundException $e) {
            return response()->json(['status' => false, 'error' => 'Booking not found'], 404);
        } catch (\Exception $e) {
            return response()->json(['status' => false, 'error' => $e->getMessage()], 500);
        }
    }
    public function booking_enquiry_store(Request $request)
    {
        try {
            $validator = Validator::make($request->all(), [
                'name'               => 'required|string|max:255',
                'email'              => 'required|email|max:255',
                'phone'              => 'required|string|max:20',
                'pick_up_location'   => 'required|string|max:255',
                'drop_up_location'   => 'required|string|max:255',
                'pick_up_date'       => 'required|date',
                'pick_up_time'       => 'required',
                'vehicle_preference' => 'required|string|max:255',
                'details'            => 'required|string|min:5',
            ]);

            if ($validator->fails()) {
                return response()->json([
                    'status' => 'error',
                    'errors' => $validator->errors()
                ], 422);
            }

            $enquiry = BookingEnquiry::create($request->all());

            try {
                Mail::to(config('mail.from.address'))
                    ->send(new BookingEnquiryMail($enquiry));

                Mail::to($enquiry->email)
                    ->send(new UserBookingEnquiryMail($enquiry));
            } catch (\Exception $mailException) {
                Log::error('Booking enquiry mail failed', [
                    'error'   => $mailException->getMessage(),
                    'enquiry' => $enquiry->id,
                ]);
            }

            return response()->json([
                'status'  => 'success',
                'message' => 'Booking enquiry submitted successfully!',
                'data'    => $enquiry
            ]);
        } catch (\Exception $e) {

            Log::error('Booking enquiry store error', [
                "message" => $e->getMessage()
            ]);

            return response()->json([
                'status'  => 'error',
                'message' => 'Something went wrong!'
            ], 500);
        }
    }
}