Плейбук: недельный фин-отчёт WB
Для нового компактного отчёта Прибыль WB за 7 дней / 1 день и режимов сравнения
использовать отдельный плейбук:
data/notes/wb/profit-week-day-playbook.md
Он описывает формат:
Артикул | Продажи net | Выручка | Себес | Лог/шт | Реклама | ДРР | Прибыль | Приб/шт | ROI
и правила сравнения:
- 7 дней: последняя закрытая неделя vs предыдущая закрытая неделя;
- 1 день: выбранный день vs среднее за предыдущие 7 дней.
Срабатывает, когда пользователь пишет «дай фин-отчёт за неделю», «финка за прошлую неделю», «сколько заработали на WB», «отчёт по Tote / Siluetta WB» и т.п. А для сравнения — «сравни периоды / сравни отчёты / сравни данные за период / неделя к неделе» (см. раздел «Сравнение периодов»).
Стек: данные в корневом Big-System-MP\mp.db, интерпретатор .venv\Scripts\python.exe,
готовый скрипт scripts/wb_fin_week.py. Методика расчёта прибыли — data/notes/wb/profit-methodology.md
(этот плейбук — операционная обёртка над ней).
Запуск
.venv\Scripts\python.exe scripts\wb_fin_week.py # Tote WB (5), последняя закрытая неделя
.venv\Scripts\python.exe scripts\wb_fin_week.py --shop 3 # Siluetta WB
.venv\Scripts\python.exe scripts\wb_fin_week.py --since 2026-06-08 --to 2026-06-14 # вручную
Магазины: 3 = Siluetta WB, 5 = Tote WB (см. таблицу shops). Вывод — в консоль (свод + разбивка по артикулам).
«Закрытая неделя» — что это и почему важно
fin_report_detail наполняется понедельными отчётами, которые WB закрыл (прислал).
Скрипт по умолчанию берёт последнюю полную неделю Пн–Вс, заканчивающуюся не позже
MAX(rr_date) в финрепе. Если просить незакрытую (текущую) неделю — финрепа по ней ещё
нет, прибыль будет пустой/неполной (см. методичку, раздел «Привязка периода»).
⚠ Перед отчётом убедиться, что финреп свежий. Доингест (квота 2 запроса/24ч!):
ssh wbbot 'cd /root/mp-system && .venv/bin/python -c "from app.wb.ingest import ingest_finreport; ingest_finreport(shop_id=5)"'
Реклама — отдельный ингест (ingest_ad_metrics_history), тоже нужна за то же окно.
Как читать свод (двухуровневый)
Выручка (покупатель) retail_amount нетто — что заплатили покупатели
К перечислению за товар for_pay нетто — начислено WB за товар (retail − комиссия − СПП)
− Логистика delivery_rub
− Хранение paid_storage
− Прочие удержания WB приёмка + штрафы + эквайринг + удержания − допвыплаты
− Реклама (удержано WB) «WB Продвижение» из финрепа (deduction)
= ИТОГО К ВЫПЛАТЕ ← фактический перевод WB на счёт продавца
− Себестоимость costs × net_qty (собственные затраты, НЕ перевод WB)
− Реклама (вне удержаний) ad_metrics_daily − удержанная (баланс / разница по срокам)
= ПРИБЫЛЬ
- К перечислению за товар ≠ Итого к выплате: первое — начисление за товар, второе — что реально придёт на счёт после всех удержаний WB.
- Себестоимость и реклама вне удержаний стоят НИЖЕ «Итого к выплате» — это не перевод WB, а собственные затраты, поэтому они влияют на прибыль, но не на сумму перевода.
⚠ Реклама не задваивается (ключевое из методички)
Реклама приходит дважды: ad_metrics_daily.sum_cost (полный расход) и fin_report_detail.deduction
с bonus_type_name LIKE '%Продвижение%' (удержание в финрепе). Это одна и та же реклама.
Скрипт: полный расход берёт из ad_metrics_daily, в своде делит на «удержано WB» (= promo из
финрепа) + «вне удержаний» (остаток). В прибыли реклама учтена один раз. Не суммировать обе.
Метрики
| Метрика | Формула |
|---|---|
| Маржа | Прибыль / Выручка |
| ДРР (доля реклам. расходов) | Реклама(полная) / Выручка — ключевая метрика здоровья |
| ROI к себесу | Прибыль / Себестоимость |
| Выкуп % | Выкупы / Заказы |
| Ср.чек | Выручка / реализованных шт |
| Лог/шт | Логистика / реализованных шт |
| Прибыль/шт | Прибыль / реализованных шт |
Разбивка по артикулам
Сортировка по прибыли (убыточные сверху — сразу видно, кто тянет вниз).
Порядок столбцов (фиксированный):
| # | Столбец | Что |
|---|---|---|
| 1 | SKU | артикул |
| 2 | Продажи | реализовано нетто, шт (Продажа − Возврат) |
| 3 | Выручка | retail_amount нетто (что заплатил покупатель) |
| 4 | К перечислению | for_pay по SKU (retail − комиссия − СПП) |
| 5 | Логистика | вся логистика по SKU (delivery_rub, сумма, не на штуку) |
| 6 | Лог/шт | Логистика / Продажи |
| 7 | Реклама | ad_metrics_daily по nm_id этого SKU |
| 8 | ДРР | Реклама / Выручка |
| 9 | Себес | costs × Продажи |
| 10 | Прибыль | по SKU (К перечислению − логистика − хранение − прочее − реклама − себес) |
| 11 | ROI | Прибыль / Себес |
| 12 | Доход | Себес + Прибыль = выручка после всех расходов, КРОМЕ себеса. Чтобы был плюс, Доход должен превышать Себес. |
Примечания:
- «К перечислению» = for_pay (чисто привязано к SKU, сходится в ИТОГО). Колонку «к выплате»
по SKU НЕ делаем — удержание рекламы и хранение идут строками без артикула, по SKU не разносятся.
- «не разнесено по SKU» — хранение/услуги WB без артикула (для сходимости свода; сидит в Прибыли и Доходе).
- «неопознанный товар» — служебная строка WB (возвраты/удержания без привязки), не реальный SKU.
На что смотреть в результате (аналитика)
- ДРР по артикулу — если у SKU ДРР под 40%+, реклама съедает прибыль (реальный кейс
06–14.06:
skirt-atlas-max-2ДРР 38.5% → прибыль −2 600 ₽ при том, что els04-* давали ROI 150–210%). - Отрицательная прибыль/ROI у артикула — кандидат на пересмотр ставок рекламы или цены.
- Низкий Выкуп % — много отмен/возвратов, бьёт по логистике.
Сравнение периодов
Триггеры: «сравни периоды / сравни отчёты / сравни данные за период / неделя к неделе».
Запуск:
.venv\Scripts\python.exe scripts\wb_fin_week.py --shop 5 --compare # тек. закрытая неделя vs предыдущая той же длины
.venv\Scripts\python.exe scripts\wb_fin_week.py --shop 5 --since 2026-06-08 --to 2026-06-14 --compare
.venv\Scripts\python.exe scripts\wb_fin_week.py --shop 5 --since ... --to ... --vs-since 2026-05-01 --vs-to 2026-05-31 # произвольный 2-й период
--compare— второй период берётся автоматически: тот же по длине, вплотную перед основным.--vs-since/--vs-to— задать второй период вручную (длина может отличаться).- Печатается ПОСЛЕ обычного отчёта (свод + разбивка): сначала свод-сравнение, затем по артикулам.
Свод сравнения — метрика | тек | пред | Δ | Δ%:
- Абсолютные метрики (Выручка, К перечислению, Итого к выплате, Логистика, Реклама, Себес, Прибыль, Заказы, Продажи) — Δ и Δ%.
- Доли (ДРР, ROI, Маржа) — Δ в процентных пунктах (пп), НЕ «процент от процента» (так корректно сравнивать проценты).
По артикулам — каждый SKU двумя строками тек/пред, столбцы как в основной таблице (Продажи, Выручка, Реклама, ДРР, Лог/шт, Прибыль, Прибыль/шт, ROI, Доход): - Сортировка по текущей прибыли (убыточные/просевшие сверху). - Новый или выбывший SKU виден нулями в одном из периодов (напр. артикул появился только на текущей неделе → у «пред» все нули).
На что смотреть при сравнении:
- Прибыль растёт быстрее выручки — масштабирование «в плюс»; медленнее — расходы съедают рост.
- Δ ДРР вверх — реклама дорожает относительно отдачи. Особый красный флаг — SKU, у которого
при росте продаж прибыль перевернулась в минус (реальный кейс skirt-atlas-max-2: ДРР 28.9%→38.5%,
прибыль +1 671 → −2 600).
- Новые SKU-драйверы — кто появился и сразу дал прибыль (кандидаты усилить).
⚠ Налог (УСН) — доход берём из фактического отчёта о реализации
Для налоговой базы УСН доход признаётся по фактическому отчёту о реализации площадки, а НЕ по дате заказа и НЕ по нашему transaction_list / дате финоперации.
- Ozon — месячный отчёт о реализации (акт начислений), доход по дате доставки.
Наш
ozon_finance_operationsдат не совпадает: операция проводится на 1–3 дня позже доставки, поэтому продажи конца месяца «переезжают» в следующий месяц. Реальный кейс: Siluetta Ozon, май — отчёт о реализации 13 продаж / 42 544 ₽, а в наших транзакциях за май только 1 (остальные 12 — операциями начала июня). Для налога верны 42 544, а не транзакции. ⚠ Сумма в отчёте о реализации ниже нашихaccruals_for_sale— она за вычетом скидок/баллов Ozon (аналог СПП). Какую цифру бухгалтер берёт в доход — подтвердить (обычно сумму из акта). - WB — доход по закрытому недельному отчёту о реализации (
fin_report_detail,reportDetailByPeriod). Тут наш источник = акт, поэтому совпадает; брать только закрытые недели.
Вывод: помесячную/годовую базу УСН по Ozon из transaction_list считать НЕЛЬЗЯ — нужен
отчёт о реализации (ЛК Ozon / отдельный эндпоинт Seller API; пока не ингестим). УСН считается
суммарно по всем магазинам и площадкам одного юрлица.
Чек-лист
- ☐ Финреп и реклама свежие за нужное окно (квота finreport 2/24ч)?
- ☐ Неделя закрыта (Пн–Вс, не текущая)?
- ☐ Правильный
--shop(3 Siluetta WB / 5 Tote WB)? - ☐ Реклама не задвоена (свод делит удержано/вне удержаний)?
- ☐ Свод сходится: К перечислению − удержания = Итого к выплате; − себес − реклама = Прибыль?
- ☐ Разбивка «к перечисл» по SKU сходится в ИТОГО
for_pay? - ☐ В ответе пользователю — свод + таблица по артикулам + 1–2 вывода (кто тянет вниз).
Воспроизведение / расширение
- Один SKU с разбивкой по размерам —
scripts/wb_profit_sku.py. - За 2 недели по всем магазинам —
scripts/report_2weeks.py. - Логика прибыли, структура
fin_report_detail, подводные камни API —data/notes/wb/profit-methodology.md.