Настройка обновления остатков по расписанию из внешних источников 1С-Битрикс
Покупатель оформляет заказ, оплачивает, ждёт доставку — а товара на складе нет. Остатки на сайте не обновлялись двое суток, и за это время позиция ушла. Возврат средств, негативный отзыв, потеря клиента. Автоматическое обновление остатков по расписанию решает эту проблему — при условии, что настроено правильно.
Как Битрикс хранит остатки
Модуль catalog хранит данные о наличии в нескольких таблицах:
-
b_catalog_product— основная таблица товаров каталога. ПолеQUANTITY— общий остаток,QUANTITY_TRACE— включён ли учёт количества,CAN_BUY_ZERO— можно ли покупать при нуле. -
b_catalog_store_product— остатки по складам. ПолеAMOUNT— количество на конкретном складе (STORE_ID). -
b_catalog_store— справочник складов.
Если на сайте один склад — достаточно обновлять QUANTITY в b_catalog_product. Если включён складской учёт (несколько складов, адресное хранение) — обновляйте b_catalog_store_product, а Битрикс пересчитает общий остаток автоматически.
Обновление через API
Простой вариант — один склад:
\Bitrix\Catalog\ProductTable::update($productId, [
'QUANTITY' => $newQuantity,
]);
Складской учёт — несколько складов:
$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,
]);
}
После обновления остатков по складам вызовите пересчёт общего количества:
CCatalogProduct::QuantityTracer($productId);
Форматы данных от поставщиков
| Формат | Парсинг | Особенности |
|---|---|---|
| CSV | fgetcsv() |
Простой, но без типизации — «10» и «10 шт.» нужно нормализовать |
| Excel (XLSX) | PhpSpreadsheet |
Часто содержит несколько листов, заголовки на 2–3 строке |
| XML (CommerceML) | SimpleXMLElement |
Стандарт 1С, структура известна заранее |
| REST API | curl / Guzzle |
JSON-ответ, пагинация, авторизация |
| FTP-файл | ftp_get() |
Файл появляется в определённое время, нужен retry |
Маппинг товаров
Ключевая задача — сопоставить идентификатор товара в прайсе поставщика с элементом каталога Битрикс. Варианты:
-
По артикулу — свойство
PROPERTY_ARTICLEилиPROPERTY_SUPPLIER_SKU. Наиболее надёжный при условии, что артикулы уникальны. - По XML_ID — если каталог изначально импортирован из того же источника.
-
По штрихкоду — таблица
b_catalog_product_barcode. Надёжно, но штрихкоды есть не у всех товаров.
Для маппинга создайте индексированную таблицу соответствий:
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)
);
Запрос через эту таблицу в 10–50 раз быстрее, чем поиск по свойствам инфоблока на каждый товар.
Обработка нулевых остатков
Когда товар заканчивается, есть три стратегии поведения:
-
Деактивация (
ACTIVE = 'N') — товар исчезает с сайта. Плохо для SEO: страница перестаёт индексироваться, теряются позиции. -
Показ с пометкой «Нет в наличии» —
QUANTITY = 0,CAN_BUY_ZERO = 'N'. Кнопка «Купить» заменяется на «Сообщить о поступлении». Оптимальный вариант. -
Предзаказ —
CAN_BUY_ZERO = 'Y'. Покупатель может оформить заказ, товар придёт с ближайшей поставкой. Подходит для товаров с предсказуемым сроком поставки.
Стратегия задаётся глобально в настройках модуля catalog и может быть переопределена для конкретного товара.
Cron и расписание
Частота обновления зависит от оборачиваемости товара:
| Тип товара | Частота обновления | Обоснование |
|---|---|---|
| Ходовой (электроника, продукты) | Каждые 15–30 мин | Быстрая оборачиваемость, высокий риск пересорта |
| Средний (одежда, инструмент) | Каждые 1–2 часа | Баланс актуальности и нагрузки |
| Медленный (мебель, оборудование) | 2–4 раза в сутки | Низкая оборачиваемость |
# Обновление остатков каждые 30 минут
*/30 * * * * /usr/bin/php /home/bitrix/scripts/update_stock.php >> /var/log/stock_update.log 2>&1
Производительность
При обновлении 50 000+ позиций поэлементное обновление через API слишком медленное — 3–5 секунд на товар из-за обработчиков событий и пересчёта кешей. Оптимизация:
-
Батчевый UPDATE — прямой SQL-запрос для обновления
b_catalog_store_productпакетами по 500–1000 строк. -
Отключение событий —
\Bitrix\Catalog\ProductTable::disableEvents()на время массового обновления. - Отложенный пересчёт — обновить все остатки, затем однократно пересчитать доступность и сбросить кеш.
Мониторинг
Обновление остатков — критический процесс. Если скрипт упал или поставщик не отдал файл — каталог показывает устаревшие данные. Минимальный мониторинг:
- Проверка времени последнего успешного обновления. Если прошло больше двух интервалов — алерт.
- Логирование количества обновлённых, пропущенных (не найдено в маппинге) и ошибочных позиций.
- Контроль аномалий: если разом обнулились остатки по 80% каталога — скорее всего, ошибка в файле поставщика, а не реальная распродажа.







