Розробка модуля підписки на товари 1С-Бітрікс
«Сповістити, коли з'явиться в наявності» — базова потреба для інтернет-магазину з товарами, які не завжди є в наявності. Стандартний Бітрікс не має такого механізму. Завдання часто закривають формою зворотного зв'язку з ручною обробкою, що погано масштабується. Модуль підписки вирішує завдання системно: автоматична постановка в чергу, відправлення сповіщень при появі залишку, статистика по затребуваності позицій.
Модель даних
Модуль vendor.waitlist:
-
b_vendor_waitlist_subscription— підписки: id, user_id, email (для незареєстрованих), product_id, sku_id (торгова пропозиція), created_at, notified_at, status (active/notified/cancelled) -
b_vendor_waitlist_notify_log— журнал сповіщень: id, subscription_id, sent_at, result (sent/failed), error
Підписка на конкретний SKU
При натисканні «Сповістити про надходження» клієнт вводить email або підписується через обліковий запис:
class WaitlistService
{
public function subscribe(int $productId, ?int $skuId, int $userId, string $email): SubscribeResult
{
// Перевіряємо, чи немає вже активної підписки від цього користувача/email на цей товар
$existing = SubscriptionTable::getList([
'filter' => [
'PRODUCT_ID' => $productId,
'SKU_ID' => $skuId,
'STATUS' => 'active',
'=EMAIL' => $email,
],
])->fetch();
if ($existing) {
return SubscribeResult::alreadySubscribed();
}
SubscriptionTable::add([
'USER_ID' => $userId ?: null,
'EMAIL' => $email,
'PRODUCT_ID' => $productId,
'SKU_ID' => $skuId,
'STATUS' => 'active',
]);
return SubscribeResult::success();
}
}
Тригер при надходженні товару
При зміні залишків через API або 1С-синхронізацію спрацьовує подія OnProductStockChanged (кастомна подія модуля, викликається з обробника OnAfterIBlockElementUpdate):
AddEventHandler('iblock', 'OnAfterIBlockElementUpdate', ['\Vendor\Waitlist\StockWatcher', 'onElementUpdate']);
public static function onElementUpdate(array &$fields): void
{
// Перевіряємо: це торгова пропозиція? Чи змінився QUANTITY?
if (!isset($fields['PROPERTY_VALUES']['QUANTITY'])) return;
$newQty = (int)$fields['PROPERTY_VALUES']['QUANTITY'];
if ($newQty <= 0) return;
// Шукаємо активні підписки на цей SKU
$subscriptions = SubscriptionTable::getList([
'filter' => ['SKU_ID' => $fields['ID'], 'STATUS' => 'active'],
])->fetchAll();
foreach ($subscriptions as $sub) {
NotifyQueueTable::add(['SUBSCRIPTION_ID' => $sub['ID']]);
}
}
Сповіщення відправляються з черги агентом — не блокуючи процес збереження елемента.
Агент відправлення сповіщень
public static function run(): string
{
$queue = NotifyQueueTable::getList(['limit' => 100, 'filter' => ['STATUS' => 'pending']])->fetchAll();
foreach ($queue as $item) {
$sub = SubscriptionTable::getById($item['SUBSCRIPTION_ID'])->fetch();
// Повторно перевіряємо залишок: раптом розкупили поки агент спав
$qty = \CIBlockElement::GetProperty($sub['SKU_ID'], false, 'QUANTITY', true);
if ($qty <= 0) {
NotifyQueueTable::delete($item['ID']);
continue;
}
$result = \Bitrix\Main\Mail\Event::send([
'EVENT_NAME' => 'WAITLIST_PRODUCT_AVAILABLE',
'LID' => SITE_ID,
'C_FIELDS' => [
'EMAIL' => $sub['EMAIL'],
'PRODUCT_ID' => $sub['PRODUCT_ID'],
'PRODUCT_URL' => \CIBlockElement::GetDetailPageUrl($sub['PRODUCT_ID']),
],
]);
SubscriptionTable::update($sub['ID'], ['STATUS' => 'notified', 'NOTIFIED_AT' => new DateTime()]);
}
return '\Vendor\Waitlist\NotifyAgent::run();';
}
Віджет на картці товару
Компонент vendor:waitlist.button підключається до картки товару. Визначає:
- Чи є у поточного користувача активна підписка на даний SKU
- Відображає кнопку «Сповістити про надходження» або «Ви підписані»
- Для незалогінених — форма введення email без реєстрації
Статистика та аналітика
В адміністративному інтерфейсі:
- Топ товарів за кількістю підписок — розуміння реального попиту
- Конверсія: скільки користувачів купили після отримання сповіщення
- Середній час від підписки до сповіщення
- Список «вічних» очікувачів — підписки старше N днів без сповіщення
Статистика попиту безпосередньо корисна для закупівельної служби.
Терміни розробки
| Етап | Термін |
|---|---|
| ORM-таблиці, сервіс підписки | 1 день |
| Тригер зміни залишків | 1 день |
| Черга та агент сповіщень | 1 день |
| Віджет картки товару | 1 день |
| Email-шаблон сповіщення | 0.5 дня |
| Статистика та аналітика | 1 день |
| Адміністративний інтерфейс | 1 день |
| Тестування | 0.5 дня |
Разом: 7 робочих днів. Підтримка push-сповіщень як додаткового каналу — +1 день.







