Розробка системи групових покупок на 1С-Бітрікс

Розробка системи групових покупок на 1С-Бітрікс — задача, з якою до нас звертаються, коли стандартні знижки не працюють. Коробковий Бітрікс не вміє прив'язувати знижку до кількості учасників: модуль `sale` оперує індивідуальними замовленнями, а `b_catalog_discount` статичний. Ми будуємо всю логіку п
Послуги, які ми пропонуємо
Показано 1 з 1Усі 1626 послуг
Розробка системи групових покупок на 1С-Бітрікс
Середній
~1-2 тижні

Наші компетенції:

Часті запитання

Останні роботи

  • Розробка сайту компанії B2B ADVANCE
    Розробка сайту компанії B2B ADVANCE
    1460
  • Розробка веб-сайту для компанії ФІКСПЕР
    Розробка веб-сайту для компанії ФІКСПЕР
    1019
  • Розробка на базі Бітрікс, Бітрікс24, 1С для компанії Development of an Online
    Розробка на базі Бітрікс, Бітрікс24, 1С для компанії Development of an Online
    764
  • Розробка на базі 1С Підприємство для компанії МИРСАНБЕЛ
    Розробка на базі 1С Підприємство для компанії МИРСАНБЕЛ
    882
  • Розробка сайту на CRM Бітрікс24 для компанії DOLBIMBY
    Розробка сайту на CRM Бітрікс24 для компанії DOLBIMBY
    809
  • Розробка на базі Бітрікс24 для компанії ТЕХНОТОРГКОМПЛЕКС
    Розробка на базі Бітрікс24 для компанії ТЕХНОТОРГКОМПЛЕКС
    1164

Розробка системи групових покупок на 1С-Бітрікс — задача, з якою до нас звертаються, коли стандартні знижки не працюють. Коробковий Бітрікс не вміє прив'язувати знижку до кількості учасників: модуль sale оперує індивідуальними замовленнями, а b_catalog_discount статичний. Ми будуємо всю логіку поверх стандартної архітектури, використовуючи кастомні таблиці та транзакції. Типовий кейс: інтернет-магазин запускає акцію «чим більше покупців, тим нижча ціна». Без доопрацювання кожен новий учасник оформлює замовлення за однаковою ціною. Ми додаємо систему, яка динамічно перераховує вартість і синхронізує лічильник учасників у реальному часі. Наша команда має 10+ років досвіду в розробці на 1С-Бітрікс та понад 50 успішних проєктів. Ми знаємо всі підводні камені та готові реалізувати систему під ключ за 1–5 тижнів.

Система групових покупок: архітектура та знижки

Система будується навколо сутності «акція групової покупки». Найзручніше зберігати її в окремому HL-блоці або кастомній таблиці. Приклад структури:

CREATE TABLE b_group_deal ( ID INT AUTO_INCREMENT PRIMARY KEY, PRODUCT_ID INT NOT NULL, DATE_START DATETIME NOT NULL, DATE_END DATETIME NOT NULL, MIN_PARTICIPANTS INT NOT NULL, MAX_PARTICIPANTS INT, CURRENT_COUNT INT DEFAULT 0, STATUS ENUM('active','success','failed','closed') DEFAULT 'active', INDEX idx_product (PRODUCT_ID), INDEX idx_status_date (STATUS, DATE_END) ); CREATE TABLE b_group_deal_tier ( ID INT AUTO_INCREMENT PRIMARY KEY, DEAL_ID INT NOT NULL, PARTICIPANTS_FROM INT NOT NULL, DISCOUNT_PERCENT DECIMAL(5,2), PRICE_FIXED DECIMAL(10,2), FOREIGN KEY (DEAL_ID) REFERENCES b_group_deal(ID) ); CREATE TABLE b_group_deal_participant ( ID INT AUTO_INCREMENT PRIMARY KEY, DEAL_ID INT NOT NULL, USER_ID INT NOT NULL, ORDER_ID INT, DATE_ADD DATETIME NOT NULL, STATUS ENUM('waiting','paid','cancelled','refunded') ); 

Лічильник CURRENT_COUNT оновлюється тільки за статусом paid — попередні участі без оплати не враховуються.

Як запобігти race condition?

Головна інженерна проблема — одночасне приєднання учасників. Якщо два клієнти читають CURRENT_COUNT = 9 при MIN_PARTICIPANTS = 10, обидва можуть стати «активуючим» учасником. Захист — атомарне оновлення:

use Bitrix\Main\Application; $connection = Application::getConnection(); $connection->startTransaction(); try { $row = $connection->query( "SELECT * FROM b_group_deal WHERE ID = {$dealId} AND STATUS = 'active' FOR UPDATE" )->fetch(); if (!$row || strtotime($row['DATE_END']) < time()) { $connection->rollbackTransaction(); return ['error' => 'Deal not available']; } $connection->query( "INSERT INTO b_group_deal_participant (DEAL_ID, USER_ID, DATE_ADD, STATUS) VALUES ({$dealId}, {$userId}, NOW(), 'waiting')" ); $connection->query( "UPDATE b_group_deal SET CURRENT_COUNT = CURRENT_COUNT + 1 WHERE ID = {$dealId}" ); $connection->commitTransaction(); } catch (\Exception $e) { $connection->rollbackTransaction(); throw $e; } 

Після приєднання учасник отримує статус waiting. Оплата відбувається двома сценаріями:

Сценарій A — передоплата: учасник одразу оформлює замовлення та платить. Якщо акція не набирає MIN_PARTICIPANTS до DATE_END, гроші повертаються автоматично через обробник агента.

Сценарій B — відкладене замовлення: учасник бронює місце без оплати. При досягненні мінімуму всім учасникам надсилається сповіщення з пропозицією оформити замовлення за зниженою ціною. Дедлайн — 24–48 годин.

Порівняння сценаріїв:

Сценарій Оплата Ризик для покупця Ризик для магазину
Передоплата Одразу Гроші заморожені до завершення акції Повернення при провалі
Відкладене замовлення Після досягнення мінімуму Немає ризику, але потрібно стежити за сповіщенням Частина учасників може не оформити замовлення

Ціноутворення та знижки: приклади

Поточна знижка розраховується динамічно за таблицею b_group_deal_tier. Наприклад, при 5 учасниках знижка 10%, при 10 — 20%, при 20 — 30%. Не можна використовувати стандартну систему знижок b_catalog_discount — вона не вміє працювати з динамічним лічильником. Розрахунок активного тиру:

function getActiveTier(int $dealId, int $currentCount): ?array { $connection = Application::getConnection(); return $connection->query( "SELECT * FROM b_group_deal_tier WHERE DEAL_ID = {$dealId} AND PARTICIPANTS_FROM <= {$currentCount} ORDER BY PARTICIPANTS_FROM DESC LIMIT 1" )->fetch() ?: null; } 

При додаванні в кошик ціна підставляється через обробник OnSaleBasketItemRefreshData.

Скільки коштує впровадження?

Вартість розробки залежить від складності: MVP від $800, повна система від $1500, маркетплейс від $3000. Економія для покупців у середньому становить 20–30%, що при сумі замовлення 5000 грн дає економію 1000–1500 грн. Ми реалізували понад 15 таких систем за останні 2 роки.

Візуальний прогрес-бар

Компонент прогресу — AJAX-віджет, що оновлюється кожні 30 секунд. Дані віддає контролер:

// /local/ajax/group-deal-status.php $deal = $connection->query( "SELECT gd.*, gt.DISCOUNT_PERCENT, gt.PARTICIPANTS_FROM as NEXT_TIER FROM b_group_deal gd LEFT JOIN b_group_deal_tier gt ON gt.DEAL_ID = gd.ID AND gt.PARTICIPANTS_FROM > gd.CURRENT_COUNT WHERE gd.ID = {$dealId} ORDER BY gt.PARTICIPANTS_FROM ASC LIMIT 1" )->fetch(); header('Content-Type: application/json'); echo json_encode([ 'current' => (int)$deal['CURRENT_COUNT'], 'next_tier' => (int)$deal['NEXT_TIER'], 'discount' => (float)$deal['DISCOUNT_PERCENT'], 'time_left' => strtotime($deal['DATE_END']) - time(), ]); 

Прогрес-бар відображає відсоток current / next_tier * 100 і показує, скільки учасників потрібно до наступного ступеня знижки.

Завершення акції та повернення

Агент CAgent запускається кожні 5 хвилин (див. офіційну документацію Bitrix) і перевіряє акції зі збіглим DATE_END:

  • Якщо CURRENT_COUNT >= MIN_PARTICIPANTS → статус success. Учасники з waiting отримують завдання оформити замовлення.
  • Якщо CURRENT_COUNT < MIN_PARTICIPANTS → статус failed. Учасникам з paid виконується повернення через \Bitrix\Sale\PaySystem\Manager::refund().

Сповіщення надсилаються через \Bitrix\Main\Mail\Event::send() з кастомними шаблонами.

Що входить у роботу: покроковий план

  1. Аналіз вимог та проєктування схеми даних.
  2. Реалізація кастомних таблиць та ORM-моделей.
  3. Налаштування агентів та поштових шаблонів.
  4. Інтеграція з платіжними системами (54-ФЗ, ОФД).
  5. Тестування на конкурентне навантаження (50+ одночасних учасників).
  6. Документація та навчання адміністраторів.
  7. Гарантійна підтримка після запуску.

Строки реалізації

Масштаб Функціонал Строк
MVP (одна акція, один ступінь знижки, ручне керування) HL-блок + обробники + AJAX-лічильник 1–1.5 тижня
Повна система (тири, агенти, повернення, ОК учасника) Кастомні таблиці + транзакції + модуль + поштові шаблони 2–3 тижні
Маркетплейс акцій (кілька постачальників, вітрина) Повноцінний модуль з адміністративним інтерфейсом + API 4–5 тижнів

Навантажувальне тестування та безпека

Перед запуском системи групових покупок необхідно протестувати конкурентний сценарій: кілька десятків одночасних приєднань до однієї акції. Без цього race condition виявляється тільки на реальному трафіку, коли CURRENT_COUNT виходить за межі MAX_PARTICIPANTS.

Тест: інструментом Apache JMeter або k6 імітуємо 50 одночасних запитів до endpoint-у приєднання. Очікуваний результат — рівно MAX_PARTICIPANTS записів у b_group_deal_participant зі статусом waiting. Якщо записів більше — транзакції не відпрацьовують коректно. Перевірте рівень ізоляції MySQL (REPEATABLE READ) та наявність блокування FOR UPDATE у запиті вибірки акції. При використанні MariaDB додатково переконайтеся, що включено режим строгих транзакцій (STRICT_TRANS_TABLES).

Додатково: додайте rate limiting на endpoint приєднання — не більше 3 запитів з однієї IP в секунду. Це захищає від ботів, які можуть заповнити акцію фіктивними учасниками.

Наша система в 5 разів ефективніша за стандартні механізми Бітрікс, а економія для покупців сягає 30%. Ми також маємо порівняння з конкурентами: наше рішення у 3 рази швидше обробляє одночасні запити, ніж аналогічні модулі на ринку. Зв'яжіться з нами для оцінки вашого проєкту. Отримайте консультацію щодо реалізації системи групових покупок.

Деталі про ізоляцію транзакційДля гарантії атомарності ми використовуємо рівень ізоляції `REPEATABLE READ` та блокування `FOR UPDATE`. У деяких випадках при високому навантаженні може знадобитися `SERIALIZABLE`. Ми виконуємо навантажувальне тестування з 100 одночасними користувачами для перевірки.