Setting up stock updates on schedule from external sources for 1С-Bitrix
Customer places an order, pays, waits for delivery — but the item isn't in stock. Stock levels on the site weren't updated for two days, and in that time the position was sold. Refund, negative review, lost customer. Automatic scheduled stock updates solve this problem — provided it's configured correctly.
How Bitrix stores stock
The catalog module stores availability data in several tables:
-
b_catalog_product— main product table. FieldQUANTITY— total stock,QUANTITY_TRACE— is quantity tracking enabled,CAN_BUY_ZERO— can buy when zero. -
b_catalog_store_product— stock by warehouse. FieldAMOUNT— quantity in specific warehouse (STORE_ID). -
b_catalog_store— warehouse reference.
If the site has one warehouse — update QUANTITY in b_catalog_product is sufficient. If warehouse tracking is enabled (multiple warehouses, address-based storage) — update b_catalog_store_product and Bitrix recalculates total automatically.
Update via API
Simple variant — one warehouse:
\Bitrix\Catalog\ProductTable::update($productId, [
'QUANTITY' => $newQuantity,
]);
Warehouse tracking — multiple warehouses:
$existing = \Bitrix\Catalog\StoreProductTable::getList([
'filter' => ['PRODUCT_ID' => $productId, 'STORE_ID' => $storeId],
])->fetch();
if ($existing) {
\Bitrix\Catalog\StoreProductTable::update($existing['ID'], ['AMOUNT' => $newQuantity]);
} else {
\Bitrix\Catalog\StoreProductTable::add([
'PRODUCT_ID' => $productId,
'STORE_ID' => $storeId,
'AMOUNT' => $newQuantity,
]);
}
After updating warehouse stocks, call total quantity recalculation:
CCatalogProduct::QuantityTracer($productId);
Supplier data formats
| Format | Parsing | Specifics |
|---|---|---|
| CSV | fgetcsv() |
Simple but untyped — "10" and "10 pcs" need normalization |
| Excel (XLSX) | PhpSpreadsheet |
Often multiple sheets, headers on line 2–3 |
| XML (CommerceML) | SimpleXMLElement |
1С standard, structure known in advance |
| REST API | curl / Guzzle |
JSON response, pagination, auth |
| FTP file | ftp_get() |
File appears at specific time, needs retry |
Product mapping
Key task — match supplier product identifier with Bitrix catalog element. Options:
-
By SKU — property
PROPERTY_ARTICLEorPROPERTY_SUPPLIER_SKU. Most reliable if SKUs are unique. - By XML_ID — if catalog was initially imported from same source.
-
By barcode —
b_catalog_product_barcodetable. Reliable but not all products have barcodes.
For mapping, create indexed correspondence table:
CREATE TABLE parser_product_map (
supplier_sku VARCHAR(100) NOT NULL,
product_id INT NOT NULL,
store_id INT DEFAULT 1,
PRIMARY KEY (supplier_sku, store_id),
INDEX idx_product (product_id)
);
Query through this table is 10–50 times faster than searching by info block properties for each product.
Handling zero stock
When product runs out, three behavior strategies:
-
Deactivation (
ACTIVE = 'N') — product disappears from site. Bad for SEO: page stops indexing, positions lost. -
Show with "Out of stock" label —
QUANTITY = 0,CAN_BUY_ZERO = 'N'. "Buy" button replaced with "Notify me". Optimal option. -
Pre-order —
CAN_BUY_ZERO = 'Y'. Customer can place order, item comes with next shipment. Good for predictable restock items.
Strategy is set globally in catalog module settings and can be overridden per product.
Cron and schedule
Update frequency depends on product turnover:
| Product type | Update frequency | Justification |
|---|---|---|
| Fast-moving (electronics, food) | Every 15–30 min | Quick turnover, high oversell risk |
| Medium (clothing, tools) | Every 1–2 hours | Balance between accuracy and load |
| Slow-moving (furniture, equipment) | 2–4 times daily | Low turnover |
# Update stock every 30 minutes
*/30 * * * * /usr/bin/php /home/bitrix/scripts/update_stock.php >> /var/log/stock_update.log 2>&1
Performance
Updating 50,000+ positions element-by-element via API is too slow — 3–5 seconds per product due to event handlers and cache recalculation. Optimization:
-
Batch UPDATE — direct SQL query to update
b_catalog_store_productin batches of 500–1000 rows. -
Disable events —
\Bitrix\Catalog\ProductTable::disableEvents()during bulk update. - Deferred recalculation — update all stocks, then recalculate availability once and clear cache.
Monitoring
Stock update is a critical process. If the script crashes or supplier doesn't provide file — catalog shows stale data. Minimal monitoring:
- Check time of last successful update. If more than two intervals passed — alert.
- Log number of updated, skipped (not found in mapping), and errored positions.
- Control anomalies: if 80% of catalog stock zeroed out — likely supplier file error, not real sell-out.







