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

45 KiB
Raw Blame History

Техническое задание

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-шаговая форма).
    • 💰 «Мой статус» (для менеджера, простая страница).
  • 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. /newbotzov_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 Авторизация и определение роли

// Псевдокод старта 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 переменные:

: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 Безопасность

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 и:

  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 клиент получает короткое сообщение:

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

  • Простая 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, всё остальное бесплатно).