Configuring Courier Delivery Route Optimization in 1C-Bitrix
Route optimization — the traveling salesman problem: there are N delivery addresses and a courier, the goal is to visit all with minimal mileage. Bitrix doesn't solve this problem itself, but serves as a data source for orders. Optimized routes are built by external services (Yandex.Routing, Google OR-Tools, Routific) and passed back as courier tasks.
Preparing delivery data
To build a route, you need a list of addresses with coordinates and time windows. Addresses are taken from order properties:
$deliveries = \Bitrix\Sale\OrderTable::getList([
'filter' => [
'STATUS_ID' => 'TD', // status "to be delivered today"
'>=DATE_STATUS' => new \Bitrix\Main\Type\Date(),
],
'select' => ['ID'],
])->fetchAll();
$points = [];
foreach ($deliveries as $row) {
$order = \Bitrix\Sale\Order::load($row['ID']);
$props = $order->getPropertyCollection();
$points[] = [
'order_id' => $row['ID'],
'address' => $props->getItemByOrderPropertyCode('ADDRESS')?->getValue(),
'lat' => $props->getItemByOrderPropertyCode('LAT')?->getValue(),
'lon' => $props->getItemByOrderPropertyCode('LON')?->getValue(),
'time_from' => $props->getItemByOrderPropertyCode('DELIVERY_TIME_FROM')?->getValue(),
'time_to' => $props->getItemByOrderPropertyCode('DELIVERY_TIME_TO')?->getValue(),
'weight' => $this->getOrderWeight($order),
];
}
Coordinates (LAT/LON) must be obtained during checkout — through geocoding via Yandex or Google API based on entered address. Save them in custom order properties.
Geocoding addresses during checkout
When filling in an address in the order form — AJAX request to geocoder:
fetch(`https://geocode-maps.yandex.ru/1.x/?apikey=KEY&format=json&geocode=${encodeURIComponent(address)}`)
.then(r => r.json())
.then(data => {
const pos = data.response.GeoObjectCollection.featureMember[0]?.GeoObject?.Point?.pos;
if (pos) {
const [lon, lat] = pos.split(' ');
document.getElementById('lat-field').value = lat;
document.getElementById('lon-field').value = lon;
}
});
Coordinates are saved to hidden form fields and included in order properties.
Integration with route optimization service
After collecting points, send them to the optimizer API. Example with Yandex.Routing (details — separate service):
$httpClient = new \Bitrix\Main\Web\HttpClient();
$response = $httpClient->post(
'https://courier.yandex.ru/api/v1/companies/{company_id}/routes',
json_encode(['vehicles' => $vehicles, 'orders' => $points]),
['Authorization' => 'Bearer ' . YANDEX_COURIER_API_KEY]
);
$routes = json_decode($response, true);
Returned routes contain an ordered list of points for each courier. Save them in bl_courier_routes and assign to couriers through CRM tasks or mobile application.
Displaying route to courier
Create a mobile page or send the courier a link to the route in Google Maps or Yandex.Maps with waypoints. Format for Google Maps:
https://www.google.com/maps/dir/DEPOT_LAT,DEPOT_LON/STOP1_LAT,STOP1_LON/STOP2_LAT,STOP2_LON/...
Generate this link from bl_courier_routes data and send to courier via SMS or email.
What we configure
- Custom order properties
LAT,LON,DELIVERY_TIME_FROM,DELIVERY_TIME_TO - Address geocoding during checkout via JavaScript + Yandex/Google API
- Agent for collecting delivery points and sending requests to route optimizer
-
bl_courier_routestable for storing optimized routes - Route link generation and distribution to couriers







