Оглавление
Часть 1 — Для пользователей (операторы, региональные управляющие)
- Регистрация в Telegram-боте
- Главное меню
- 📊 Статус ресторанов
- ❌ Стоп Лист
- ⭐ Рейтинг моих ресторанов
- ⚙️ Настройки
- Какие уведомления приходят
- Веб-дашборд
- Часто задаваемые вопросы
Часть 2 — Для администраторов
- Архитектура системы
- Установка
- Конфигурация переменных окружения
- Управление процессами
- Управление администраторами дашборда
- Настройка модераторов бота
- Резервное копирование БД
- Решение проблем
Что такое Restaurant Pulse
Restaurant Pulse — внутренняя система мониторинга для сети ресторанов, состоящая из двух независимо развёрнутых компонентов с общей базой данных:
- Telegram-бот — оперативные push-уведомления и быстрые отчёты прямо в мессенджере.
- Веб-дашборд — детальная аналитика, фильтры, графики, отзывы клиентов.
Система непрерывно опрашивает различные каналы продаж (несколько площадок — здесь обозначены как Агрегатор A, B, C, D) и площадки отзывов и фиксирует:
- когда ресторан пропадает с агрегатора (полный «стоп»);
- когда отдельные позиции меню (SKU) становятся недоступны (SKU-стопы);
- когда существенно меняется время доставки;
- когда меняются способы оплаты;
- когда появляются новые отзывы клиентов.
Возможности
✅ Telegram-уведомления в течение 1–2 минут после события
✅ Эскалация: повторный алерт каждый час, пока ресторан в стопе
✅ Отдельный мониторинг позиций меню — ловит ситуации «забыли включить»
✅ Ежедневный сводный отчёт по всем выбранным ресторанам
✅ Индивидуальные настройки уведомлений (4 канала с независимыми чекбоксами)
✅ Веб-дашборд с фильтрами, графиками и оценкой финансовых потерь
✅ Объединённая лента отзывов с разных площадок
Часть 1 — Для пользователей
Регистрация в Telegram-боте
Шаг 1. Первый вход
Откройте Telegram и перейдите по ссылке, которую вам передал администратор. Нажмите «Начать» (или отправьте /start).
Шаг 2. Выберите роль
Бот предложит два варианта:
- Старший менеджмент — операционный директор, либо сотрудники функциональных подразделений. Выберите, если вам необходимы все регионы сети.
- Локальный менеджмент — управляющие и менеджера ресторанов. Выберите, если вы работаете в одном регионе.
Шаг 3. Если локальный менеджмент — выберите регион
Появится список регионов. Выберите свой (регионы заранее заданы географией сети).
Каждый регион автоматически охватывает несколько городов — отдельно выбирать города не нужно.
Шаг 4. Дождитесь подтверждения
После выбора роли заявка уходит модератору бота. Вы увидите:
Заявка отправлена на подтверждение
Когда модератор одобрит, придёт сообщение:
Регистрация подтверждена. Используйте /menu
Если заявка отклонена — обратитесь к модерации бота.
Шаг 5. Откройте меню
Отправьте /menu или /start — появится главное меню из 4 кнопок.
Совет: в самом начале зайдите в ⚙️ Настройки → Выбрать рестораны и отметьте необходимые рестораны Далее зайдите в Настройки уведомлений и отметьте необходимые метрики
Главное меню
После регистрации бот показывает 4 кнопки:
📊 Статус ресторанов
❌ Стоп Лист
⭐ Рейтинг моих ресторанов
⚙️ Настройки
📊 Статус ресторанов
Показывает подробный отчёт по конкретному ресторану.
- После нажатия появляется список ваших ресторанов, сгруппированный по городам.
- Выберите ресторан.
- Бот покажет блок по каждому каналу продаж, на котором есть этот ресторан:
- Статус (открыт / на стопе)
- Рейтинг на этой площадке
- Время доставки
- Дополнительная информация конкретного канала продаж (часы работы, способы оплаты, прогноз доставки)
«⬅️ Назад» возвращает к списку.
Данные подтягиваются из базы данных (обновляется каждые 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-кнопками.
- Создайте приватную Telegram-группу, добавьте туда бота и администраторов.
- Узнайте
chat_idгруппы (отрицательное число, формат-100xxxxxxxxxx). - Пропишите
ACCESS_REQUEST_CHAT_IDв.envи перезапустите с--update-env. - Новые заявки будут приходить в группу с кнопками [✅ Принять] / [❌ Отклонить].
Решение проблем
Бот не запускается
node -c index.js # проверка синтаксиса
node index.js # ручной запуск, видны ошибки
Частые причины:
- неверный
MONGO_URIили MongoDB не запущена; - неверный
BOT_TOKENили бот заблокирован; - не установлен Playwright (
npx playwright install chromium).
Не приходят уведомления о стопах
pm2 list— бот в статусеonline?pm2 logs restaurant-pulse --lines 100— есть ли ошибки?- Проверьте
users: ваша запись имеетstatus: 'approved'и непустойobservingRestaurants? - Проверьте
notificationPreferences.restaurantStop— может бытьfalse. - Сейчас «тихие часы» (23:00–08:00)?
Один из агрегаторов возвращает 403
- Проверьте прокси (некоторые агрегаторы требуют региональные).
- Проверьте
EXTERNAL_API_TOKEN— некоторые платформы периодически обновляют токены веб-клиента.
Дашборд показывает ошибки сети
pm2 logs dashboard --lines 100— что в логах Next.js?- Проверьте
MONGODB_URIв.env.local. - 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 — внутренняя система мониторинга.