import XLSX from 'xlsx'; import { readFileSync, existsSync } from 'fs'; import Papa from 'papaparse'; const ADS_FILE = 'Ads Weekly.xlsx'; const DATA_FILE = 'dist/Amazon-Sell-Out-2023-2025.csv'; // Need to check if this exists locally or if I need to fetch it. async function main() { console.log('--- AD SPEND BY PRODUCT LINE (UK, 2026) ---'); // 1. Build Metadata Map (ASIN -> Line) from Sales Records const metaMap = new Map(); // Check local CSV if it exists, otherwise we might need to fetch it const dropboxUrl = "https://www.dropbox.com/scl/fi/b9zxn4z5i7sxwfakk5g5y/Amazon-Sell-Out-2023-2025.csv?rlkey=uoto6v0mm99py8nszy8ldtez8&st=pzn1zkrg&dl=1"; console.log('Fetching Sales data to build ASIN-Line mapping...'); const csvResponse = await fetch(dropboxUrl); const csvText = await csvResponse.text(); console.log('Parsing CSV...'); const results = Papa.parse(csvText, { header: true, skipEmptyLines: true }); const rows = results.data as any[]; if (rows.length > 0) { console.log('CSV Columns:', Object.keys(rows[0])); } rows.forEach(r => { const asin = String(rowValue(r, ['CUSTOMER REFERENCE', 'ASIN'])).trim().toUpperCase(); const line = rowValue(r, ['PRODUCT Line', 'Line']) || 'Unassigned'; if (asin && !metaMap.has(asin)) { metaMap.set(asin, line); } }); console.log(`Built mapping for ${metaMap.size} unique ASINs.`); // Helper to get case-insensitive row value function rowValue(row: any, aliases: string[]): string { for (const a of aliases) { if (row[a]) return row[a]; const lowerA = a.toLowerCase(); const found = Object.keys(row).find(k => k.toLowerCase() === lowerA); if (found) return row[found]; } return ''; } // 2. Parse Ads Data if (!existsSync(ADS_FILE)) { console.error(`Error: ${ADS_FILE} not found.`); return; } const buf = readFileSync(ADS_FILE); const wb = XLSX.read(buf, { type: 'buffer' }); const spendByLine = new Map(); let totalUkSpend = 0; let foundMatches: any[] = []; for (const sheetName of wb.SheetNames) { const ws = wb.Sheets[sheetName]; const rows: any[] = XLSX.utils.sheet_to_json(ws, { defval: '' }); rows.forEach((r: any) => { const countryRaw = String(r.Country || '').toUpperCase(); const asin = String(r.ASIN || '').trim().toUpperCase(); const cost = parseFloat(r.Cost) || 0; const line = metaMap.get(asin) || 'Unassigned'; // Still track official UK 2026 total for the summary if (sheetName === '2026' && (countryRaw === 'UK' || countryRaw === 'GB' || countryRaw === 'AMAZON UK' || countryRaw === 'AMAZON GB')) { spendByLine.set(line, (spendByLine.get(line) || 0) + cost); totalUkSpend += cost; } // DEBUG: Find ALL "INKEE" records anywhere that might explain the 126 if (line.toUpperCase() === 'INKEE' && cost > 0) { foundMatches.push({ Sheet: sheetName, Country: countryRaw, ASIN: asin, Cost: cost, Week: r.Week }); } }); } console.log('\n--- ALL INKEE AD RECORDS FOUND (ANY COUNTRY/YEAR) ---'); console.table(foundMatches.slice(0, 50)); // Showing first 50 if (foundMatches.length > 50) console.log(`... and ${foundMatches.length - 50} more records.`); const totalsByGroup = foundMatches.reduce((acc, curr) => { const key = `${curr.Sheet} | ${curr.Country}`; acc[key] = (acc[key] || 0) + curr.Cost; return acc; }, {}); console.log('\nSummary of INKEE Spend by Sheet and Country:'); console.table(totalsByGroup); // 3. Output results console.log('\nOfficial Results for Amazon UK (2026 YTD) based on sheet "2026":'); const sortedLines = Array.from(spendByLine.entries()) .sort((a, b) => b[1] - a[1]); console.log('--------------------------------------------------'); console.log(`${'Product Line'.padEnd(30)} | ${'Ad Spend (£)'.padStart(15)}`); console.log('--------------------------------------------------'); sortedLines.forEach(([line, spend]) => { console.log(`${line.padEnd(30)} | ${spend.toFixed(2).padStart(15)}`); }); console.log('--------------------------------------------------'); console.log(`${'TOTAL'.padEnd(30)} | ${totalUkSpend.toFixed(2).padStart(15)}`); } main().catch(console.error);