Setting up product availability for 1C-Bitrix stores

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
    1212
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Website development for FIXPER company
    815
  • 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
    565
  • 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
    657
  • image_crm_technotorgcomplex_453_0.webp
    Development based on Bitrix24 for the company TECHNOTORGKOMPLEKS
    980

Setting up product availability by stores in 1C-Bitrix

Customer picks a product on site, goes to the store — and finds out it's not there. 3 units in inventory, but they're in another branch. This happens when the site shows total inventory across all warehouses instead of actual availability at specific point.

Multi-warehouse inventory architecture

The catalog module supports warehouses starting with Bitrix 16.x. Inventory by warehouse stored in b_catalog_store_product:

  • PRODUCT_ID — ID of catalog element
  • STORE_ID — ID of warehouse from b_catalog_store
  • AMOUNT — quantity on warehouse
  • QUANTITY_RESERVED — reserved for orders

b_catalog_store — this is the catalog warehouse table. It's different from b_sale_store (pickup points for self-pickup). Connection "pickup point → warehouse" is established via custom field or manually — in standard Bitrix schema these two entities are separated.

Total inventory in b_catalog_product.QUANTITY — aggregate of all warehouses. With multi-warehouse tracking enabled (CCatalogStore::IsStoreProductQuantityEnable()) field QUANTITY updates automatically on b_catalog_store_product changes.

Binding warehouse to pickup point

Standard task: each pickup point (b_sale_store) corresponds to one or more warehouses (b_catalog_store). Create custom field in b_catalog_store:

CUserTypeEntity::Add([
    'ENTITY_ID'  => 'CAT_STORE',
    'FIELD_NAME' => 'UF_SALE_STORE_ID',
    'USER_TYPE_ID' => 'integer',
    'MANDATORY'  => 'N',
]);

After this when requesting availability by pickup point filter b_catalog_store_product via JOIN with b_catalog_store by UF_SALE_STORE_ID.

Displaying availability on product card

Query product availability across all linked warehouses:

$availability = \Bitrix\Catalog\StoreProductTable::getList([
    'filter' => [
        'PRODUCT_ID' => $productId,
        '>AMOUNT'    => 0,
    ],
    'select' => ['STORE_ID', 'AMOUNT', 'QUANTITY_RESERVED'],
])->fetchAll();

// Get pickup point IDs via UF_SALE_STORE_ID
$storeIds = array_column($availability, 'STORE_ID');
$saleStores = \Bitrix\Catalog\StoreTable::getList([
    'filter' => ['ID' => $storeIds],
    'select' => ['ID', 'UF_SALE_STORE_ID'],
])->fetchAll();

Available quantity: AMOUNT - QUANTITY_RESERVED. If result ≤ 0 — product is reserved, physically on warehouse but not available for sale.

Reserving on order placement

When customer adds product to cart or places order, reservation should be created. This is done via \Bitrix\Catalog\StoreProductTable::update() with QUANTITY_RESERVED increase. Standard Bitrix mechanism does this on order status change, but not on adding to cart.

If you need to reserve at cart stage — add handler OnSaleBasketItemAdd:

AddEventHandler('sale', 'OnSaleBasketItemAdd', function(\Bitrix\Main\Event $event) {
    $item = $event->getParameter('ENTITY');
    // Increase QUANTITY_RESERVED on warehouse linked to nearest point
    // with user geolocation or chosen store
});

Syncing with 1C

Inventory by warehouse comes from 1C via standard exchange or REST API. On exchange via CommerceML/XML file data is written to b_catalog_store_product via CCatalogStore::UpdateProductQuantity(). With direct REST — via method catalog.storeproduct.update.

Important: on 1C exchange it can send full inventory (rewrite) or delta. With delta protect against negative AMOUNT values: add CHECK constraint at DB level or check in code before update().

What we configure

  • Checking multi-warehouse tracking is enabled and b_catalog_store_product is populated
  • Custom field UF_SALE_STORE_ID in b_catalog_store for linking to catalog warehouses
  • Displaying availability by pickup points on product card
  • Calculating available quantity accounting for QUANTITY_RESERVED
  • Handler for reserving on adding to cart (if required)
  • Scheme for syncing inventory from 1C with protection from negative values