mirror of
https://github.com/christianvidalwolf-prog/CrazeAnalytix.git
synced 2026-08-03 11:55:22 +02:00
fix: logic to show BSR improvements (rank drops) in green
This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
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<string, string>();
|
||||
|
||||
// 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<string, number>();
|
||||
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);
|
||||
Reference in New Issue
Block a user