From b8e04478df740dc275b5c950181e82a21f5548ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Falc=C3=B3n?= Date: Thu, 14 May 2026 10:28:39 +0100 Subject: [PATCH] Fix imported transaction date shifts (#394) ## Summary - format imported dates from local date parts instead of UTC ISO strings - add regression coverage for Europe/Madrid date imports ## Tests - npm test -- resources/js/lib/file-parser.test.ts --- resources/js/lib/file-parser.test.ts | 37 +++++++++++++++++++++++++++- resources/js/lib/file-parser.ts | 10 +++++++- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/resources/js/lib/file-parser.test.ts b/resources/js/lib/file-parser.test.ts index 3b6b742c..6b328a58 100644 --- a/resources/js/lib/file-parser.test.ts +++ b/resources/js/lib/file-parser.test.ts @@ -1,6 +1,10 @@ import { DateFormat } from '@/types/import'; import { describe, expect, it } from 'vitest'; -import { autoDetectDateFormat, getLocaleDateFormat } from './file-parser'; +import { + autoDetectDateFormat, + convertRowsToTransactions, + getLocaleDateFormat, +} from './file-parser'; describe('getLocaleDateFormat', () => { it('returns null for undefined locale', () => { @@ -32,6 +36,37 @@ describe('getLocaleDateFormat', () => { }); }); +describe('convertRowsToTransactions', () => { + it('keeps imported dates stable in timezones ahead of UTC', () => { + const originalTimezone = process.env.TZ; + process.env.TZ = 'Europe/Madrid'; + + try { + const transactions = convertRowsToTransactions( + [ + { + date: '04/05/2026', + description: 'Tarjeta Abril', + amount: '10.00', + }, + ], + { + transaction_date: 'date', + description: 'description', + amount: 'amount', + balance: null, + }, + DateFormat.DayMonthYear, + ); + + expect(transactions).toHaveLength(1); + expect(transactions[0].transaction_date).toBe('2026-05-04'); + } finally { + process.env.TZ = originalTimezone; + } + }); +}); + describe('autoDetectDateFormat', () => { it('returns null for empty data', () => { expect(autoDetectDateFormat([], 'date')).toBeNull(); diff --git a/resources/js/lib/file-parser.ts b/resources/js/lib/file-parser.ts index 84326886..ccc2aef1 100644 --- a/resources/js/lib/file-parser.ts +++ b/resources/js/lib/file-parser.ts @@ -447,6 +447,14 @@ export function parseDate( return date; } +function formatLocalDate(date: Date): string { + const year = date.getFullYear(); + const month = String(date.getMonth() + 1).padStart(2, '0'); + const day = String(date.getDate()).padStart(2, '0'); + + return `${year}-${month}-${day}`; +} + export function parseAmount(amountStr: string | number): number | null { if (typeof amountStr === 'number') { return amountStr; @@ -572,7 +580,7 @@ export function convertRowsToTransactions( continue; } - const formattedDate = date.toISOString().split('T')[0]; + const formattedDate = formatLocalDate(date); let balance: number | null = null; if (mapping.balance && row[mapping.balance]) {