Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.bookovia.com/llms.txt

Use this file to discover all available pages before exploring further.

Overview

The Fleet Route Optimization API uses advanced algorithms and machine learning to generate optimal routes for your fleet operations. Minimize travel time, reduce fuel consumption, improve delivery windows, and maximize overall fleet efficiency through intelligent route planning and real-time optimization.

Authentication

All requests require authentication using your API key in the header:
Authorization: Bearer YOUR_API_KEY

Endpoints

Optimize Routes

POST /api/v1/fleet/optimization/routes

Get Optimization Status

GET /api/v1/fleet/optimization/{optimization_id}

Apply Optimized Routes

PUT /api/v1/fleet/optimization/{optimization_id}/apply

Request Parameters

Route Optimization Request

ParameterTypeRequiredDescription
fleet_idstringYesFleet identifier
vehiclesarrayYesList of available vehicles
destinationsarrayYesDelivery/pickup locations
constraintsobjectNoOptimization constraints
optimization_goalsarrayNoPriority objectives (default: [“minimize_time”, “minimize_distance”])
time_windowsbooleanNoHonor delivery time windows (default: true)
real_time_trafficbooleanNoUse real-time traffic data (default: true)
driver_preferencesbooleanNoConsider driver preferences (default: false)

Vehicle Object

{
  "vehicle_id": "vehicle_001",
  "capacity": {
    "weight": 1000.0,
    "volume": 50.0,
    "packages": 25
  },
  "start_location": {
    "latitude": 40.7128,
    "longitude": -74.0060,
    "address": "Distribution Center A"
  },
  "end_location": {
    "latitude": 40.7128,
    "longitude": -74.0060,
    "address": "Distribution Center A"
  },
  "driver_id": "driver_456",
  "shift_start": "08:00",
  "shift_end": "17:00",
  "break_windows": [
    {
      "start": "12:00",
      "end": "13:00",
      "duration": 30
    }
  ],
  "vehicle_type": "delivery_truck",
  "restrictions": ["no_highways", "weight_limit_bridges"]
}

Destination Object

{
  "destination_id": "dest_001",
  "location": {
    "latitude": 40.7489,
    "longitude": -73.9857,
    "address": "123 Customer St, New York, NY"
  },
  "delivery_requirements": {
    "weight": 25.5,
    "volume": 2.3,
    "packages": 3,
    "special_handling": ["fragile", "refrigerated"]
  },
  "time_window": {
    "earliest": "09:00",
    "latest": "17:00",
    "service_duration": 15
  },
  "priority": "high",
  "customer_id": "customer_789",
  "delivery_notes": "Ring doorbell, leave at door if no answer"
}

Constraints Object

{
  "max_route_duration": 480,
  "max_route_distance": 200,
  "driver_break_requirements": true,
  "vehicle_capacity_strict": true,
  "time_window_violations": "minimize",
  "traffic_restrictions": {
    "avoid_toll_roads": false,
    "avoid_highways": false,
    "avoid_ferries": true
  },
  "fuel_efficiency_priority": 0.3,
  "delivery_time_priority": 0.4,
  "cost_priority": 0.3
}

Response Format

{
  "success": true,
  "data": {
    "optimization_id": "opt_12345",
    "status": "completed",
    "fleet_id": "fleet_001",
    "optimization_summary": {
      "total_vehicles": 15,
      "total_destinations": 87,
      "optimization_time": 45.2,
      "algorithm_used": "genetic_algorithm",
      "confidence_score": 94.7
    },
    "performance_metrics": {
      "total_distance": 1247.8,
      "total_time": 6840,
      "fuel_consumption_estimate": 156.2,
      "cost_estimate": 2847.50,
      "delivery_efficiency": 92.3,
      "time_window_compliance": 98.9
    },
    "improvement_summary": {
      "distance_saved": 387.2,
      "time_saved": 2160,
      "fuel_saved": 48.5,
      "cost_saved": 892.30,
      "improvement_percentage": 23.8
    },
    "optimized_routes": [
      {
        "vehicle_id": "vehicle_001",
        "driver_id": "driver_456",
        "route_summary": {
          "total_distance": 87.3,
          "total_time": 420,
          "total_stops": 8,
          "estimated_fuel": 12.5,
          "route_efficiency": 95.2
        },
        "route_sequence": [
          {
            "sequence": 1,
            "destination_id": "depot",
            "location": {
              "latitude": 40.7128,
              "longitude": -74.0060,
              "address": "Distribution Center A"
            },
            "arrival_time": "08:00:00",
            "departure_time": "08:15:00",
            "activity_type": "start"
          },
          {
            "sequence": 2,
            "destination_id": "dest_001",
            "location": {
              "latitude": 40.7489,
              "longitude": -73.9857,
              "address": "123 Customer St, New York, NY"
            },
            "arrival_time": "08:47:00",
            "departure_time": "09:02:00",
            "activity_type": "delivery",
            "service_duration": 15,
            "packages": 3,
            "delivery_notes": "Ring doorbell, leave at door if no answer"
          }
        ],
        "route_optimization_details": {
          "optimization_factors": [
            {
              "factor": "traffic_optimization",
              "weight": 0.4,
              "impact": "reduced travel time by 23 minutes"
            },
            {
              "factor": "delivery_sequence",
              "weight": 0.3,
              "impact": "minimized backtracking"
            }
          ],
          "alternative_routes": 3,
          "confidence_level": 0.94
        }
      }
    ],
    "unassigned_destinations": [
      {
        "destination_id": "dest_099",
        "reason": "exceeds_vehicle_capacity",
        "recommendations": ["assign_larger_vehicle", "split_delivery"]
      }
    ],
    "optimization_insights": {
      "bottlenecks": [
        {
          "type": "time_window_constraint",
          "description": "5 destinations have tight time windows causing routing conflicts",
          "affected_destinations": ["dest_023", "dest_045", "dest_067", "dest_078", "dest_089"]
        }
      ],
      "recommendations": [
        {
          "category": "capacity_utilization",
          "description": "Vehicle vehicle_003 is underutilized at 67% capacity",
          "action": "consider_additional_stops"
        }
      ]
    }
  }
}

SDK Examples

import { BookoviaSDK } from '@bookovia/sdk';

const sdk = new BookoviaSDK({ apiKey: 'your-api-key' });

async function optimizeFleetRoutes(fleetId, vehicles, destinations) {
  try {
    const optimization = await sdk.fleet.optimization.optimizeRoutes({
      fleet_id: fleetId,
      vehicles: vehicles,
      destinations: destinations,
      constraints: {
        max_route_duration: 480, // 8 hours
        max_route_distance: 200,
        fuel_efficiency_priority: 0.3,
        delivery_time_priority: 0.4,
        cost_priority: 0.3
      },
      optimization_goals: ["minimize_time", "minimize_fuel", "maximize_efficiency"],
      real_time_traffic: true,
      time_windows: true
    });

    console.log(`Optimization completed in ${optimization.optimization_summary.optimization_time}s`);
    console.log(`Total savings: $${optimization.improvement_summary.cost_saved}`);
    console.log(`Distance reduction: ${optimization.improvement_summary.distance_saved} miles`);
    
    // Display optimization results
    optimization.optimized_routes.forEach((route, index) => {
      console.log(`\nRoute ${index + 1} (${route.vehicle_id}):`);
      console.log(`- Distance: ${route.route_summary.total_distance} miles`);
      console.log(`- Time: ${Math.floor(route.route_summary.total_time / 60)} minutes`);
      console.log(`- Stops: ${route.route_summary.total_stops}`);
      console.log(`- Efficiency: ${route.route_summary.route_efficiency}%`);
    });
    
    // Check for unassigned destinations
    if (optimization.unassigned_destinations.length > 0) {
      console.log(`\n⚠️ ${optimization.unassigned_destinations.length} destinations could not be assigned:`);
      optimization.unassigned_destinations.forEach(dest => {
        console.log(`- ${dest.destination_id}: ${dest.reason}`);
      });
    }
    
    return optimization;
  } catch (error) {
    console.error('Route optimization failed:', error);
    throw error;
  }
}

// Apply optimized routes to fleet
async function applyOptimizedRoutes(optimizationId) {
  try {
    const result = await sdk.fleet.optimization.applyRoutes(optimizationId);
    
    console.log(`Routes applied successfully to ${result.vehicles_updated} vehicles`);
    console.log(`Estimated implementation time: ${result.estimated_rollout_time} minutes`);
    
    return result;
  } catch (error) {
    console.error('Failed to apply routes:', error);
    throw error;
  }
}

Use Cases

Multi-Depot Route Optimization

Optimize routes across multiple distribution centers and vehicle types for complex logistics operations.
// Multi-depot optimization with vehicle type constraints
async function optimizeMultiDepotRoutes(fleetId, depots, mixedVehicleFleet, deliveries) {
  const optimizationRequests = [];
  
  // Group vehicles by depot and capability
  const vehiclesByDepot = groupVehiclesByDepot(mixedVehicleFleet);
  const deliveriesByRegion = clusterDeliveriesByRegion(deliveries);
  
  // Create optimization request for each depot
  for (const [depotId, vehicles] of Object.entries(vehiclesByDepot)) {
    const nearbyDeliveries = findNearbyDeliveries(depots[depotId], deliveriesByRegion);
    
    optimizationRequests.push({
      depot_id: depotId,
      vehicles: vehicles,
      destinations: nearbyDeliveries,
      constraints: {
        max_route_duration: 480,
        cross_depot_transfers: true,
        vehicle_specialization: true,
        load_balancing_priority: 0.3
      }
    });
  }
  
  // Run parallel optimizations
  const results = await Promise.all(
    optimizationRequests.map(request =>
      sdk.fleet.optimization.optimizeRoutes({
        fleet_id: fleetId,
        ...request,
        optimization_goals: ["minimize_cost", "balance_workload", "maximize_service_quality"]
      })
    )
  );
  
  // Cross-depot optimization for remaining unassigned deliveries
  const unassignedDeliveries = results.flatMap(result => result.unassigned_destinations);
  
  if (unassignedDeliveries.length > 0) {
    const crossDepotOptimization = await optimizeCrossDepotAssignments(
      fleetId, depots, mixedVehicleFleet, unassignedDeliveries
    );
    
    results.push(crossDepotOptimization);
  }
  
  return {
    total_depots: Object.keys(depots).length,
    optimization_results: results,
    combined_metrics: calculateCombinedMetrics(results),
    inter_depot_transfers: identifyInterDepotTransfers(results),
    resource_utilization: calculateResourceUtilization(results)
  };
}

function groupVehiclesByDepot(vehicles) {
  return vehicles.reduce((groups, vehicle) => {
    const depot = vehicle.home_depot || vehicle.start_location.depot_id;
    if (!groups[depot]) groups[depot] = [];
    groups[depot].push(vehicle);
    return groups;
  }, {});
}

function clusterDeliveriesByRegion(deliveries) {
  // K-means clustering algorithm for delivery grouping
  const clusters = performKMeansClustering(deliveries, 5);
  
  return clusters.map(cluster => ({
    region_id: cluster.id,
    center: cluster.centroid,
    deliveries: cluster.points,
    density: cluster.points.length / cluster.area
  }));
}

async function optimizeCrossDepotAssignments(fleetId, depots, vehicles, unassignedDeliveries) {
  // Special optimization for cross-depot assignments
  return await sdk.fleet.optimization.optimizeRoutes({
    fleet_id: fleetId,
    vehicles: vehicles,
    destinations: unassignedDeliveries,
    constraints: {
      allow_cross_depot: true,
      transfer_cost_penalty: 50, // $50 per cross-depot transfer
      max_transfer_distance: 100 // miles
    },
    optimization_goals: ["minimize_transfers", "minimize_cost"]
  });
}

Dynamic Re-optimization During Execution

Continuously re-optimize routes based on real-time conditions and unexpected events.
import asyncio
from datetime import datetime, timedelta

class DynamicRouteOptimizer:
    def __init__(self, sdk, fleet_id):
        self.sdk = sdk
        self.fleet_id = fleet_id
        self.active_optimizations = {}
        self.monitoring_active = True
        
    async def start_dynamic_optimization(self, initial_routes):
        """Start dynamic optimization with continuous monitoring"""
        # Apply initial optimized routes
        initial_optimization = await self.sdk.fleet.optimization.optimize_routes(
            fleet_id=self.fleet_id,
            vehicles=initial_routes['vehicles'],
            destinations=initial_routes['destinations'],
            optimization_goals=['minimize_time', 'maximize_flexibility']
        )
        
        await self.sdk.fleet.optimization.apply_routes(initial_optimization.optimization_id)
        self.active_optimizations['current'] = initial_optimization
        
        # Start monitoring loop
        await asyncio.gather(
            self.monitor_route_execution(),
            self.monitor_new_orders(),
            self.monitor_traffic_conditions(),
            self.monitor_vehicle_breakdowns()
        )
    
    async def monitor_route_execution(self):
        """Monitor route execution and trigger re-optimization when needed"""
        while self.monitoring_active:
            try:
                current_opt = self.active_optimizations.get('current')
                if not current_opt:
                    await asyncio.sleep(30)
                    continue
                
                # Check execution status
                status = await self.sdk.fleet.optimization.get_execution_status(
                    current_opt.optimization_id
                )
                
                # Trigger re-optimization if needed
                reoptimization_needed = self.evaluate_reoptimization_need(status)
                
                if reoptimization_needed['should_reoptimize']:
                    await self.trigger_reoptimization(
                        reason=reoptimization_needed['reason'],
                        affected_vehicles=reoptimization_needed['vehicles'],
                        priority=reoptimization_needed['priority']
                    )
                
                await asyncio.sleep(60)  # Check every minute
                
            except Exception as e:
                print(f"Error monitoring routes: {e}")
                await asyncio.sleep(30)
    
    async def monitor_new_orders(self):
        """Monitor for new orders that need to be inserted into existing routes"""
        while self.monitoring_active:
            try:
                # Check for new orders (this would integrate with your order system)
                new_orders = await self.get_new_orders()
                
                if new_orders:
                    await self.handle_new_orders(new_orders)
                
                await asyncio.sleep(30)  # Check every 30 seconds
                
            except Exception as e:
                print(f"Error monitoring new orders: {e}")
                await asyncio.sleep(30)
    
    async def monitor_traffic_conditions(self):
        """Monitor traffic conditions and re-optimize if significant delays"""
        while self.monitoring_active:
            try:
                # Get current traffic data
                traffic_data = await self.get_traffic_conditions()
                
                # Analyze impact on current routes
                traffic_impact = self.analyze_traffic_impact(traffic_data)
                
                if traffic_impact['significant_delays']:
                    await self.trigger_traffic_reoptimization(traffic_impact)
                
                await asyncio.sleep(300)  # Check every 5 minutes
                
            except Exception as e:
                print(f"Error monitoring traffic: {e}")
                await asyncio.sleep(300)
    
    async def monitor_vehicle_breakdowns(self):
        """Monitor vehicle health and handle breakdowns"""
        while self.monitoring_active:
            try:
                # Check vehicle status
                vehicle_statuses = await self.get_vehicle_health_status()
                
                broken_vehicles = [
                    v for v in vehicle_statuses 
                    if v['status'] in ['breakdown', 'maintenance_required']
                ]
                
                if broken_vehicles:
                    await self.handle_vehicle_breakdowns(broken_vehicles)
                
                await asyncio.sleep(120)  # Check every 2 minutes
                
            except Exception as e:
                print(f"Error monitoring vehicles: {e}")
                await asyncio.sleep(120)
    
    def evaluate_reoptimization_need(self, execution_status):
        """Evaluate if re-optimization is needed based on execution status"""
        reasons = []
        affected_vehicles = []
        priority = 'low'
        
        # Check for significant delays
        if execution_status.average_delay > 30:  # 30+ minutes average delay
            reasons.append('significant_delays')
            priority = 'high'
        
        # Check for route deviations
        major_deviations = [
            dev for dev in execution_status.route_deviations 
            if dev.time_impact > 45
        ]
        
        if major_deviations:
            reasons.append('major_route_deviations')
            affected_vehicles.extend([dev.vehicle_id for dev in major_deviations])
            priority = 'medium'
        
        # Check completion rate
        completion_rate = execution_status.completed_deliveries / execution_status.total_deliveries
        expected_completion = self.calculate_expected_completion_rate()
        
        if completion_rate < expected_completion * 0.8:  # 20% behind schedule
            reasons.append('behind_schedule')
            priority = 'high'
        
        return {
            'should_reoptimize': len(reasons) > 0,
            'reason': ', '.join(reasons),
            'vehicles': list(set(affected_vehicles)),
            'priority': priority
        }
    
    async def trigger_reoptimization(self, reason, affected_vehicles, priority):
        """Trigger re-optimization with specific focus areas"""
        print(f"Triggering re-optimization: {reason} (Priority: {priority})")
        
        # Get current state
        current_state = await self.get_current_route_state()
        
        # Determine optimization scope
        if priority == 'high' or len(affected_vehicles) > 5:
            # Full fleet re-optimization
            scope = 'full_fleet'
            vehicles_to_optimize = current_state['all_vehicles']
        else:
            # Partial re-optimization focusing on affected vehicles
            scope = 'partial'
            vehicles_to_optimize = [
                v for v in current_state['all_vehicles'] 
                if v['vehicle_id'] in affected_vehicles
            ]
        
        # Include remaining destinations
        remaining_destinations = [
            dest for dest in current_state['destinations']
            if dest['status'] == 'pending'
        ]
        
        # Optimize with current constraints
        reoptimization = await self.sdk.fleet.optimization.optimize_routes(
            fleet_id=self.fleet_id,
            vehicles=vehicles_to_optimize,
            destinations=remaining_destinations,
            constraints={
                'preserve_completed_deliveries': True,
                'minimize_route_disruption': True,
                'reoptimization_scope': scope,
                'priority_reason': reason
            },
            optimization_goals=['minimize_disruption', 'recover_schedule', 'minimize_cost']
        )
        
        # Apply the re-optimization
        if self.should_apply_reoptimization(reoptimization):
            await self.sdk.fleet.optimization.apply_routes(reoptimization.optimization_id)
            self.active_optimizations['current'] = reoptimization
            
            print(f"Re-optimization applied: {reoptimization.improvement_summary}")
        else:
            print("Re-optimization not beneficial, keeping current routes")
    
    def should_apply_reoptimization(self, new_optimization):
        """Determine if the new optimization should be applied"""
        # Apply if improvement is significant enough to justify disruption
        improvement_threshold = 0.05  # 5% improvement minimum
        
        cost_improvement = new_optimization.improvement_summary.cost_saved
        current_cost = new_optimization.performance_metrics.cost_estimate
        
        improvement_percentage = cost_improvement / current_cost
        
        return improvement_percentage > improvement_threshold
    
    async def handle_new_orders(self, new_orders):
        """Handle insertion of new orders into existing routes"""
        print(f"Handling {len(new_orders)} new orders")
        
        # Try to insert into existing routes first
        insertion_attempts = []
        
        for order in new_orders:
            best_insertion = await self.find_best_route_insertion(order)
            
            if best_insertion['feasible']:
                insertion_attempts.append(best_insertion)
            else:
                # Queue for next full re-optimization
                await self.queue_for_next_optimization(order)
        
        # Apply feasible insertions
        if insertion_attempts:
            await self.apply_route_insertions(insertion_attempts)
    
    async def find_best_route_insertion(self, order):
        """Find the best route to insert a new order"""
        current_routes = await self.get_current_active_routes()
        
        best_insertion = {
            'feasible': False,
            'cost_increase': float('inf'),
            'route_id': None,
            'insertion_point': None
        }
        
        for route in current_routes:
            # Check if order can be inserted into this route
            insertion_options = await self.evaluate_insertion_options(order, route)
            
            for option in insertion_options:
                if (option['feasible'] and 
                    option['cost_increase'] < best_insertion['cost_increase']):
                    best_insertion = option
        
        return best_insertion
    
    async def get_current_route_state(self):
        """Get the current state of all routes"""
        # Implementation would fetch current route execution state
        # This is a placeholder for the actual implementation
        return {
            'all_vehicles': [],
            'destinations': [],
            'completed_deliveries': [],
            'pending_deliveries': []
        }
    
    async def get_new_orders(self):
        """Get new orders that need to be scheduled"""
        # Integration with order management system
        return []
    
    async def get_traffic_conditions(self):
        """Get current traffic conditions"""
        # Integration with traffic data provider
        return {}
    
    async def get_vehicle_health_status(self):
        """Get current vehicle health status"""
        # Integration with vehicle monitoring system
        return []

# Usage
async def main():
    optimizer = DynamicRouteOptimizer(sdk, "fleet_001")
    
    initial_routes = {
        'vehicles': [...],  # Your vehicle list
        'destinations': [...]  # Your destination list
    }
    
    await optimizer.start_dynamic_optimization(initial_routes)

# asyncio.run(main())

Cost-Optimized Route Planning

Balance multiple cost factors including fuel, driver wages, vehicle wear, and delivery performance.
package main

import (
    "context"
    "fmt"
    "math"
    "sort"
)

type CostOptimizedPlanner struct {
    client     *bookovia.Client
    costModel  *CostModel
}

type CostModel struct {
    FuelCostPerMile      float64 `json:"fuel_cost_per_mile"`
    DriverWagePerHour    float64 `json:"driver_wage_per_hour"`
    VehicleWearPerMile   float64 `json:"vehicle_wear_per_mile"`
    LateDeliveryPenalty  float64 `json:"late_delivery_penalty"`
    OvertimePremium      float64 `json:"overtime_premium"`
    TollCostWeight       float64 `json:"toll_cost_weight"`
}

type CostAnalysis struct {
    TotalCost           float64              `json:"total_cost"`
    CostBreakdown       CostBreakdown        `json:"cost_breakdown"`
    CostPerDelivery     float64              `json:"cost_per_delivery"`
    CostEfficiencyScore float64              `json:"cost_efficiency_score"`
    Recommendations     []CostRecommendation `json:"recommendations"`
}

type CostBreakdown struct {
    FuelCosts      float64 `json:"fuel_costs"`
    LaborCosts     float64 `json:"labor_costs"`
    VehicleCosts   float64 `json:"vehicle_costs"`
    PenaltyCosts   float64 `json:"penalty_costs"`
    TollCosts      float64 `json:"toll_costs"`
    OvertimeCosts  float64 `json:"overtime_costs"`
}

func NewCostOptimizedPlanner(client *bookovia.Client) *CostOptimizedPlanner {
    return &CostOptimizedPlanner{
        client: client,
        costModel: &CostModel{
            FuelCostPerMile:      0.45,  // $0.45 per mile
            DriverWagePerHour:    25.0,  // $25/hour
            VehicleWearPerMile:   0.15,  // $0.15 per mile
            LateDeliveryPenalty:  50.0,  // $50 per late delivery
            OvertimePremium:      1.5,   // 1.5x wage for overtime
            TollCostWeight:       1.0,   // Full toll costs
        },
    }
}

func (cop *CostOptimizedPlanner) OptimizeForCost(ctx context.Context, fleetID string, vehicles []bookovia.Vehicle, destinations []bookovia.Destination) (*bookovia.OptimizationResult, *CostAnalysis, error) {
    // Create cost-weighted optimization request
    request := &bookovia.RouteOptimizationRequest{
        FleetID:      fleetID,
        Vehicles:     vehicles,
        Destinations: destinations,
        Constraints: &bookovia.OptimizationConstraints{
            MaxRouteDuration:        480,
            MaxRouteDistance:        300,
            FuelEfficiencyPriority:  0.4,  // Higher weight for fuel efficiency
            CostPriority:           0.5,   // Highest weight for overall cost
            DeliveryTimePriority:   0.1,   // Lower weight for speed
        },
        OptimizationGoals: []string{
            "minimize_total_cost",
            "minimize_fuel_consumption", 
            "minimize_overtime",
            "maximize_vehicle_utilization",
        },
        CostModel: cop.costModel,
    }
    
    // Run optimization
    optimization, err := cop.client.Fleet.Optimization.OptimizeRoutes(ctx, request)
    if err != nil {
        return nil, nil, fmt.Errorf("cost optimization failed: %w", err)
    }
    
    // Analyze costs in detail
    costAnalysis := cop.analyzeCosts(optimization)
    
    // Generate cost-saving recommendations
    recommendations := cop.generateCostRecommendations(optimization, costAnalysis)
    costAnalysis.Recommendations = recommendations
    
    return optimization, costAnalysis, nil
}

func (cop *CostOptimizedPlanner) analyzeCosts(optimization *bookovia.OptimizationResult) *CostAnalysis {
    var totalFuelCosts, totalLaborCosts, totalVehicleCosts float64
    var totalPenaltyCosts, totalTollCosts, totalOvertimeCosts float64
    
    for _, route := range optimization.OptimizedRoutes {
        // Calculate fuel costs
        fuelCost := route.RouteSummary.TotalDistance * cop.costModel.FuelCostPerMile
        totalFuelCosts += fuelCost
        
        // Calculate labor costs
        regularHours := math.Min(float64(route.RouteSummary.TotalTime/3600), 8.0)
        overtimeHours := math.Max(float64(route.RouteSummary.TotalTime/3600)-8.0, 0.0)
        
        laborCost := regularHours * cop.costModel.DriverWagePerHour
        overtimeCost := overtimeHours * cop.costModel.DriverWagePerHour * cop.costModel.OvertimePremium
        
        totalLaborCosts += laborCost
        totalOvertimeCosts += overtimeCost
        
        // Calculate vehicle wear costs
        vehicleCost := route.RouteSummary.TotalDistance * cop.costModel.VehicleWearPerMile
        totalVehicleCosts += vehicleCost
        
        // Calculate penalty costs (for late deliveries)
        lateDeliveries := cop.countLateDeliveries(route)
        penaltyCost := float64(lateDeliveries) * cop.costModel.LateDeliveryPenalty
        totalPenaltyCosts += penaltyCost
        
        // Calculate toll costs (if applicable)
        tollCost := cop.calculateTollCosts(route)
        totalTollCosts += tollCost
    }
    
    totalCost := totalFuelCosts + totalLaborCosts + totalVehicleCosts + 
                 totalPenaltyCosts + totalTollCosts + totalOvertimeCosts
    
    costPerDelivery := totalCost / float64(len(optimization.OptimizedRoutes))
    
    // Calculate efficiency score (lower cost = higher score)
    industryBenchmark := 45.0 // $45 average cost per delivery
    efficiencyScore := math.Max(0, (industryBenchmark - costPerDelivery) / industryBenchmark * 100)
    
    return &CostAnalysis{
        TotalCost: totalCost,
        CostBreakdown: CostBreakdown{
            FuelCosts:     totalFuelCosts,
            LaborCosts:    totalLaborCosts,
            VehicleCosts:  totalVehicleCosts,
            PenaltyCosts:  totalPenaltyCosts,
            TollCosts:     totalTollCosts,
            OvertimeCosts: totalOvertimeCosts,
        },
        CostPerDelivery:     costPerDelivery,
        CostEfficiencyScore: efficiencyScore,
    }
}

func (cop *CostOptimizedPlanner) generateCostRecommendations(optimization *bookovia.OptimizationResult, analysis *CostAnalysis) []CostRecommendation {
    var recommendations []CostRecommendation
    
    // Analyze cost breakdown for recommendations
    totalCost := analysis.TotalCost
    
    // High fuel costs
    if analysis.CostBreakdown.FuelCosts/totalCost > 0.4 {
        recommendations = append(recommendations, CostRecommendation{
            Category:    "fuel_efficiency",
            Priority:    "high",
            Description: "Fuel costs are high (>40% of total). Consider route consolidation or fuel-efficient vehicles.",
            EstimatedSavings: analysis.CostBreakdown.FuelCosts * 0.15, // 15% potential savings
            ActionItems: []string{
                "Consolidate nearby deliveries",
                "Use smaller, more fuel-efficient vehicles for light loads",
                "Optimize routes to avoid traffic congestion",
            },
        })
    }
    
    // High overtime costs
    if analysis.CostBreakdown.OvertimeCosts > 0 {
        recommendations = append(recommendations, CostRecommendation{
            Category:    "overtime_reduction", 
            Priority:    "medium",
            Description: fmt.Sprintf("Overtime costs detected: $%.2f. Optimize shift scheduling.", analysis.CostBreakdown.OvertimeCosts),
            EstimatedSavings: analysis.CostBreakdown.OvertimeCosts * 0.8, // 80% savings by eliminating overtime
            ActionItems: []string{
                "Redistribute routes to stay within regular hours",
                "Add additional drivers for peak periods",
                "Implement staggered shift starts",
            },
        })
    }
    
    // High penalty costs
    if analysis.CostBreakdown.PenaltyCosts > 0 {
        recommendations = append(recommendations, CostRecommendation{
            Category:    "delivery_performance",
            Priority:    "high",
            Description: fmt.Sprintf("Late delivery penalties: $%.2f. Improve time window adherence.", analysis.CostBreakdown.PenaltyCosts),
            EstimatedSavings: analysis.CostBreakdown.PenaltyCosts,
            ActionItems: []string{
                "Build buffer time into schedules",
                "Prioritize time-sensitive deliveries",
                "Improve route sequencing for time windows",
            },
        })
    }
    
    // Vehicle utilization analysis
    underutilizedRoutes := cop.findUnderutilizedRoutes(optimization)
    if len(underutilizedRoutes) > 0 {
        potentialSavings := cop.calculateConsolidationSavings(underutilizedRoutes)
        recommendations = append(recommendations, CostRecommendation{
            Category:    "route_consolidation",
            Priority:    "medium",
            Description: fmt.Sprintf("%d routes are underutilized and could be consolidated.", len(underutilizedRoutes)),
            EstimatedSavings: potentialSavings,
            ActionItems: []string{
                "Merge underutilized routes where possible",
                "Use smaller vehicles for low-volume routes",
                "Consider outsourcing low-density areas",
            },
        })
    }
    
    // Sort recommendations by estimated savings
    sort.Slice(recommendations, func(i, j int) bool {
        return recommendations[i].EstimatedSavings > recommendations[j].EstimatedSavings
    })
    
    return recommendations
}

type CostRecommendation struct {
    Category         string   `json:"category"`
    Priority         string   `json:"priority"`
    Description      string   `json:"description"`
    EstimatedSavings float64  `json:"estimated_savings"`
    ActionItems      []string `json:"action_items"`
}

func (cop *CostOptimizedPlanner) countLateDeliveries(route bookovia.OptimizedRoute) int {
    lateCount := 0
    
    for _, stop := range route.RouteSequence {
        if stop.ActivityType == "delivery" && stop.TimeWindow != nil {
            arrivalTime := parseTime(stop.ArrivalTime)
            latestTime := parseTime(stop.TimeWindow.Latest)
            
            if arrivalTime.After(latestTime) {
                lateCount++
            }
        }
    }
    
    return lateCount
}

func (cop *CostOptimizedPlanner) calculateTollCosts(route bookovia.OptimizedRoute) float64 {
    // Simplified toll calculation - in reality, this would integrate with toll APIs
    tollCost := 0.0
    
    // Estimate based on route characteristics
    if route.RouteSummary.TotalDistance > 100 {
        // Assume highway usage for long routes
        tollCost = route.RouteSummary.TotalDistance * 0.08 // $0.08 per mile on toll roads
    }
    
    return tollCost
}

func (cop *CostOptimizedPlanner) findUnderutilizedRoutes(optimization *bookovia.OptimizationResult) []bookovia.OptimizedRoute {
    var underutilized []bookovia.OptimizedRoute
    
    for _, route := range optimization.OptimizedRoutes {
        // Consider route underutilized if efficiency is low or has few stops
        if route.RouteSummary.RouteEfficiency < 70 || route.RouteSummary.TotalStops < 5 {
            underutilized = append(underutilized, route)
        }
    }
    
    return underutilized
}

func (cop *CostOptimizedPlanner) calculateConsolidationSavings(routes []bookovia.OptimizedRoute) float64 {
    // Estimate savings from consolidating underutilized routes
    totalDistance := 0.0
    totalTime := 0.0
    
    for _, route := range routes {
        totalDistance += route.RouteSummary.TotalDistance
        totalTime += float64(route.RouteSummary.TotalTime)
    }
    
    // Assume 25% reduction in distance/time through consolidation
    savings := (totalDistance * cop.costModel.FuelCostPerMile * 0.25) +
               (totalTime/3600 * cop.costModel.DriverWagePerHour * 0.25)
    
    return savings
}

// Utility function to parse time (simplified)
func parseTime(timeStr string) time.Time {
    // Implementation would parse the actual time format
    return time.Now()
}

Error Handling

Status CodeError TypeDescription
400INVALID_PARAMETERSInvalid optimization parameters
401UNAUTHORIZEDInvalid or missing API key
403FORBIDDENNo access to specified fleet
404FLEET_NOT_FOUNDSpecified fleet ID does not exist
422OPTIMIZATION_FAILEDUnable to find feasible solution
422INSUFFICIENT_CAPACITYVehicle capacity cannot meet demands
429RATE_LIMIT_EXCEEDEDToo many optimization requests
500OPTIMIZATION_ERRORError in optimization processing

Best Practices

Route Planning

  • Always include realistic time windows and service durations
  • Consider driver break requirements and shift limits
  • Use appropriate vehicle capacity constraints
  • Include special handling requirements for deliveries

Optimization Performance

  • Limit optimization scope for large fleets (>100 vehicles)
  • Use incremental optimization for minor route changes
  • Cache optimization results for similar scenarios
  • Balance optimization time vs. solution quality

Real-Time Adaptation

  • Monitor route execution continuously
  • Set clear thresholds for re-optimization triggers
  • Minimize route disruption when re-optimizing
  • Maintain fallback plans for optimization failures

Cost Management

  • Regularly update cost models with current rates
  • Include all relevant cost factors in optimization
  • Monitor actual vs. predicted costs for model tuning
  • Consider long-term impact of routing decisions

Related Endpoints

Explore other fleet management capabilities: