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:
@ -232,7 +232,11 @@ const SalesTab = React.memo(({
|
||||
}
|
||||
if (result.data?.getWildberriesStatistics?.success) {
|
||||
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
|
||||
}
|
||||
} catch (error) {
|
||||
|
@ -8224,6 +8224,42 @@ const wildberriesQueries = {
|
||||
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) {
|
||||
@ -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 {
|
||||
success: true,
|
||||
message: 'Данные получены из кеша',
|
||||
@ -8990,6 +9037,8 @@ resolvers.Query = {
|
||||
dateTo: cache.dateTo ? cache.dateTo.toISOString().split('T')[0] : null,
|
||||
productsTotalSales: cache.productsTotalSales ? Number(cache.productsTotalSales) : null,
|
||||
advertisingTotalCost: cache.advertisingTotalCost ? Number(cache.advertisingTotalCost) : null,
|
||||
// Возвращаем expiresAt в ISO, чтобы клиент корректно парсил дату
|
||||
expiresAt: cache.expiresAt.toISOString(),
|
||||
createdAt: cache.createdAt.toISOString(),
|
||||
updatedAt: cache.updatedAt.toISOString(),
|
||||
},
|
||||
|
@ -851,7 +851,8 @@ class WildberriesService {
|
||||
// Обрабатываем статистику по дням для каждой кампании
|
||||
if (advertStat.days && advertStat.days.length > 0) {
|
||||
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})`)
|
||||
|
||||
|
Reference in New Issue
Block a user