Плейбук: где лежит товар WB и куда уехала поставка
Срабатывает, когда пользователь просит:
- «где лежит товар на WB»;
- «на каких складах наш остаток»;
- «куда WB отправил поставку»;
- «есть ли товар в Москве / на Юге / в СЗ»;
- «какой срок доставки по регионам».
Заведён 16.09.2026. Скрипт — scripts/wb_card_geo.py (read-only, без токена).
Почему нужен отдельный способ
С 15.08.2026 WB поменял FBW-поставки: продавец сдаёт товар в ПВЗ, СЦ или ПФЦ,
а по складам хранения WB распределяет сам. Выбора склада, транзита и карты складов
в кабинете больше нет, перераспределение между складами отключено ещё с конца июля
(см. redistribution-playbook.md). С 29.09.2026 — платная перевозка от точки сдачи
до склада хранения, 3–7 ₽/л.
Проверено на наших данных 16.09.2026 — склад скрыт везде:
| Источник | Что показывает с середины августа |
|---|---|
stocks_snapshot.warehouse |
Склад WB |
orders.warehouse / raw_json.warehouseName |
Склад WB РФ (с 32-й недели 2026) |
fin_report_detail.office_name |
пусто или Склад WB |
Единственный найденный источник размещения — публичная карточка товара покупателя.
Как это работает
GET https://user-geo-data.wildberries.ru/get-geo-info?latitude=..&longitude=..— кодdestдля точки покупателя. ⚠ Только эти два параметра: сcurrency,locale,addressсервис игнорирует координаты и отдаёт город по IP.GET https://card.wb.ru/cards/v4/detail?appType=1&curr=rub&dest=<dest>&spp=30&nm=<nm>. Вproducts[0].sizes[].stocks[]:
| Поле | Смысл |
|---|---|
wh |
ID склада (10-значный, не старые 507/117986; названия нет) |
qty |
остаток размера на этом складе |
dist |
расстояние склада до покупателя по данным WB |
time1 + time2 |
срок доставки, часы |
products[0].totalQuantity |
весь продаваемый остаток карточки |
- Для одного
destкарточка отдаёт только ближайший склад по каждому размеру. Поэтому опрашиваем 41 город по 7 нашим кластерам и объединяем пары(размер, wh).
Покрытие проверено 16.09.2026: 13 артикулов Siluetta и Tote, сумма по складам
150 шт против totalQuantity 147 шт (остаток меняется за 5 минут прогона);
по отдельным карточкам 15 = 15, 24 = 24. 11 городов покрытия не дают — нужны все 41.
Команды
# снимок: nm_id с остатком из последнего stocks_snapshot (боевая база — на Hetzner)
python scripts/wb_card_geo.py snapshot
# или вручную
python scripts/wb_card_geo.py snapshot --nm 234267200 401254682
python scripts/wb_card_geo.py report data/wb_card_geo/2026-09-16_1434.json
python scripts/wb_card_geo.py diff data/wb_card_geo/<до>.json data/wb_card_geo/<после>.json
Снимки — data/wb_card_geo/*.json (в .gitignore: количества — коммерческие данные).
Один снимок — около 540 запросов, 4–5 минут. Чаще пары раз в день не запускать.
report выдаёт:
- где лежит товар — склад привязан к ближайшей из 41 точки, если
dist ≤ 150; иначе «не определено» с ближайшим городом и числом городов, из которых склад виден; - срок доставки по кластерам — медиана часов, доля ≤48 ч и ≤72 ч по всем размерам в наличии и всем городам кластера.
Куда уехала поставка через СЦ
Да, это определяется разницей двух снимков.
- До сдачи —
snapshotв день отгрузки в СЦ/ПВЗ. - После приёмки — статус поставки «Принято»; затем
snapshotраз в день 5–7 дней: распределение от точки сдачи до складов хранения растягивается во времени. diff <до> <после>— прирост по(nm, размер, склад)и сумма по локациям. Пометка «новый склад» — склад, которого не было в первом снимке.- Сверить с составом поставки (
GET /api/v1/supplies/{ID}/goods, см.app/wb/endpoints.py): сумма прироста по размеру не должна превышать принятое количество.
Что искажает разницу
- Возвраты. При выкупе 25–30% невыкупы возвращаются на склады каждый день и тоже дают прирост. Надёжнее всего атрибуция по размерам, которых не было в остатке, или крупной партии, заметно больше суточных возвратов.
- Продажи. Уменьшают остаток на складах за тот же период — учитывать только прирост.
- Товар в пути от СЦ к складу хранения в карточке, скорее всего, не виден, пока не принят складом (не проверено).
Ограничения — проговаривать в ответе
dist— не расстояние по карте. Похоже на путь по сети WB: для одних и тех же складов Ростов получает больше, чем Краснодар. Поэтому координаты склада не вычисляются, только близость к точке опроса.- Около трети штук на 16.09 — «не определено». Далёкий склад виден только из городов, для которых он ближайший. Точнее, чем «рядом с Владимиром (46 км)», метод склад не называет.
- Стабильность
whмежду днями не проверена. В пределах двух часов 16.09 ID совпали 17 из 17. Если ID меняются каждый день —diffсломан, остаётся толькоreport. Первое, что сделать при следующем снимке, — сравнить множестваwh. - Карточка показывает продаваемый остаток: резерв и товар в пути не видны.
- Эндпоинт недокументированный (
v4), WB может его изменить или закрыть.
Срез 16.09.2026 (Siluetta + Tote, 147 шт)
| Где | Шт | Доля |
|---|---|---|
| Центральный: у Владимира | 32 | 21% |
| Уральский: у Екатеринбурга | 24 | 16% |
| Центральный: у Рязани | 19 | 13% |
| Приволжский: у Казани | 12 | 8% |
| Северо-Западный: у Калининграда | 4 | 3% |
| Сибирь: у Новосибирска и Красноярска | 5 | 3% |
| Центральный: у Воронежа | 2 | 1% |
| не определено | 52 | 35% |
| Кластер | Медиана срока | ≤48 ч | ≤72 ч |
|---|---|---|---|
| Москва и МО | 38 ч | 54% | 91% |
| Центральный | 41 ч | 66% | 80% |
| Северо-Западный | 48 ч | 51% | 70% |
| Южный и СК | 58 ч | 30% | 71% |
| Приволжский | 35 ч | 77% | 91% |
| Уральский | 43 ч | 70% | 92% |
| Сибирь | 78 ч | 24% | 46% |
Рядом с Москвой/МО, Санкт-Петербургом, Краснодаром и Ростовом остатка нет; слабее всего по сроку — Юг и Сибирь.
Открытые проверки
- Стабильность
whмежду днями (см. выше). - Зависит ли распределение от точки сдачи: сдать небольшую партию в СЦ на Юге,
через неделю
diff— появился ли склад сdist ≤ 150у Краснодара/Ростова. - Виден ли товар в пути от СЦ до склада хранения.