mirror of
https://github.com/christianvidalwolf-prog/CrazeAnalytix.git
synced 2026-08-03 13:45:23 +02:00
fix: resolve vendor data upload error by implementing client-side parsing and sequential batching
This commit is contained in:
@@ -1,7 +1,57 @@
|
||||
import { SalesRecord, AdsRecord, TrafficRecord, CombinedKPIs, FilterState, AggregatedData, LineGrowthMetric, ItemGrowthMetric, SeasonalityPoint, YearlySplitData, PivotRow, YearlyData, TimeSeriesData, ComparisonTimeSeriesPoint, ForecastRecord, MonthlyForecastPoint, ProductForecastData } from '../types';
|
||||
import { SalesRecord, AdsRecord, TrafficRecord, CombinedKPIs, FilterState, AggregatedData, LineGrowthMetric, ItemGrowthMetric, SeasonalityPoint, YearlySplitData, PivotRow, YearlyData, TimeSeriesData, ComparisonTimeSeriesPoint, ForecastRecord, MonthlyForecastPoint, ProductForecastData, VendorCSVRow, VendorDailyRow } from '../types';
|
||||
import * as XLSX from 'xlsx';
|
||||
import Papa from 'papaparse';
|
||||
|
||||
/**
|
||||
* Parses Vendor CSV and returns mapped VendorDailyRow items.
|
||||
*/
|
||||
export const processVendorCSV = (fileOrContent: File | string): Promise<VendorDailyRow[]> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const config = {
|
||||
header: true,
|
||||
skipEmptyLines: true,
|
||||
complete: (results: any) => {
|
||||
const rows = results.data
|
||||
.filter((row: any) => row['Date'] && row['Market'] && row['ASIN'])
|
||||
.map((row: any) => ({
|
||||
date: row['Date'],
|
||||
market: row['Market'],
|
||||
asin: row['ASIN'],
|
||||
product_title: row['Product Title'] || null,
|
||||
tags: row['Tags'] || null,
|
||||
bsr_top_rank: parseIntSafe(row['Top Level Category (Rank)']),
|
||||
bsr_top_category: row['Top Level Category (Name)'] || null,
|
||||
bsr_detail_rank: parseIntSafe(row['Detail Level Category (Rank)']),
|
||||
bsr_detail_category: row['Detail Level Category (Name)'] || null,
|
||||
avg_rating: parseCurrency(row['Average Rating']), // Uses existing parseCurrency which handles EU/US
|
||||
num_reviews: parseIntSafe(row['Number of Reviews']),
|
||||
buybox_owner: row['Buybox Seller Name'] || null,
|
||||
buybox_price: parseCurrency(row['Buybox Price']),
|
||||
amazon_has_buybox: row['Amazon Has Buybox'] === '1',
|
||||
glance_views: parseIntSafe(row['Glance Views']),
|
||||
}));
|
||||
resolve(rows);
|
||||
},
|
||||
error: (error: any) => {
|
||||
reject(error);
|
||||
}
|
||||
};
|
||||
|
||||
if (typeof fileOrContent === 'string') {
|
||||
Papa.parse(fileOrContent, config);
|
||||
} else {
|
||||
Papa.parse(fileOrContent, config);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
function parseIntSafe(val: string | undefined | null): number | null {
|
||||
if (!val || typeof val !== 'string' || val.trim() === '') return null;
|
||||
const cleaned = val.replace(/\./g, '').replace(',', '.').replace(/[^0-9.]/g, '');
|
||||
const num = parseInt(cleaned, 10);
|
||||
return isNaN(num) ? null : num;
|
||||
}
|
||||
|
||||
// Helper to parse currency values handling both EU (1.234,56) and US/Standard (1,234.56 or 1234.56) formats
|
||||
const parseCurrency = (value: string): number => {
|
||||
if (!value) return 0;
|
||||
|
||||
+1
-19
@@ -1,5 +1,6 @@
|
||||
|
||||
import { createClient, SupabaseClient } from '@supabase/supabase-js';
|
||||
import { VendorDailyRow } from '../types';
|
||||
|
||||
const supabaseUrl = process.env.SUPABASE_URL || '';
|
||||
const supabaseAnonKey = process.env.SUPABASE_ANON_KEY || '';
|
||||
@@ -16,25 +17,6 @@ const getClient = (): SupabaseClient => {
|
||||
return _client;
|
||||
};
|
||||
|
||||
export interface VendorDailyRow {
|
||||
id?: number;
|
||||
date: string;
|
||||
market: string;
|
||||
asin: string;
|
||||
product_title: string | null;
|
||||
tags: string | null;
|
||||
bsr_top_rank: number | null;
|
||||
bsr_top_category: string | null;
|
||||
bsr_detail_rank: number | null;
|
||||
bsr_detail_category: string | null;
|
||||
avg_rating: number | null;
|
||||
num_reviews: number | null;
|
||||
buybox_owner: string | null;
|
||||
buybox_price: number | null;
|
||||
amazon_has_buybox: boolean | null;
|
||||
glance_views: number | null;
|
||||
}
|
||||
|
||||
export interface VendorFilters {
|
||||
markets?: string[];
|
||||
tags?: string[];
|
||||
|
||||
Reference in New Issue
Block a user