Настройка единого складского учёта онлайн и оффлайн 1С-Битрикс
Сайт показывает «в наличии 5 штук». В это время в магазине продают последние три единицы. Через час онлайн-покупатель оформляет заказ на 4 штуки — и менеджер звонит с отказом. Это происходит, когда онлайн и оффлайн работают с разными базами остатков.
Источники истины об остатках
В типичной конфигурации: 1С — мастер-источник остатков, Битрикс — потребитель. 1С знает о всех движениях товара: поступления, продажи онлайн, продажи оффлайн, инвентаризации, списания. Битрикс получает актуальные данные через синхронизацию.
Проблема в частоте синхронизации. Стандартный обмен через CommerceML работает по расписанию — раз в 15–60 минут. За это время в оффлайн-магазине может быть продано несколько единиц, а сайт продолжает показывать старые остатки.
Немедленное обновление при оффлайн-продаже
Для минимизации расхождения — интеграция кассы с Битрикс в реальном времени. При каждой продаже на оффлайн-кассе немедленный webhook в Битрикс:
// /local/ajax/pos-sale-callback.php
$data = json_decode(file_get_contents('php://input'), true);
foreach ($data['items'] as $item) {
$product = \CCatalogProduct::GetByID($item['sku']);
if (!$product) continue;
// Уменьшаем остаток на конкретном складе
\Bitrix\Catalog\StoreProductTable::update(
['PRODUCT_ID' => $item['product_id'], 'STORE_ID' => $data['store_id']],
['AMOUNT' => new \Bitrix\Main\DB\SqlExpression('AMOUNT - ?', $item['quantity'])]
);
// Пересчитываем суммарный остаток в b_catalog_product
\CCatalogProduct::RecalcQuantity($item['product_id']);
}
RecalcQuantity() пересчитывает b_catalog_product.QUANTITY как сумму по всем складам в b_catalog_store_product. После этого кеш товара должен быть инвалидирован — через BXClearCache(false, '/catalog/') или тегированный кеш.
Резервирование онлайн-остатков
Частая практика для магазинов с несколькими каналами продаж: выделить отдельный «онлайн-склад» в b_catalog_store, остатки которого предназначены только для интернет-магазина. Физически товар может быть на одном складе, но логически разделён.
При этом оффлайн-продажи уменьшают «физический склад», а онлайн-заказы резервируются из «онлайн-склада». Ночью 1С пополняет онлайн-склад из физического по заданной пропорции.
Физический склад: 100 единиц
Онлайн-квота: 30% = 30 единиц → хранится в b_catalog_store_product (STORE_ID = online_store)
Оффлайн-квота: 70% = 70 единиц → не попадает в Битрикс
Это исключает ситуацию overselling, но снижает доступный остаток для онлайн-продаж.
Работа с документами складского учёта
В Битрикс модуль catalog поддерживает складские документы: \Bitrix\Catalog\Document\DocumentTable. Типы документов: A — приход, S — продажа, M — перемещение, R — возврат.
При проведении документа через \Bitrix\Catalog\Document\DocumentController::conduct() автоматически пересчитываются остатки в b_catalog_store_product. Это правильный способ двигать остатки — через документы, а не прямым UPDATE.
Для оффлайн-продаж: при получении webhook от кассы создаём документ типа S с позициями продажи и проводим его. Это обеспечивает полную историю движения товара и корректный складской учёт.
Инвентаризация и сверка
Расхождения между 1С и Битрикс неизбежны. Важно уметь их находить. Раз в сутки запускаем агент-сверщик:
// Получаем остатки из 1С через REST API
$bx1cItems = get1cQuantities();
// Сравниваем с b_catalog_store_product
foreach ($bx1cItems as $sku => $qty) {
$bitrixQty = StoreProductTable::getList([
'filter' => ['PRODUCT.XML_ID' => $sku],
'select' => ['AMOUNT'],
])->fetch()['AMOUNT'] ?? 0;
if (abs($bitrixQty - $qty) > 0) {
logDiscrepancy($sku, $bitrixQty, $qty);
}
}
Лог расхождений позволяет принять решение: корректировать Битрикс по 1С (1С — мастер) или сигнализировать о проблеме в интеграции.
Что настраиваем
- Webhook-endpoint для получения данных о продажах с оффлайн-касс
- Обновление
b_catalog_store_productчерез документы типаS - Вызов
RecalcQuantity()и инвалидацию кеша после каждого движения - Схему разделения остатков (онлайн-квота vs физический склад) при необходимости
- Ночной агент-сверщик с 1С и логированием расхождений







