# Техническое задание # 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 ` | все | спец-сценарий: переход по ссылке-приглашению от менеджера | | `/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. **Блок «Семья и готовка»** — 4–5 быстрых вопросов с радиокнопками: - Состав семьи: 1 взрослый / пара / семья с детьми / 2+ поколения - Частота готовки: ежедневно / 3–4 раза в неделю / реже - Любимые техники: выпечка / на пару / гриль / 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. - Документация процедуры: ### 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:** 5–7 рабочих дней. **Ожидаемая стоимость инфраструктуры в месяц:** $5–15 (только OpenAI, всё остальное бесплатно).