Проектирование записи через бота: выбор услуги и времени, подтверждение, перенос, отмена и синхронизация календаря.

Чат-бот для записи клиентов: сценарий, календарь и защита от накладок
Чат-бот для записи клиентов: сценарий, календарь и защита от накладок

Непротиворечивый сценарий онлайн-записи строится на последовательности: сбор параметров (услуга, дата, время) → запрос свободных слотов из календаря → создание записи с временным статусом → подтверждение клиентом → фиксация в календаре → синхронизация с внешними системами. Бот должен показывать только свободные окна, блокировать выбранное время на стороне календаря до завершения диалога и откатывать резервирование, если клиент не подтвердил. Перенос и отмена обрабатываются отдельными ветками с проверкой статуса записи.

Сбор параметров записи: услуга, специалист, желаемая дата

Диалог начинается с выявления намерения клиента записаться. Бот предлагает список услуг в виде кнопок или карточек, если их не больше восьми; при большем количестве добавляется текстовый поиск с уточнением. Каждая услуга несёт атрибуты: длительность в минутах, привязку к специалисту или помещению, стоимость.

После выбора услуги бот определяет, нужен ли выбор конкретного специалиста. Если клиент не имеет предпочтений, бот предлагает «любой свободный». Этот выбор влияет на фильтрацию слотов: запрос к календарю идёт либо для одного сотрудника, либо для всех, кто может оказать услугу.

Далее бот запрашивает желаемую дату. Клиент может ввести текстом («завтра», «15 марта») или выбрать из календаря в интерфейсе мессенджера. Бот нормализует дату в формат ISO 8601 и передаёт в модуль календаря вместе с идентификатором услуги и специалиста.

На этом этапе важно не допустить накопления контекста без проверки. Если клиент не ответил в течение заданного таймаута, бот сохраняет состояние диалога и напоминает о незавершённой записи при следующем обращении.

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

Модуль календаря получает запрос: дата, услуга, специалист, длительность. Он проверяет расписание работы, уже занятые слоты, перерывы и выходные. Результат — список временных окон, каждое с меткой начала, конца и идентификатором ресурса (специалиста или кабинета).

Бот показывает клиенту до шести ближайших свободных окон в виде кнопок с временем начала. Если свободных слотов нет, бот предлагает выбрать другую дату или получить уведомление, когда появится окно.

При клике на время бот переводит слот в статус «зарезервировано» на стороне календаря с флагом «temporary» и устанавливает время жизни этой блокировки — обычно от трёх до пяти минут. Если за это время клиент не подтвердит запись, резервирование снимается автоматически, и слот возвращается в пул свободных.

Для защиты от одновременной записи двух клиентов на один слот используется транзакционная блокировка: календарь проверяет, свободен ли слот, блокирует его атомарно и возвращает идентификатор резервирования. Если другой клиент попытается зарезервировать тот же слот в этот момент, календарь вернёт ошибку, и бот покажет обновлённый список окон.

Подтверждение записи клиентом

После выбора времени бот собирает данные клиента: имя, телефон или email для напоминаний. Если клиент уже общался с ботом, эти данные извлекаются из профиля, и бот просит подтвердить их актуальность.

Бот формирует карточку записи: услуга, специалист, дата, время начала и окончания, адрес, стоимость. Клиент видит кнопки «Подтвердить» и «Изменить». При подтверждении бот отправляет команду календарю: перевести резервирование из временного статуса в постоянный. Календарь создаёт событие с уникальным идентификатором записи, сохраняет данные клиента и отправляет подтверждение боту.

Бот выдаёт клиенту сообщение с подтверждением, номером записи и ссылкой для переноса или отмены. Если используется внешняя система учёта (CRM, электронная медицинская карта), бот отправляет туда же событие через API с теми же данными. Синхронизация должна быть идемпотентной: повторная отправка с тем же идентификатором не создаёт дубль.

Если клиент нажимает «Изменить», бот откатывает резервирование и возвращается к выбору даты или времени, сохраняя остальные параметры.

Таблица статусов записи
Таблица статусов записи

Таблица статусов записи

Статус Описание Время жизни Действия клиента
temporary Слот зарезервирован, ожидается подтверждение 3–5 минут Подтвердить, изменить, отменить
confirmed Запись подтверждена клиентом До времени начала Перенести, отменить
rescheduled Клиент перенёс запись, старая отменена До нового времени начала Перенести снова, отменить
cancelled Запись отменена клиентом или системой Архив Создать новую запись
completed Услуга оказана Архив Оставить отзыв, записаться снова
no-show Клиент не пришёл Архив Записаться снова

Перенос записи: проверка возможности и обновление слота

Клиент может перенести запись, отправив боту команду «Перенести» или перейдя по ссылке из подтверждающего сообщения. Бот проверяет статус записи в календаре: перенос доступен только для записей в статусе confirmed или rescheduled и только если до времени начала остаётся больше установленного минимума (например, два часа).

Если условия выполнены, бот запускает диалог выбора новой даты и времени. Показывает свободные слоты так же, как при первой записи. После выбора нового времени бот резервирует его с временным статусом, показывает карточку для подтверждения. При подтверждении календарь атомарно освобождает старый слот, переводит новый в confirmed, обновляет идентификатор события и отправляет уведомление клиенту и специалисту.

Старая запись переводится в статус cancelled с пометкой «перенесена», новая получает ссылку на старую для истории. Если внешняя CRM не поддерживает обновление событий, бот отменяет старое и создаёт новое с указанием связи.

Отмена записи и возврат слота

Клиент отменяет запись командой или кнопкой. Бот запрашивает подтверждение: «Вы уверены, что хотите отменить запись на 15 марта в 14:00?» При подтверждении календарь переводит запись в статус cancelled, освобождает слот и отправляет уведомление специалисту.

Если до начала остаётся меньше установленного минимума (например, два часа), бот предупреждает о возможных последствиях: штраф, невозврат предоплаты, ограничение на новые записи. Логика таких ограничений описывается в правилах бизнеса и передаётся боту в виде конфигурации.

После отмены слот возвращается в список свободных немедленно. Если используется внешний календарь (Google Calendar, Outlook), бот отправляет запрос на удаление события через API. Синхронизация должна быть двусторонней: если специалист отменит встречу в своём календаре, webhook сообщит боту, и бот уведомит клиента.

Синхронизация с внешними календарями и CRM

Большинство сценариев записи требуют интеграции с существующими системами. Бот может работать с календарём через протокол CalDAV, API Google Calendar, Microsoft Graph или собственный API календарной системы.

При создании записи бот отправляет событие с полями: summary (название услуги), start, end, location, attendees (email клиента и специалиста), description (номер записи, телефон). Внешний календарь возвращает уникальный идентификатор события. Бот сохраняет этот идентификатор в своей базе для последующих обновлений и отмены.

Если CRM поддерживает webhook, бот подписывается на события изменения записи: создание, перенос, отмена, завершение. Когда администратор или специалист меняет параметры встречи в CRM, webhook отправляет уведомление боту, бот обновляет свою базу и отправляет клиенту сообщение об изменении.

При отсутствии webhook бот может периодически опрашивать календарь (polling) на предмет изменений, но это увеличивает задержку уведомления клиента и создаёт дополнительную нагрузку на API.

Для защиты от рассинхронизации бот ведёт лог всех операций с временными метками и идентификаторами запросов. При обнаружении конфликта (например, событие удалено в календаре, но запись остаётся подтверждённой в базе бота) срабатывает алерт для администратора.

Условный пример: салон красоты с двумя мастерами
Условный пример: салон красоты с двумя мастерами

Условный пример: салон красоты с двумя мастерами

Представим салон с двумя мастерами маникюра. Клиент пишет боту: «Хочу записаться на маникюр». Бот показывает две услуги: «Классический маникюр (60 минут, 1500 ₽)» и «Маникюр с покрытием (90 минут, 2500 ₽)». Клиент выбирает второй вариант.

Бот спрашивает: «Есть предпочтения по мастеру?» Клиент отвечает: «Любой». Бот запрашивает дату. Клиент вводит: «15 марта». Бот обращается к календарю: какие окна длиной 90 минут свободны у обоих мастеров 15 марта?

Календарь возвращает: мастер Анна свободна 10:00–11:30 и 14:00–15:30, мастер Ольга — 11:00–12:30 и 16:00–17:30. Бот показывает клиенту четыре кнопки с временем и именем мастера. Клиент выбирает «14:00 — Анна».

Бот блокирует этот слот на три минуты, запрашивает имя и телефон. Клиент вводит данные. Бот показывает карточку: «Маникюр с покрытием, 15 марта, 14:00–15:30, мастер Анна, 2500 ₽». Клиент нажимает «Подтвердить».

Календарь создаёт событие с идентификатором rec_12345, отправляет его в Google Calendar мастера Анны и в CRM салона. Бот выдаёт: «Запись подтверждена! Номер: 12345. Перенести или отменить можно по ссылке». Клиент получает SMS-напоминание за день и за час до визита.

За шесть часов до визита клиент решает перенести. Пишет боту: «Перенести». Бот проверяет: до начала больше двух часов, перенос возможен. Предлагает новые даты. Клиент выбирает 16 марта, 11:00. Бот резервирует, показывает карточку, клиент подтверждает. Календарь освобождает 15 марта 14:00, занимает 16 марта 11:00, обновляет событие в Google Calendar и CRM. Мастер Анна видит изменение в своём календаре.

Проверка результата и мониторинг работы бота

После запуска бота записи необходимо отслеживать метрики: процент завершённых записей, процент отмен, среднее время диалога до подтверждения, количество ошибок синхронизации с календарём, количество дублей и накладок.

Ключевая метрика — количество накладок (два клиента на один слот). Если она не равна нулю, значит, механизм блокировки слотов работает неправильно. Проверьте: использует ли календарь транзакционную блокировку, корректно ли бот обрабатывает отказ при резервировании, срабатывает ли автоматическое снятие временной блокировки.

Процент отмен с временным статусом (клиент не подтвердил за отведённое время) показывает, достаточно ли времени даётся на подтверждение и понятен ли интерфейс. Если больше 20 % резервирований истекают, увеличьте таймаут или упростите шаг подтверждения.

Среднее время диалога до подтверждения должно быть в пределах одной-двух минут. Если больше, проверьте: не слишком ли много шагов, не задаёт ли бот лишних вопросов, достаточно ли быстро отвечает календарь.

Для отладки ошибок синхронизации ведите лог всех запросов к календарю и ответов от него с временными метками и идентификаторами. При обнаружении расхождения между базой бота и календарём запускайте автоматическую сверку: бот запрашивает все записи клиента за период, сравнивает с локальной базой и обновляет статусы.

Типичные ошибки при проектировании записи

Первая ошибка — показ занятых слотов из-за отсутствия проверки в момент выбора. Бот запрашивает свободные окна при загрузке списка, но не проверяет повторно при клике клиента. Если другой клиент занял слот за это время, первый увидит ошибку после ввода данных. Решение: резервировать слот сразу при клике и проверять статус перед резервированием.

Вторая ошибка — отсутствие автоматического снятия временных резервирований. Клиент выбрал время, отвлёкся, не подтвердил — слот остаётся заблокированным навсегда. Решение: устанавливать TTL (time to live) для временных записей на уровне базы данных или календаря, запускать фоновую задачу очистки каждую минуту.

Третья ошибка — отсутствие идемпотентности при синхронизации. Бот отправляет событие в CRM, получает таймаут, повторяет запрос — в CRM создаются два дубля. Решение: генерировать уникальный идентификатор операции на стороне бота, передавать его в CRM, CRM проверяет наличие записи с таким идентификатором перед созданием.

Четвёртая ошибка — игнорирование часовых поясов. Клиент в Москве, специалист в Новосибирске, бот показывает время в UTC — все запутались. Решение: хранить часовой пояс клиента и специалиста, показывать время в часовом поясе клиента, передавать в календарь время в ISO 8601 с указанием зоны.

Пятая ошибка — отсутствие обработки отмены со стороны специалиста. Администратор удалил событие в календаре, но бот не узнал об этом, клиент пришёл впустую. Решение: настроить webhook от календаря к боту или запускать периодическую сверку, отправлять клиенту уведомление об отмене немедленно.

Безопасность и управление рисками
Безопасность и управление рисками

Безопасность и управление рисками

Бот записи работает с персональными данными (имя, телефон, email, адрес) и коммерческими данными (расписание специалистов, стоимость услуг). Необходимо ограничить доступ к этим данным, шифровать их при передаче и хранении, логировать все операции для аудита.

OWASP перечисляет риски LLM-приложений, включая prompt injection (внедрение вредоносных инструкций в запрос клиента) и утечки данных через логи (OWASP Top 10 для LLM). Если бот использует языковую модель для интерпретации запросов клиента, необходимо валидировать входные данные, ограничивать контекст запроса к модели, не передавать в prompt данные других клиентов.

NIST AI Risk Management Framework рекомендует связывать управление рисками ИИ с целями организации и допустимым уровнем риска (NIST AI RMF). Для бота записи это означает: определить, какие ошибки допустимы (например, задержка уведомления на минуту), а какие критичны (накладка двух клиентов), и выстроить архитектуру, минимизирующую критичные риски.

Чрезмерная автономность бота также представляет риск. Если бот может переносить или отменять записи без подтверждения клиента, злоумышленник может отправить команду от имени клиента. Решение: требовать подтверждения через код из SMS или callback-кнопку, привязанную к идентификатору сессии.

Неограниченное потребление ресурсов: клиент отправляет тысячи запросов на резервирование слотов за секунду, блокирует календарь. Решение: вводить rate limiting (ограничение частоты запросов) на уровне бота и API календаря, блокировать клиента при превышении лимита.

Чек-лист проектирования бота записи

  • Собрать список услуг с атрибутами: название, длительность, стоимость, привязка к специалисту или ресурсу.
  • Определить расписание работы специалистов и перерывы, внести в календарь.
  • Настроить механизм запроса свободных слотов: фильтрация по дате, услуге, специалисту, длительности.
  • Реализовать транзакционное резервирование слота с временным статусом и TTL.
  • Добавить проверку статуса слота перед резервированием для защиты от накладок.
  • Создать диалоговую ветку подтверждения записи с отображением полной карточки.
  • Реализовать перевод записи из временного статуса в подтверждённый при согласии клиента.
  • Настроить синхронизацию с внешним календарём (API, webhook) с проверкой идемпотентности.
  • Добавить ветку переноса с проверкой минимального времени до начала и освобождением старого слота.
  • Добавить ветку отмены с подтверждением и немедленным освобождением слота.
  • Настроить уведомления клиенту: подтверждение, напоминание, изменение, отмена.
  • Настроить уведомления специалисту: новая запись, перенос, отмена.
  • Реализовать двустороннюю синхронизацию: изменение в календаре → уведомление боту → уведомление клиенту.
  • Добавить обработку часовых поясов при отображении и хранении времени.
  • Внедрить логирование всех операций с календарём для аудита и отладки.
  • Настроить мониторинг метрик: накладки, отмены, время диалога, ошибки синхронизации.
  • Ввести rate limiting для защиты от злоупотреблений.
  • Защитить персональные данные: шифрование при передаче и хранении, ограничение доступа, валидация входных данных.
  • Протестировать сценарий на конкурентных запросах: два клиента одновременно выбирают один слот.
  • Протестировать откат временного резервирования при истечении TTL.

Частые вопросы

Как обрабатывать запись на несколько услуг одновременно?

Бот собирает список услуг, суммирует их длительность, запрашивает слот с общей продолжительностью. Если услуги требуют разных специалистов, бот резервирует последовательные слоты для каждого или предлагает выбрать дату, когда все специалисты свободны одновременно. В календаре создаётся либо одно событие с несколькими участниками, либо связанные события с общим идентификатором записи.

Можно ли записаться без указания телефона?

Технически да, если клиент общается через мессенджер и у бота есть способ уведомить его внутри платформы. Однако для SMS-напоминаний и звонка администратора телефон необходим. Бот может сделать телефон опциональным, но предупредить, что напоминания придут только в чат.

Что делать, если календарь недоступен в момент записи?

Бот сообщает клиенту: «Календарь временно недоступен, попробуйте через минуту» и сохраняет состояние диалога. Через минуту клиент возвращается, бот повторяет запрос. Если календарь недоступен долго, бот переводит режим в «только приём заявок»: клиент оставляет контакт и желаемую услугу, администратор обрабатывает заявку вручную и отправляет подтверждение через бота.

Как обрабатывать групповые записи?

Бот запрашивает количество участников, проверяет доступность ресурса (помещения, оборудования) для такого числа людей, резервирует общий слот. В календаре создаётся одно событие с указанием количества участников. Если требуется индивидуальная идентификация участников (например, для медицинского осмотра группы), бот запрашивает данные каждого и создаёт связанные записи.

Нужно ли хранить историю всех записей клиента?

Да, история позволяет боту предлагать повторную запись к тому же специалисту, анализировать частоту визитов, применять скидки для постоянных клиентов. Храните статус каждой записи, дату создания, изменения и завершения. Согласно требованиям защиты персональных данных, предоставьте клиенту возможность запросить удаление своей истории.

Практический вывод

Непротиворечивый сценарий онлайн-записи требует синхронной работы бота и календаря: запрос свободных слотов, транзакционное резервирование с временным статусом, подтверждение клиентом, фиксация в календаре, синхронизация с внешними системами. Защита от накладок достигается атомарной блокировкой слота и автоматическим снятием резервирования по истечении таймаута. Перенос и отмена обрабатываются отдельными ветками с проверкой статуса и освобождением ресурса. Двусторонняя синхронизация через webhook или API гарантирует, что изменения в календаре немедленно доходят до клиента. Мониторинг метрик, логирование операций и управление рисками обеспечивают надёжность системы в промышленной эксплуатации.