01 · Документация

Руководство пользователя

Оглавление

Часть 1 — Для пользователей (операторы, региональные управляющие)

Часть 2 — Для администраторов


Что такое Restaurant Pulse

Restaurant Pulse — внутренняя система мониторинга для сети ресторанов, состоящая из двух независимо развёрнутых компонентов с общей базой данных:

  1. Telegram-бот — оперативные push-уведомления и быстрые отчёты прямо в мессенджере.
  2. Веб-дашборд — детальная аналитика, фильтры, графики, отзывы клиентов.

Система непрерывно опрашивает различные каналы продаж (несколько площадок — здесь обозначены как Агрегатор A, B, C, D) и площадки отзывов и фиксирует:

  • когда ресторан пропадает с агрегатора (полный «стоп»);
  • когда отдельные позиции меню (SKU) становятся недоступны (SKU-стопы);
  • когда существенно меняется время доставки;
  • когда меняются способы оплаты;
  • когда появляются новые отзывы клиентов.

Возможности

✅ Telegram-уведомления в течение 1–2 минут после события
✅ Эскалация: повторный алерт каждый час, пока ресторан в стопе
✅ Отдельный мониторинг позиций меню — ловит ситуации «забыли включить»
✅ Ежедневный сводный отчёт по всем выбранным ресторанам
✅ Индивидуальные настройки уведомлений (4 канала с независимыми чекбоксами)
✅ Веб-дашборд с фильтрами, графиками и оценкой финансовых потерь
✅ Объединённая лента отзывов с разных площадок


Часть 1 — Для пользователей

Регистрация в Telegram-боте

Шаг 1. Первый вход

Откройте Telegram и перейдите по ссылке, которую вам передал администратор. Нажмите «Начать» (или отправьте /start).

Шаг 2. Выберите роль

Бот предложит два варианта:

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

Шаг 3. Если локальный менеджмент — выберите регион

Появится список регионов. Выберите свой (регионы заранее заданы географией сети).

Каждый регион автоматически охватывает несколько городов — отдельно выбирать города не нужно.

Шаг 4. Дождитесь подтверждения

После выбора роли заявка уходит модератору бота. Вы увидите:

Заявка отправлена на подтверждение

Когда модератор одобрит, придёт сообщение:

Регистрация подтверждена. Используйте /menu

Если заявка отклонена — обратитесь к модерации бота.

Шаг 5. Откройте меню

Отправьте /menu или /start — появится главное меню из 4 кнопок.

Совет: в самом начале зайдите в ⚙️ Настройки → Выбрать рестораны и отметьте необходимые рестораны Далее зайдите в Настройки уведомлений и отметьте необходимые метрики


Главное меню

После регистрации бот показывает 4 кнопки:

📊 Статус ресторанов
❌ Стоп Лист
⭐ Рейтинг моих ресторанов
⚙️ Настройки

📊 Статус ресторанов

Показывает подробный отчёт по конкретному ресторану.

  1. После нажатия появляется список ваших ресторанов, сгруппированный по городам.
  2. Выберите ресторан.
  3. Бот покажет блок по каждому каналу продаж, на котором есть этот ресторан:
    • Статус (открыт / на стопе)
    • Рейтинг на этой площадке
    • Время доставки
    • Дополнительная информация конкретного канала продаж (часы работы, способы оплаты, прогноз доставки)

«⬅️ Назад» возвращает к списку.

Данные подтягиваются из базы данных (обновляется каждые 5 минут), поэтому экран открывается мгновенно.


❌ Стоп Лист

Открывает подменю:

🚫 Стопы по ресторанам
🍱 Стопы SKU
⬅️ Назад

🚫 Стопы по ресторанам

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

Пример:

❌ Рестораны на стопе  (3 ресторана)

📍 Город 1
• Название ресторана — Канал продаж A, Канал продаж B
   с 14:30 (1 ч 45 мин)

📍 Город 2
• Название ресторана — Канал продаж C
   с ~09:05 (5 ч 18 мин)

Что значит знак ~ перед временем?

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

🍱 Стопы SKU

Показывает позиции меню на стопе в ваших ресторанах. Это уникальная функция — она ловит случаи, когда конкретное блюдо временно отключили на бэкенде сети.

Пример:

📍 Город 1, Название ресторана:
  • Ролл «Классический» — на стопе 3 ч 12 мин
  • Сет «Букет» — на стопе 8 ч 45 мин

📍 Город 2, Название ресторана:
  • Онигири — на стопе 1 ч 02 мин

Если позиций нет — ✅ Все позиции доступны.

Лимит: до 30 верхних позиций на ресторан, чтобы сообщение оставалось читаемым.


⭐ Рейтинг моих ресторанов

Сводка средних оценок по всем платформам:

  • Рейтинг Агрегатора A — звёзды на самом агрегаторе.
  • Рейтинг Maps-площадки — звёзды + количество отзывов.
  • Рейтинг Агрегатора C — звёзды от стороннего источника.
  • Агрегатор B — рейтинг по городу (платформа не отдаёт рейтинг по конкретной точке).

Используйте раздел, чтобы быстро увидеть рестораны с проблемами по оценкам.


⚙️ Настройки

Открывает подменю:

🍽 Выбрать рестораны
🔔 Настройки уведомлений
⬅️ Назад

🍽 Выбрать рестораны

Здесь вы решаете, за какими ресторанами следить. От выбора зависит:

  • какие рестораны видны в 📊, ❌, ⭐;
  • по каким ресторанам приходят push-уведомления.

Два режима:

«Выбрать все рестораны» — следим за всеми ресторанами, к которым у вас есть доступ (вся сеть для старшего менеджмента, регион для локального).

«Выбрать ресторан» — открывается чекбокс-список. Отмечаете рестораны и нажимаете 💾 Сохранить.

🔔 Настройки уведомлений

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

ЧекбоксЧто приходит
Операционные измененияИзменения времени доставки и способов оплаты.
Стопы ресторановКогда ресторан появляется/исчезает с агрегатора + почасовые напоминания о затяжных стопах (1ч, 2ч, 3ч…).
Стопы SKUКогда позиция меню залипла на стопе ≥ N часов + напоминание раз в сутки, пока висит.
ОтзывыКаждый новый отзыв с площадок отзывов — приходит индивидуально.

Нажатие на чекбокс мгновенно переключает галочку (✅ → ⬜). Перезапуск бота настройки не сбрасывает.


Какие уведомления приходят

1. Стоп ресторана / снятие стопа

Филиал: Город Название ресторана
Канал продаж: Агрегатор A
Дата: 05.05.2026, 14:30

Статус: ❌ Скрыт с площадки агрегатора

2. Затяжной стоп

⚠️ Обратите внимание!

Ресторан Город Название ресторана (Агрегатор A) находится в стопе 3 часа

Приходит каждый час, пока стоп активен.

3. Изменение времени доставки

Филиал: Город Название ресторана
Канал продаж: Агрегатор C
Дата: 05.05.2026, 16:34

Изменение: время доставки ⏱️

Было: 45 мин
Стало: 90 мин

Защита от спама: API некоторых площадок часто пересчитывают оценку времени в зависимости от своих локальных данных. Чтобы не заваливать вас сообщениями вида «15→40→15→40 мин», бот применяет cooldown — не чаще одного алерта в 15 минут на ресторан.

4. Изменение способов оплаты

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

5. Группировка массовых уведомлений

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

6. SKU надолго на стопе

🍱 SKU долго на стопе — Город Название ресторана

📦 Название позиции
   Категория: Суши
   Цена: 499

⏰ На стопе уже: 2 ч 15 мин

Возможно, забыли снять?

Приходит, когда SKU висит ≥ 2 часов. Если ещё через сутки не снят — приходит напоминание.

7. Новый отзыв

📍 Maps-площадка
Дата: 05.05.2026
Отзыв на ресторан Город, Название ресторана от Имя Автора
Оценка: 4 ⭐⭐⭐⭐

Текст отзыва

8. Ежедневный отчёт

Раз в сутки в персонально настроенный для региона час бот присылает:

  • сводку всех стоп-событий за день;
  • сводку отзывов со средней оценкой и распределением.

Тихие часы

С 23:00 до 08:00 (по локальному времени) уведомления о стопах, изменении времени доставки и способов оплаты не отправляются, чтобы не будить ночью.


Веб-дашборд

Кроме Telegram-бота у системы есть веб-интерфейс. URL получите у администратора.

Авторизация

Введите выданный логин и пароль. Сессия живёт 24 часа.

Раздел «Дашборд»

Главный аналитический экран:

  • KPI за выбранный период:
    • количество стоп-событий;
    • средняя длительность стопа;
    • максимальный простой и какой ресторан;
    • средняя длительность простоя в день (% от рабочего времени).
  • Графики:
    • динамика нагрузки по часам;
    • доли агрегаторов;
    • топ-5 городов по числу событий;
    • топ-5 проблемных ресторанов с рейтингом риска.
  • Фильтры: город, агрегатор, период, поиск по названию, «только стопы > 10 минут».

Раздел «Стоп-события»

Полная таблица ресторанных стопов. Два режима:

  • Активные — что прямо сейчас в стопе (с живым таймером длительности).
  • Прошедшие — архив с датами начала и конца, длительностью, фильтрами.

Сортировка по любой колонке, пагинация по 50. Активный режим автоматически обновляется каждые 30 секунд.

Раздел «SKU-стопы»

Таблица позиций меню в стопе. Фильтры: город, ресторан, поиск по названию SKU, «только ≥ 2 часа».

Раздел «Рестораны»

Карта всей сети. Каждый город — «созвездие», каждый ресторан — звезда. На иконке виден рейтинг Maps-площадок.

Раздел «Отзывы»

Две вкладки:

  • Отзывы площадок — отзывы Maps-площадки. Фильтры: место, рейтинг (1–5), есть текст / есть ответ владельца, период. Кнопка «Синхронизировать» запускает обновление.
  • Доставка — отзывы Delivery-площадки. Помимо отзыва видны детали заказа: состав, суммы, оценка курьера, оценка блюд.

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

❓ Я не получаю уведомлений, хотя зарегистрирован

Скорее всего вы не выбрали рестораны. Зайдите в ⚙️ Настройки → 🍽 Выбрать рестораны → «Выбрать все рестораны» (или отметьте конкретные).

❓ Слишком много уведомлений. Можно отключить?

Можно отключить категорию целиком в ⚙️ Настройки → 🔔 Настройки уведомлений. Точечно по одному ресторану выключить нельзя — либо весь канал, либо никакой.

❓ Ночью бот молчит, хотя ресторан упал.

Окно «тихих часов» 23:00–08:00 сделано специально. События, произошедшие в это время, приходят утром одним сводным сообщением.

❓ Один из агрегаторов показывает странные скачки времени доставки.

Так работает его API — он пересчитывает оценку каждые несколько минут в зависимости от своих данных. Бот защищён от спама: алерт по этому агрегатору не чаще раза в 15 минут.

❓ Что значит ~ перед временем старта?

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

❓ Вижу ресторан, к которому не должно быть доступа.

Сообщите администратору — возможно, неверно указан регион в карточке.

❓ Как сменить регион?

Через администратора. Самостоятельно нельзя — это сделано специально, чтобы исключить ошибки.


Часть 2 — Для администраторов

Архитектура системы

┌────────────────┐         ┌──────────────────┐
│  Telegram-бот  │         │   Веб-дашборд    │
│  (Node.js)     │         │   (Next.js)      │
└────────┬───────┘         └────────┬─────────┘
         │                          │
         │   общая MongoDB          │
         └──────────┬───────────────┘
                    │
            ┌───────▼────────┐
            │   MongoDB      │
            │   коллекции:   │
            │   • users      │
            │   • restaurants│
            │   • stopevents │
            │   • skustops   │
            │   • reviews    │
            │   • sessions   │
            └────────────────┘

  Внешние API:
   • Агрегатор A   (HTTP, ключ)
   • Агрегатор B   (HTTP, ключ)
   • Агрегатор C   (через прокси)
   • Агрегатор D   (через браузерную автоматизацию)
   • Сторонний скрапер для Maps-площадки

Размещение:

  • Бот работает на Linux VPS.
  • Дашборд — production-сборка Next.js, может быть на том же VPS или отдельно.
  • MongoDB — локально на VPS, доступ только через 127.0.0.1:27017 с авторизацией.

Установка

Требования

  • Linux-сервер (Ubuntu 22.04+)
  • Node.js 20+
  • MongoDB 7.x
  • pm2 (npm i -g pm2)
  • Доступ в интернет (для опроса агрегаторов)

Telegram-бот

git clone <repo-url> restaurant-pulse
cd restaurant-pulse/bot
npm install
npx playwright install chromium
cp .env.example .env       # отредактировать
node -c index.js           # проверка синтаксиса
pm2 start index.js --name restaurant-pulse
pm2 save

Дашборд

cd restaurant-pulse/dashboard
npm install
cp .env.local.example .env.local   # отредактировать
npm run build
pm2 start "npm run start" --name dashboard

Конфигурация переменных окружения

Бот (.env)

# Обязательные
BOT_TOKEN=<токен-вашего-telegram-бота>
MONGO_URI=mongodb://USER:PASS@127.0.0.1:27017/dbname?authSource=admin
CHECK_INTERVAL=300000

# Контроль доступа
ACCESS_REQUEST_CHAT_ID=<chat-id-группы-модераторов>
BROWSER_HEADLESS=true

# Внешние API (вставьте свои ключи)
AGGREGATOR_A_API_KEY=
AGGREGATOR_A_TIMEOUT_MS=10000
AGGREGATOR_B_API_KEY=
AGGREGATOR_B_TIMEOUT_MS=10000

# Агрегатор C требует прокси
EXTERNAL_PROXY_HOST=
EXTERNAL_PROXY_PORT=
EXTERNAL_PROXY_USER=
EXTERNAL_PROXY_PASS=
EXTERNAL_API_TOKEN=
EXTERNAL_API_TIMEOUT_MS=20000
EXTERNAL_RATINGS_CACHE_TTL_S=900

# SKU-мониторинг
SKU_MONITOR_ENABLED=true
SKU_MONITOR_INTERVAL_MS=300000
SKU_ALERT_THRESHOLD_MS=7200000
SKU_REPEAT_ALERT_MS=86400000
SKU_FETCH_TIMEOUT_MS=10000

# Защита от флаппинга для алертов времени доставки
DELIVERY_TIME_ALERT_COOLDOWN_MS=900000

# Опционально: сторонний скрапер
SCRAPER_TOKEN=

# Расписание ежедневных отчётов
ADMIN_REPORT_HOUR=22
REPORT_TIME_JSON={"Регион A":22,"Регион B":23}

Дашборд (.env.local)

MONGODB_URI=mongodb://USER:PASS@127.0.0.1:27017/dbname?authSource=admin
CRON_SECRET=<случайная-строка-для-защиты-cron>

Управление процессами

pm2 list                                      # список процессов
pm2 logs restaurant-pulse                     # лог бота
pm2 logs dashboard                            # лог дашборда
pm2 restart restaurant-pulse --update-env     # обязательно --update-env после правки .env
pm2 monit                                     # интерактивный мониторинг

Аварийное отключение SKU-мониторинга

Если SKU-мониторинг сильно нагружает систему:

SKU_MONITOR_ENABLED=false
pm2 restart restaurant-pulse --update-env

Бот продолжит работу, SKU-цикл не запустится. Существующие SKU-события останутся в БД, дашборд продолжит их показывать.

Cron-задачи (синхронизация отзывов)

В дашборде есть два cron-эндпоинта. Настройте crontab -e:

0 * * * * curl -H "Authorization: Bearer $CRON_SECRET" http://localhost:3000/api/cron/reviews
0 * * * * curl -H "Authorization: Bearer $CRON_SECRET" http://localhost:3000/api/cron/delivery-reviews

Управление администраторами дашборда

В дашборде нет UI-регистрации. Аккаунты создаются вручную через mongosh:

mongosh "mongodb://USER:PASS@127.0.0.1:27017/dbname?authSource=admin"
db.auth.insertOne({
  login: "admin",
  password: "<надёжный-пароль>",
  name: "Имя Администратора"
})

Удалить:

db.auth.deleteOne({ login: "admin" })
db.sessions.deleteMany({ login: "admin" })

Настройка модераторов бота

Модераторы получают заявки на доступ в приватной группе и одобряют/отклоняют их inline-кнопками.

  1. Создайте приватную Telegram-группу, добавьте туда бота и администраторов.
  2. Узнайте chat_id группы (отрицательное число, формат -100xxxxxxxxxx).
  3. Пропишите ACCESS_REQUEST_CHAT_ID в .env и перезапустите с --update-env.
  4. Новые заявки будут приходить в группу с кнопками [✅ Принять] / [❌ Отклонить].

Решение проблем

Бот не запускается

node -c index.js          # проверка синтаксиса
node index.js             # ручной запуск, видны ошибки

Частые причины:

  • неверный MONGO_URI или MongoDB не запущена;
  • неверный BOT_TOKEN или бот заблокирован;
  • не установлен Playwright (npx playwright install chromium).

Не приходят уведомления о стопах

  1. pm2 list — бот в статусе online?
  2. pm2 logs restaurant-pulse --lines 100 — есть ли ошибки?
  3. Проверьте users: ваша запись имеет status: 'approved' и непустой observingRestaurants?
  4. Проверьте notificationPreferences.restaurantStop — может быть false.
  5. Сейчас «тихие часы» (23:00–08:00)?

Один из агрегаторов возвращает 403

  1. Проверьте прокси (некоторые агрегаторы требуют региональные).
  2. Проверьте EXTERNAL_API_TOKEN — некоторые платформы периодически обновляют токены веб-клиента.

Дашборд показывает ошибки сети

  1. pm2 logs dashboard --lines 100 — что в логах Next.js?
  2. Проверьте MONGODB_URI в .env.local.
  3. DevTools браузера → Network — какой статус у запросов в /api/*?

SKU-мониторинг сильно грузит сервер

SKU_MONITOR_INTERVAL_MS=900000   # каждые 15 мин вместо 5

Или отключите целиком: SKU_MONITOR_ENABLED=false. Перезапуск с --update-env.

Откат после неудачного обновления

Все ручные правки основного файла бота сопровождаются бэкапами вида index.bak-pre-update-YYYYMMDD_HHMMSS.js в той же директории. Откат:

cp /opt/restaurant-pulse/index.bak-pre-update-... /opt/restaurant-pulse/index.js
pm2 restart restaurant-pulse --update-env

Лицензия и контакты

Эта документация опубликована как материал портфолио. Сама система — проприетарное ПО, принадлежащее владельцам. Никакого публичного развёртывания, интеграций или коммерческого использования без явного разрешения.

По техническим вопросам архитектуры см. парный документ API_DOCUMENTATION_PUBLIC.md.


Restaurant Pulse — внутренняя система мониторинга.