Setting up regional warehouses and delivery in 1C-Bitrix

Our company is engaged in the development, support and maintenance of Bitrix and Bitrix24 solutions of any complexity. From simple one-page sites to complex online stores, CRM systems with 1C and telephony integration. The experience of developers is confirmed by certificates from the vendor.
Our competencies:
Development stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1175
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Website development for FIXPER company
    811
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Development based on Bitrix, Bitrix24, 1C for the company Development of an Online Appointment Booking Widget for a Medical Center
    564
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Development based on 1C Enterprise for MIRSANBEL
    747
  • image_crm_dolbimby_434_0.webp
    Website development on CRM Bitrix24 for DOLBIMBY
    655
  • image_crm_technotorgcomplex_453_0.webp
    Development based on Bitrix24 for the company TECHNOTORGKOMPLEKS
    976

Configuring Regional Warehouses and Delivery in 1C-Bitrix

When an online store operates multiple warehouses in different cities, the simple "one warehouse — one delivery" model breaks down. A customer in Yekaterinburg should receive shipment from the Ural warehouse, not wait for dispatch from Moscow. 1C-Bitrix provides the tools for this architecture, but correct configuration requires understanding the relationships between the sale, catalog modules, and delivery services.

Warehouses in 1C-Bitrix

Warehouses are managed through the trade catalog module: Trade Catalog → Warehouses. Each warehouse is a record in the b_catalog_store table with fields: address, GPS coordinates, active flag, and location link.

Stock levels per warehouse are stored in b_catalog_store_product:

SELECT cs.title, csp.amount, csp.quantity_reserved
FROM b_catalog_store_product csp
JOIN b_catalog_store cs ON cs.id = csp.store_id
WHERE csp.product_id = 12345;

Reservation on add-to-cart or order placement is configured under Trade Catalog → Settings → Reservation.

Warehouse Selection Logic for an Order

1C-Bitrix does not automatically select a warehouse based on the customer's geolocation out of the box — this requires custom logic. It is implemented via an event handler before shipment creation:

AddEventHandler('sale', 'OnBeforeShipmentSave', 'SelectOptimalStore');

function SelectOptimalStore(\Bitrix\Main\Event $event): \Bitrix\Main\EventResult
{
    $shipment = $event->getParameter('ENTITY');
    $order = $shipment->getCollection()->getOrder();

    // Get the customer's region from the delivery address
    $propertyCollection = $order->getPropertyCollection();
    $cityProp = $propertyCollection->getDeliveryLocation();
    $cityId = $cityProp ? $cityProp->getValue() : null;

    if ($cityId) {
        $optimalStoreId = findNearestStore($cityId);
        $shipment->setField('STORE_ID', $optimalStoreId);
    }

    return new \Bitrix\Main\EventResult(\Bitrix\Main\EventResult::SUCCESS);
}

The findNearestStore function is implemented using the b_catalog_store table filtered by geographic criteria or a pre-defined "region → warehouse" mapping.

Regional Delivery Services

A separate set of delivery services is configured for each warehouse/region. Technically, this means creating multiple instances of the same service with different parameters:

  • CDEK "Moscow" — from_location: 44 (Moscow code in CDEK)
  • CDEK "Yekaterinburg" — from_location: 270 (Yekaterinburg code)

The delivery service display condition is set through rules: Store → Settings → Delivery Rules. Warehouse binding:

// Custom delivery handler with warehouse binding
class RegionalDeliveryHandler extends \Bitrix\Sale\Delivery\Services\Base
{
    public function isCompatible(\Bitrix\Sale\Shipment $shipment): bool
    {
        $storeId = $shipment->getField('STORE_ID');
        return in_array($storeId, $this->arParams['ALLOWED_STORES']);
    }

    protected function calculateConcrete(\Bitrix\Sale\Shipment $shipment): \Bitrix\Sale\Result
    {
        // Calculate cost taking the source warehouse into account
        $fromCity = $this->getStoreCityCode($shipment->getField('STORE_ID'));
        return $this->callDeliveryApi($fromCity, $shipment);
    }
}

Stock and Availability

An important consideration with regional warehouses: the customer sees "in stock," but the nearest warehouse has none — stock is only available at the central warehouse. The solution is to display stock for the specific warehouse or a combined total with an estimated delivery date:

$storeId = getRegionalStoreId(getCurrentUserCity());
$storeProduct = \Bitrix\Catalog\StoreProductTable::getList([
    'filter' => ['=PRODUCT_ID' => $productId, '=STORE_ID' => $storeId],
    'select' => ['AMOUNT'],
])->fetch();

$isAvailable = $storeProduct && $storeProduct['AMOUNT'] > 0;

Timeline

Configuration Timeline
Warehouse setup + region-to-warehouse mapping 1–2 days
Automatic warehouse selection + regional delivery services 3–5 days
Full setup with reservation and 1C synchronization 5–10 days