Напоминание о записи за 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
- Клиент создаёт бронирование → получает Deep Link → подписывается на бота (BR-002, NR-001).
- Провайдер подтверждает бронирование → статус
confirmed(BR-001). - За 2 часа до
start_atпланировщик находит бронирование. - Проверяет наличие подписки CLIENT_BOOKING →
telegram_chat_idнайден. - Отправляет сообщение через Telegram Bot API с соблюдением лимитов (C-003).
- Фиксирует факт отправки (идемпотентность).
- Клиент получает сообщение с деталями записи.
Альтернативный сценарий A: клиент без Telegram
- Клиент создал бронирование через веб-сайт, не перешёл по Deep Link.
- Подписки нет (BR-002) → напоминание пропускается, логируется
reminder_skipped: no_subscription.
Альтернативный сценарий B: бронирование отменено после постановки в очередь
- Бронирование было
confirmed(BR-001), встало в очередь на напоминание. - До момента отправки провайдер отменяет бронирование → статус
cancelled. - Планировщик перепроверяет статус перед отправкой → НЕ отправляет.
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-подписки.