← На главнуюEnglish

Кейс · Клиентский проект

STOKCEN — приём заявок и работа с покупателем

Покупатели магазина бытовой техники просят помочь с выбором духового шкафа, посудомоечной машины или телевизора. Я построил процесс: запрос превращается в структурированную заявку для менеджера магазина, покупатель получает предложение, а вся переписка остаётся привязанной к заявке.

Моя роль
Под ключ для клиента: процесс, архитектура, разработка, тесты и развёртывание
Статус
Работает у клиента; первая версия — февраль 2026, текущая — сентябрь 2026
Формат
Telegram-бот, мини-приложение и веб-дашборд
Открыть бота

Задача

Клиент продаёт бытовую технику в нескольких магазинах. Запрос на подбор полезен, только если он полный: размеры, тип установки и подключения, цвет, примерный бюджет. Дальше он должен быстро попасть к менеджеру нужного магазина, вернуться к покупателю конкретным предложением и не потеряться в переписке. Это запрос на подбор, а не покупка: оплаты и резерва нет.

Главная проблема — не чат, а структура и ответственность. Свободное сообщение нельзя сравнить, направить и учесть, а заявку без одного ответственного либо обрабатывают дважды, либо не обрабатывает никто.

Объём первой версии

Вошло
Пошаговый опрос для каждой категории техники, который задаётся конфигурацией. Одна открытая заявка на покупателя. Маршрутизация по магазину и одна кнопка «Взять». Предложения с моделями, ценами и альтернативами. Статусы для покупателя. Роли и админ-панель в Telegram. Дашборд владельца только для чтения.
Не вошло
Оплата и резерв, интеграция со складом и CRM, AI-функции. Ценность — в надёжном процессе, а не в автоматизации ради автоматизации.

Что сделано

  1. ОпросПокупатель выбирает магазин и категорию и отвечает на вопросы по одному: размеры, тип установки и подключения, цвет, бюджет. Любой вопрос можно пропустить.
  2. ЗаявкаПеред отправкой покупатель видит черновик и может поправить или удалить позиции. Новая заявка заменяет прежнюю открытую.
  3. МаршрутизацияЗаявку с кнопкой «Взять» получают все менеджеры выбранного магазина; владельцем становится первый нажавший. Если менеджеров в магазине нет, её получают супервайзеры, затем администраторы.
  4. ПредложениеМенеджер добавляет модель и цену по каждой позиции, может предложить альтернативы или отметить отсутствие. Отправленное предложение не редактируется: исправление отправляется новой версией.
  5. ДиалогВ мини-приложении покупатель выбирает варианты и подтверждает. Его сообщения боту привязываются к заявке, а менеджер отвечает из мини-приложения.

Владелец бизнеса управляет людьми, ролями, магазинами и рассылками в админ-панели Telegram, а на веб-дашборде видит заявки по статусам, сравнение магазинов и среднее время до взятия заявки.

Первая версия процесса: покупатель → пошаговый диалог → маршрутизация → уведомление менеджеру → взятие → модель и цена → предложение → статусы; владелец видит дашборд и админ-панель.

Моя роль

Сделано мной
Весь продукт для клиента: процесс и модель данных, архитектура, бэкенд, бот и мини-приложение, маршрутизация, уведомления, диалог покупателя и менеджера, дашборд, тесты и развёртывание.
Со стороны клиента
Сам бизнес: магазины, сотрудники, ассортимент и параметры, важные для каждой категории. Разрешение показать проект в портфолио.

Ключевые решения

Маршрутизация по магазину и атомарное «Взять»
Заявка уходит всем менеджерам магазина, владельцем становится первый взявший. Взятие — одно условное обновление в базе, поэтому одну заявку не могут взять двое.
Версии предложений
Отправленное предложение не меняется, исправление — новая версия: покупатель и менеджер всегда обсуждают одно и то же, а история остаётся понятной.
SQLite и outbox вместо лишней инфраструктуры
Чтобы состояние переживало перезапуск, а уведомления не терялись, не понадобились ни Redis, ни отдельный сервер базы данных. Хватило SQLite и очереди исходящих уведомлений (outbox) внутри процесса: в базу пишет только бот, дашборд её только читает.
Простые отзываемые сессии мини-приложения
Подписанные данные запуска Telegram проверяются один раз, дальше работает непрозрачная сессионная cookie, на сервере хранится только её хеш; смена роли или магазина её отзывает. От JWT и refresh-токенов я отказался.

Проверка

  • Около 300 тестов бэкенда и более 100 тестов мини-приложения.
  • Каждый релиз собирается изолированно, проходит независимое ревью, проверяется в браузере на ширинах 320–430 px в светлой и тёмной теме на синтетических данных и ещё раз после развёртывания.
  • Внутреннее ревью ранней версии нашло несколько проблем с правами доступа и одновременной обработкой заявок; их исправили до следующего этапа — мини-приложения.
  • План отката готовится до каждого релиза; старые резервные копии базы для обычного отката не используются.

Статус

Работает у клиента. Разработка — с февраля 2026 года; веб-дашборд появился в апреле, роли и магазины — в августе, мини-приложение — в конце августа, диалог покупателя и менеджера — в сентябре 2026. Бот открыт для всех, мини-приложением и дашбордом пользуются покупатели и сотрудники клиента. Публичных бизнес-показателей у проекта нет.

Технологии

Бот и API
Python, aiogram 3, aiohttp; один процесс обслуживает бота и API мини-приложения
Мини-приложение
React 18, TypeScript, Vite; тесты на Vitest и Testing Library
Данные
SQLite с аддитивными миграциями; надёжный outbox уведомлений
Дашборд
Streamlit, только чтение, за аутентификацией
Авторизация
Данные запуска Telegram с проверкой HMAC, отзываемые сессионные cookie
Инфраструктура
Docker Compose; статика мини-приложения за nginx

Обсудим похожую задачу?

Напишите на почту или в Telegram — расскажу подробнее о любом решении из этого кейса.