ERP-кейс
ENRU
Кейс - кастомная ERP

ERP, на которой работает маркетплейс-бизнес с оборотом $4 млн в месяц

Кастомный бэк-офис для селлера одежды на Wildberries. Компания: оборот $4 млн в месяц, каталог 600+ SKU, 12 кабинетов продавца и около 30 пользователей. Одна система закрыла аналитику, ответы покупателям, создание карточек и учёт себестоимости.

FastAPIPostgreSQL 16CeleryReact 18 LLM APIGoogle Sheets APIBitrix24
61
миграция схемы данных
~298
API-эндпоинтов, из них 100 в модуле снабжения
110
таблиц БД, прод-база 15 ГБ
~37
показателей на SKU каждую ночь (карта T1..T37)
12 / 30
кабинетов / ежедневных пользователей
~75K
строк кода: Python + TypeScript
01 Контекст и боль

Как бизнес жил до системы

Быстрорастущий селлер с 12 кабинетами на маркетплейсе. У каждого кабинета свой личный кабинет, свои API-ключи и своя таблица. Цифры, по которым управляли бизнесом, собирались руками.

12 личных кабинетов, ноль общей картины

Каждый кабинет продавца живёт отдельно. Заказы, реклама, остатки и финансы лежали в 12 местах. Целиком компанию не видел никто.

Ручные таблицы, каждый день

Менеджеры переносили цифры из 5-6 экранов личного кабинета в ежедневную таблицу. Реалистично 1-2 минуты на SKU. При тысяче с лишним активных SKU в одном кабинете полное ручное покрытие физически невозможно: хвост каталога выпадал из контроля.

Часы на вопрос "какая у нас маржа?"

Маркетплейс закрывает финотчёт неделями, с задержкой около 3 дней. Реальная маржа по SKU за день была неизвестна. Отчёты собирались часами и устаревали к моменту готовности.

Очередь из покупателей

На старте: 210 неотвеченных отзывов и 1023 вопроса покупателей по кабинетам. Новая карточка товара требовала 15-30 минут ручной работы в 3 разных системах.

02 Архитектура системы

Один контур данных, четыре рабочих поверхности

Ночные Celery-задачи забирают 6 доменов Wildberries API в PostgreSQL. Расчётный слой превращает сырые строки в маржу, алерты и себестоимость. Люди работают через React SPA, через привычные Google Sheets или просто получают алерты. Два конвейера автоматизации возвращают работу обратно на маркетплейс.

АНАЛИТИЧЕСКИЙ КОНТУР · КАЖДУЮ НОЧЬ Wildberries API 6 доменов: статистика · контент реклама · отзывы поставки · аналитика rate-limit на каждый домен Ночной синк Celery Beat, 38 задач 01:00 МСК, 11 шагов ретраи 429 через Redis watchdog зависших синков PostgreSQL 16 15 ГБ · 110 таблиц крупнейшая: 8,2 млн строк Redis 7: кэш + брокер Расчётный слой FIFO-себестоимость · маржа гейт факт / прогноз 11 типов алертов · снапшоты React SPA 54 экрана · ~30 юзеров Мост в Google Sheets 200+ значений на SKU двусторонний Алерты + Excel 29 отчётов-выгрузок КОНВЕЙЕРЫ АВТОМАТИЗАЦИИ Bitrix24 доски задач закупок Конвейер карточек regex-парсер, ~480 строк очередь апрува, без LLM Wildberries новые карточки товара до 62 в день LLM API Haiku · Sonnet · Opus Бот отзывов и вопросов 14 интентов, стайлгайд черновики, сам не отправляет Менеджер утверждает safe send 4 SQL-слоя защиты Wildberries ответы на отзывы и вопросы статусы + алерты в БД
Внешние системы Сервисы ERP Хранилище данных Контрольная точка человека
38задач в расписании Celery
11шагов ночного синка
8,2 млнстрок в крупнейшей таблице
61Alembic-миграция
7Docker-контейнеров за Nginx

Инженерные детали, на которых это живёт: rate-limit на каждый домен маркетплейса, идемпотентные upsert-ы везде, advisory-локи вокруг пересчётов, watchdog для зависших синков и аудит-лог каждой мутации в денежных модулях.

03 Флагманский модуль

РНП "Рука на Пульсе": ~37 показателей на SKU каждое утро

Сердце системы: ежедневная панель по каждому SKU. На каждый артикул и каждую дату система считает около 37 показателей (внутренняя карта T1..T37): полную воронку продаж, экономику рекламы, подтверждённую и прогнозную маржу, остатки и транзит. Всё пересчитывается ночью. Руками вводятся только себестоимость и транзит из Китая.

Воронка

Просмотры, корзина, заказы, выкупы. Конверсия на каждом шаге. Отмены и возвраты по датам. Процент выкупа считается тремя способами, каждый под свою задачу.

Реклама

Расход, ДРР, CTR, CPC, CPM, CPO по SKU за день. Данные забираются окнами по 31 дню, с retry-очередью на 429 от маркетплейса.

Маржа и экономика

Маржа факт из закрытого финотчёта. Маржа план из 8-компонентной модели, которая учитывает невыкупы. Эффективная комиссия вместо номинальной. ROI по единой формуле везде.

Остатки и оборачиваемость

Остатки по складам и размерам, товар в пути к покупателю и обратно, ручной транзит из Китая. Алерты zero-stock и low-stock вместо визуального контроля тысячи строк.

Как делаются цифры

  1. 01:00 МСК. Ночной синк проходит 11 шагов по 6 доменам API маркетплейса: заказы, продажи, остатки, склады, карточки, цены, реклама, воронка, платное хранение, финотчёт, затем средние. Soft-таймаут 180 минут, watchdog каждые 5.
  2. Пересчёт. Средняя логистика и эффективная комиссия пересобираются по 3 последним закрытым неделям финотчёта. Процент выкупа считается по когорте: каждый заказ в окне 30 дней прослеживается до финального исхода.
  3. 00:05 заморозка плана. Плановая маржа за вчера снапшотится: прошлые дни не "плывут" при обновлении средних. Классическая болезнь ручных таблиц, вылеченная архитектурно.
  4. Гейт факт / прогноз. Маркетплейс подтверждает финансы неделями с лагом 3 дня. Для каждой даты система решает отдельно: этот день подтверждён финотчётом или это прогноз из воронки. UI помечает, каким цифрам уже можно верить.
  5. Дневная история. По каждому SKU хранится история 40 метрик x 14 дней, мост в таблицу отдаёт её ответом 20-30 МБ с gzip. Ежечасно пересчитываются 11 типов алертов с авторезолвом.

Примеры метрик и их формулы

МетрикаНа какой вопрос отвечаетКак считается
% выкупа (когорта) Сколько заказов доходит до оплаченной продажи? Каждый заказ в окне 30 дней (лаг 7 дней) прослеживается до исхода. чистые / (чистые + возвраты + отмены), минимум 30 завершённых заказов.
ДРР Окупается ли реклама? расход на рекламу / сумма заказов x 100, считается так же, как в кабинете маркетплейса.
Эффективная комиссия Сколько маркетплейс забирает на самом деле? (розница - к перечислению - эквайринг) / розничная цена x 100 по строкам продаж финотчёта. Номинальная ставка категории показывается только справочно.
Маржа факт Реальная прибыль за день нетто-выручка - комиссия - логистика - хранение - штрафы - эквайринг - себестоимость - реклама. Считается только для дней, подтверждённых финотчётом, иначе прочерк.
Маржа план Ожидаемая прибыль до закрытия отчёта 8 компонент. ожидаемые продажи = заказы x % выкупа. Невыкупленный заказ всё равно оплачивает два плеча логистики. Ежедневно замораживается снапшотом.
ROI Отдача на вложенные деньги маржа / (себестоимость + реклама) x 100. Одна формула в списке, карточке и таблице.
Оценка эффекта

Ручная версия этой таблицы существовать не может

Собрать одну дневную строку по SKU руками: 1-2 минуты по 5-6 экранам личного кабинета. Только в одном кабинете больше 1100 активных SKU. Это 19-38 человеко-часов в день на один кабинет, поэтому селлеры обычно ведут руками только топ-100 SKU и теряют хвост. Консервативная оценка заменённой рутины: 250-350 человеко-часов в месяц, примерно 2-4 фултайм-аналитика. Система делает это каждую ночь, и хвост каталога остаётся под контролем.

РНП: список SKU с алертами, заказами, маржой, ROI и ДРР
Список SKU: светофор алертов, заказы, маржа, ROI и ДРР в строке. Проблемные товары всплывают наверх.
Развёрнутая карточка SKU: 33 строки метрик в 8 группах, даты в столбцах
Развёрнутая карточка SKU: даты в столбцах, 33 строки метрик в 8 сворачиваемых группах, факт чёрным, план синим.
~37показателей на SKU (карта T1..T37)
1100+активных SKU в одном кабинете
40 x 14метрик x дней в daily-history
11типов алертов с авторезолвом
18REST-эндпоинтов модуля
04 AI-модуль

AI-бот ответов на отзывы и вопросы покупателей

На маркетплейсе селлера кормят скорость и тон ответов. Бот: конвейер из трёх LLM-моделей, который готовит каждый ответ в голосе бренда. Кнопку "отправить" всегда нажимает человек.

Входящие отзывы + вопросы синк 3 раза в день 12 кабинетов Haiku классификатор интентов 14 интентов кэш ответов 30 дней Sonnet пишет один ответ tool-loop: карточка товара оценка уверенности Менеджер утвердить или исправить low confidence никогда не уходит сам WB reply API 1 зап/сек чанки 40-70 Стайлгайд бренда 24 правила · 12 шаблонов из 161 gold-эталона Opus тренер стиля ночная дистилляция отклонённый черновик + правка менеджера становятся gold-эталоном
Внешние системы LLM-модели в конвейере Обученный актив Контрольная точка человека

1. Haiku классифицирует

Самая дешёвая модель раскладывает каждое обращение на 14 интентов: возврат брака, подбор размера, "когда появится", уход за вещью, доставка, пересорт и другие. Одинаковые тексты попадают в 30-дневный кэш и не стоят ничего. Отзывы без текста вообще не доходят до LLM: срабатывает шаблон.

2. Sonnet пишет

Один ответ, а не десять вариантов. Через tool-loop модель подтягивает карточку товара, если вопрос про ткань или уход. Жёсткие правила бизнеса выше всего: никаких обещаний скидок, никаких штампов, всегда подпись бренда. У каждого ответа есть оценка уверенности.

3. Opus обучает голос

Каждая правка менеджера сохраняется как gold-эталон. Из 161 эталона Opus дистиллировал стайлгайд бренда: 24 пронумерованных правила плюс 12 шаблонов по интентам. Запреты бизнеса стоят выше выученных паттернов, это явное проектное решение.

Контрольные точки человека, by design

  1. Бот никогда не отправляет сам. Каждый черновик ждёт в UI со своим интентом, уверенностью и обоснованием. Менеджер утверждает или отклоняет.
  2. Отклонение обучает бота. Модалка исправления сохраняет тройку: текст покупателя, неудачный черновик, исправленный ответ. Это учебный материал для ночной дистилляции стиля.
  3. Низкая уверенность не уходит никогда. Черновики ниже порога помечаются, поднимаются наверх списка и исключаются из любой массовой отправки. Опции "всё равно отправить" не существует.
  4. У массовой отправки 4 SQL-слоя защиты плюс порог по рейтингу, согласованный с бизнесом. Сначала всегда dry-run.
  5. Честный отказ. Если AI API недоступен, UI показывает красную плашку и пустое поле ручного ответа. Никаких тихих шаблонов покупателям.
  6. Аккуратная отправка на маркетплейс. Случайные чанки по 40-70 ответов, паузы 7-29 секунд между ответами и около 20 минут между чанками, 1 запрос в секунду.

Что разгребли

Очередь на старте: 210 неотвеченных отзывов и 1023 вопроса по кабинетам. Одна офлайн-сессия генерации подготовила и залила 60 ответов на отзывы плюс 661 ответ на вопросы для самого загруженного кабинета. По оценке клиента, с ответов на отзывы снята работа примерно 6 сотрудников.

Сколько это стоит

Промпт-инжиниринг с измеримым результатом: входной промпт ужат с 6-8K токенов (80 сырых примеров) до 1,5-2K токенов (дистиллированный стайлгайд плюс 7 эталонов по интенту). Плюс кэши на каждом шаге и short-circuit для пустых отзывов.

Бот отзывов: очередь с AI-черновиками, интентом, уверенностью и кнопками утверждения
Рабочее место: слева очередь, справа полный отзыв с AI-черновиком, интентом, уверенностью и кнопками "подходит / исправить".
05 Модуль автоматизации

Конвейер карточек: из задачи Bitrix24 в живую карточку на маркетплейсе

Отдел закупок планирует новинки задачами на канбан-досках Bitrix24. Конвейер превращает завершённую задачу закупки в полноценную карточку товара: распарсенные атрибуты, баркоды, категория, бренд, менеджер, фото. То, что занимало 15-30 минут ручной работы в 3 системах, стало контролируемым конвейером.

Bitrix24 канбан-доски триггер-стадия: товар закуплен Скан + парсинг regex, ~480 строк, без LLM цена, размерная сетка, цвет, состав, габариты упаковки Обогащение категория + ТН ВЭД из листа "Номенклатура", роутинг бренда и менеджера WB Content API баркоды на каждый размер заливка карточки + фото кроп 900 x 1200 3 верификации карточка в WB, стадия задачи, строка таблицы подтверждена Обратная запись строка в Sheets, задача переименована + комментарий 26+ алерт-кодов skip-on-alert без тихих дефолтов нехватка данных даёт типизированный алерт, а не битую карточку
Внешние системы Шаги конвейера Проверки консистентности

Что течёт по конвейеру

Триггер: канбан-стадия "товар закуплен". Конвейер забирает заголовок, описание, комментарии и вложения задачи. Regex-парсер на ~480 строк извлекает цену, себестоимость, состав ткани, цвет, полную размерную сетку с количествами и габариты упаковки. Категория и код ТН ВЭД берутся из Google-листа "Номенклатура", который ведут менеджеры. Бренд и ответственный назначаются round-robin-правилами. Дальше: баркоды на каждый размер, заливка карточки, фото с кропом 900 x 1200 и обратная запись в таблицу и исходную задачу.

Без LLM в рантайме. Осознанно.

Парсер: детерминированный regex, а не модель. Одинаковый вход даёт одинаковый выход, всё покрывается регресс-тестами по реальным инцидентам, ноль стоимости инференса и никаких выдуманных цен. Модуль построен по детальным письменным ТЗ: контракт данных, формулы, крайние случаи и критерии приёмки. Правило модуля: жёсткие алерты вместо тихих дефолтов.

~62карточки в пиковый день
142задачи разобраны одним прогоном
141блокер данных классифицирован автоматически
26+типизированных алерт-кодов
44REST-эндпоинта, 15 своих таблиц

Конвейер заодно стал аудитом качества данных

На первом полном прогоне по 142 задачам конвейер создал ноль карточек. Вместо этого он выдал точную классификацию 141 блокера данных: 42 задачи без габаритов, 21 без цены, 38 без строк категории. Менеджеры получили точные списки доработок. Через несколько дней тот же конвейер выдавал до 62 карточек в день. Идемпотентность на 4 уровнях: повторный прогон никогда не создаёт дублей. Инвариант жёсткий: одна задача равна полному циклу по всем 3 системам, с 3 независимыми проверками.

Очередь апрува конвейера карточек с распарсенными черновиками
Очередь апрува: распарсенные черновики с извлечёнными атрибутами, превью фото и действиями "применить / править / отклонить".
06 Учётный модуль

Снабжение и честная себестоимость: FIFO-движок на всю цепочку

Заказы фабрикам, производство, международная и внутренняя логистика, приёмки на фулфилмент, долги поставщикам и настоящая FIFO-себестоимость единицы. Модуль прошёл путь с нуля до прода примерно за 3 недели и стал финансовым каркасом системы.

FIFO landed cost

Каждая приёмка создаёт неизменяемую партию себестоимости: товар в юанях, международная логистика в долларах, плечи по РФ в рублях, приёмка фулфилмента. Валюты пересчитываются по курсу ЦБ на дату оплаты. Каждая проданная единица списывает самую старую партию, возвраты восстанавливаются в новейший слой, всё идемпотентно на уровне строки продажи.

Долги и cash-need

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

Точки контроля

13 детерминированных SQL-правил алертов следят за цепочкой: заказ завис в планировании, производство не началось вовремя, сумма оплат не сходится с суммой заказа. Уровни серьёзности, авторезолв и аудит-лог каждой мутации. 29 Excel-отчётов для финансовой команды.

3256FIFO-партий себестоимости
608 тыс.единиц проведено через партии
десятки млн ₽COGS посчитано FIFO за период
100эндпоинтов /api/supply
24свои таблицы, 14 экранов UI
~3 неделис нуля до прода
Дашборд снабжения: KPI-плитки, воронка заказов, алерты и плановые оплаты
Дашборд снабжения: KPI по долгам и cash-need, воронка заказов из 7 этапов, топ алертов и ближайшие оплаты.
Карточка заказа фабрике: позиции, оплаты и таймлайн этапов
Карточка заказа фабрике: позиции, оплаты, таймлайн этапов и остатки на фулфилменте в одном месте.
Экран FIFO-себестоимости: расчётная себестоимость рядом с прежними ручными цифрами
FIFO-костинг: расчётный landed cost по партии и единице рядом с прежними ручными цифрами.
07 Приём внедрения

Мост в Google Sheets: команде не пришлось переезжать

Менеджеры любили свою таблицу и не хотели новый инструмент. Таблица осталась. Теперь её заполняет бэкенд.

Каждое утро мост заливает в привычный лист 200+ значений на SKU: цены, комиссии, конверсии воронки, остатки, проценты выкупа, вчерашнюю рекламу. Менеджеры вводят руками только план действий и заметки, и эти правки возвращаются в базу. Дневная история 40 метрик x 14 дней уходит ответом 20-30 МБ с gzip и рендерится в знакомые вкладки архива.

Безопасность строгая: сервис-токены хранятся хэшем, плюс whitelist таблиц. Лист привязан ровно к одному кабинету и физически не может прочитать данные другого.

Почему это важно

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

08 Как это построено

Сначала бизнес-анализ, потом инженерная реализация

Один аналитик-разработчик, пошаговые проверяемые изменения. Это факт методики, а не заголовок: заголовок в том, что на результате работает живой бизнес.

  1. Сначала ТЗ. Каждый модуль начинался с письменной спецификации: контракт данных, формулы, крайние случаи, критерии приёмки. Несколько ТЗ доведены до уровня пошагового сценария реализации.
  2. Документация как часть системы. Runbook уровня репозитория задаёт health-чеки, операционные правила и жёсткие запреты, чтобы командой можно было безопасно эксплуатировать систему.
  3. Закалка через инциденты. Фиксы закрепляются датированными комментариями и регресс-тестами. Идемпотентность, kill-switch и аудит-логи здесь практика по умолчанию, а не доработка потом.
  4. Честные цифры. Каждая цифра этого кейса сверена с репозиторием и продовой документацией. Оценки помечены как оценки.

Стек

PythonFastAPISQLAlchemy 2 asyncAlembic Celery + BeatPostgreSQL 16Redis 7 Docker ComposeNginx React 18TypeScriptViteTailwind Radix UIZustandTanStack Query

Интеграции

Wildberries API, 6 доменовGoogle Sheets API Bitrix24 RESTLLM APIКурсы ЦБ РФ

Темп поставки

110 таблиц базы61 миграция~298 эндпоинтов
09 Результат

Было и стало

ОбластьБылоСтало
Ежедневная аналитика Ручной перенос из 5-6 экранов личного кабинета. Под контролем только топ SKU. По оценке, 250-350 человеко-часов рутины в месяц. Ночной пересчёт ~37 показателей по 1100+ SKU на кабинет. Под контролем весь каталог, проблемы поднимают алерты.
Видимость маржи Какая-то маржа, раз в неделю, после закрытия финотчёта. Маржа факт и план по SKU за каждый день, с явной пометкой, какие дни подтверждены.
Отзывы и вопросы Очередь из 210 отзывов и 1023 вопросов. Каждый ответ менеджеры писали руками. AI-черновики в голосе бренда, утверждает человек. По оценке клиента, снята работа ~6 сотрудников.
Новые карточки товара 15-30 минут ручной работы на карточку в 3 системах. Контролируемый конвейер, до 62 карточек в день на пике, с типизированными алертами на плохих данных.
Юнит-экономика Примерная себестоимость в таблицах, без учёта полной цены доставки до склада. FIFO landed cost по 3256 партиям и 608 тыс. единиц, долги и cash-need на одном дашборде.
Инструменты 12 отдельных личных кабинетов плюс несвязанные таблицы. Одна ERP: ~298 эндпоинтов, 110 таблиц, веб-приложение и привычные Sheets на одной базе данных.

Кирилл Седов

Бизнес-аналитик и разработчик систем. Начинаю с бизнес-процесса и контракта данных, потом автоматизирую. Эта система проанализирована, описана и выведена в прод одним человеком для живого бизнеса с оборотом $4 млн в месяц.

Связаться в LinkedIn