Stock Availability Filtering for 1C-Bitrix
The "in stock only" filter is one of the most in-demand features in an online store. Users do not want to see made-to-order or out-of-stock items when they need to make an urgent purchase. In Bitrix with the trading catalog module, stock levels are stored in b_catalog_store_product, and filtering by them requires an understanding of how the trading catalog module manages availability.
Stock Storage Architecture
-
b_catalog_product— theQUANTITYfield (total stock),QUANTITY_TRACE(is stock tracking enabled?),CAN_BUY_ZERO(allow purchase when stock is zero?) -
b_catalog_store_product— stock levels per warehouse (STORE_ID,PRODUCT_ID,AMOUNT) -
b_catalog_product_set— kits and bundles (separate logic)
For trade offers (SKU) — stock levels are stored at the offer level, not the parent product level.
"In Stock" Filter via GetList
// Only products with non-zero stock
$filter = [
'IBLOCK_ID' => $iblockId,
'ACTIVE' => 'Y',
// Stock > 0 or purchase allowed with zero stock
[
'LOGIC' => 'OR',
['>CATALOG_QUANTITY' => 0],
['CATALOG_CAN_BUY_ZERO' => 'Y'],
],
// Product with stock tracking
'CATALOG_QUANTITY_TRACE' => 'Y',
];
Or a simpler version for catalogs without CAN_BUY_ZERO:
$filter['>CATALOG_QUANTITY'] = 0;
Filtering by Specific Warehouse
For a multi-warehouse setup (delivery from different cities):
// Products in stock at warehouse ID=3 (e.g., Moscow warehouse)
$storeId = 3;
$minAmount = 1;
// Retrieve IDs of products available at the specified warehouse
$productIds = [];
$rs = \Bitrix\Catalog\StoreProductTable::getList([
'filter' => [
'STORE_ID' => $storeId,
'>AMOUNT' => $minAmount,
],
'select' => ['PRODUCT_ID'],
]);
while ($row = $rs->fetch()) {
$productIds[] = (int)$row['PRODUCT_ID'];
}
if (!empty($productIds)) {
$filter['ID'] = $productIds;
} else {
// No products at the warehouse — return an empty result
return ['items' => [], 'total' => 0];
}
Filtering by Trade Offer (SKU) Availability
For products with variants — check that at least one trade offer is in stock:
// Find parent products that have at least one offer in stock
$parentIds = [];
$offersRs = \CIBlockElement::GetList(
[],
[
'IBLOCK_ID' => OFFERS_IBLOCK_ID, // trade offers infoblock
'ACTIVE' => 'Y',
'>CATALOG_QUANTITY' => 0,
],
false,
false,
['ID', 'PROPERTY_CML2_LINK'] // CML2_LINK — link to the parent product
);
while ($offer = $offersRs->Fetch()) {
$parentId = $offer['PROPERTY_CML2_LINK_VALUE'];
if ($parentId) $parentIds[] = (int)$parentId;
}
$parentIds = array_unique($parentIds);
// Filter the main catalog
if (!empty($parentIds)) {
$filter['ID'] = $parentIds;
}
AJAX "In Stock Only" Toggle
// "In Stock Only" checkbox
const inStockToggle = document.getElementById('filter-in-stock')
inStockToggle.addEventListener('change', () => {
const filters = getActiveFilters()
filters.inStock = inStockToggle.checked
loadCatalog({
...filters,
page: 1,
})
})
// Restore state from URL
const urlParams = new URLSearchParams(window.location.search)
if (urlParams.get('in_stock') === '1') {
inStockToggle.checked = true
}
Displaying Stock Quantity
Show the user a specific stock count or an availability level:
// In the product card template
$quantity = $arItem['CATALOG_QUANTITY'];
$availability = match(true) {
$quantity <= 0 => ['label' => 'Out of stock', 'class' => 'out-of-stock'],
$quantity <= 3 => ['label' => 'Last few items', 'class' => 'low-stock'],
$quantity <= 10 => ['label' => 'Low stock', 'class' => 'limited-stock'],
default => ['label' => 'In stock', 'class' => 'in-stock'],
};
Updating Availability When Receiving Data from 1C
If stock levels are synchronized from 1C via CommerceML or REST, the filter cache must be invalidated on update:
// In the stock update handler
AddEventHandler('catalog', 'OnProductQuantityChange', function($productId) {
\Bitrix\Main\Data\Cache::clearByTag("catalog_filter_section_{$sectionId}");
\CBitrixComponent::clearComponentCache('bitrix:catalog.smart.filter');
});
Timeline
"In Stock" checkbox with AJAX filtering and URL state — 4–8 hours. Multi-warehouse filter with city selection and SKU logic — 2–3 business days.







