diff --git a/services/dataProcessor.ts b/services/dataProcessor.ts index b36f473..f6db581 100644 --- a/services/dataProcessor.ts +++ b/services/dataProcessor.ts @@ -667,43 +667,70 @@ export const processBSRExcel = async (fileOrBuffer: File | ArrayBuffer): Promise const workbook = XLSX.read(arrayBuffer, { type: 'array' }); const allData: BSRRecord[] = []; - // Typically BSR is in the first sheet - const sheetName = workbook.SheetNames[0]; - const worksheet = workbook.Sheets[sheetName]; - const jsonData: any[] = XLSX.utils.sheet_to_json(worksheet, { defval: "" }); + // Process all sheets — markets may be split across tabs + for (const sheetName of workbook.SheetNames) { + const worksheet = workbook.Sheets[sheetName]; + const jsonData: any[] = XLSX.utils.sheet_to_json(worksheet, { defval: "" }); + if (jsonData.length === 0) continue; - console.log(`Processing BSR sheet "${sheetName}": ${jsonData.length} rows`); + console.log(`[BSR] Processing sheet "${sheetName}": ${jsonData.length} rows. Columns:`, Object.keys(jsonData[0])); - for (let i = 0; i < jsonData.length; i++) { - const row = jsonData[i]; + for (const row of jsonData) { + const marketRaw = getColumnValue(row, ['market', 'country', 'marketplace', 'Market', 'Country', 'Marketplace']); + const asinRaw = getColumnValue(row, ['asin', 'ASIN']); + if (!marketRaw || !asinRaw) continue; - const weekRaw = getColumnValue(row, ['week', 'woche', 'semana']); - const marketRaw = getColumnValue(row, ['market', 'country', 'marketplace']); - const asinRaw = getColumnValue(row, ['asin']); - const topLevelBSRRaw = getColumnValue(row, ['Mean Weekly Top Level BSR']); - const topLevelNameRaw = getColumnValue(row, ['Top Level Category Name']); - const detailLevelBSRRaw = getColumnValue(row, ['Mean Weekly Detail Level BSR']); - const detailLevelNameRaw = getColumnValue(row, ['Detail Level Category Name']); - const avgRatingRaw = getColumnValue(row, ['Mean Weekly Average Rating']); + // Week: try direct week column first, else derive from Date column + let week = 0; + const weekRaw = getColumnValue(row, ['week', 'woche', 'semana', 'week number', 'weeknumber', 'Week', 'Week Number']); + if (weekRaw) { + week = parseInt(String(weekRaw).match(/\d+/)?.[0] || '0', 10); + } + if (!week) { + const dateRaw = getColumnValue(row, ['date', 'fecha', 'datum', 'Date']); + if (dateRaw) { + const d = new Date(dateRaw); + if (!isNaN(d.getTime())) { + // ISO week number + const tmp = new Date(d); + tmp.setHours(0, 0, 0, 0); + tmp.setDate(tmp.getDate() + 3 - ((tmp.getDay() + 6) % 7)); + const w1 = new Date(tmp.getFullYear(), 0, 4); + week = 1 + Math.round(((tmp.getTime() - w1.getTime()) / 86400000 - 3 + ((w1.getDay() + 6) % 7)) / 7); + } + } + } + if (!week) continue; - if (!weekRaw || !marketRaw || !asinRaw) continue; - - const week = parseInt(String(weekRaw).match(/\\d+/)?.[0] || '0', 10); - if (isNaN(week) || week === 0) continue; - - allData.push({ - week, - market: String(marketRaw).trim(), - asin: String(asinRaw).trim(), - topLevelBSR: parseIntSafe(String(topLevelBSRRaw)), - topLevelName: topLevelNameRaw ? String(topLevelNameRaw).trim() : null, - detailLevelBSR: parseIntSafe(String(detailLevelBSRRaw)), - detailLevelName: detailLevelNameRaw ? String(detailLevelNameRaw).trim() : null, - avgRating: parseFloat(String(avgRatingRaw)) || null, - }); + allData.push({ + week, + market: String(marketRaw).trim(), + asin: String(asinRaw).trim(), + topLevelBSR: parseIntSafe(getColumnValue(row, [ + 'Mean Weekly Top Level BSR', 'Top Level Category (Rank)', 'Top Level BSR', + 'TopLevelBSR', 'bsr top', 'BSR Top Level', 'top level bsr', + ])), + topLevelName: getColumnValue(row, [ + 'Top Level Category Name', 'Top Level Category (Name)', + 'TopLevelName', 'top category name', 'Top Category', + ]) || null, + detailLevelBSR: parseIntSafe(getColumnValue(row, [ + 'Mean Weekly Detail Level BSR', 'Detail Level Category (Rank)', 'Detail Level BSR', + 'DetailLevelBSR', 'bsr detail', 'BSR Detail Level', 'detail level bsr', + ])), + detailLevelName: getColumnValue(row, [ + 'Detail Level Category Name', 'Detail Level Category (Name)', + 'DetailLevelName', 'detail category name', 'Detail Category', + ]) || null, + avgRating: parseFloat(getColumnValue(row, [ + 'Mean Weekly Average Rating', 'Average Rating', 'AvgRating', + 'Rating', 'avg rating', + ])) || null, + }); + } } - console.log(`Total BSR records loaded: ${allData.length}`); + console.log(`[BSR] Total records loaded: ${allData.length}`); return allData; } catch (error) { console.error("Error processing BSR Excel:", error);