45 KiB
Техническое задание
Telegram-бот + MiniApp «AI-подбор техники для кухни ЗОВ»
Версия: 1.0 Дата: 2026-05-08 Заказчик: Василий (vasrusgen@gmail.com), куратор партнёрской сети ЗОВ Канал: @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-шаговая форма).
- 💰 «Мой статус» (для менеджера, простая страница).
- 🔧 «Подбор техники» (для менеджера, на базе существующего HTML-чек-листа
- 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
/newbot→zov_tech_bot(или альтернативное имя, если занято)./setdomain→ домен MiniApp (wasrusgen.github.io)./newapp→ создать MiniApp:- Title: «Подбор техники ЗОВ»
- Short name:
podbor - Web App URL:
https://wasrusgen.github.io/zov-tech/
/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 Авторизация и определение роли
// Псевдокод старта 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:
- Проверяет HMAC
initDataпоBOT_TOKEN(стандартная процедура Telegram). - Ищет
tg_idв листе «Пользователи». - Если нет — создаёт запись (роль уже сохранена ботом, должна быть в БД).
- Возвращает профиль + статус.
4.3 Кабинет менеджера
Главный экран #/m:
┌─────────────────────────────────────┐
│ Привет, {ФИО} │
│ Салон: {salon} │
│ Статус: 🟢 active до 12.08.2026 │
│ │
│ ─────────────────────────────── │
│ │
│ 🔧 Подбор техники для клиента → │
│ 📐 Замеры → │
│ 📋 Заявки клиентов → │
│ 💼 Сделки (скоро) · │
│ 📚 База знаний (скоро) · │
│ 💰 Мой статус → │
│ 🆘 Связь с куратором → │
└─────────────────────────────────────┘
Пункты «Сделки», «База знаний» в MVP — disabled-кнопки с текстом «Скоро».
Страница #/m/podbor:
Это существующий файл 02_Чек-лист_клиенту.html с минимальными доработками:
- Удалить захардкоженный блок менеджера (Любовь Алпеева) — подставлять из
me.user. - Добавить поле «Размеры ниш» (см. п. 4.5 — пробелы из анализа).
- Добавить поле «Бюджет по категориям».
- Добавить блок «Сценарий использования» (семья, готовка).
- Кнопку «Отправить» завести на
POST /api/podborвместоmailto:. - После отправки —
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 нужно добавить:
- Блок «Параметры кухни» в онбординг (или подгружать из последнего замера).
- Бюджет по категориям — простая таблица в финальном экране.
- Блок «Семья и готовка» — 4–5 быстрых вопросов с радиокнопками:
- Состав семьи: 1 взрослый / пара / семья с детьми / 2+ поколения
- Частота готовки: ежедневно / 3–4 раза в неделю / реже
- Любимые техники: выпечка / на пару / гриль / wok / низкотемпературное (multi-select)
- Приём гостей: часто / иногда / редко
- Чекбокс «уже есть, не меняю» в каждой категории — клиент исключает позиции.
- Webhook вместо
mailto:— POST на backend. - Обязательные поля: имя, контакт, общий бюджет, адрес.
4.6 Дизайн-токены (брендинг ЗОВ)
Использовать существующие в HTML переменные:
: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 | ФИО полное |
| 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 | |
| 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 Деплой
- Привязать скрипт к Google Sheet «ЗОВ — База».
- Deploy → New deployment → Type «Web app».
- Execute as: «Me».
- Who has access: «Anyone» (для приёма запросов с MiniApp).
- Получить 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 Бизнес-логика статусов менеджера
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:
{
"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
{
"model": "gpt-4o-mini",
"temperature": 0.3,
"max_tokens": 4000,
"response_format": { "type": "json_object" }
}
7.4 Постобработка ответа
Backend получает JSON от OpenAI и:
- Валидирует схему. При расхождении — алёрт куратору, ответ всё равно пытается доставить.
- Сохраняет в
Leads.ai_response(raw JSON). - Рендерит в человекочитаемый вид (текст + кнопки).
- Отправляет менеджеру через бота:
✅ Подбор готов
Клиент: Пётр Сидоров
Бюджет: 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 подписаны
initDataTelegram. - 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клиент получает короткое сообщение:
Заполняя форму подбора, вы соглашаетесь с обработкой данных в рамках консультации по подбору кухни. Подробнее — политика.
- Простая 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. Приложение: что отдаём разработчику
При выдаче ТЗ разработчику передаём:
- Этот документ (
ТЗ_ЗОВ_Бот_MiniApp_v1.md). - Текущий HTML-чек-лист
02_Чек-лист_клиенту.html. - Доступ к Telegram-каналу @wasrusgen1 (для размещения кнопки).
- Креды от Google-аккаунта для создания Sheet и Apps Script.
- (После регистрации бота) — токен и admin_tg_id в зашифрованном виде.
Ожидаемое время выполнения MVP: 5–7 рабочих дней. Ожидаемая стоимость инфраструктуры в месяц: $5–15 (только OpenAI, всё остальное бесплатно).