Настройка триггера поступления товара на склад 1С-Битрикс

Наша компания занимается разработкой, поддержкой и обслуживанием решений на Битрикс и Битрикс24 любой сложности. От простых одностраничных сайтов до сложных интернет магазинов, CRM систем с интеграцией 1С и телефонии. Опыт разработчиков подтвержден сертификатами от вендора.
Предлагаемые услуги
Показано 1 из 1 услугВсе 1626 услуг
Настройка триггера поступления товара на склад 1С-Битрикс
Простая
~1 рабочий день
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1181
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    813
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Разработка на базе Битрикс, Битрикс24, 1С для компании Development of an Online Appointment Booking Widget for a Medical Center
    564
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Разработка на базе 1С Предприятие для компании МИРСАНБЕЛ
    747
  • image_crm_dolbimby_434_0.webp
    Разработка сайта на CRM Битрикс24 для компании DOLBIMBY
    655
  • image_crm_technotorgcomplex_453_0.webp
    Разработка на базе Битрикс24 для компании ТЕХНОТОРГКОМПЛЕКС
    976

Настройка триггера поступления товара на склад 1С-Битрикс

Товар заканчивается, пользователь нажимает «Уведомить о поступлении» и... ничего. Письмо не приходит никогда, потому что никто не настроил связь между событием пополнения склада и списком ожидающих. Это частый кейс: форма подписки есть, склад пополняется, но автоматика не запущена.

Где хранятся остатки и как они обновляются

В Битрикс остатки товаров живут в двух местах в зависимости от конфигурации:

Простой каталог (без складского учёта): поле CATALOG_QUANTITY в b_catalog_product. Обновляется напрямую через CCatalogProduct::Update() или через обмен с 1С.

Многоскладской учёт (модуль catalog + склады): таблица b_catalog_store_product с полями PRODUCT_ID, STORE_ID, AMOUNT. Общий остаток агрегируется. При обмене 1С через модуль sale.crm.lead или через стандартный обмен данные пишутся в b_catalog_store_product.

Событие изменения остатка — OnProductUpdate в модуле catalog. Оно срабатывает при любом изменении записи в b_catalog_product, включая количество:

AddEventHandler('catalog', 'OnProductUpdate', function($id, $fields) {
    if (isset($fields['QUANTITY']) && $fields['QUANTITY'] > 0) {
        // Товар поступил на склад — была нулевая позиция
        checkAndNotifyWaitlist($id);
    }
});

Проблема: OnProductUpdate срабатывает при любом изменении продукта, не только при пополнении склада. Чтобы отфильтровать именно событие «появился из нуля», нужно сравнивать предыдущее значение. До PHP-события данные ещё в БД, поэтому читаем старое значение в OnBeforeProductUpdate:

AddEventHandler('catalog', 'OnBeforeProductUpdate', function($id, &$fields) {
    $old = \Bitrix\Catalog\ProductTable::getByPrimary($id, ['select' => ['QUANTITY']])->fetch();
    $fields['_OLD_QUANTITY'] = (float)($old['QUANTITY'] ?? 0);
});

Хранение подписок на поступление

Модуль catalog не имеет встроенного механизма «уведомить о поступлении». Нужна собственная таблица:

CREATE TABLE bl_stock_notify (
    id          SERIAL PRIMARY KEY,
    product_id  INT NOT NULL,
    user_id     INT,
    email       VARCHAR(255) NOT NULL,
    created_at  TIMESTAMP DEFAULT NOW(),
    notified_at TIMESTAMP,
    UNIQUE (product_id, email)
);

Форма на сайте пишет в эту таблицу. Уникальный ключ (product_id, email) защищает от дублей при повторных подписках.

Обработчик пополнения

function checkAndNotifyWaitlist(int $productId): void
{
    $connection = \Bitrix\Main\Application::getConnection();
    $waitlist = $connection->query(
        "SELECT * FROM bl_stock_notify WHERE product_id = {$productId} AND notified_at IS NULL"
    )->fetchAll();

    if (empty($waitlist)) {
        return;
    }

    $product = \CIBlockElement::GetByID($productId)->GetNextElement();
    $name    = $product->GetField('NAME');
    $url     = $product->GetField('DETAIL_PAGE_URL');

    foreach ($waitlist as $row) {
        \Bitrix\Main\Mail\Event::send([
            'EVENT_NAME' => 'STOCK_ARRIVED',
            'LID'        => SITE_ID,
            'C_FIELDS'   => [
                'EMAIL'        => $row['email'],
                'PRODUCT_NAME' => $name,
                'PRODUCT_URL'  => 'https://' . $_SERVER['SERVER_NAME'] . $url,
            ],
        ]);

        $connection->queryExecute(
            "UPDATE bl_stock_notify SET notified_at = NOW() WHERE id = {$row['id']}"
        );
    }
}

Интеграция с многоскладским учётом

При многоскладском учёте событие OnProductUpdate не срабатывает при изменении b_catalog_store_product. Для складских операций нужно подписаться на события модуля catalog более глубокого уровня — либо использовать хук после записи документа складского учёта через \Bitrix\Catalog\Document\DocumentTable.

Альтернативный подход: агент, который каждые 5 минут проверяет b_catalog_store_product на появление ненулевых остатков по товарам из листа ожидания. Менее элегантно, но работает стабильнее при нестандартных схемах обновления остатков (например, при прямом UPDATE через 1С-коннектор).

Что настраиваем

  • Обработчики OnBeforeProductUpdate и OnProductUpdate с проверкой перехода «0 → N»
  • Таблицу bl_stock_notify и форму подписки на сайте
  • Шаблон письма STOCK_ARRIVED в административном разделе почтовых событий
  • Для многоскладской конфигурации — агент или обработчик документов склада
  • Логику частичного поступления: если пришло 2 единицы, а подписалось 10 — уведомить всех или первых двух?