Regular additional planning of the route

Additional planning means adding more orders to a route that has already been planned. This may be necessary if:

  • Orders have already been assigned to routes, but new orders have appeared.
  • The courier starts the run with only part of the orders to reduce downtime. More orders are added to the route later.

If you use additional planning frequently, we recommend automating it.

Note

This scenario can only be implemented using API requests.

What's passed to the new planning task:

  • A full list of orders (old and new ones).
  • The route obtained during the previous planning and the settings determining the possibility of changing this route.
  • The courier's current location (if necessary).

An additional planning task may appear at different times and in different situations:

  • Option 1: The courier is at the depot. The sequence of already assigned orders is fixed, and new orders are added to the end of the route.

  • Option 2: The courier is at the depot. The sequence of already assigned orders isn't fixed, and new orders are added anywhere.

  • Option 3: The courier is traveling along the route. The sequence of already assigned orders is fixed, and new orders are added to the end of the route.

  • Option 4: The courier is traveling along the route. The sequence of remaining orders isn't fixed, and new orders are added anywhere in the remaining part of the route.

: A new order.

: An order in a fixed sequence.

: An order without a fixed sequence.

All the options allow the courier to visit an intermediate depot while traveling along the route.

How to implement this scenario

During the initial route planning, consider the following:

  • Whether the vehicle has enough space for more orders (specify a smaller carrying capacity).
  • Whether the courier has enough time (specify a shorter shift).

During the additional planning, you need to remove any additional restrictions that were added during the initial planning to intentionally underload the vehicles.

In the additional planning request, use the locations object to pass in the general list of orders that includes both the already planned orders and orders that require additional planning.

Also include the initial_routes object with data on originally planned runs in the request. This data can be copied from the result.routes object in the API response for the first planning task. For each run, pass in the following objects:

  • route: Array of stops in the run.
  • run_number: Run number.
  • shift: Courier shift.
  • vehicle_id: Courier ID.

Fixed order sequence

If a previously planned run needs to be saved without any changes, set immutable = true for it in the initial_routes object. If the order of stops in a run shouldn't change, set fixed_order = true.

If you only want to prohibit changes on a part of a run (a sequence of consecutive stops), set node.value.fixed_position = true for each of these stops.

To have an order delivered by the courier that was originally assigned, set fixed_vehicle = true for that order. If you want an order to remain in the same shift, set fixed_shift = true, and to keep it in the same run, set fixed_run = true. If none of these attributes is set, new orders may get mixed in with the existing ones randomly.

If you use courier location tracking (location with the type courier), the immutable attribute won't work. Instead, fix the position of each location in initial_routes using the parameter node.value.fixed_position = true and remove the immutable attribute.

Order completion time

The planning algorithm only uses the parameters you provide in your API request. It doesn't consider when you sent the request. This means that if you provide incorrect parameters, the algorithm might build a route that starts before the current time. For example, you set the time window for the depot (restaurant) from 9:00 to 21:00. If you submit a planning request at 9:30, the algorithm might build a route with the courier leaving at 9:20. To avoid this, try one of these options:

  • Whenever you submit a planning request, set the depot start time to match the exact time of planning. For example, if you submit the request at 9:30, specify the depot operating hours to start at 9:30 and end at 21:00.

  • For each order, specify the time when it's ready: depot_ready_time. It should be a future time, not a past time.

Tracking delivered orders

If some orders have already been delivered by the time of additional planning, indicate their visit time in the following fields:

  • actual_arrival_time_s: Arrival at the delivery location.
  • actual_service_start_time_s: Order handling start time.
  • actual_departure_time_s: Departure from the delivery location.

If these parameters are specified for any of the orders, you need to specify them for all the previous orders as well. If actual_arrival_time_s and actual_departure_time_s are specified for the order, you also need to specify node.value.fixed_position = true.

You can also use the arrival_time_s and departure_time_s fields. You can only set them for either all or none of the run locations. Arrival and departure times must be unique for all orders, which is why we don't recommend including multi-orders in additional planning. If a courier's shift starts later than the visit time of their first order, an error will occur during additional planning.

Example
{
    "initial_routes": [
        {
            "route": [
                {
                    "arrival_time_s": 24562,
                    "departure_time_s": 24562,
                    "node": {
                        "value": {
                            "fixed_position": true;
                            ...
                        }
                        ...
                    }
                },
                {
                    "arrival_time_s": 24680,
                    "departure_time_s": 24860,
                    "node": {
                        "value": {
                            "fixed_position": true;
                            ...
                        }
                        ...
                    }
                }
                ...
            ],
            "run_number": 1,
            "shift": {
                "id": "shift_id"
            },
            "vehicle_id": "vehicle1"
        },
        {
            "route": [
                {
                    "actual_arrival_time_s": 31572,
                    "actual_departure_time_s": 31572,
                    "actual_service_start_time_s": 31572,
                    "arrival_time_s": 31572,
                    "departure_time_s": 31572,
                    "node": {
                        "value": {
                            "fixed_position": true;
                            ...
                        }
                        ...
                    }
                },
                {
                    "actual_arrival_time_s": 31740,
                    "actual_departure_time_s": 31920,
                    "actual_service_start_time_s": 31740,
                    "arrival_time_s": 31740,
                    "departure_time_s": 31920,
                    "node": {
                        "value": {
                            "fixed_position": true;
                            ...
                        }
                        ...
                    }
                },
                ...
            ],
            "run_number": 2,
            "shift": {
                "id": "shift_id"
            },
            "vehicle_id": "vehicle1"
        },
        ...
    ]
}

Loaded orders

The IDs of the orders that were loaded into a vehicle before it departed a depot need to be listed in the loaded_orders field for node locations with the depot type. If the new order is not on the loaded_orders list, an additional visit to the depot for loading this order is planned for the courier. If loaded_orders not set, all orders were considered loaded at the depot.

An order can be loaded into a vehicle during the initial planning, but during additional planning it may be set as unassigned. In this case, the order will still take up space in the vehicle. To have the algorithm take this into account, set keep_in_vehicle = true for the order.

Note

If the number of orders after additional planning exceeds the available couriers' capacity for the specified time windows, some orders may not be assigned. If an order must be delivered, set undroppable = true for it.

Assigning orders to available couriers

To assign new orders only to couriers who have completed their current routes, specify in the planning that couriers must return to the depot after completing their routes. Specify depot coordinates using the [nodes] method (https://docs.routeq.com/doc/en/delivery/ref/routes/setsRouteNodesAndTheirSequenceInTheRoute) for the depot nodes.

To restrict adding orders to specific couriers, use tags. For more information, see Vehicle tags.

Balanced loading

The planning algorithm can distribute orders evenly among couriers based on factors such as the number of orders handled, route time, and mileage. To do this, use the balancing option.

When using this option, you need to pass all previous orders and routes (initial_routes) to all additional planning requests made throughout the day.

Courier's current location

If a courier has already started a route, additional planning should take their current location into account. The current location of the courier is specified in the initial_routes block at a separate node location with the type type = courier. You can specify the courier's coordinates at this location using one of the following methods:

  • Specify the identifier of the courier's last visited order in the value.location_id field. The coordinates of this order are considered to be the current coordinates of the courier.

    Example of specifying the courier's location from the last completed order
    "initial_routes": [
        {
            "route": [
                ...
                {
                    "arrival_time_s": 35000,
                    "departure_time_s": 35000,
                    "node": {
                        "type": "courier",
                        "value": {
                            "location_id": "Order 5"
                        }
                    }
                },   
                ...
            ]
        }
    ],
    ...
    "locations": [
        ...
    ]    
    
  • Specify the location identifier In the value.location_id field and add this location with the courier's coordinates to the locations block.

    Example of specifying a courier's coordinates at a location
    "initial_routes": [
        {
            "route": [
                ...
                {
                    "arrival_time_s": 35000,
                    "departure_time_s": 35000,
                    "node": {
                        "type": "courier",
                        "value": {
                            "location_id": "Courier Position"
                        }
                    }
                },   
                ...
            ]
        }
    ],   
    ...
    "locations": [
        ...
        {
            "id": "Courier Position",
            "point": {
                "lat": "61.67259",
                "lon": "50.82052"
            },
            "time_window": "18:00 - 20:00"
        }      
    ]
    

The value.location_id field requires a text value, so all order and depot IDs within the route must be in text format.

If you want to specify the time the courier spends at this location, you can pass it with the actual_arrival_time_s and actual_departure_time_s fields. In this case, you need to fill in these fields for all previous locations on the route (see Tracking delivered orders). The actual_arrival_time_s value for the courier's location should be greater than or equal to actual_departure_time_s for the previous order.

When indicating the courier's location, use the arrival_time_s and departure_time_s fields to specify the current time of submitting the additional planning request.

Examples

Example 1. First planning.

In the first planning, the courier picks up 10 orders from the depot and delivers them: Order 3 → Order 5 → Order 9 → Order 1 → Order 2 → Order 8 → Order 10 → Order 6 → Order 4 → Order 7.

API request (JSON)API responseView on map

Example 2.1. Additional planning without a courier's location.

First planning is as in Example 1. During additional planning, 4 more orders are added. By the time additional planning starts, the courier has already delivered the first two orders. To indicate this, the initial_routes object for the depot and the first two orders has fixed_position = true.

The delivery sequence for the remaining orders in the new solution has changed to: Order 3 → Order 5 → Order 9 → Order 12 → Order 11 → Order 13 → Order 1 → Order 2 → Order 8 → Order 10 → Order 14 → Order 6 → Order 4 → Order 7.

API request (JSON)API responseView on map

Example 2.2. Example of specifying the courier's location from the last completed order.

First planning is as in Example 1. During additional planning, 4 more orders are added. By the time additional planning starts, the courier has already delivered the first two orders. To indicate this, we specify fixed_position = true in the initial_routes object for the depot and the first two orders, and add a courier's location type = courier, where Order 5 (the last completed order) is specified.

The delivery sequence for the remaining orders in the new solution has changed to: Order 3 → Order 5 → Order 11 → Order 12 → Order 9 → Order 13 → Order 1 → Order 2 → Order 8 → Order 10 → Order 14 → Order 6 → Order 4 → Order 7.

API request (JSON)API responseView on map

Example 2.3. Example of specifying a courier's coordinates at a particular location.

First planning is as in Example 1. During additional planning, 4 more orders are added. By the time additional planning starts, the courier has already delivered the first two orders. To indicate this, the initial_routes object for the depot and the first two orders has fixed_position = true. The current position of the courier is defined by the location "Courier Position".

The delivery sequence for the remaining orders in the new solution has changed to: Order 3 → Order 5 → Order 11 → Order 12 → Order 9 → Order 7 → Order 4 → Order 6 → Order 14 → Order 8 → Order 2 → Order 1 → Order 13 → Order 10.

API request (JSON)API responseView on map

Contact support