mirror of
https://github.com/christianvidalwolf-prog/CrazeAnalytix.git
synced 2026-08-03 11:35:24 +02:00
fix(bsr): fix regex bug and expand column aliases in processBSRExcel
- Fix critical regex bug: /\\d+/ was matching literal '\d' instead of digits, causing all rows to be rejected (week always = 0) - Add VendorCSV format support: 'Top Level Category (Rank)', 'Date', etc. - Derive ISO week number from Date column when no Week column exists - Process all sheets (not just first) to handle multi-tab workbooks - Log column names on load to aid future debugging Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
17a3df9fb3
commit
702bb021f8
+58
-31
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user