feat: restrict data to Amazon customers only (DE/FR/ES/IT/UK/SC)

This commit is contained in:
Christian Vidal Wolf
2026-01-16 10:44:43 +01:00
parent 470db20458
commit a1ad3aa944
+23 -15
View File
@@ -40,7 +40,7 @@ const parseCurrency = (value: string): number => {
}; };
const parseUnits = (value: string): number => { const parseUnits = (value: string): number => {
if(!value) return 0; if (!value) return 0;
// Remove dots (thousands separators in EU) and commas (thousands in US) just to be safe for integers // Remove dots (thousands separators in EU) and commas (thousands in US) just to be safe for integers
const clean = value.replace(/[\.,]/g, ''); const clean = value.replace(/[\.,]/g, '');
const num = parseInt(clean, 10); const num = parseInt(clean, 10);
@@ -151,6 +151,14 @@ const getColumnValue = (row: any, aliases: string[]): string => {
} }
return ''; return '';
}; };
// Allowed Customers Whitelist
const ALLOWED_CUSTOMERS = ['Amazon DE', 'Amazon FR', 'Amazon ES', 'Amazon IT', 'Amazon UK', 'Amazon SC'];
const isAllowedCustomer = (customer: string): boolean => {
if (!customer) return false;
const normCustomer = customer.trim().toLowerCase();
return ALLOWED_CUSTOMERS.some(allowed => allowed.toLowerCase() === normCustomer);
};
// --- SALES / SELL OUT MAPPING --- // --- SALES / SELL OUT MAPPING ---
@@ -216,8 +224,8 @@ export const processCSV = (fileOrContent: File | string): Promise<SalesRecord[]>
const data: SalesRecord[] = results.data.map((row: any, index: number) => { const data: SalesRecord[] = results.data.map((row: any, index: number) => {
return mapRowToRecord(row, index); return mapRowToRecord(row, index);
}) })
// Relaxed filtering: Only exclude rows with absolutely no year info even after backfill // Filter: Valid Year AND Allowed Customer
.filter((r: SalesRecord) => r.year > 0); .filter((r: SalesRecord) => r.year > 0 && isAllowedCustomer(r.customer));
resolve(data); resolve(data);
} catch (err) { } catch (err) {
@@ -240,8 +248,8 @@ export const processExcel = async (file: File): Promise<SalesRecord[]> => {
const data: SalesRecord[] = jsonData.map((row: any, index: number) => { const data: SalesRecord[] = jsonData.map((row: any, index: number) => {
return mapRowToRecord(row, index); return mapRowToRecord(row, index);
}) })
// Relaxed filtering // Filter: Valid Year AND Allowed Customer
.filter((r: SalesRecord) => r.year > 0); .filter((r: SalesRecord) => r.year > 0 && isAllowedCustomer(r.customer));
return data; return data;
} catch (error) { } catch (error) {
@@ -608,7 +616,7 @@ const calculateGenericSplit = (data: SalesRecord[], groupField: keyof SalesRecor
totals.set(key, (totals.get(key) || 0) + item[valueField]); totals.set(key, (totals.get(key) || 0) + item[valueField]);
}); });
let sortedKeys = Array.from(totals.entries()).sort((a,b) => b[1] - a[1]).map(e => e[0]); let sortedKeys = Array.from(totals.entries()).sort((a, b) => b[1] - a[1]).map(e => e[0]);
if (limit) sortedKeys = sortedKeys.slice(0, limit); if (limit) sortedKeys = sortedKeys.slice(0, limit);
const keySet = new Set(sortedKeys); const keySet = new Set(sortedKeys);
@@ -919,7 +927,7 @@ export const getUniqueValues = (data: SalesRecord[], field: keyof SalesRecord):
export const pivotSalesData = (data: SalesRecord[], dimensions: string[] = ['title', 'customer', 'line', 'sku']): { rows: PivotRow[], years: string[] } => { export const pivotSalesData = (data: SalesRecord[], dimensions: string[] = ['title', 'customer', 'line', 'sku']): { rows: PivotRow[], years: string[] } => {
// 1. Determine all years present in the data for columns // 1. Determine all years present in the data for columns
const yearsSet = new Set(data.map(d => d.year)); const yearsSet = new Set(data.map(d => d.year));
const years = Array.from(yearsSet).sort((a,b) => b-a).map(String); const years = Array.from(yearsSet).sort((a, b) => b - a).map(String);
const map = new Map<string, PivotRow>(); const map = new Map<string, PivotRow>();
@@ -1036,14 +1044,14 @@ export const generateItemMoversCSV = (
ASIN: item.asin || '-', ASIN: item.asin || '-',
'Product Title': item.title || '-', 'Product Title': item.title || '-',
'Product Line': item.line || '-', 'Product Line': item.line || '-',
[`Sell Out ${periods.previous}`]: item.previousYearSellOut.toLocaleString('de-DE', {minimumFractionDigits: 0, maximumFractionDigits: 0}), [`Sell Out ${periods.previous}`]: item.previousYearSellOut.toLocaleString('de-DE', { minimumFractionDigits: 0, maximumFractionDigits: 0 }),
[`Sell Out ${periods.current}`]: item.currentYearSellOut.toLocaleString('de-DE', {minimumFractionDigits: 0, maximumFractionDigits: 0}), [`Sell Out ${periods.current}`]: item.currentYearSellOut.toLocaleString('de-DE', { minimumFractionDigits: 0, maximumFractionDigits: 0 }),
'SO Diff': item.sellOutGrowthValue.toLocaleString('de-DE', {minimumFractionDigits: 0, maximumFractionDigits: 0}), 'SO Diff': item.sellOutGrowthValue.toLocaleString('de-DE', { minimumFractionDigits: 0, maximumFractionDigits: 0 }),
'SO Growth %': item.sellOutGrowthPercentage.toLocaleString('de-DE', {minimumFractionDigits: 1, maximumFractionDigits: 1}) + '%', 'SO Growth %': item.sellOutGrowthPercentage.toLocaleString('de-DE', { minimumFractionDigits: 1, maximumFractionDigits: 1 }) + '%',
[`Units ${periods.previous}`]: item.previousYearUnits.toLocaleString('de-DE', {minimumFractionDigits: 0, maximumFractionDigits: 0}), [`Units ${periods.previous}`]: item.previousYearUnits.toLocaleString('de-DE', { minimumFractionDigits: 0, maximumFractionDigits: 0 }),
[`Units ${periods.current}`]: item.currentYearUnits.toLocaleString('de-DE', {minimumFractionDigits: 0, maximumFractionDigits: 0}), [`Units ${periods.current}`]: item.currentYearUnits.toLocaleString('de-DE', { minimumFractionDigits: 0, maximumFractionDigits: 0 }),
'Units Diff': item.unitsGrowthValue.toLocaleString('de-DE', {minimumFractionDigits: 0, maximumFractionDigits: 0}), 'Units Diff': item.unitsGrowthValue.toLocaleString('de-DE', { minimumFractionDigits: 0, maximumFractionDigits: 0 }),
'Units Growth %': item.unitsGrowthPercentage.toLocaleString('de-DE', {minimumFractionDigits: 1, maximumFractionDigits: 1}) + '%', 'Units Growth %': item.unitsGrowthPercentage.toLocaleString('de-DE', { minimumFractionDigits: 1, maximumFractionDigits: 1 }) + '%',
})); }));
// @ts-ignore // @ts-ignore