Add Buy Box Lost detection feature with visual warning badges

This commit is contained in:
Christian Vidal Wolf
2026-01-29 09:42:39 +01:00
parent e4fbdb60b1
commit 04b208969d
7 changed files with 138 additions and 8 deletions
+58
View File
@@ -1937,3 +1937,61 @@ export const processStockExcel = async (fileOrBuffer: File | ArrayBuffer): Promi
throw error;
}
};
// Sheet configuration for Buy Box tracking
const BB_SHEET_CONFIG: { sheet: string; country: string; reasonCol: number }[] = [
{ sheet: 'BB_FR', country: 'FR', reasonCol: 18 }, // Col S = index 18
{ sheet: 'BB_UK', country: 'UK', reasonCol: 9 }, // Col J = index 9
{ sheet: 'BB_DE', country: 'DE', reasonCol: 13 }, // Col N = index 13
{ sheet: 'BB_IT', country: 'IT', reasonCol: 12 }, // Col M = index 12
{ sheet: 'BB_ES', country: 'ES', reasonCol: 13 }, // Col N = index 13
];
export const processBuyBoxExcel = async (fileOrBuffer: File | ArrayBuffer): Promise<Map<string, { countries: string[]; reasons: Record<string, string> }>> => {
try {
const arrayBuffer = fileOrBuffer instanceof File
? await fileOrBuffer.arrayBuffer()
: fileOrBuffer;
const workbook = XLSX.read(arrayBuffer, { type: 'array' });
// Map: ASIN -> { countries: [], reasons: {} }
const buyBoxMap = new Map<string, { countries: string[]; reasons: Record<string, string> }>();
for (const config of BB_SHEET_CONFIG) {
const worksheet = workbook.Sheets[config.sheet];
if (!worksheet) {
console.warn(`[BuyBox] Sheet ${config.sheet} not found, skipping...`);
continue;
}
const jsonData: any[][] = XLSX.utils.sheet_to_json(worksheet, { header: 1 });
// Skip header row (index 0)
for (let i = 1; i < jsonData.length; i++) {
const row = jsonData[i];
const asin = String(row[1] || '').trim().toUpperCase(); // Col B = index 1
if (!asin || asin.length < 5) continue;
const rawReason = String(row[config.reasonCol] || '').trim();
const reason = rawReason || 'Unknown';
// Only add if there's actually a BB lost (non-empty reason or explicit entry)
if (!buyBoxMap.has(asin)) {
buyBoxMap.set(asin, { countries: [], reasons: {} });
}
const entry = buyBoxMap.get(asin)!;
if (!entry.countries.includes(config.country)) {
entry.countries.push(config.country);
}
entry.reasons[config.country] = reason;
}
}
console.log(`[BuyBox] Processed ${buyBoxMap.size} ASINs with BB lost`);
return buyBoxMap;
} catch (error) {
console.error("Error processing Buy Box Excel:", error);
throw error;
}
};