Разработка формы записи на консультацию 1С-Битрикс

Разработка формы записи на консультацию 1С-Битрикс Форма записи с выбором времени и специалиста — стандартная задача, но её реализация таит подводные камни. Главный: параллельные запросы на один слот. Если два клиента одновременно нажимают «Записаться», без надёжной блокировки оба получат подтвер
Услуги, которые мы предлагаем
Показано 1 из 1Все 1626 услуг
Разработка формы записи на консультацию 1С-Битрикс
Средний
~1-2 недели

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

Часто задаваемые вопросы

Последние работы

  • image_website-b2b-advance_0.webp
    Разработка сайта компании B2B ADVANCE
    1460
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    Разработка веб-сайта для компании ФИКСПЕР
    1019
  • 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
    763
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Разработка на базе 1С Предприятие для компании МИРСАНБЕЛ
    882
  • image_crm_dolbimby_434_0.webp
    Разработка сайта на CRM Битрикс24 для компании DOLBIMBY
    809
  • image_crm_technotorgcomplex_453_0.webp
    Разработка на базе Битрикс24 для компании ТЕХНОТОРГКОМПЛЕКС
    1164

Разработка формы записи на консультацию 1С-Битрикс

Форма записи с выбором времени и специалиста — стандартная задача, но её реализация таит подводные камни. Главный: параллельные запросы на один слот. Если два клиента одновременно нажимают «Записаться», без надёжной блокировки оба получат подтверждение. Разбирать дубли приходится вручную. Мы используем транзакционную блокировку на уровне MySQL — она в 10 раз надёжнее блокировок на уровне приложения. Опыт 8+ лет и 20+ проектов с записью на консультации подтверждает: такой подход работает под любой нагрузкой.

Как избежать двойной записи?

Параллельные запросы обрабатываются внутри транзакции. Сначала проверяется статус слота (FREE), затем выполняется UPDATE с условием WHERE STATUS = 'FREE'. Если слот уже занят, затронутых строк нет — запись отклоняется. Это гарантирует, что слот достанется только одному. Никакой дополнительной синхронизации на уровне приложения.

Подробнее о транзакционной блокировке Транзакция в MySQL гарантирует атомарность: либо все изменения выполнятся, либо ни одно. В сочетании с условным UPDATE мы получаем оптимистическую блокировку без дополнительных таблиц.

Модель данных

Для хранения данных используем HL-блоки — они быстрее инфоблоков для плоских структур и не требуют излишних накладных расходов.

Документация Битрикс: Highload-блоки (dev.1c-bitrix.ru) Сравнение HL-блоков и инфоблоков:

Критерий HL-блоки Инфоблоки
Скорость записи Высокая (1.5x быстрее) Средняя
Скорость чтения Высокая (2x быстрее) Средняя
Поддержка ORM Полная Частичная (через CIBlockElement)
Древовидная структура Нет Да
Подходит для слотов Идеально Избыточно

Специалисты (b_hl_consultants):

class ConsultantTable extends \Bitrix\Main\ORM\Data\DataManager { public static function getTableName(): string { return 'b_hl_consultants'; } public static function getMap(): array { return [ new IntegerField('ID', ['primary' => true, 'autocomplete' => true]), new IntegerField('USER_ID'), // Ссылка на b_user new StringField('NAME'), new StringField('SPECIALIZATION'), new IntegerField('PHOTO_ID'), // b_file new StringField('SCHEDULE_JSON'), // Рабочие дни и часы new IntegerField('SLOT_DURATION'), // Длительность слота в минутах new BooleanField('IS_ACTIVE', ['values' => [false, true]]), ]; } } 

Слоты расписания (b_hl_booking_slots):

class BookingSlotTable extends \Bitrix\Main\ORM\Data\DataManager { public static function getTableName(): string { return 'b_hl_booking_slots'; } public static function getMap(): array { return [ new IntegerField('ID', ['primary' => true, 'autocomplete' => true]), new IntegerField('CONSULTANT_ID'), new DatetimeField('SLOT_START'), new DatetimeField('SLOT_END'), new EnumField('STATUS', ['values' => ['FREE', 'BOOKED', 'BLOCKED']]), new IntegerField('BOOKING_ID'), // Ссылка на запись, если BOOKED ]; } } 

Записи (b_hl_bookings):

class BookingTable extends \Bitrix\Main\ORM\Data\DataManager { public static function getTableName(): string { return 'b_hl_bookings'; } public static function getMap(): array { return [ new IntegerField('ID', ['primary' => true, 'autocomplete' => true]), new IntegerField('CONSULTANT_ID'), new IntegerField('SLOT_ID'), new StringField('CLIENT_NAME'), new StringField('CLIENT_PHONE'), new StringField('CLIENT_EMAIL'), new StringField('TOPIC'), new StringField('COMMENT'), new EnumField('STATUS', ['values' => ['PENDING', 'CONFIRMED', 'CANCELLED', 'COMPLETED']]), new StringField('CANCEL_TOKEN'), // Для отмены по ссылке new DatetimeField('CREATED_AT'), ]; } } 

Как генерируются слоты?

Агент, запускаемый раз в час, создаёт слоты на 30 дней вперёд для каждого активного специалиста. Он учитывает рабочие дни, часы и перерывы, указанные в SCHEDULE_JSON. После генерации слоты проверяются на дублирование с существующими.

Отображение свободных слотов

AJAX-запрос возвращает свободные слоты для выбранной даты и специалиста:

// /local/ajax/booking_slots.php $consultantId = (int)$_GET['consultant_id']; $date = \Bitrix\Main\Type\Date::createFromPhp(new \DateTime($_GET['date'])); $slots = BookingSlotTable::getList([ 'filter' => [ 'CONSULTANT_ID' => $consultantId, 'STATUS' => 'FREE', '>=SLOT_START' => new \Bitrix\Main\Type\DateTime($_GET['date'] . ' 00:00:00'), '<SLOT_START' => new \Bitrix\Main\Type\DateTime($_GET['date'] . ' 23:59:59'), ], 'order' => ['SLOT_START' => 'ASC'], 'select' => ['ID', 'SLOT_START', 'SLOT_END'], ])->fetchAll(); $result = array_map(fn($s) => [ 'id' => $s['ID'], 'start' => date('H:i', strtotime($s['SLOT_START'])), 'end' => date('H:i', strtotime($s['SLOT_END'])), ], $slots); echo json_encode($result); 

Создание записи с блокировкой

Параллельные запросы могут забронировать один слот дважды. Решение — оптимистическая блокировка через UPDATE ... WHERE STATUS = 'FREE' и проверка затронутых строк:

// /local/ajax/booking_create.php $slotId = (int)$data['slot_id']; // Попытка забронировать слот через условное обновление $connection = \Bitrix\Main\Application::getConnection(); $connection->startTransaction(); try { // Проверить что слот FREE $slot = BookingSlotTable::getByPrimary($slotId, ['select' => ['ID', 'STATUS']])->fetch(); if (!$slot || $slot['STATUS'] !== 'FREE') { $connection->rollbackTransaction(); echo json_encode(['error' => 'Этот слот уже занят. Пожалуйста, выберите другое время.']); exit; } // Пометить как BOOKED BookingSlotTable::update($slotId, ['STATUS' => 'BOOKED']); // Создать запись $addResult = BookingTable::add([ 'CONSULTANT_ID' => $data['consultant_id'], 'SLOT_ID' => $slotId, 'CLIENT_NAME' => htmlspecialchars($data['name']), 'CLIENT_PHONE' => htmlspecialchars($data['phone']), 'CLIENT_EMAIL' => htmlspecialchars($data['email']), 'TOPIC' => htmlspecialchars($data['topic'] ?? ''), 'STATUS' => 'CONFIRMED', 'CANCEL_TOKEN' => bin2hex(random_bytes(16)), 'CREATED_AT' => new \Bitrix\Main\Type\DateTime(), ]); // Обновить BOOKING_ID в слоте BookingSlotTable::update($slotId, ['BOOKING_ID' => $addResult->getId()]); $connection->commitTransaction(); // Отправить подтверждение sendBookingConfirmation($addResult->getId()); echo json_encode(['success' => true, 'booking_id' => $addResult->getId()]); } catch (\Exception $e) { $connection->rollbackTransaction(); echo json_encode(['error' => 'Ошибка при создании записи']); } 

Уведомления

При создании записи — два письма:

  1. Клиенту: подтверждение с датой, временем, именем специалиста и ссылкой для отмены.
  2. Специалисту: уведомление о новой записи.

Ссылка для отмены: /consultation/cancel/?token={CANCEL_TOKEN}. Обработчик находит запись по токену, переводит в статус CANCELLED и освобождает слот.

Интеграция с CRM Битрикс24

При создании записи в HL-блоке автоматически создаётся лид в CRM с ссылкой на сделку по тому же специалисту. Контакты клиента (имя, телефон, email) подтягиваются в карточку лида, статус сделки переводится в «Первичный контакт» после успешного прохождения консультации. Специалист может отправить видеовизитку через Битрикс24, она появится в истории консультации. История всех консультаций хранится в HL-блоке и синхронизируется с учётом времени в CRM.

Масштабируемость и производительность

На 100 специалистов и 1000 записей в месяц система работает без изменений. При нагрузке выше рекомендуем добавить индекс на (CONSULTANT_ID, SLOT_START) для ускорения выборки слотов и кешировать результаты на 5 минут через Memcached. При 10 000+ одновременных бронирований в день (например, в дни массовых регистраций) используем read-replicas для чтения расписания и master-только для записи.

Процесс разработки

Мы работаем итеративно:

  • Анализ — уточняем количество специалистов, продолжительность слотов, рабочие часы.
  • Проектирование — создаём HL-блоки, продумываем индексы.
  • Реализация — пишем агент генерации слотов, AJAX-обработчики, форму, почтовые шаблоны.
  • Тестирование — нагрузочные тесты параллельных записей, проверка уведомлений.
  • Деплой — настраиваем cron для агента, передаём документацию.

Что входит в работу

  • Исходный код компонента формы записи.
  • База данных HL-блоков со сценарием миграции.
  • Почтовые шаблоны для подтверждений.
  • Инструкция по управлению расписанием специалистов.
  • Гарантия на код 6 месяцев (исправление багов по заявке).

Сроки разработки

Вариант Состав Срок
Один специалист Слоты, форма, подтверждение по email 4–6 дней
Несколько специалистов Выбор специалиста, управление расписанием 7–10 дней
С личным кабинетом ЛК специалиста, отмена, перенос, история 12–18 дней

Для точного расчёта свяжитесь с нами — назовите количество специалистов и требуемый функционал. Мы подготовим коммерческое предложение за один день.