env('RESTAURANT_DELIVERY_ENABLED', true), /* |-------------------------------------------------------------------------- | Firebase Configuration |-------------------------------------------------------------------------- | All Firebase credentials are loaded from environment variables. | See .env.example for required variables. */ 'firebase' => [ 'enabled' => env('FIREBASE_ENABLED', false), // Firebase Credentials - Two options: // Option 1: Path to service account JSON file 'credentials_path' => env('FIREBASE_CREDENTIALS', storage_path('app/firebase/firebase_credentials.json')), // Option 2: Inline credentials (JSON string from env - useful for Heroku/Docker) 'credentials_json' => env('FIREBASE_CREDENTIALS_JSON'), // Firebase Project Settings (from Firebase Console) 'project_id' => env('FIREBASE_PROJECT_ID'), 'database_url' => env('FIREBASE_DATABASE_URL'), 'storage_bucket' => env('FIREBASE_STORAGE_BUCKET'), // Firebase Web Config (for client-side SDK - pass to frontend) 'web_config' => [ 'api_key' => env('FIREBASE_API_KEY'), 'auth_domain' => env('FIREBASE_AUTH_DOMAIN'), 'database_url' => env('FIREBASE_DATABASE_URL'), 'project_id' => env('FIREBASE_PROJECT_ID'), 'storage_bucket' => env('FIREBASE_STORAGE_BUCKET'), 'messaging_sender_id' => env('FIREBASE_MESSAGING_SENDER_ID'), 'app_id' => env('FIREBASE_APP_ID'), 'measurement_id' => env('FIREBASE_MEASUREMENT_ID'), ], // Firebase Cloud Messaging (FCM) for Push Notifications 'fcm' => [ 'server_key' => env('FIREBASE_SERVER_KEY'), 'sender_id' => env('FIREBASE_MESSAGING_SENDER_ID'), ], // Realtime Database paths (customizable via env) 'paths' => [ 'riders_location' => env('FIREBASE_PATH_RIDERS_LOCATION', 'riders/{rider_id}/live_location'), 'delivery_tracking' => env('FIREBASE_PATH_DELIVERY_TRACKING', 'deliveries/{delivery_id}/tracking'), 'rider_status' => env('FIREBASE_PATH_RIDER_STATUS', 'riders/{rider_id}/status'), 'delivery_status' => env('FIREBASE_PATH_DELIVERY_STATUS', 'deliveries/{delivery_id}/status'), 'rider_assignments' => env('FIREBASE_PATH_RIDER_ASSIGNMENTS', 'riders/{rider_id}/assignments'), ], // Location update settings 'location' => [ 'update_interval' => env('FIREBASE_LOCATION_INTERVAL', 5), // seconds 'stale_threshold' => env('FIREBASE_STALE_THRESHOLD', 30), // seconds 'offline_threshold' => env('FIREBASE_OFFLINE_THRESHOLD', 120), // seconds 'accuracy_threshold' => env('FIREBASE_ACCURACY_THRESHOLD', 50), // meters 'min_distance_change' => env('FIREBASE_MIN_DISTANCE', 10), // meters ], // Firestore collections (if using Firestore instead of Realtime DB) 'firestore' => [ 'enabled' => env('FIRESTORE_ENABLED', false), 'collections' => [ 'deliveries' => env('FIRESTORE_COLLECTION_DELIVERIES', 'deliveries'), 'riders' => env('FIRESTORE_COLLECTION_RIDERS', 'riders'), 'tracking_history' => env('FIRESTORE_COLLECTION_TRACKING', 'tracking_history'), 'ratings' => env('FIRESTORE_COLLECTION_RATINGS', 'ratings'), ], ], ], /* |-------------------------------------------------------------------------- | Maps Configuration |-------------------------------------------------------------------------- | All map API credentials are loaded from environment variables. | Google Maps: Enable APIs at https://console.cloud.google.com/ | Mapbox: Get token at https://www.mapbox.com/ */ 'maps' => [ 'enabled' => env('GOOGLE_ENABLED', false), 'provider' => env('MAPS_PROVIDER', 'google'), // google, mapbox 'google' => [ // Google Maps API Key - Enable: Maps JS, Directions, Distance Matrix, Geocoding 'api_key' => env('GOOGLE_MAPS_API_KEY'), // Server-side API Key (optional - for backend operations) 'server_api_key' => env('GOOGLE_MAPS_SERVER_KEY', env('GOOGLE_MAPS_API_KEY')), // API Features 'directions_api' => env('GOOGLE_MAPS_DIRECTIONS_API', true), 'distance_matrix_api' => env('GOOGLE_MAPS_DISTANCE_MATRIX_API', true), 'geocoding_api' => env('GOOGLE_MAPS_GEOCODING_API', true), 'places_api' => env('GOOGLE_MAPS_PLACES_API', false), // Client config (for frontend) 'client_config' => [ 'api_key' => env('GOOGLE_MAPS_API_KEY'), 'libraries' => ['places', 'geometry', 'drawing'], 'region' => env('GOOGLE_MAPS_REGION', 'BD'), 'language' => env('GOOGLE_MAPS_LANGUAGE', 'en'), ], ], 'mapbox' => [ 'access_token' => env('MAPBOX_ACCESS_TOKEN'), 'public_token' => env('MAPBOX_PUBLIC_TOKEN', env('MAPBOX_ACCESS_TOKEN')), 'directions_api' => env('MAPBOX_DIRECTIONS_API', true), 'style' => env('MAPBOX_STYLE', 'mapbox://styles/mapbox/streets-v11'), ], // Route settings 'route' => [ 'cache_duration' => env('MAPS_ROUTE_CACHE_DURATION', 300), // 5 minutes 'alternatives' => env('MAPS_ROUTE_ALTERNATIVES', true), 'traffic_model' => env('MAPS_TRAFFIC_MODEL', 'best_guess'), // best_guess, pessimistic, optimistic 'avoid' => env('MAPS_ROUTE_AVOID', ''), // tolls, highways, ferries ], ], /* |-------------------------------------------------------------------------- | Distance Configuration |-------------------------------------------------------------------------- */ 'distance' => [ 'unit' => env('RESTAURANT_DELIVERY_DISTANCE_UNIT', 'km'), // km, miles 'calculation_method' => env('RESTAURANT_DELIVERY_DISTANCE_METHOD', 'google_api'), // haversine, google_api, mapbox_api 'earth_radius_km' => 6371, 'earth_radius_miles' => 3959, ], /* |-------------------------------------------------------------------------- | Real-Time Tracking Animation |-------------------------------------------------------------------------- */ 'tracking' => [ 'animation' => [ 'enabled' => true, 'interpolation_points' => 10, // smooth animation points between updates 'animation_duration' => 1000, // ms per animation step 'easing' => 'linear', // linear, ease-in-out ], 'map' => [ 'default_zoom' => 15, 'tracking_zoom' => 17, 'auto_center' => true, 'show_route_polyline' => true, 'show_eta' => true, 'show_distance' => true, ], 'markers' => [ 'rider' => [ 'icon' => '/images/markers/rider.png', 'size' => [40, 40], 'anchor' => [20, 40], ], 'restaurant' => [ 'icon' => '/images/markers/restaurant.png', 'size' => [40, 40], 'anchor' => [20, 40], ], 'customer' => [ 'icon' => '/images/markers/customer.png', 'size' => [40, 40], 'anchor' => [20, 40], ], ], 'polyline' => [ 'color' => '#4A90D9', 'weight' => 4, 'opacity' => 0.8, 'completed_color' => '#10B981', ], ], /* |-------------------------------------------------------------------------- | Delivery Flow Configuration |-------------------------------------------------------------------------- */ 'delivery_flow' => [ 'statuses' => [ 'pending' => [ 'label' => 'Order Placed', 'description' => 'Waiting for restaurant confirmation', 'color' => '#6B7280', ], 'confirmed' => [ 'label' => 'Order Confirmed', 'description' => 'Restaurant is preparing your food', 'color' => '#3B82F6', ], 'preparing' => [ 'label' => 'Preparing', 'description' => 'Your food is being prepared', 'color' => '#F59E0B', ], 'ready_for_pickup' => [ 'label' => 'Ready for Pickup', 'description' => 'Food is ready, waiting for rider', 'color' => '#8B5CF6', ], 'rider_assigned' => [ 'label' => 'Rider Assigned', 'description' => 'A rider has been assigned', 'color' => '#06B6D4', ], 'rider_at_restaurant' => [ 'label' => 'Rider at Restaurant', 'description' => 'Rider has arrived at restaurant', 'color' => '#14B8A6', ], 'picked_up' => [ 'label' => 'Picked Up', 'description' => 'Rider has picked up your order', 'color' => '#22C55E', ], 'on_the_way' => [ 'label' => 'On The Way', 'description' => 'Rider is on the way to you', 'color' => '#10B981', ], 'arrived' => [ 'label' => 'Arrived', 'description' => 'Rider has arrived at your location', 'color' => '#059669', ], 'delivered' => [ 'label' => 'Delivered', 'description' => 'Order has been delivered', 'color' => '#047857', ], 'cancelled' => [ 'label' => 'Cancelled', 'description' => 'Order has been cancelled', 'color' => '#EF4444', ], 'failed' => [ 'label' => 'Failed', 'description' => 'Delivery failed', 'color' => '#DC2626', ], ], 'auto_status_updates' => [ 'geofence_radius' => 100, // meters - auto update status when rider enters this radius 'arrival_confirmation' => true, // require rider to confirm arrival ], ], /* |-------------------------------------------------------------------------- | Rider Assignment Configuration |-------------------------------------------------------------------------- */ 'assignment' => [ 'auto_assign' => env('RESTAURANT_DELIVERY_AUTO_ASSIGN', true), 'assignment_radius' => env('RESTAURANT_DELIVERY_ASSIGNMENT_RADIUS', 5), // km 'max_concurrent_orders' => env('RESTAURANT_DELIVERY_MAX_CONCURRENT', 3), 'assignment_timeout' => env('RESTAURANT_DELIVERY_ASSIGNMENT_TIMEOUT', 60), // seconds 'max_reassignments' => 3, // Scoring weights for auto-assignment 'scoring' => [ 'distance_weight' => 40, // Closer is better 'rating_weight' => 25, // Higher rating is better 'acceptance_rate_weight' => 15, 'current_orders_weight' => 10, // Fewer current orders is better 'experience_weight' => 10, // More deliveries is better ], // Broadcast assignment to multiple riders 'broadcast' => [ 'enabled' => true, 'max_riders' => 5, 'accept_timeout' => 30, // seconds ], ], /* |-------------------------------------------------------------------------- | Rating System Configuration |-------------------------------------------------------------------------- */ 'rating' => [ 'enabled' => true, 'min_rating' => 1, 'max_rating' => 5, 'allow_review' => true, 'review_max_length' => 500, 'rating_window' => 72, // hours after delivery to submit rating 'anonymous_reviews' => false, // Rating categories 'categories' => [ 'overall' => ['label' => 'Overall Experience', 'required' => true], 'speed' => ['label' => 'Delivery Speed', 'required' => false], 'communication' => ['label' => 'Communication', 'required' => false], 'food_condition' => ['label' => 'Food Condition', 'required' => false], 'professionalism' => ['label' => 'Professionalism', 'required' => false], ], // Rating impact thresholds 'thresholds' => [ 'minimum_for_assignment' => 3.5, // Minimum rating to receive orders 'warning_threshold' => 3.0, // Send warning notification 'suspension_threshold' => 2.5, // Auto-suspend rider 'minimum_ratings_for_threshold' => 10, // Min ratings before thresholds apply ], // Rating display 'display' => [ 'show_on_tracking' => true, 'show_review_count' => true, 'show_recent_reviews' => 3, ], ], /* |-------------------------------------------------------------------------- | Tip System Configuration |-------------------------------------------------------------------------- */ 'tip' => [ 'enabled' => true, 'allow_pre_delivery' => true, // Tip at checkout 'allow_post_delivery' => true, // Tip after delivery 'post_delivery_window' => 24, // hours // Pre-set tip options 'preset_amounts' => [20, 50, 100, 200], // In local currency 'preset_percentages' => [5, 10, 15, 20], // Of order total 'default_type' => 'amount', // amount, percentage // Custom tip limits 'min_tip' => 10, 'max_tip' => 1000, 'max_percentage' => 50, // Tip distribution 'rider_share' => 100, // Percentage of tip that goes to rider 'platform_share' => 0, // Display 'show_suggested' => true, 'suggested_message' => 'Show appreciation for great service!', ], /* |-------------------------------------------------------------------------- | Pricing Configuration |-------------------------------------------------------------------------- */ 'pricing' => [ 'currency' => env('RESTAURANT_DELIVERY_CURRENCY', 'BDT'), 'currency_symbol' => env('RESTAURANT_DELIVERY_CURRENCY_SYMBOL', '৳'), 'default' => [ 'base_fare' => 30.00, 'minimum_fare' => 30.00, 'per_km_charge' => 8.00, 'free_distance' => 0.5, // First 0.5 km free 'max_distance' => 20.00, ], // Surge pricing 'surge' => [ 'enabled' => true, 'auto_calculate' => true, 'min_multiplier' => 1.0, 'max_multiplier' => 3.0, // Surge triggers 'triggers' => [ 'high_demand' => [ 'threshold' => 0.8, // 80% of riders busy 'multiplier' => 1.5, ], 'very_high_demand' => [ 'threshold' => 0.95, 'multiplier' => 2.0, ], 'bad_weather' => [ 'enabled' => true, 'multiplier' => 1.3, ], ], ], // Peak hours 'peak_hours' => [ 'enabled' => true, 'multiplier' => 1.3, 'slots' => [ ['start' => '12:00', 'end' => '14:00', 'days' => [1, 2, 3, 4, 5, 6, 7]], ['start' => '19:00', 'end' => '22:00', 'days' => [1, 2, 3, 4, 5, 6, 7]], ], ], // Late night 'late_night' => [ 'enabled' => true, 'multiplier' => 1.25, 'start' => '23:00', 'end' => '06:00', ], // Small order fee 'small_order' => [ 'enabled' => true, 'threshold' => 200, // Order total below this 'fee' => 15, ], // Restaurant-specific pricing override 'restaurant_override' => true, // Allow restaurants to set custom delivery fees ], /* |-------------------------------------------------------------------------- | Rider Earnings Configuration |-------------------------------------------------------------------------- */ 'earnings' => [ // Commission models 'commission_models' => [ 'fixed' => [ 'label' => 'Fixed per delivery', 'default_rate' => 30, ], 'percentage' => [ 'label' => 'Percentage of delivery fee', 'default_rate' => 70, // Rider gets 70% ], 'per_km' => [ 'label' => 'Per kilometer', 'default_rate' => 8, ], 'hybrid' => [ 'label' => 'Base + per km', 'base_rate' => 20, 'per_km_rate' => 5, ], ], // Bonuses 'bonuses' => [ 'peak_hour_bonus' => [ 'enabled' => true, 'amount' => 10, 'type' => 'fixed', // fixed, percentage ], 'rain_bonus' => [ 'enabled' => true, 'amount' => 15, 'type' => 'fixed', ], 'consecutive_delivery_bonus' => [ 'enabled' => true, 'threshold' => 5, // After 5 consecutive deliveries 'amount' => 50, ], 'rating_bonus' => [ 'enabled' => true, 'min_rating' => 4.8, 'amount' => 5, // Per delivery ], 'weekly_target_bonus' => [ 'enabled' => true, 'targets' => [ ['deliveries' => 50, 'bonus' => 500], ['deliveries' => 100, 'bonus' => 1200], ['deliveries' => 150, 'bonus' => 2000], ], ], ], // Penalties 'penalties' => [ 'cancellation' => [ 'enabled' => true, 'amount' => 20, 'free_cancellations' => 2, // Per day ], 'late_delivery' => [ 'enabled' => true, 'threshold' => 15, // Minutes late 'amount' => 10, ], ], // Payout settings 'payout' => [ 'frequency' => 'weekly', // daily, weekly, monthly 'minimum_amount' => 500, 'auto_payout' => true, 'payout_day' => 'monday', // For weekly 'payment_methods' => ['bank_transfer', 'bkash', 'nagad', 'rocket'], ], ], /* |-------------------------------------------------------------------------- | Notifications Configuration |-------------------------------------------------------------------------- */ 'notifications' => [ 'channels' => ['database', 'push', 'sms'], 'push' => [ 'provider' => env('PUSH_PROVIDER', 'firebase'), // firebase, onesignal 'firebase_server_key' => env('FIREBASE_SERVER_KEY'), ], 'sms' => [ 'provider' => env('SMS_PROVIDER', 'twilio'), 'enabled_for' => ['rider_assigned', 'out_for_delivery', 'delivered'], ], // Customer notifications 'customer' => [ 'order_confirmed' => true, 'rider_assigned' => true, 'rider_at_restaurant' => true, 'out_for_delivery' => true, 'arrived' => true, 'delivered' => true, 'delayed' => true, ], // Rider notifications 'rider' => [ 'new_order' => true, 'order_cancelled' => true, 'customer_message' => true, 'bonus_earned' => true, 'payout_processed' => true, ], // Restaurant notifications 'restaurant' => [ 'new_order' => true, 'rider_arriving' => true, 'rider_picked_up' => true, 'delivery_completed' => true, 'rating_received' => true, ], ], /* |-------------------------------------------------------------------------- | Edge Case Handling |-------------------------------------------------------------------------- */ 'edge_cases' => [ // GPS issues 'gps_off' => [ 'detection_timeout' => 60, // seconds 'action' => 'notify_rider', // notify_rider, reassign, pause_tracking 'max_offline_duration' => 300, // 5 minutes before reassignment ], // Rider offline 'rider_offline' => [ 'grace_period' => 120, // seconds 'auto_reassign' => true, 'notify_customer' => true, ], // Route deviation 'route_deviation' => [ 'enabled' => true, 'threshold' => 500, // meters off route 'action' => 'notify_customer', // notify_customer, notify_admin ], // Delivery timeout 'delivery_timeout' => [ 'enabled' => true, 'threshold' => 60, // minutes 'action' => 'escalate', // escalate, auto_refund ], // Contact failure 'contact_failure' => [ 'max_attempts' => 3, 'wait_time' => 300, // 5 minutes 'action' => 'return_to_restaurant', ], ], /* |-------------------------------------------------------------------------- | Cache Configuration |-------------------------------------------------------------------------- */ 'cache' => [ 'driver' => env('RESTAURANT_DELIVERY_CACHE_DRIVER', 'redis'), 'prefix' => 'restaurant_delivery_', 'ttl' => [ 'rider_location' => 30, // seconds 'zone_pricing' => 3600, // 1 hour 'route_calculation' => 300, // 5 minutes 'rider_stats' => 300, // 5 minutes 'surge_pricing' => 60, // 1 minute ], ], /* |-------------------------------------------------------------------------- | Queue Configuration |-------------------------------------------------------------------------- */ 'queue' => [ 'connection' => env('RESTAURANT_DELIVERY_QUEUE_CONNECTION', 'redis'), 'queues' => [ 'assignment' => 'restaurant-delivery-assignment', 'tracking' => 'restaurant-delivery-tracking', 'notifications' => 'restaurant-delivery-notifications', 'earnings' => 'restaurant-delivery-earnings', 'analytics' => 'restaurant-delivery-analytics', ], ], /* |-------------------------------------------------------------------------- | Logging Configuration |-------------------------------------------------------------------------- */ 'logging' => [ 'channel' => env('RESTAURANT_DELIVERY_LOG_CHANNEL', 'restaurant-delivery'), 'level' => env('RESTAURANT_DELIVERY_LOG_LEVEL', 'info'), 'log_location_updates' => false, // Can generate a lot of logs 'log_api_requests' => true, ], /* |-------------------------------------------------------------------------- | API Configuration |-------------------------------------------------------------------------- */ 'api' => [ 'prefix' => 'api/v1/restaurant-delivery', 'middleware' => ['api', 'auth:sanctum'], 'rate_limit' => env('RESTAURANT_DELIVERY_API_RATE_LIMIT', 60), 'throttle' => [ 'location_update' => '120,1', // 120 requests per minute for location 'general' => '60,1', ], ], ];