zov-tech/docs/ТЗ_ЗОВ_Бот_MiniApp_v1.md

951 lines
45 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Техническое задание
# Telegram-бот + MiniApp «AI-подбор техники для кухни ЗОВ»
**Версия:** 1.0
**Дата:** 2026-05-08
**Заказчик:** Василий (vasrusgen@gmail.com), куратор партнёрской сети ЗОВ
**Канал:** [@wasrusgen1](https://t.me/wasrusgen1)
**Целевая аудитория продукта:** 112 менеджеров салонов ЗОВ + конечные клиенты, ведомые через канал
---
## 1. Контекст и цели
### 1.1 Что это за продукт
Telegram-бот выступает шлюзом авторизации, после чего открывается единый MiniApp с двумя ролями:
- **Кабинет менеджера** — рабочий инструмент: подбор техники для клиента, замеры, заявки, сделки, статус доступа.
- **Кабинет клиента** — воронка покупки кухни: замер, подбор, калькулятор, идеи, связь с менеджером.
Внутри MiniApp клиент или менеджер заполняют структурированный чек-лист. Данные уходят в backend, который вызывает LLM (OpenAI / Claude). LLM возвращает готовое предложение по технике с учётом брендов, ниш, бюджета и сценария использования. Результат доставляется обратно в Telegram.
### 1.2 Какую проблему решает
- Сокращает срок согласования кухни с клиентом (главная боль ЗОВ).
- Привязывает менеджера к куратору: «работаешь со мной — инструмент бесплатно, ушёл — платно».
- Превращает 112 менеджеров в управляемую партнёрскую сеть с метриками.
- Даёт клиентам бесплатную ценность до контакта с менеджером (калькулятор, идеи, самозамер).
### 1.3 Бизнес-модель в продукте
| Сегмент | Доступ | Условие |
|---|---|---|
| Менеджеры ЗОВ (свои салоны) | бесплатно навсегда | по умолчанию |
| Менеджеры партнёрских салонов, активные | бесплатно | сделка через куратора за последние 90 дней |
| Менеджеры партнёрских салонов, неактивные | платно | подписка / pay-per-use |
| Конечные клиенты | базовый доступ бесплатно | подбор + замер открыты, премиум-функции потом |
Точное определение «активного менеджера» — поле `last_order_date` в реестре + 90 дней.
### 1.4 Что в скоупе MVP
- Бот с одним диалогом (выбор роли + кнопка «Открыть кабинет»).
- MiniApp с двумя меню (менеджер / клиент), но **рабочих пунктов всего три**:
- 🔧 «Подбор техники» (для менеджера, на базе существующего HTML-чек-листа `02_Чек-лист_клиенту.html`).
- 📐 «Самозамер» (для клиента, новая 5-шаговая форма).
- 💰 «Мой статус» (для менеджера, простая страница).
- Backend на Google Apps Script + Google Sheet как БД.
- AI-подбор через OpenAI API (`gpt-4o-mini`) с готовым промптом.
- Доставка результата менеджеру через бота.
### 1.5 Что НЕ в скоупе MVP (на будущее)
- Платёжная интеграция (ЮKassa / Telegram Stars).
- Раздел «Сделки», «База знаний», «Обучение», «FAQ», «Записаться в салон».
- Личный кабинет клиента с историей.
- Push-уведомления об активности.
- Партнёрская комиссия с производителей техники.
- Мобильное нативное приложение (всегда останется MiniApp).
---
## 2. Архитектура
### 2.1 Компоненты
```
Telegram канал @wasrusgen1
│ кнопка/ссылка "Открыть подбор"
Telegram бот @zov_tech_bot
│ /start → выбор роли → кнопка WebApp
MiniApp (SPA, HTML+JS)
на хостинге GitHub Pages / Netlify (HTTPS обязателен)
│ POST /api/*
Backend Google Apps Script (Web App URL)
│ R/W
Google Sheet "ЗОВ — База"
│ при подборе:
OpenAI API (gpt-4o-mini)
│ результат
Backend → Telegram Bot API → менеджер/клиент
```
### 2.2 Технологический стек
| Слой | Технология | Обоснование |
|---|---|---|
| Бот | Python + aiogram **либо** n8n + Telegram Trigger | aiogram — гибче, n8n — без кода |
| MiniApp | HTML + Vanilla JS + минимальный CSS | существующий чек-лист уже в этом стеке |
| Хостинг MiniApp | GitHub Pages | бесплатно, HTTPS, Git-history |
| Backend | Google Apps Script (Web App) | бесплатно, нативная связка с Sheet |
| БД | Google Sheet | прозрачность для заказчика, ручное редактирование |
| AI | OpenAI API, модель `gpt-4o-mini` | дёшево (~$0.001 на запрос), хватает для подбора |
| Платежи (вне MVP) | ЮKassa или Telegram Stars | российские реалии |
### 2.3 Окружения
- **Dev:** локальный HTML, бот в режиме polling, тестовая Google Sheet.
- **Prod:** GitHub Pages, бот в режиме webhook, прод-Sheet с реестром.
---
## 3. Бот @zov_tech_bot
### 3.1 Общие принципы
- Бот **не содержит продуктовой логики**. Он только аутентифицирует и открывает MiniApp.
- Все длинные диалоги, формы, чек-листы — внутри MiniApp.
- Бот шлёт результаты подбора и системные уведомления.
### 3.2 Команды
| Команда | Доступ | Действие |
|---|---|---|
| `/start` | все | приветствие, выбор роли (если новый пользователь) или кнопка «Открыть кабинет» (если уже зарегистрирован) |
| `/start <invite_code>` | все | спец-сценарий: переход по ссылке-приглашению от менеджера |
| `/menu` | все | повторная кнопка «Открыть кабинет» |
| `/help` | все | краткая справка + контакт куратора |
| `/admin` | только админ (tg_id куратора) | админ-меню (см. 3.5) |
### 3.3 Дерево диалогов
```
[НОВЫЙ ПОЛЬЗОВАТЕЛЬ]
/start
"👋 Здравствуйте! Я помогу подобрать технику для кухни.
Кто вы?"
[👤 Менеджер] [🏠 Клиент]
│ │
▼ ▼
сохранить сохранить
role=manager role=client
в БД в БД
│ │
▼ ▼
"Отлично, открываю "Спасибо! Открываю
ваш кабинет 👇" кабинет 👇"
[🚀 Открыть кабинет] [🚀 Открыть кабинет]
(WebApp button с URL MiniApp)
[ВЕРНУВШИЙСЯ ПОЛЬЗОВАТЕЛЬ]
/start
"С возвращением, {имя}!"
[🚀 Открыть кабинет]
[ССЫЛКА-ПРИГЛАШЕНИЕ ОТ МЕНЕДЖЕРА]
/start client_inv_AB12CD
проверить invite_code в БД
│ найден → manager_id = X
сохранить role=client + manager_id=X
"Здравствуйте! Вас сопровождает {ФИО менеджера}, ЗОВ {салон}.
Открываю кабинет 👇"
[🚀 Открыть кабинет]
```
### 3.4 Кнопка «Открыть кабинет»
Это **WebApp-кнопка** Telegram (не URL-button), которая открывает MiniApp с подписанным `initData`.
Параметр `web_app.url`:
```
https://wasrusgen.github.io/zov-tech/?v=1
```
`initData` содержит `tg_id`, имя пользователя, hash для проверки. Backend проверяет hash и определяет роль по БД.
### 3.5 Админ-функции (для куратора)
Команда `/admin` доступна только при `tg_id == ADMIN_TG_ID` (env-переменная).
Меню:
- `📊 Статистика` — сколько активных менеджеров, заявок за неделю, конверсия
- `👤 Управление менеджерами`
- `+ Добавить менеджера` (диалог: ФИО, tg_username, salon)
- `✏️ Изменить статус` (выбор → active / lapsed + дата)
- `🔍 Найти менеджера` (по ФИО / tg_username)
- `📨 Рассылка` — отправить сообщение всем менеджерам / всем клиентам / выбранным сегментам
### 3.6 Системные уведомления (исходящие от бота)
| Триггер | Получатель | Текст |
|---|---|---|
| Клиент завершил подбор | менеджер этого клиента | «Новая заявка от {ФИО клиента}: {short_summary}. [Открыть в кабинете]» |
| Менеджер запросил подбор | менеджер | «Готово! Подбор для {ФИО клиента}: [PDF / текст]» |
| Клиент сделал самозамер | менеджер этого клиента | «{ФИО клиента} прислал замер кухни. [Посмотреть]» |
| Статус менеджера изменён куратором | менеджер | «Ваш доступ продлён до {дата}» / «Доступ переведён в платный режим» |
Все уведомления сопровождаются inline-кнопкой, открывающей соответствующий экран MiniApp.
### 3.7 Технические требования к боту
- Режим **webhook** в проде, polling в деве.
- Хранилище состояний — память (FSM aiogram) или Redis для масштаба. На MVP — память.
- Логирование всех `update` в файл / Sheet «Логи бота».
- Обработка ошибок: при exception — сообщение «Произошла ошибка, мы уже разбираемся» + alert куратору.
### 3.8 Регистрация бота в @BotFather
1. `/newbot``zov_tech_bot` (или альтернативное имя, если занято).
2. `/setdomain` → домен MiniApp (`wasrusgen.github.io`).
3. `/newapp` → создать MiniApp:
- Title: «Подбор техники ЗОВ»
- Short name: `podbor`
- Web App URL: `https://wasrusgen.github.io/zov-tech/`
4. `/setmenubutton` → опционально, кнопка-меню в боте, ведущая в MiniApp.
---
## 4. MiniApp
### 4.1 Карта страниц (hash-роутинг внутри одного SPA)
```
#/ — авто-редирект по роли
#/m — главное меню менеджера
#/m/podbor — чек-лист подбора (существующий HTML)
#/m/measurements — список замеров
#/m/measurements/new — форма замера (менеджер за клиента)
#/m/measurements/:id — карточка одного замера
#/m/leads — список заявок (просмотр, MVP — read-only)
#/m/status — мой статус и доступ
#/m/help — связь с куратором
#/c — главное меню клиента
#/c/measure — выбор: вызвать замерщика / замерить самому
#/c/measure/self — 5-шаговая форма самозамера
#/c/measure/visit — заявка на выезд замерщика
#/c/podbor — упрощённый чек-лист (вне MVP, заглушка)
#/c/contact — связь с менеджером
```
### 4.2 Авторизация и определение роли
```js
// Псевдокод старта MiniApp
const tg = window.Telegram.WebApp;
tg.ready();
tg.expand();
const initData = tg.initData; // подписанная строка
const startParam = tg.initDataUnsafe.start_param || null;
const me = await fetch('/api/me', {
method: 'POST',
body: JSON.stringify({ initData, startParam })
}).then(r => r.json());
// me = { role: "manager"|"client", user: {...}, manager: {...}, status: "active"|"lapsed" }
if (me.role === 'manager') router.go('#/m');
else router.go('#/c');
```
Backend `/api/me`:
1. Проверяет HMAC `initData` по `BOT_TOKEN` (стандартная процедура Telegram).
2. Ищет `tg_id` в листе «Пользователи».
3. Если нет — создаёт запись (роль уже сохранена ботом, должна быть в БД).
4. Возвращает профиль + статус.
### 4.3 Кабинет менеджера
**Главный экран `#/m`:**
```
┌─────────────────────────────────────┐
│ Привет, {ФИО} │
│ Салон: {salon} │
│ Статус: 🟢 active до 12.08.2026 │
│ │
│ ─────────────────────────────── │
│ │
│ 🔧 Подбор техники для клиента → │
│ 📐 Замеры → │
│ 📋 Заявки клиентов → │
│ 💼 Сделки (скоро) · │
│ 📚 База знаний (скоро) · │
│ 💰 Мой статус → │
│ 🆘 Связь с куратором → │
└─────────────────────────────────────┘
```
Пункты «Сделки», «База знаний» в MVP — disabled-кнопки с текстом «Скоро».
**Страница `#/m/podbor`:**
Это существующий файл `02_Чек-лист_клиенту.html` с минимальными доработками:
1. Удалить захардкоженный блок менеджера (Любовь Алпеева) — подставлять из `me.user`.
2. Добавить поле «Размеры ниш» (см. п. 4.5 — пробелы из анализа).
3. Добавить поле «Бюджет по категориям».
4. Добавить блок «Сценарий использования» (семья, готовка).
5. Кнопку «Отправить» завести на `POST /api/podbor` вместо `mailto:`.
6. После отправки — `tg.showAlert('Заявка отправлена, результат придёт в чат')` + `tg.close()`.
**Страница `#/m/measurements`:**
Список замеров клиентов этого менеджера. Колонки: дата, ФИО клиента, статус (🟡 запрошен / 🟢 готов / 🔵 загружен вручную), кнопка «Открыть».
**Страница `#/m/measurements/new`:**
Та же форма, что и у клиента в `#/c/measure/self`, но с дополнительным полем «Клиент» (выбор из списка или ввод).
**Страница `#/m/status`:**
```
┌─────────────────────────────────────┐
│ Ваш статус │
│ │
│ 🟢 Active │
│ Доступ продлён до 12.08.2026 │
│ Осталось 96 дней │
│ │
│ Последняя сделка через куратора: │
│ «Кухня Петров, 14.05.2026» │
│ │
│ Заявок за всё время: 23 │
│ Сделок через подбор: 7 (30%) │
│ │
│ Чтобы продлить доступ — │
│ проведите следующую сделку │
│ через @wasrusgen. │
└─────────────────────────────────────┘
```
Если `status == lapsed`:
```
┌─────────────────────────────────────┐
│ ⚠️ Доступ ограничен │
│ │
│ Последняя сделка через куратора │
│ была 12.02.2026. │
│ Бесплатный доступ закончился. │
│ │
│ Варианты: │
│ • Возобновить сопровождение через │
│ @wasrusgen — доступ снова free. │
│ • Подписка 3 000 ₽/мес. │
│ • Pay-per-use 500 ₽/подбор. │
│ │
│ [Связаться с куратором] │
│ [Оформить подписку] (вне MVP) │
└─────────────────────────────────────┘
```
### 4.4 Кабинет клиента
**Главный экран `#/c`:**
```
┌─────────────────────────────────────┐
│ Привет, {имя} │
│ {если есть} │
│ Менеджер: {ФИО}, ЗОВ {салон} │
│ │
│ ─────────────────────────────── │
│ │
│ 📐 Замер кухни → │
│ 🔧 Подобрать технику (скоро) · │
│ 📐 Калькулятор бюджета (скоро) · │
│ 💡 Идеи и кейсы (скоро) · │
│ 📞 Связаться с менеджером → │
│ 📍 Записаться в салон (скоро) · │
└─────────────────────────────────────┘
```
В MVP активны: «Замер кухни», «Связаться с менеджером».
**Страница `#/c/measure`:**
Развилка:
```
Выберите способ замера:
[📞 Вызвать замерщика]
Бесплатно при заказе кухни
2 000 ₽ — отдельная услуга
[📏 Замерить самому]
5 шагов с инструкцией
Займёт ~15 минут
```
**Страница `#/c/measure/self`:**
5 экранов, каждый — отдельный шаг. Прогресс-бар сверху.
**Шаг 1: План кухни**
- Выбор формы (radio-картинки): прямая / Г-образная / П-образная / с островом / свой вариант
- Поле «Площадь, м²» (number)
- Поле «Высота потолка, мм» (number, default 2700)
**Шаг 2: Стены и габариты**
- Длина стены 1, мм
- Длина стены 2, мм (если Г-/П-образная)
- Длина стены 3, мм (если П-образная)
- Загрузка фото общего вида (опционально)
**Шаг 3: Окна и двери**
- Чекбоксы: «Есть окно» / «Есть дверь» / «Есть выход на балкон»
- Для каждого активного — поля: положение (выбор стены), ширина, высота, расстояние от пола
**Шаг 4: Коммуникации (важно для AI-подбора)**
- Тип подключения варочной: газ / электрика 220 / электрика 380
- Наличие вентиляционной шахты на кухне: да / нет / не знаю
- Расположение мойки: стена 1 / 2 / 3 / остров
- Свободное поле «Особенности коммуникаций»
**Шаг 5: Ниши под технику (если планируется встройка)**
Чекбокс «Планирую встроенную технику» → раскрывает блок:
- Холодильник: Ш × В × Г, мм
- Варочная: Ш × В × Г, мм
- Духовой шкаф: Ш × В × Г, мм
- Посудомойка: Ш × В × Г, мм
- Стиральная (если на кухне): Ш × В × Г, мм
- Микроволновка: Ш × В × Г, мм
- Кофемашина: Ш × В × Г, мм
Поля опциональные. Если не планируется встройка — блок свёрнут, шаг можно пропустить.
**Финал:**
- Кнопка «Сохранить замер».
- POST `/api/measurement` → сохранение + уведомление менеджеру (если manager_id привязан).
- `tg.showAlert('Замер сохранён')` + `tg.close()`.
### 4.5 Доработки существующего чек-листа подбора
Согласно анализу `02_Чек-лист_клиенту.html` нужно добавить:
1. **Блок «Параметры кухни»** в онбординг (или подгружать из последнего замера).
2. **Бюджет по категориям** — простая таблица в финальном экране.
3. **Блок «Семья и готовка»** — 45 быстрых вопросов с радиокнопками:
- Состав семьи: 1 взрослый / пара / семья с детьми / 2+ поколения
- Частота готовки: ежедневно / 34 раза в неделю / реже
- Любимые техники: выпечка / на пару / гриль / wok / низкотемпературное (multi-select)
- Приём гостей: часто / иногда / редко
4. **Чекбокс «уже есть, не меняю»** в каждой категории — клиент исключает позиции.
5. **Webhook вместо `mailto:`** — POST на backend.
6. **Обязательные поля**: имя, контакт, общий бюджет, адрес.
### 4.6 Дизайн-токены (брендинг ЗОВ)
Использовать существующие в HTML переменные:
```css
:root {
--bronze: #76BD22; /* фирменный зелёный */
--accent: #003E7E; /* фирменный синий */
--cream: #FAFAFA;
--sand: #F0F9E8;
}
```
Шрифт — системный sans-serif (как в текущем HTML). Скруглённые углы 8px, тени минимальные.
---
## 5. База данных (Google Sheets)
Файл: **«ЗОВ — База»** (один документ, несколько листов).
### 5.1 Лист «Users»
Все пользователи бота (менеджеры + клиенты).
| Колонка | Тип | Описание |
|---|---|---|
| tg_id | number | Telegram user ID, **первичный ключ** |
| tg_username | text | @username, может отсутствовать |
| first_name | text | Имя из Telegram |
| last_name | text | Фамилия из Telegram |
| role | text | `manager` / `client` / `admin` |
| created_at | datetime | Дата первого `/start` |
| last_seen_at | datetime | Последний контакт с ботом |
| invite_code_used | text | Код приглашения, если был |
### 5.2 Лист «Managers»
Расширенный профиль менеджеров.
| Колонка | Тип | Описание |
|---|---|---|
| tg_id | number | FK → Users.tg_id |
| full_name | text | ФИО полное |
| email | text | Рабочая почта |
| phone | text | Телефон |
| salon | text | Название салона |
| city | text | Город |
| is_zov_employee | bool | true = свой, false = партнёр |
| status | formula | `=IF(active_until>=TODAY();"active";"lapsed")` |
| last_order_date | date | Дата последней сделки через куратора |
| active_until | formula | `=last_order_date+90` |
| total_leads | formula | `=COUNTIF(Leads.manager_tg_id; tg_id)` |
| total_deals | number | Заполняется куратором вручную |
| conversion_rate | formula | `=total_deals / total_leads` |
| invite_code | text | Уникальный код для генерации client-ссылок (например `MGR_AB12`) |
### 5.3 Лист «Clients»
| Колонка | Тип | Описание |
|---|---|---|
| tg_id | number | FK → Users.tg_id |
| full_name | text | |
| phone | text | |
| email | text | |
| address | text | |
| city | text | |
| budget_total | number | Общий бюджет на кухню + технику |
| manager_tg_id | number | FK → Managers.tg_id, **связка клиент—менеджер** |
| source | text | `channel` / `manager_invite` / `direct` |
| last_measurement_id | text | FK → Measurements.id |
### 5.4 Лист «Measurements»
| Колонка | Тип | Описание |
|---|---|---|
| id | text | UUID |
| created_at | datetime | |
| client_tg_id | number | FK → Clients.tg_id |
| manager_tg_id | number | FK → Managers.tg_id |
| filled_by | text | `client_self` / `manager_for_client` |
| layout | text | прямая / Г / П / остров / другое |
| area_m2 | number | |
| ceiling_mm | number | |
| walls_json | json-text | `{"w1":3200,"w2":2400,"w3":null}` |
| openings_json | json-text | окна, двери |
| infra_json | json-text | газ/электрика, шахта, мойка |
| niches_json | json-text | размеры ниш под встройку |
| photos_urls | text | через запятую |
| notes | text | |
| status | text | `draft` / `submitted` / `verified` |
### 5.5 Лист «Leads» (заявки на подбор)
| Колонка | Тип | Описание |
|---|---|---|
| id | text | UUID |
| created_at | datetime | |
| manager_tg_id | number | кто отправил |
| client_tg_id | number | для кого |
| client_name | text | |
| measurement_id | text | FK → Measurements.id, может быть пусто |
| checklist_json | json-text | весь ответ чек-листа |
| ai_response | long-text | результат от LLM |
| ai_model | text | `gpt-4o-mini` |
| ai_tokens_used | number | для контроля расходов |
| sent_to_tg | bool | результат доставлен в Telegram |
| deal_status | text | `new` / `in_progress` / `won` / `lost` (заполняет менеджер вручную или куратор) |
| deal_amount | number | сумма закрытой кухни |
### 5.6 Лист «Logs»
Лог всех action-событий (для дебага и аналитики).
| Колонка | Тип |
|---|---|
| timestamp | datetime |
| event | text (`bot_start`, `role_selected`, `miniapp_opened`, `measurement_submitted`, `lead_created`, `ai_response_received`, `ai_error`, ...) |
| tg_id | number |
| payload | json-text |
### 5.7 Лист «Settings»
Параметры, которые могут меняться без правки кода.
| key | value | description |
|---|---|---|
| ACTIVE_PERIOD_DAYS | 90 | срок active-статуса после сделки |
| GRACE_PERIOD_DAYS | 14 | grace-период перед переводом в lapsed |
| AI_MODEL | gpt-4o-mini | какая модель используется |
| AI_TEMPERATURE | 0.3 | температура для подбора |
| ADMIN_TG_ID | <ваш tg_id> | кто получает алерты |
| PAID_PRICE_PER_LEAD | 500 | цена pay-per-use |
| PAID_SUBSCRIPTION | 3000 | цена подписки |
### 5.8 Лист «Dashboard» (для куратора)
Сводка с формулами:
```
Активных менеджеров: =COUNTIF(Managers.status; "active")
Lapsed-менеджеров: =COUNTIF(Managers.status; "lapsed")
Заявок за 30 дней: =COUNTIFS(Leads.created_at; ">="&TODAY()-30)
Конверсия в сделку: =COUNTIF(Leads.deal_status; "won") / COUNTA(Leads.id)
Средний чек закрытых сделок: =AVERAGEIF(Leads.deal_status; "won"; Leads.deal_amount)
Топ-5 менеджеров по сделкам: pivot
Расход на AI за 30 дней: =SUMPRODUCT(Leads.ai_tokens_used) * 0.0000015 * <курс>
```
---
## 6. Backend (Google Apps Script)
### 6.1 Структура проекта
```
ZOV_Backend.gs
├─ doPost(e) — единая точка входа, роутер
├─ /api/me — определить пользователя по initData
├─ /api/measurement — сохранить замер
├─ /api/podbor — создать заявку, вызвать AI, отправить в Telegram
├─ /api/lead/:id — получить заявку (для менеджера)
├─ /api/manager/status — статус менеджера
├─ helpers/
│ ├─ verifyInitData(initData, botToken)
│ ├─ readSheet(sheetName, query)
│ ├─ writeSheet(sheetName, row)
│ ├─ callOpenAI(prompt, params)
│ ├─ sendTelegram(chatId, text, options)
│ └─ generateUuid()
```
### 6.2 Деплой
1. Привязать скрипт к Google Sheet «ЗОВ — База».
2. Deploy → New deployment → Type «Web app».
3. Execute as: «Me».
4. Who has access: «Anyone» (для приёма запросов с MiniApp).
5. Получить URL `https://script.google.com/macros/s/.../exec` — это backend endpoint, прописать в MiniApp как `BACKEND_URL`.
### 6.3 Переменные окружения (Script Properties)
| Ключ | Описание |
|---|---|
| `BOT_TOKEN` | Токен бота от BotFather |
| `OPENAI_API_KEY` | ключ OpenAI |
| `ADMIN_TG_ID` | ваш Telegram ID |
| `SHEET_ID` | ID Google Sheet |
### 6.4 Безопасность
- Все запросы из MiniApp **обязаны** содержать `initData` от Telegram.
- Backend проверяет HMAC `initData` по `BOT_TOKEN` (стандартная процедура).
- Без валидного `initData` любой запрос → 401.
- Документация процедуры: <https://core.telegram.org/bots/webapps#validating-data-received-via-the-mini-app>
### 6.5 Бизнес-логика статусов менеджера
```pseudo
function getManagerStatus(tg_id):
m = Managers.find(tg_id)
if not m: return "unknown"
if m.is_zov_employee: return "active" // свои всегда active
active_until = m.last_order_date + ACTIVE_PERIOD_DAYS
grace_until = active_until + GRACE_PERIOD_DAYS
today = TODAY()
if today <= active_until: return "active"
if today <= grace_until: return "grace" // мягкое предупреждение
return "lapsed"
```
---
## 7. AI-подбор
### 7.1 Входные данные (контракт LLM-вызова)
JSON, который backend собирает перед отправкой в OpenAI:
```json
{
"client": {
"name": "Пётр Сидоров",
"city": "Москва",
"family": "пара_с_ребёнком",
"cooking_frequency": "ежедневно",
"favorite_techniques": ["выпечка", "пар"],
"guests": "иногда"
},
"kitchen": {
"layout": "Г-образная",
"area_m2": 12,
"ceiling_mm": 2700,
"walls": { "w1": 3200, "w2": 2400 },
"infra": {
"stove_power": "электрика_220",
"vent_shaft": true
},
"niches": {
"fridge": { "w": 600, "h": 1850, "d": 600 },
"hob": { "w": 600, "h": 60, "d": 520 },
"oven": { "w": 600, "h": 600, "d": 560 },
"dw": { "w": 450, "h": 820, "d": 555 }
}
},
"budget": {
"total": 350000,
"by_category": {
"fridge": 80000,
"hob": 50000,
"oven": 60000,
"hood": 25000,
"dw": 50000,
"microwave": 15000,
"coffee": 40000,
"washer": 30000
}
},
"preferences": {
"fridge": {
"tier": "middle",
"brands_preferred": ["Bosch", "Liebherr"],
"brands_alternative": ["Samsung"],
"type": "двухкамерный",
"color": "inox",
"features": ["NoFrost", "инвертор", "≤40 дБ"]
},
"hob": { "...": "..." }
/* и т.д. для всех 8 категорий, как в чек-листе */
},
"exclusions": ["microwave"] // уже есть, не подбирать
}
```
### 7.2 Промпт (system + user)
**System prompt:**
```
Ты — эксперт-консультант по подбору кухонной техники для фабрики мебели «ЗОВ».
Ты работаешь с менеджерами салонов и помогаешь им быстро согласовать с клиентом
комплект техники под их кухню.
Принципы подбора:
1. Физические ограничения важнее эстетики. Если ниша 600×1850×600 — не предлагай
холодильник 700×2000×650, даже если он лучше.
2. Уважай бюджет. Если в категории задан лимит — не превышай его более чем на 10%.
3. Уважай предпочтения по брендам. Сначала пробуй preferred (★), потом alternative (✓),
потом нейтральные альтернативы. Если ни один preferred бренд не подходит по цене —
скажи прямо.
4. Связывай выбор со сценарием использования. Семья с детьми = простота интерфейса,
защита от детей, легко мыть. Любитель выпечки = пар + 4D HotAir + термощуп.
5. Учитывай инфраструктуру. Газ исключает индукцию (если пользователь не готов
менять подключение). Нет шахты = только рециркуляция в вытяжке.
6. По каждой позиции: модель, цена, 2-3 ключевых преимущества под этого клиента,
1 предупреждение/нюанс если он есть.
Формат ответа — JSON по схеме:
{
"summary": "1-2 предложения",
"items": [
{
"category": "fridge",
"brand": "Bosch",
"model": "KGN39LB35R",
"price_rub": 79990,
"size_mm": { "w": 600, "h": 2030, "d": 660 },
"fits_niche": true,
"highlights": ["NoFrost", "инвертор", "тихий 39 дБ"],
"caveats": "Глубина 660мм — на 60мм глубже стандартной ниши, проверьте",
"match_score": 0.92,
"rationale": "Соответствует предпочтениям по бренду и тиру..."
}
],
"total_price_rub": 350000,
"budget_status": "в рамках" | "превышение" | "значительно ниже",
"warnings": ["..."],
"next_steps": ["..."]
}
Не выдумывай несуществующие модели. Если не уверен в модели — указывай линейку
("Bosch Serie 4, 60см, NoFrost") а не конкретный артикул.
Если данных недостаточно для подбора в категории — оставляй её с пометкой
"need_more_info" и указывай, чего не хватает.
Отвечай только валидным JSON без оборачивания в markdown-блоки.
```
**User prompt:**
```
Подбери технику для следующего клиента:
{JSON_INPUT}
Дай развёрнутое предложение в формате, описанном в инструкции.
```
### 7.3 Параметры вызова OpenAI
```python
{
"model": "gpt-4o-mini",
"temperature": 0.3,
"max_tokens": 4000,
"response_format": { "type": "json_object" }
}
```
### 7.4 Постобработка ответа
Backend получает JSON от OpenAI и:
1. Валидирует схему. При расхождении — алёрт куратору, ответ всё равно пытается доставить.
2. Сохраняет в `Leads.ai_response` (raw JSON).
3. Рендерит в человекочитаемый вид (текст + кнопки).
4. Отправляет менеджеру через бота:
```
✅ Подбор готов
Клиент: Пётр Сидоров
Бюджет: 350 000 ₽
🧊 Холодильник
Bosch Serie 4 KGN39LB35R — 79 990 ₽
✓ NoFrost, инвертор, тихий 39 дБ
⚠️ Глубина 660мм — на 60мм больше ниши, проверьте
🔥 Варочная панель
Electrolux EHF6342XOK — 49 990 ₽
✓ Hi-Light, защита от детей, простой интерфейс
...
ИТОГО: 348 970 ₽ (в рамках бюджета)
[📄 Скачать предложение для клиента]
[💬 Открыть в кабинете]
```
---
## 8. Безопасность и приватность
### 8.1 Аутентификация
- Все вызовы backend от MiniApp подписаны `initData` Telegram.
- Backend верифицирует HMAC `initData` ≤ 24 часов давности.
- Без подписи → 401.
### 8.2 Контроль доступа
- Менеджер видит **только свои** заявки и замеры (фильтр `WHERE manager_tg_id = me.tg_id`).
- Клиент видит **только свои** замеры.
- Куратор (admin) видит всё.
### 8.3 Хранение PII
- Имена, телефоны, адреса клиентов лежат в Google Sheet куратора.
- Доступ к Sheet — только у куратора.
- В логи не пишутся телефоны/email открытым текстом — только маскированно (`+7***1234`).
### 8.4 Согласие на обработку данных
- При первом `/start` клиент получает короткое сообщение:
> Заполняя форму подбора, вы соглашаетесь с обработкой данных в рамках консультации по подбору кухни. Подробнее — [политика](https://wasrusgen.github.io/zov-tech/privacy.html).
- Простая HTML-страница `privacy.html` рядом с MiniApp.
---
## 9. Метрики успеха MVP
Через 60 дней после запуска проверяем:
| Метрика | Целевое значение |
|---|---|
| Зарегистрированных менеджеров | ≥ 60 из 112 |
| Менеджеров, сделавших ≥1 подбор | ≥ 30 |
| Сделанных замеров клиентами | ≥ 50 |
| Заявок на подбор | ≥ 80 |
| AI-подборов с положительной обратной связью | ≥ 70% |
| Время от заявки до результата | ≤ 60 секунд |
| Конверсия подбор → закрытая сделка | ≥ 20% |
| Стоимость одного подбора (AI) | ≤ 0.5 ₽ |
---
## 10. Дорожная карта после MVP
**Спринт 4 (через 1 месяц после MVP):**
- Раздел «Сделки» с возможностью менеджеру отмечать выигранные сделки.
- Авто-продление статуса по факту отметки сделки (с подтверждением куратора).
- Раздел «База знаний» с гайдами и сравнениями.
**Спринт 5 (через 2 месяца):**
- Платный режим для lapsed-менеджеров через ЮKassa или Telegram Stars.
- Подписка / pay-per-use, биллинг.
**Спринт 6 (3+ месяца):**
- Записаться в салон (выбор салона + дата + слот).
- Личный кабинет клиента с историей замеров и заявок.
- Раздел «Идеи и кейсы» с галереей.
- Партнёрки с производителями техники.
---
## 11. Чек-лист запуска
```
[ ] Бот создан в @BotFather, токен сохранён в Apps Script Properties
[ ] Домен MiniApp привязан к боту (/setdomain)
[ ] MiniApp зарегистрирован в @BotFather (/newapp)
[ ] HTML захостен на GitHub Pages, HTTPS работает
[ ] Google Sheet «ЗОВ — База» создан, листы 5.1—5.7 готовы
[ ] Apps Script деплой как Web App, URL получен
[ ] OpenAI ключ получен, лимиты выставлены ($20/мес)
[ ] Реестр 112 менеджеров загружен в Sheet «Managers»
[ ] Свои менеджеры ЗОВ помечены is_zov_employee=true
[ ] Существующий чек-лист `02_Чек-лист_клиенту.html` доработан (4.5)
[ ] Форма самозамера реализована (4.4 шаги 1-5)
[ ] AI-промпт протестирован на 5 синтетических заявках
[ ] Уведомления бота работают (3.6)
[ ] Privacy-страница опубликована
[ ] /admin меню работает только для ADMIN_TG_ID
[ ] Бот переведён в режим webhook
[ ] Закрепили пост в канале с кнопкой WebApp
[ ] Сделали внутренний прогон с 3 «своими» менеджерами
```
---
## 12. Контакты и ответственные
| Роль | Кто | Контакт |
|---|---|---|
| Заказчик / куратор | Василий | vasrusgen@gmail.com, @wasrusgen |
| Канал | @wasrusgen1 | |
| Telegram-бот | @zov_tech_bot (после регистрации) | |
| MiniApp URL | https://wasrusgen.github.io/zov-tech/ (плановый) | |
---
## 13. Приложение: что отдаём разработчику
При выдаче ТЗ разработчику передаём:
1. Этот документ (`ТЗ_ЗОВот_MiniApp_v1.md`).
2. Текущий HTML-чек-лист `02_Чек-лист_клиенту.html`.
3. Доступ к Telegram-каналу @wasrusgen1 (для размещения кнопки).
4. Креды от Google-аккаунта для создания Sheet и Apps Script.
5. (После регистрации бота) — токен и admin_tg_id в зашифрованном виде.
**Ожидаемое время выполнения MVP:** 57 рабочих дней.
**Ожидаемая стоимость инфраструктуры в месяц:** $515 (только OpenAI, всё остальное бесплатно).