Система анализа продаж на маркетплейсах — цель
Замер: 2026-08-14 · чем проверено: девять страниц функционального уровня, замер живой базы, замер карты блоков
Читать первым и при любом споре «зачем мы это делаем». Верхний уровень иерархии: какая цель достигается. Как это устроено — уровнем ниже.
Прежняя редакция этого документа описывала целевое устройство и сама об этом предупреждала во второй строке. Замысел, ещё не ставший состоянием, вынесен в CONCEPT-K-CHEMU-IDYOM.md и помечен как замысел.
Цель
Мы торгуем на девяти площадках. Каждая ведёт свой учёт, называет вещи по-своему и показывает нам только свою часть картины — ту, которая ей видна.
Цель системы одна: принимать торговые решения по своим числам, а не по чужим сводкам. Всё остальное — следствие.
Из неё вытекают четыре вопроса, ради которых система существует:
- что продаётся, а что лежит;
- сколько мы на этом заработали;
- что везти дальше и куда;
- где мы теряем деньги.
Чем отвечаем на каждый и достигнуто ли это
| Вопрос | Чем достигается | Сегодня |
|---|---|---|
| Что продаётся, а что лежит | сбор → разбор и хранение → показ | ✅ работает |
| Сколько заработали | те же плюс расчёты | ⚠️ считается, но денежная база рейтинга ещё старая — см. ниже |
| Что везти дальше и куда | расчёты и собственные данные | ⚠️ отгрузка работает, 1С подключена и данные приходят целиком; неполной считается их аттестация — см. ниже |
| Где теряем деньги | расчёты, реестр описаний | ⚠️ частично: не все площадки отдают возвраты и логистику |
Три служебные функции не отвечают на вопросы напрямую, но без них ответы не стоят ничего: расписание — чтобы числа приходили сами; сторожа и расписки — чтобы числу можно было верить; права — чтобы данные видел тот, кому положено.
Чего система придерживается всегда
Это не описание устройства, а обязательства. Они не меняются от того, как переписан код.
Собранное не переписывается. Ответ площадки сохраняется один раз и остаётся неизменным. Переспросить площадку за прошлый месяц нельзя — значит сырьё хранится навсегда, и любой пересчёт делается по нему.
Разбор повторяем. Один и тот же ответ, обработанный дважды, даёт одинаковый результат.
Видно, откуда взялась любая цифра. По каждой строке прослеживается, из какого ответа площадки она получена и когда.
Описание не расходится с данными. Столбца, который описан, но которого нет, существовать не может, и это проверяется автоматически.
Данные площадок не складываются между собой. Выручка Ozon и выручка Wildberries означают разное; их сумма выглядит как итог, но смысла не имеет, и ошибка в ней невидима. Итог по всем площадкам система сама не считает.
Все числа хранятся положительными. Что вычесть, а что прибавить, решает формула, а не знак в данных.
У продажи две денежные величины — сколько заплатил покупатель и сколько площадка перечислила нам. Хранятся отдельно; если площадка одну не отдаёт, поле остаётся пустым. Подставить туда вторую значит соврать в отчёте.
Новый источник добавляется процедурой, а не переделкой системы.
Что решает человек, а не программа
Какой рейтинг смотреть. Внутренний по площадке отвечает «как эта модель идёт здесь», общий — «чего она стоит вообще». Возим по рейтингу той площадки, куда везём: у каждой свои конкуренты, и модель может идти плохо не потому, что плоха. Если там она не продавалась, внутренний рейтинг строить не на чем, и бренд-менеджер переключается на общий. Выбор — за человеком.
Общий рейтинг — единственное место, где данные площадок всё же сводятся. Это допустимо потому, что он расставляет товары по порядку, а не измеряет деньги, и считается по штукам: проданным за вычетом возвращённых.
Итог по всем площадкам. Если он нужен, человек строит его осознанно, понимая, что складывает.
Где цель сегодня не достигнута
Названо по замерам 14.08.2026, а не по впечатлению. У каждого пункта стоит команда, которой его проверяют — не верить и не сомневаться, а прогнать.
Причина такая: устаревшее утверждение опровергается замером, а не пометкой. Сегодня из этой самой страницы пришлось убирать «товарный мастер 1С не подключён» — оно было написано по памяти, а не по проверке, и прожило в документе, пока владелец не возразил.
-
Движения склада из 1С приходят целиком, но не аттестуются. Формулировка важна: неполны не данные, а расписка о них. Замер трёх прогонов —
225 получено / 225 разобрано,269 / 269,323 / 323: не потеряно ни строки. При этом каждый прогон встаёт вpartialс «receipt completeness failed: every output must be traceable», и дальше по цепочке это читается как «данные неполные», хотя они полные.Причина в имени поля, а не в данных: проверка ищет поле с именем
payload_id, а в описании оно названоload_batch_id— значение в нём то самое. Починка идёт.Второе, отдельное: окно запроса — три дня, поэтому за раз доезжает немного. Служба 1С отдаёт любой период; адрес и формат — в блоке «Сбор».
Сама 1С подключена и собирается: каталог поставщика — начисто каждый день, 152 335 строк.
Проверить:
ssh s3-int 'docker exec gwptd-v3-mysql sh -lc "MYSQL_PWD=\$MYSQL_ROOT_PASSWORD mysql -uroot --batch -e \
\"SELECT endpoint_code,status,started_at FROM gwptd_intake.collection_run \
WHERE endpoint_code LIKE \\\"1c.%\\\" ORDER BY started_at DESC LIMIT 4\""' -
Часть площадок собирается не полностью. На 14.08 в 17:05 — 72 успешных, 12 частичных, 2 подвисших в
running; через двадцать минут уже 73 / 12 / 1. Числа здесь живые и меняются между прогонами — брать их из команды ниже, а не отсюда. Написанное число стареет по устройству; постоянно в этом пункте одно: частичные есть всегда, аrunningдольше суток означает подвисший прогон. Девять амазоновских таблиц пусты.Проверить:
ssh s3-int 'docker exec gwptd-v3-mysql sh -lc "MYSQL_PWD=\$MYSQL_ROOT_PASSWORD mysql -uroot --batch -e \
\"SELECT status,COUNT(*) FROM (SELECT endpoint_code,status,ROW_NUMBER() OVER \
(PARTITION BY endpoint_code ORDER BY started_at DESC) rn FROM gwptd_intake.collection_run) t \
WHERE rn=1 GROUP BY status\""' -
Планировщик построен и не подключён. 10 940 строк в 28 модулях, шесть таблиц учёта слотов пусты. Проверено жёстко:
SchedulerControlPlaneне создаётся нигде вне тестов, служб для него нет, в расписании его нет. Расписание держится на cron.Проверить — пустой вывод означает «не подключён»:
grep -rl "SchedulerControlPlane(" --include="*.py" marketplace-collector-v3/ | grep -v test
Ни один из этих пунктов не отменяет цели. Все они означают одно: по этим направлениям мы пока отвечаем хуже, чем собирались, и знаем, насколько.
Ниже по иерархии
- Для чего нужна каждая часть — девять страниц функционального уровня;
- как всё устроено — восемь страниц описательного;
- вход в документацию целиком — docs/README.md, раздел «Система сверху вниз»;
- что решено владельцем — DECISIONS.md;
- чего нельзя терять при правках — DO-NOT-REGRESS.md.