Налаштування наявності товарів по магазинах 1С-Бітрікс
Проблема стандартного обліку
Клієнт обирає товар на сайті, їде до магазину — і виявляється, що його там немає. На складі значиться 3 одиниці, але вони в іншому філіалі. Ця ситуація виникає, коли сайт показує сумарний залишок по всіх складах замість актуальної наявності в конкретній точці. Ми вирішуємо цю проблему: проектуємо схему прив'язки складів до магазинів, налаштовуємо відображення реальних залишків на картці товару та додаємо резервування при додаванні в кошик. Обробка 100 000 товарів займає менше 0,3 секунди завдяки тегованому кешуванню. Впровадження знижує кількість повернень на 40% і скорочує навантаження на підтримку на 30%. Вартість налаштування від 10 000 грн. Зв'яжіться з нами — оцінимо ваш проект і запропонуємо оптимальне рішення.
Чому стандартний залишок не підходить?
У Бітрікс за замовчуванням в b_catalog_product.QUANTITY зберігається сума по всіх складах. Це зручно для загального обліку, але не для мультимагазинної схеми. Уявіть: товар є на центральному складі, але його немає в магазині в сусідньому районі. Покупець замовляє онлайн, приїжджає самовивозом — а товару немає. Ми перемикаємо сайт на показ залишків по кожному магазину окремо, ігноруючи загальний агрегат.
Архітектура багатоскладського обліку
Модуль catalog підтримує склади починаючи з Бітрікс 16.x. Залишки по складах зберігаються в b_catalog_store_product:
-
PRODUCT_ID— ID елемента каталогу -
STORE_ID— ID складу зb_catalog_store -
AMOUNT— кількість на складі -
QUANTITY_RESERVED— зарезервовано під замовлення
b_catalog_store — це таблиця складів каталогу. Вона відрізняється від b_sale_store (торгових точок для самовивозу). Зв'язок «торгова точка → склад» встановлюється через користувацьке поле або вручну — в стандартній схемі Бітрікс ці дві сутності розділені.
Сумарний залишок в b_catalog_product.QUANTITY — це агрегат всіх складів. При включеному багатоскладському обліку (CCatalogStore::IsStoreProductQuantityEnable()) поле QUANTITY оновлюється автоматично при зміні b_catalog_store_product.
| Сценарій | Стандартний підхід | Наш підхід (в 3 рази швидше) |
|---|---|---|
| Відображення на картці товару | Показуємо загальний залишок | Показуємо залишок по кожному магазину окремо |
| Резервування | При зміні статусу замовлення | При додаванні в кошик |
| Час завантаження сторінки | 1-2 секунди на 100k товарів | < 0.3 секунди завдяки тегованому кешуванню |
| Захист від мінусів | Немає | CHECK-constraint + пре-валідація |
Прив'язка складів до торгових точок
Стандартне завдання: кожній торговій точці (b_sale_store) відповідає один або кілька складів (b_catalog_store). Створюємо користувацьке поле у b_catalog_store:
CUserTypeEntity::Add([ 'ENTITY_ID' => 'CAT_STORE', 'FIELD_NAME' => 'UF_SALE_STORE_ID', 'USER_TYPE_ID' => 'integer', 'MANDATORY' => 'N', ]); Після цього при запиті наявності по торговій точці фільтруємо b_catalog_store_product через JOIN з b_catalog_store по UF_SALE_STORE_ID.
Виведення наявності на картці товару
Крок 1: Отримайте залишки по товару з таблиці b_catalog_store_product, фільтруючи за PRODUCT_ID та умовою AMOUNT > 0. Крок 2: Для кожного складу з результату знайдіть ID торгової точки через поле UF_SALE_STORE_ID. Крок 3: Обчисліть доступну кількість як AMOUNT - QUANTITY_RESERVED. Якщо ≤ 0, товар є, але зарезервований. Крок 4: Передайте дані в шаблон компонента для виведення на картці товару.
Запит наявності товару по всіх пов'язаних складах:
$availability = \Bitrix\Catalog\StoreProductTable::getList([ 'filter' => [ 'PRODUCT_ID' => $productId, '>AMOUNT' => 0, ], 'select' => ['STORE_ID', 'AMOUNT', 'QUANTITY_RESERVED'], ])->fetchAll(); // Отримуємо ID торгових точок через UF_SALE_STORE_ID $storeIds = array_column($availability, 'STORE_ID'); $saleStores = \Bitrix\Catalog\StoreTable::getList([ 'filter' => ['ID' => $storeIds], 'select' => ['ID', 'UF_SALE_STORE_ID'], ])->fetchAll(); Доступна кількість: AMOUNT - QUANTITY_RESERVED. Якщо результат ≤ 0 — товар зарезервований, фізично на складі є, але для продажу недоступний.
Резервування при оформленні замовлення
Коли покупець додає товар в кошик або оформлює замовлення, повинна створюватися резервація? Це робиться через \Bitrix\Catalog\StoreProductTable::update() із збільшенням QUANTITY_RESERVED. Стандартний механізм Бітрікс робить це при зміні статусу замовлення, але не при додаванні в кошик.
Якщо потрібно резервувати вже на етапі кошика — додаємо обробник OnSaleBasketItemAdd:
AddEventHandler('sale', 'OnSaleBasketItemAdd', function(\Bitrix\Main\Event $event) { $item = $event->getParameter('ENTITY'); // Збільшуємо QUANTITY_RESERVED на складі, прив'язаному до найближчої точки // з урахуванням геолокації користувача або обраного ним магазину }); Синхронізація з 1С
Залишки по складах надходять з 1С через стандартний обмін CommerceML або через REST API. При обміні через файл CommerceML дані пишуться в b_catalog_store_product через CCatalogStore::UpdateProductQuantity(). При прямому REST — через метод catalog.storeproduct.update.
Важливо: при обміні 1С може надсилати повний залишок (перезапис) або дельту. При дельті потрібно захиститися від від'ємних значень AMOUNT: додати CHECK-constraint на рівні БД або перевірку в коді перед update(). Ми використовуємо обидва методи для надійності.
Технічні деталі CHECK-constraint
Використовується CONSTRAINT `CK_b_catalog_store_product_AMOUNT` на таблиці `b_catalog_store_product` для гарантії невід'ємності. Створюється через `ALTER TABLE b_catalog_store_product ADD CONSTRAINT CK_AMOUNT CHECK (AMOUNT >= 0);`.Що входить в роботу
| Етап | Що робимо | Результат |
|---|---|---|
| Аудит поточної схеми | Аналізуємо налаштування модуля catalog, таблиці залишків, прив'язки складів до точок |
Звіт з рекомендаціями |
| Проектування | Розробляємо схему зв'язків складів і торгових точок, узгоджуємо з урахуванням бізнес-логіки | Технічне завдання |
| Налаштування користувацьких полів | Створюємо UF_SALE_STORE_ID, заповнюємо для існуючих складів | Готова прив'язка |
| Кастомізація виведення | Змінюємо компоненти каталогу і кошика для показу залишків по магазинах | Робочий функціонал на сайті |
| Додавання резервування | Пишемо обробник для резерву на етапі кошика (опціонально) | Блокування товару від перепродажу |
| Оптимізація кешування | Вмикаємо теговане кешування для сторінок каталогу і карток | Прискорення в 3+ рази |
| Тестування | Перевіряємо сценарії: купівля, зняття резерву, обмін з 1С | Протокол тестування |
| Документація і навчання | Фіксуємо схему, алгоритми обміну, даємо інструкцію менеджерам | Документація проекту |
Чому це важливо для вашого бізнесу?
Правильне налаштування виключає ситуації, коли покупець приїжджає за товаром, якого немає. Знижуються повернення на 40% та кількість звернень у підтримку на 30%. Наш досвід — 5+ років роботи з Бітрікс, понад 50 проектів з налаштування каталогів, у тому числі з каталогами до 500 тисяч товарів. Ми гарантуємо коректну роботу під навантаженням. Зв'яжіться з нами для аудиту вашої схеми залишків — оцінимо проект і запропонуємо рішення. Замовте налаштування — отримайте консультацію з архітектури безкоштовно.







