mirror of
https://github.com/christianvidalwolf-prog/CrazeAnalytix.git
synced 2026-08-03 12:15:23 +02:00
fix(dataProcessor): parse DD/M/YY dates from column C in sell-out CSV
Add support for European day-first date format (e.g. "23/2/26" = 23 Feb 2026) in the sell-out CSV pipeline so months and years are correctly extracted from column C of Amazon Sell Out 2023-2025.csv. - normalizeMonth: detect DD/MM/YY when first part > 12, return "Mon-YY" - mapRowToRecord: add 'C', 'Date', 'Fecha', 'DATA' to month column aliases - validateSellOutHeaders: accept date columns as substitute for YEAR + MONTH Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
ad1695d360
commit
2eed94b94b
@@ -193,9 +193,30 @@ const normalizeMonth = (rawMonth: string): string => {
|
||||
}
|
||||
|
||||
// 2. Handle numeric months "01", "1", "01-2023"
|
||||
// If it's a full date string like "2023-04-01" or "01/04/2023"
|
||||
// If it's a full date string like "2023-04-01", "01/04/2023", or "23/2/26" (DD/M/YY)
|
||||
if (m.includes('/') || m.includes('-')) {
|
||||
// Try parsing standard date
|
||||
// Handle DD/M/YY or DD/MM/YY (European day-first format, e.g. "23/2/26" = 23 Feb 2026)
|
||||
const parts = m.split(m.includes('/') ? '/' : '-');
|
||||
if (parts.length === 3) {
|
||||
const [a, b, c] = parts.map(p => parseInt(p, 10));
|
||||
if (!isNaN(a) && !isNaN(b) && !isNaN(c)) {
|
||||
// If first part > 12: definitely day-first → DD/MM/YY
|
||||
if (a > 12 && b >= 1 && b <= 12) {
|
||||
const yearShort = c < 100 ? String(c).padStart(2, '0') : String(c).slice(2);
|
||||
const result = `${MONTH_ORDER[b - 1]}-${yearShort}`;
|
||||
monthCache[rawMonth] = result;
|
||||
return result;
|
||||
}
|
||||
// YYYY/MM/DD or YYYY-MM-DD (ISO-like, year is 4 digits in first position)
|
||||
if (a > 31 && b >= 1 && b <= 12) {
|
||||
const yearShort = String(a).slice(2);
|
||||
const result = `${MONTH_ORDER[b - 1]}-${yearShort}`;
|
||||
monthCache[rawMonth] = result;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Try parsing standard date as fallback
|
||||
const date = new Date(m);
|
||||
if (!isNaN(date.getTime())) {
|
||||
const monthIdx = date.getMonth();
|
||||
@@ -289,8 +310,10 @@ const isAllowedCustomer = (customer: string): boolean => {
|
||||
export const validateSellOutHeaders = (headers: string[]) => {
|
||||
const normHeaders = headers.map(h => String(h).trim().toLowerCase());
|
||||
|
||||
const hasYear = normHeaders.includes('year');
|
||||
const hasTime = normHeaders.includes('month') || normHeaders.includes('week');
|
||||
// A date column (e.g. column named "C", "Date", "Fecha") can provide both year and month
|
||||
const hasDateCol = ['c', 'date', 'fecha', 'data'].some(d => normHeaders.includes(d));
|
||||
const hasYear = normHeaders.includes('year') || hasDateCol;
|
||||
const hasTime = normHeaders.includes('month') || normHeaders.includes('week') || hasDateCol;
|
||||
const hasCustomerRef = normHeaders.includes('customer reference') || normHeaders.includes('asin');
|
||||
const hasEan = normHeaders.includes('ean');
|
||||
const hasUnits = normHeaders.includes('units');
|
||||
@@ -315,7 +338,7 @@ const mapRowToRecord = (row: any, index: number): SalesRecord => {
|
||||
const yearStr = getColumnValue(row, ['YEAR', 'Year', 'D']);
|
||||
// Sanitize year string before parsing (remove commas/dots e.g. "2,023")
|
||||
let year = parseInt(yearStr.replace(/[,.]/g, '')) || 0;
|
||||
const monthStr = getColumnValue(row, ['MONTH', 'Month', 'Period']);
|
||||
const monthStr = getColumnValue(row, ['MONTH', 'Month', 'Period', 'C', 'Date', 'DATE', 'Fecha', 'FECHA', 'Data', 'DATA']);
|
||||
const month = normalizeMonth(monthStr);
|
||||
|
||||
// BACKFILL YEAR if missing but present in Month (e.g. "Apr-23")
|
||||
|
||||
Reference in New Issue
Block a user