Миграция отчёта по регионам на Ленту заказов
Wildberries отключит GET /api/v1/analytics/region-sale 3 ноября 2026 года. В SDK 4.x метод sdk.reports.getAnalyticsRegionSale() остаётся доступным для совместимости и один раз за процесс выводит предупреждение. Новые региональные выборки следует строить на sdk.analytics.getOrderFeed().
Лента заказов возвращает отдельные события, а старый эндпоинт — готовые региональные агрегаты. По Ленте можно считать заказы по географии доставки, но она не является точной заменой полей saleInvoiceCostPrice, saleInvoiceCostPricePerc и saleItemInvoiceQty.
Границы контракта
- Период не превышает 31 день и определяется датой текущего статуса заказа.
- В первом запросе
snapshotTimeотсутствует; во всех следующих страницах используетсяdata.snapshotTimeиз первого ответа. - Увеличивайте
offset, не меняя период, фильтры, limit и snapshot. destinationCityиdestinationDistrictзадают географию доставки.- Одна строка Ленты — один заказ, одно сборочное задание и одна единица товара. Отдельного поля quantity нет, поэтому каждая включённая строка даёт одну единицу.
- Учитывайте
statusявно. Для простого отчёта по выкупленным товарам оставляйте толькоbuyout. СтатусыreturnиreturnDefectiveсчитайте отдельно, если бизнес-правила не задают другой расчёт. sellerPriceне учитывает скидки WB Клуба и оптовые скидки B2B. Это поле не доказано как эквивалент старой инвойсной стоимости или доли региона.
Пагинация одного snapshot и группировка
import type { WildberriesSDK } from 'daytona-wildberries-typescript-sdk';
type RegionCount = {
destinationDistrict: string;
destinationCity: string;
purchasedItems: number;
};
async function getPurchasedItemsByRegion(
sdk: WildberriesSDK,
start: string,
end: string
): Promise<RegionCount[]> {
const limit = 10_000;
const grouped = new Map<string, RegionCount>();
let offset = 0;
let snapshotTime: string | undefined;
while (true) {
const page = await sdk.analytics.getOrderFeed({
selectedPeriod: { start, end },
pagination: { offset, limit, snapshotTime },
});
snapshotTime ??= page.data.snapshotTime;
for (const order of page.data.orders) {
if (order.status !== 'buyout') continue;
const key = `${order.destinationDistrict}\u0000${order.destinationCity}`;
const current = grouped.get(key) ?? {
destinationDistrict: order.destinationDistrict,
destinationCity: order.destinationCity,
purchasedItems: 0,
};
current.purchasedItems += 1;
grouped.set(key, current);
}
if (page.data.orders.length < limit) break;
const nextOffset = offset + page.data.orders.length;
if (nextOffset <= offset) {
throw new Error('Order Feed pagination did not advance');
}
offset = nextOffset;
}
return [...grouped.values()];
}Пример сразу добавляет каждую страницу в агрегат, поэтому память растёт с числом регионов, а не заказов. Если ответ полной страницы не позволяет увеличить offset, пример завершится с ошибкой. При изменении периода или фильтра начинайте новый snapshot. Если страница завершилась ошибкой, повторите тот же offset с тем же snapshotTime: новый snapshot посреди прохода может дать пропуски или дубли при смене статусов.
Что требует отдельного бизнес-правила
Пример считает только количество выкупленных единиц. Перед заменой рабочего отчёта определите обработку отмен, обычных и дефектных возвратов, B2B-строк и заказов, текущий статус которых вышел за выбранный период. Денежные расчёты держите отдельно и явно указывайте исходное поле. Опубликованный контракт не задаёт формулу, которая воспроизводит денежные показатели и доли старого регионального отчёта.