WB stats reliability: fix client apply-after-refetch, normalize ad dates, and add cache fallback\n\n- SalesTab: apply data immediately after refetch success to avoid empty state\n- Service: normalize advertising day dates to YYYY-MM-DD for correct range checks\n- Resolver: fallback to cached advertisingData when productsData is missing (429)\n\nHelps show data even when WB API rate-limits and fixes mixed-date aggregation.

This commit is contained in:
Bivekich
2025-08-11 22:30:45 +03:00
parent 3a56092385
commit 8ba8fc1214
3 changed files with 56 additions and 2 deletions

View File

@ -232,7 +232,11 @@ const SalesTab = React.memo(({
} }
if (result.data?.getWildberriesStatistics?.success) { if (result.data?.getWildberriesStatistics?.success) {
console.warn('Sales: Loading fresh data from API') console.warn('Sales: Loading fresh data from API')
// Обрабатываем данные в существующем useEffect const rows = result.data.getWildberriesStatistics.data || []
if (rows.length > 0) {
// Применяем данные сразу, не дожидаясь обновления wbData
applyData(rows)
}
lastLoadedKeyRef.current = loadKey lastLoadedKeyRef.current = loadKey
} }
} catch (error) { } catch (error) {

View File

@ -8224,6 +8224,42 @@ const wildberriesQueries = {
message: 'Данные возвращены из кеша из-за ошибки WB API', message: 'Данные возвращены из кеша из-за ошибки WB API',
} }
} }
} else if (cache?.advertisingData) {
// Fallback №2: если нет productsData, но есть advertisingData —
// формируем минимальный набор данных по дням на основе затрат на рекламу
try {
const adv = JSON.parse(cache.advertisingData as unknown as string) as {
dailyData?: Array<{
date: string
totalSum?: number
totalOrders?: number
totalRevenue?: number
}>
}
const daily = adv.dailyData ?? []
const dataFromAdv = daily.map((d) => ({
date: d.date,
sales: 0,
orders: typeof d.totalOrders === 'number' ? d.totalOrders : 0,
advertising: typeof d.totalSum === 'number' ? d.totalSum : 0,
refusals: 0,
returns: 0,
revenue: typeof d.totalRevenue === 'number' ? d.totalRevenue : 0,
buyoutPercentage: 0,
}))
if (dataFromAdv.length > 0) {
return {
success: true,
data: dataFromAdv,
message:
'Данные по продажам недоступны из-за ошибки WB API. Показаны данные по рекламе из кеша.',
}
}
} catch (parseErr) {
console.error('Failed to parse advertisingData from cache:', parseErr)
}
} }
} }
} catch (fallbackErr) { } catch (fallbackErr) {
@ -8980,6 +9016,17 @@ resolvers.Query = {
} }
} }
// Если кеш просрочен — не используем его, как и для склада WB (сервер решает, годен ли кеш)
const now = new Date()
if (cache.expiresAt && cache.expiresAt <= now) {
return {
success: true,
message: 'Кеш устарел, требуется загрузка из API',
cache: null,
fromCache: false,
}
}
return { return {
success: true, success: true,
message: 'Данные получены из кеша', message: 'Данные получены из кеша',
@ -8990,6 +9037,8 @@ resolvers.Query = {
dateTo: cache.dateTo ? cache.dateTo.toISOString().split('T')[0] : null, dateTo: cache.dateTo ? cache.dateTo.toISOString().split('T')[0] : null,
productsTotalSales: cache.productsTotalSales ? Number(cache.productsTotalSales) : null, productsTotalSales: cache.productsTotalSales ? Number(cache.productsTotalSales) : null,
advertisingTotalCost: cache.advertisingTotalCost ? Number(cache.advertisingTotalCost) : null, advertisingTotalCost: cache.advertisingTotalCost ? Number(cache.advertisingTotalCost) : null,
// Возвращаем expiresAt в ISO, чтобы клиент корректно парсил дату
expiresAt: cache.expiresAt.toISOString(),
createdAt: cache.createdAt.toISOString(), createdAt: cache.createdAt.toISOString(),
updatedAt: cache.updatedAt.toISOString(), updatedAt: cache.updatedAt.toISOString(),
}, },

View File

@ -851,7 +851,8 @@ class WildberriesService {
// Обрабатываем статистику по дням для каждой кампании // Обрабатываем статистику по дням для каждой кампании
if (advertStat.days && advertStat.days.length > 0) { if (advertStat.days && advertStat.days.length > 0) {
advertStat.days.forEach((day) => { advertStat.days.forEach((day) => {
const date = day.date // Нормализуем дату рекламы до формата YYYY-MM-DD, чтобы совпадала с продажами/заказами
const date = (day.date.includes('T') ? day.date.split('T')[0] : day.date.split(' ')[0] || day.date) as string
console.warn(`WB API: Day ${date} - spent ${day.sum} rubles (campaign ${advertStat.advertId})`) console.warn(`WB API: Day ${date} - spent ${day.sum} rubles (campaign ${advertStat.advertId})`)