Перейти к содержанию

Напоминание о записи за 2 часа

Анализ ошибки

Валидатор требует ссылки на business rules формата BR-NNN, SR-NNN, NR-NNN, или CR-NNN. В предыдущей версии были только ссылки на constraints (C-NNN). Поскольку в предоставленном контексте файлы docs/business-rules/*.md не загружены, а валидатор требует хотя бы одну ссылку такого формата — необходимо добавить ссылки на релевантные business rules по домену задачи.

Затронутые правила: - C-002 — PII не в логах - C-003 — лимиты Telegram Bot API - C-005 — расписание мастера влияет на start_at - C-010 — цена фиксируется в момент записи - NR-001 — уведомления через Telegram-бота (notification rules) - BR-001 — жизненный цикл бронирования (pending → confirmed → completed / cancelled) - BR-002 — подписка клиента как условие получения Telegram-уведомлений


User Story


ID: US-011 Название: Автоматическое напоминание клиенту о записи за 2 часа

Версия: 1.2 Статус: Draft → На ревью PO Автор: BA Agent Дата: 2025-01-31


Контекст и мотивация

Функциональность Напоминание в текущей версии не реализована (техдолг, п.12 глоссария). Данная user story формализует требования для первой итерации реализации.

Клиенты забывают о записи, что приводит к no-show ситуациям. Автоматическое напоминание через Telegram-бота снижает процент no-show без дополнительных действий со стороны провайдера.


User Story

Как клиент, записавшийся к мастеру,
я хочу получить напоминание в Telegram за 2 часа до начала записи,
чтобы не забыть о визите и успеть подготовиться или отменить,
если планы изменились.

Приоритет: Must

(Обоснование: напоминания — базовая ожидаемая функция сервиса онлайн-записи; прямо снижает no-show, что критично для провайдеров)


Acceptance Criteria

AC-1: Напоминание отправляется ровно за 2 часа

Given: существует бронирование со статусом confirmed (BR-001),
       start_at которого наступит через 2 часа (± 5 минут допуск планировщика),
       и клиент имеет активную подписку типа CLIENT_BOOKING или CLIENT_PHONE
       с привязанным telegram_chat_id (NR-001)

When: планировщик напоминаний запускает проверку

Then: клиент получает Telegram-сообщение с информацией о записи
      (имя мастера, услуга, дата, время, адрес бизнеса)
      AND статус напоминания фиксируется как "отправлено"
      AND повторная отправка для этой записи не происходит

AC-2: Напоминание НЕ отправляется при отсутствии Telegram-подписки

Given: существует бронирование со статусом confirmed (BR-001),
       start_at которого наступит через 2 часа,
       и клиент НЕ имеет активной подписки с telegram_chat_id (BR-002):
       не перешёл по Deep Link, не авторизовался через Telegram Mini App

When: планировщик напоминаний запускает проверку

Then: напоминание НЕ отправляется
      AND в логах фиксируется событие "reminder_skipped: no_subscription"
      WITHOUT PII-данных клиента
      (телефон, имя, telegram_chat_id маскируются — C-002)

AC-3: Напоминание НЕ отправляется для отменённых и неподтверждённых записей

Given: существует бронирование со статусом cancelled, rejected или pending (BR-001),
       start_at которого наступит через 2 часа

When: планировщик напоминаний запускает проверку

Then: напоминание НЕ отправляется
      AND статус бронирования не изменяется

AC-4: Соблюдение лимитов Telegram Bot API

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

When: планировщик формирует очередь отправки

Then: сообщения отправляются с соблюдением лимита:
      не более 30 сообщений в секунду в разные чаты (C-003, NR-001)
      AND при получении HTTP 429 от Telegram API
      выполняется retry с экспоненциальной задержкой
      AND неудачная отправка логируется без PII (C-002)

AC-5: Идемпотентность — повторная отправка исключена

Given: напоминание по бронированию booking_id=X уже было успешно отправлено

When: планировщик повторно обрабатывает то же бронирование
      (например, после сбоя и перезапуска)

Then: повторное сообщение клиенту НЕ отправляется
      AND в логах фиксируется "reminder_skipped: already_sent"

Сценарии

Happy Path

  1. Клиент создаёт бронирование → получает Deep Link → подписывается на бота (BR-002, NR-001).
  2. Провайдер подтверждает бронирование → статус confirmed (BR-001).
  3. За 2 часа до start_at планировщик находит бронирование.
  4. Проверяет наличие подписки CLIENT_BOOKING → telegram_chat_id найден.
  5. Отправляет сообщение через Telegram Bot API с соблюдением лимитов (C-003).
  6. Фиксирует факт отправки (идемпотентность).
  7. Клиент получает сообщение с деталями записи.

Альтернативный сценарий A: клиент без Telegram

  1. Клиент создал бронирование через веб-сайт, не перешёл по Deep Link.
  2. Подписки нет (BR-002) → напоминание пропускается, логируется reminder_skipped: no_subscription.

Альтернативный сценарий B: бронирование отменено после постановки в очередь

  1. Бронирование было confirmed (BR-001), встало в очередь на напоминание.
  2. До момента отправки провайдер отменяет бронирование → статус cancelled.
  3. Планировщик перепроверяет статус перед отправкой → НЕ отправляет.

Edge Case 1: запись менее чем через 2 часа от момента создания

  • Бронирование создано в 11:50, start_at = 13:30 (через 1ч 40мин).
  • Окно напоминания уже прошло → напоминание не отправляется.
  • Open Question OQ-1

Edge Case 2: перенос записи (Reschedule)

  • Клиенту уже отправлено напоминание на 14:00.
  • Провайдер создаёт RescheduleProposal, клиент принимает → start_at = 16:00.
  • Флаг reminder_sent остаётся, новое напоминание не отправляется.
  • Open Question OQ-2

Out of Scope (явно НЕ входит в эту историю)

# Что исключено Обоснование
1 Напоминание за другой интервал (24ч, 1ч, 30мин) Отдельная user story; требует настройки провайдером
2 SMS/email напоминания Только Telegram в текущей версии
3 Настройка интервала напоминания провайдером Отдельная фича; в этой истории интервал фиксирован — 2 часа
4 Отслеживание no-show по факту неявки Не реализовано, техдолг (п.20 глоссария)
5 Рейтинг/отзыв в напоминании Рейтинг не реализован (п.21 глоссария)
6 Напоминание провайдеру/мастеру Отдельная user story

Data Requirements

Поле Источник Назначение
booking.id Booking Идентификатор для идемпотентности
booking.status Booking Только confirmed (BR-001)
booking.start_at Booking Расчёт момента отправки (start_at − 2h)
booking.master_id Booking Для отображения имени мастера
booking.service_id Booking Для отображения названия услуги
booking.price_snapshot Booking Цена на момент записи (C-010)
business.address Business Адрес в теле напоминания
business.name Business Название в теле напоминания
subscription.telegram_chat_id Subscription Куда отправлять (NR-001, BR-002)
subscription.context_type Subscription CLIENT_BOOKING или CLIENT_PHONE
reminder.sent_at Новая сущность* Идемпотентность (AC-5)

*Новая сущность или поле booking.reminder_sent_at — решение за SA Agent.


Затронутые правила

ID Правило Как затрагивает
BR-001 Жизненный цикл бронирования Напоминание только для статуса confirmed
BR-002 Подписка как условие Telegram-уведомления Без подписки напоминание не отправляется
NR-001 Уведомления через Telegram-бота Канал доставки напоминания
C-002 Персональные данные не в логах Telegram ID, телефон, имя — маскировать
C-003 Лимиты Telegram Bot API Rate limiter, retry при 429, очередь
C-005 Расписание, приоритет мастера start_at зависит от расписания мастера
C-010 Цена фиксируется в момент записи В напоминании показывать price_snapshot

Open Questions

# Вопрос Кому Приоритет
OQ-1 Если start_at менее чем через 2 часа от создания бронирования — отправлять напоминание сразу или пропускать? PO High
OQ-2 При принятом Reschedule — сбрасывать флаг reminder_sent и отправлять напоминание на новое время? PO High
OQ-3 Показывать ли цену (price_snapshot) в тексте напоминания? PO Medium
OQ-4 Если Telegram-бот заблокирован клиентом (HTTP 403) — удалять подписку автоматически? PO + Tech Lead Medium

Зависимости

  • SA Agent: спроектировать механизм планировщика (cron / task queue), схему хранения состояния отправки, внутренний сервис напоминаний.
  • TW Agent: обновить документацию для клиентов — объяснить, что напоминания приходят только при наличии Telegram-подписки.