Разработка сайта мероприятий на 1С-Битрикс
Сайт конференции — это не информационная страница с расписанием. Это транзакционная система: регистрация, продажа билетов, рассылка уведомлений, генерация QR-кодов на вход, личный кабинет участника. Всё это работает в рамках модулей sale, catalog, subscribe и инфоблоков. Ошибка в архитектуре данных на старте — и через полгода при запуске второго мероприятия обнаруживается, что инфоблок «Мероприятия» содержит и докладчиков, и расписание, и билеты в одной плоской структуре. Переделать на проде — значит мигрировать данные, переписать шаблоны компонентов и пересобрать логику корзины.
Структура инфоблоков: что хранить и где
Для сайта мероприятий нужны минимум четыре инфоблока. Можно обойтись тремя, склеив расписание с мероприятиями, — но при появлении многодневных конференций с параллельными потоками это решение развалится.
Инфоблок «Мероприятия» (тип events) — основная сущность. Свойства:
-
DATE_START,DATE_END— тип «Дата/время». Используются в фильтрации и сортировке, индекс наb_iblock_element_propertyпоIBLOCK_PROPERTY_ID+VALUE_DATEобязателен -
VENUE— привязка к элементу инфоблока «Площадки» или Highload-блоку. Площадка содержит адрес, координаты, вместимость зала -
CAPACITY— числовое, максимальное количество участников. Проверяется при оформлении заказа через обработчикOnSaleOrderBeforeSaved -
STATUS— список: «Регистрация открыта», «Регистрация закрыта», «Завершено», «Отменено» -
STREAM_URL— строка, ссылка на трансляцию (YouTube/Vimeo). Отображается только авторизованным участникам с оплаченным билетом -
SCHEMA_ORG— вычисляемое, не хранится в БД. Формируется вresult_modifier.phpкомпонента детальной страницы
Инфоблок «Спикеры» (тип speakers) — отдельный, не вложенный в мероприятия. Один спикер выступает на нескольких мероприятиях, привязка через множественное свойство типа «Привязка к элементу» (E). Свойства: PHOTO (файл), BIO (HTML/текст), COMPANY, POSITION, SOCIAL_LINKS (множественная строка).
Инфоблок «Расписание» (тип schedule) — каждый элемент = один слот. Свойства:
-
EVENT_ID— привязка к мероприятию -
SPEAKER_ID— множественная привязка к спикерам -
TIME_START,TIME_END— время внутри дня -
HALL— зал/поток (для параллельных секций) -
SLOT_TYPE— список: «Доклад», «Воркшоп», «Перерыв», «Нетворкинг»
Инфоблок «Билеты» (тип tickets) — связка с модулем catalog. Каждый тип билета — элемент инфоблока, подключённый как товар торгового каталога. Свойства: EVENT_ID, TICKET_TYPE (стандарт, VIP, онлайн), AVAILABLE_SEATS, VALID_UNTIL.
Почему не Highload-блоки? Для спикеров и расписания объём данных невелик — десятки-сотни записей. Инфоблоки дают штатные компоненты news.list, news.detail, визуальный редактор в админке. Highload оправдан для площадок, если их больше 500, и для лога check-in (тысячи записей с QR-сканов).
Продажа билетов: архитектура через модуль sale
Это центральная и самая сложная часть. Билет — это товар в каталоге Битрикс, но с нестандартной логикой: привязка к дате, ограничение по количеству, именной (привязан к участнику).
Товар = элемент инфоблока «Билеты», подключённого к торговому каталогу через CCatalog::Add(). Каждый тип билета на каждое мероприятие — отдельный товар. Конференция на 500 человек с тремя типами билетов — три товара в каталоге, каждый со своим остатком на складе.
Складской учёт реализует ограничение вместимости. Создаётся склад в модуле catalog, у каждого товара-билета устанавливается количество = доступное число мест. При оформлении заказа модуль sale автоматически уменьшает остаток. Когда остаток = 0, кнопка «Купить» заменяется на «Билеты распроданы» — через проверку CCatalogProduct::GetByID() в шаблоне компонента.
Процесс оформления заказа:
- Пользователь выбирает мероприятие и тип билета
- Добавление в корзину через
\Bitrix\Sale\Basket::addItem()— не через старыйCSaleBasket::Add() - На этапе оформления — кастомный шаг
order.ajaxс полями: ФИО участника, email, телефон, компания. Эти данные записываются в свойства заказа (\Bitrix\Sale\Order::setField()) и в свойства корзины - Оплата через платёжную систему: Яндекс.Касса (ЮKassa), Stripe или PayPal. Настройка через модуль
sale→ «Платёжные системы» → обработчикyookassaили кастомный обработчик вlocal/php_interface/include/sale_payment/ - После успешной оплаты — событие
OnSalePaymentEntitySaved. Обработчик генерирует QR-код, отправляет email с билетом, создаёт запись в CRM
Проверка вместимости в реальном времени. Стандартный складской учёт работает на уровне заказа, но между добавлением в корзину и оплатой проходит время. Чтобы не продать 501 билет на 500 мест:
- Обработчик
OnSaleOrderBeforeSavedпроверяет текущий остаток и отклоняет заказ, если мест нет - Резервирование через
CCatalogProduct::Update()с уменьшениемQUANTITYпри добавлении в корзину и возвратом через 30 минут по агенту, если заказ не оформлен
Промокоды — через catalog.discount. Создаём правило скидки с условием «Промокод = X», тип скидки — процент или фиксированная сумма. В шаблоне sale.order.ajax добавляем поле ввода промокода, применение через \Bitrix\Sale\Discount::setBasketItemDiscount(). Для раннего бронирования — скидка с условием по дате: действует до определённой даты, автоматически отключается.
Регистрация и интеграция с CRM
Регистрация на бесплатное мероприятие — без модуля sale. Кастомный компонент project:event.register с формой:
- Валидация на фронте (JS) и на бэкенде (в
component.php) - Запись в Highload-блок «Регистрации»:
EVENT_ID,USER_ID,STATUS,REGISTERED_AT - Создание лида в CRM через REST API:
CRest::call('crm.lead.add', [...])или через модульcrmнапрямую, если Битрикс24 развёрнут на том же сервере
Для платных мероприятий регистрация происходит автоматически при оплате заказа. Обработчик OnSalePaymentEntitySaved создаёт запись в Highload-блоке и обновляет статус лида в CRM.
Личный кабинет участника строится на sale.personal.section с кастомным шаблоном:
- Список зарегистрированных мероприятий (выборка из Highload-блока по
USER_ID) - История заказов и билеты (штатный
sale.personal.order) - Скачивание билета с QR-кодом (PDF, сгенерированный через
TCPDFилиDompdf) - Доступ к трансляции (ссылка на
STREAM_URLпоявляется за 30 минут до начала) - Сертификат участника после мероприятия (PDF с данными из Highload-блока)
QR-код и check-in
При успешной оплате генерируется QR-код. Содержимое — уникальный хеш заказа: md5($orderId . $userId . $salt). Хеш хранится в свойстве заказа QR_HASH.
Генерация QR через библиотеку endroid/qr-code (Composer-пакет, подключается в local/php_interface/). QR вставляется в PDF-билет и отправляется на email.
На входе — мобильное приложение или веб-страница /check-in/ со сканером камеры (библиотека html5-qrcode). Сканированный хеш отправляется POST-запросом на /api/checkin/, контроллер проверяет:
- Существует ли заказ с таким
QR_HASH - Оплачен ли заказ (
\Bitrix\Sale\Order::isPaid()) - Не был ли билет уже использован (поле
CHECKED_INв свойствах заказа)
При успехе — обновление свойства заказа, запись в лог check-in (Highload-блок), ответ 200 с данными участника.
Календарь мероприятий
Два подхода к отображению:
Кастомный компонент + FullCalendar.js. Компонент project:event.calendar выдаёт JSON-массив мероприятий через AJAX. На фронте — FullCalendar с eventSources, указывающим на /api/events/calendar/. Каждое событие содержит title, start, end, url (ссылка на детальную страницу), color (по типу мероприятия). Кеширование JSON-ответа — 10 минут с тегированным кешем по инфоблоку мероприятий.
Штатный компонент iblock.element.list с кастомным шаблоном, который выводит сетку по датам. Проще в поддержке, но менее интерактивно — нет переключения месяц/неделя/день без кастомного JS.
Для серии мероприятий (ежегодная конференция) — фильтрация по разделу инфоблока. Каждый год = раздел, мероприятия внутри = элементы.
Таймер обратного отсчёта и трансляция
Таймер — JS-компонент, получающий DATE_START мероприятия из data-атрибута. Серверное время передаётся через <?= time() ?> для синхронизации. Никакого внешнего API — чистый setInterval с расчётом разницы.
Трансляция — iframe YouTube/Vimeo, обёрнутый в компонент с проверкой доступа. Компонент project:event.stream в component.php проверяет:
- Авторизован ли пользователь
- Есть ли оплаченный заказ с билетом типа «Онлайн» или «VIP» на это мероприятие
- Не закончилось ли мероприятие
Если проверка не пройдена — редирект на страницу покупки билета.
Email-уведомления
Модуль subscribe + почтовые события модуля main:
-
Подтверждение регистрации — почтовое событие
EVENT_REGISTER_CONFIRM, шаблон в «Настройки» → «Почтовые события» -
Билет после оплаты —
EVENT_TICKET_PAID, с вложением PDF -
Напоминание за 24 часа — агент
CAgent, который выбирает мероприятия сDATE_START= завтра и отправляет письма зарегистрированным участникам черезCEvent::Send() -
Изменение расписания — обработчик
OnAfterIBlockElementUpdateна инфоблоке «Расписание», рассылает уведомления участникам мероприятия
SEO: Schema.org Event
В result_modifier.php детальной страницы мероприятия формируется JSON-LD:
{
"@context": "https://schema.org",
"@type": "Event",
"name": "...",
"startDate": "2025-09-15T10:00:00+03:00",
"endDate": "2025-09-15T18:00:00+03:00",
"location": {
"@type": "Place",
"name": "...",
"address": "..."
},
"offers": {
"@type": "Offer",
"price": "...",
"priceCurrency": "BYN",
"availability": "https://schema.org/InStock",
"validFrom": "..."
},
"performer": [...]
}
Разметка выводится в <head> через $APPLICATION->AddHeadString(). Поле availability обновляется динамически: InStock при наличии билетов, SoldOut при нулевом остатке.
Мульти-мероприятия: серии и ежегодные конференции
Разделы инфоблока «Мероприятия» работают как группировка: «Конференция 2024», «Конференция 2025». Общие данные серии (описание, логотип, архив) — свойства раздела через CIBlockSection::GetList().
Для годовых отчётов и аналитики (сколько участников за 3 года, динамика продаж) — кастомный компонент с выборкой из b_sale_order по свойству EVENT_ID и группировкой по годам.
Этапы разработки
- Проектирование (1-2 недели) — структура инфоблоков, схема данных, прототипы страниц, описание бизнес-процессов регистрации и оплаты
- Дизайн (1-2 недели) — макеты страниц: каталог мероприятий, детальная, расписание, личный кабинет, check-in
- Бэкенд (2-4 недели) — инфоблоки, торговый каталог, компоненты регистрации и оплаты, интеграция с платёжной системой, генерация QR
- Фронтенд (2-3 недели) — шаблоны компонентов, календарь, таймер, адаптив, страница check-in со сканером
- Интеграции (1-2 недели) — CRM, email-уведомления, трансляция
- Тестирование (1-2 недели) — функциональное, оплата в тестовом режиме, нагрузочное (имитация 500 одновременных покупок)
- Запуск (3-5 дней) — деплой, мониторинг, проверка на реальном мероприятии
| Масштаб проекта | Ориентировочные сроки |
|---|---|
| Одно мероприятие, регистрация без оплаты | 3-5 недель |
| Мероприятие с продажей билетов и QR | 6-9 недель |
| Платформа серии мероприятий с личным кабинетом | 8-12 недель |
Сроки зависят от количества типов билетов, интеграций с внешними сервисами и требований к личному кабинету участника.







