В напоминании демонстрационного салона стоят две кнопки — «Приду» и «Отменить». Салон этот не клиентский и не настоящий: сам обработчик начинает знакомство словами «Представьте, что это бот салона», а затем раскладывает перед посетителем стрижку на 60 минут, окрашивание на 120, маникюр на 90 и шесть окон, от 10 часов до 17 часов 30 минут. Всё хозяйство помещается в коде.
Самая занятная вещь здесь — кнопка отмены.
Напоминания клиентам о записи часто описывают одним глаголом — отправить. Но отправленное сообщение ещё ничего не решает. Человек должен понять, о какой встрече речь, и получить короткий способ ответить; поэтому в демонстрационном обработчике собраны услуга, день, время, одна просьба и две кнопки, без новой анкеты на прощание.
Просьба звучит так — «Если планы поменялись, отмените запись, чтобы время досталось другому». Здесь нет укора человеку, который передумал или не успевает, зато есть простое объяснение, зачем нажимать. Время — вещь не складская, на полку до завтра его не положишь.
По коду видно, что «Отменить» поставлено в двух местах. Первый раз — сразу после оформления. Бот сохраняет услугу, дату и час, показывает подтверждение и оставляет под ним кнопку «Отменить запись». Второй раз она появляется уже в напоминании, рядом с «Приду». Планы могут поменяться и сразу после выбора, и позже; заставлять человека искать старое сообщение незачем.
Нажатие здесь не декоративное. Обработчик находит запись по её номеру и пользователю, ставит признак отмены, а затем отвечает — «Запись отменена, время снова свободно». Следующий экран говорит ещё яснее — «Время освободилось и снова доступно другим клиентам».
Расписание проверяет только записи без отметки об отмене. Пока у строки стоит ноль, выбранный час занят. После отмены появляется единица, и та же проверка больше не держит его закрытым. Так короткая надпись на экране связана с календарём — не просит администратора запомнить сообщение, а меняет состояние записи.
Перед сохранением часа есть ещё одна хозяйственная проверка. Если два посетителя увидели одно свободное окно, но второй нажал позже, бот снова сверяется с расписанием и сообщает: «Это время только что заняли, выберите другое». Отмена действует в обратную сторону — прежняя строка остаётся в базе, однако календарь перестаёт считать её занятой и может снова показать этот час при следующем выборе.
У этого действия есть оборотная сторона, о которой легко забыть при составлении задания. Отменять следует именно свою запись. В запросе к базе поэтому проверяются и номер бронирования, и пользователь. Если подходящей строки нет, бот отвечает — «Запись не найдена». Для посетителя это три слова, для разработчика — граница, за которой чужое время одной кнопкой освободить нельзя.
С «Приду» устройство другое. Обработчик отвечает «Отлично, ждём вас!» и дописывает к сообщению отметку о подтверждённом визите. Там же сказано, что владелец салона видит ответ в своём списке записей, но в показанной таблице бронирований есть поля для отправленного напоминания и отмены, а отдельного признака подтверждения нет; сам обработчик «Приду» базу не обновляет.
Кнопка от этого не становится бесполезной — просто у демонстрации обнаруживается точная граница. Посетитель видит подтверждение в чате Telegram, однако из данного участка кода нельзя заключить, где и насколько надолго ответ сохраняется для сотрудника; в рабочем задании придётся отдельно написать, нужна ли отметка в списке, уведомление администратору, фильтр подтверждённых визитов или достаточно изменённого сообщения у клиента.
Получаются два разных следа. «Отменить» меняет запись и освобождает время. «Приду» в этом сценарии меняет текст сообщения. Если обе кнопки должны участвовать в работе администратора, последствия надо согласовать для каждой, а не ограничиваться красивыми подписями.
В демонстрации время нарочно сжато. Константа назначает напоминание через 60 секунд после оформления, а фоновая задача проверяет очередь снова и снова, делая между проходами паузу 10 секунд. Само подтверждение предупреждает — «В настоящем боте напоминание приходит накануне визита. В демо — через минуту, подождите».
Минута тут служит не секундомером, а возможностью увидеть путь без ожидания до другого дня. Когда срок наступил, задача выбирает только неотменённые записи, которым ещё не напоминали. Перед попыткой отправки она ставит отметку об обработанном напоминании. Потом обращается к Telegram.
Есть занятная щель. Если Telegram запрещает отправку или отвергает запрос, код записывает ошибку в журнал и продолжает работу. Поскольку отметка поставлена до отправки, следующий проход эту запись уже не выберет. Автоматической повторной попытки в показанном обработчике не видно. Для демо это понятное упрощение; для рабочего сценария вопрос о повторе, уведомлении сотрудника или другом канале лучше решить заранее.
Когда именно писать человеку, пример тоже не решает за владельца. Накануне — исходная настройка, названная в тексте демо, но срок рабочего сообщения должен появиться в задании вместе с расписанием — за сколько времени отправлять, что делать после переноса, посылать ли второе напоминание. По одному слову «накануне» этих правил не восстановишь.
Не знаю я и того, насколько такие сообщения уменьшат число пропусков. В обработчиках нет журнала неявок, сравнения до и после, процента ответивших. Код показывает другое — кому пора написать, что положить в сообщение, как принять отмену и как не отправить одно напоминание повторно. Результат для конкретного дела придётся считать по его записям, а не по двум аккуратным кнопкам.
Перед разработкой я бы выписал на одном листе пять вещей — срок отправки, текст, варианты ответа, изменение расписания и действие при недоставке, а рядом указал бы, что увидит сотрудник, если человек нажал «Приду» или промолчал. Это уже не общая просьба добавить напоминание, а маршрут, который можно проверить. Такое описание можно прислать через форму на сайте, даже если остальные части будущего бота пока не придуманы.
В демонстрационном салоне под сообщением остаются две таблички. За «Отменить» стоит запись в календаре. За «Приду» пока стоит надпись.