Commit Graph

13 Commits

Author SHA1 Message Date
Víctor Falcón 744d874464
fix(import): honor selected date format for CSV imports (#494)
## Problem

Importing a CSV with `DD/MM/YYYY` dates (e.g. `02/06/2026`) parsed them
as `MM/DD/YYYY`, and the **Date Format** selector either didn't appear
or had no effect — the preview showed the same wrong date regardless of
the chosen format.

## Root cause

The `xlsx` parser coerced CSV date-like strings into Excel **serial
numbers** at read time, guessing the format itself. `parseDate` then hit
its numeric short-circuit and **ignored the selected format entirely**,
so the Date Format radio never changed the preview.

On top of that, ambiguous dates (valid as both DD/MM and MM/DD) were
resolved silently by browser locale, and a saved import config force-hid
the selector — so a wrong guess couldn't be corrected.

## Changes

- **`parseFile` reads with `raw: true`** — CSV cells stay as their
original strings; `parseDate` applies the chosen format. Native
`.xls/.xlsx` dates still arrive as numbers and use the serial path.
- **`detectDateFormat()`** now returns `{ format, ambiguous }`. When
multiple formats parse the sample equally, the importer keeps the Date
Format selector visible (defaulting to the locale/saved best guess) —
even when a saved config exists — so a previously-saved wrong format can
be fixed. `autoDetectDateFormat()` kept as a thin wrapper.
- Applied to both the transactions and account-balances import drawers.
- **UI:** moved the Date Format selector above the preview and switched
the mapping form from broken Tailwind v4 `space-y`/`space-x` to
`flex`/`gap`.

## Tests

- New `parseFile` regression test: `02/06/2026` stays a string and
parses to June (DD-MM) vs February (MM-DD).
- New `detectDateFormat` tests for the `ambiguous` flag.
- All 39 `file-parser` tests pass; lint/format clean.
2026-06-05 15:10:48 +02:00
Víctor Falcón f9d1303d98
feat(importer): support YYYYMMDD date format (#470)
## Summary
Adds a compact `YYYYMMDD` (no separators) date format to the
transactions and balance importers.

- New `DateFormat.YearMonthDayCompact = 'YYYYMMDD'` enum value
- `parseDate` parses the 8-digit form (`20241231` → `2024-12-31`)
- `autoDetectDateFormat` recognizes it (unambiguous, no separators)
- Both mapping UIs (transactions + balances) expose it as a selectable
option

## Testing
- `bunx vitest run resources/js/lib/file-parser.test.ts` — 34 passed
- Added tests: compact auto-detection + compact conversion
- `bun run format`, `bun run lint` clean
2026-06-01 16:44:46 +02:00
Víctor Falcón 144d919c0b
fix(import): correct balance for same-day, zero and negative values (#456)
## Problem

CSV imports only carry a date (no timestamp). Rows are newest-on-top and
we import top-to-bottom. Three balance bugs:

1. **Same-day balance wrong.** The store loop did `Map.set(date,
balance)` per row, so when a day had 2+ transactions the **last**
(bottom = oldest) row overwrote the newest. The correct daily balance is
the **first** (newest) row.
2. **Zero balance dropped.** The parser guard `row[mapping.balance]`
treated numeric `0` as falsy, so a real `0` balance became `null`. `0`
is valid.
3. **Negative balance lost its sign.** `parseAmount` stripped `-` via
`replace(/[^\d]/g,'')`, so negative balances (and amounts) came out
positive.

## Fix

- `import-transactions-drawer.tsx`: keep the **first** occurrence per
date (`!balancesToImport.has(date)`).
- `file-parser.ts`: guard balance on null/undefined/empty-string only,
so `0` is kept.
- `file-parser.ts`: `parseAmount` now detects a leading `-` (or `(...)`)
and applies the sign — fixes negative balances and negative amounts.

## Tests

Added 4 cases to `file-parser.test.ts`: zero (number), zero (string),
negative, empty→null. Full suite: **144 passed**.

> Note: the same-day "keep first" logic lives in the React component and
relies on `newTransactions` staying in CSV order (top = newest), which
holds in current code.
2026-05-30 16:19:27 +02:00
Víctor Falcón 10da06ed84
feat(transactions): add counterparty fields (#440)
## Summary
- add creditor/debtor fields to transactions with raw_data backfill
- store counterparties on bank sync and CSV/XLS imports
- add creditor/debtor filters plus hidden table columns

## Tests
- php artisan test --compact tests/Feature/LocalizationTest.php
tests/Feature/OpenBanking/TransactionSyncServiceTest.php
tests/Feature/TransactionFilterTest.php
- npm test -- resources/js/lib/file-parser.test.ts --run
- vendor/bin/pint --dirty --format agent

Note: `npm run types` still has pre-existing unrelated errors; no
creditor/debtor/import-related errors remained in filtered output.

## Screenshot
<img width="1241" height="676" alt="8odYWtFcvUM"
src="https://github.com/user-attachments/assets/55653485-d588-4beb-9e6a-5c7c81ba7cf8"
/>
2026-05-27 16:20:55 +02:00
Víctor Falcón 66ff427481
feat(import): calculate balances from transactions (#403)
## Why

Some banks return transactions without a balance column. The CSV/Excel
importer happily creates the transactions but leaves the account without
any balance history, making the account look incomplete.

## What

Opt-in flow that derives per-day balances from the transactions
themselves, using a single reference point (the balance on the date of
the latest transaction).

### Mapping step
- New checkbox **"Calculate balances from transactions"** next to the
  Balance column select.
- Available only when no balance column is mapped (disabled + visually
  faded otherwise).
- When checked, a balance input appears labeled with the latest
  transaction date using a relative format:
  - `Today`
  - `Yesterday`
  - `Monday, 3 of Jun`
- If an `AccountBalance` already exists for that date, it is pre-filled
  automatically (no need to ask) with a small hint.
- The reference balance is **mandatory** when the checkbox is checked;
  the Next button is disabled until it is provided.

### Preview step
- A new `Balance` column shows the balance about to be created for each
  date, regardless of whether it came from the file or was calculated.

### Persistence
- Balances are computed by walking backwards across distinct transaction
  dates and subtracting each day's net movement.
- They flow through the existing import path that POSTs to
  `AccountBalanceController@store`, so no new endpoint was needed.

## Feature flag

Hidden behind a new Pennant feature, **off by default**:

```bash
php artisan feature:enable CalculateBalancesOnImport user@example.com
# or
php artisan feature:enable CalculateBalancesOnImport all
```

The flag is exposed to the frontend via Inertia shared props
(`features.calculateBalancesOnImport`).

## Tests

- New vitest cases for `getLatestTransactionDate` and
  `calculateBalancesFromTransactions` (sparse dates, reference date
  without txns, empty list).
- `LocalizationTest` passes (new ES strings added).
- Full vitest suite green (106 tests).
2026-05-20 10:29:14 +01:00
Víctor Falcón b8e04478df
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
2026-05-14 10:28:39 +01:00
Víctor Falcón a19a8d52ec
Fix: Use locale to disambiguate date format during CSV import (#107)
## Summary
- When CSV dates are ambiguous (e.g. `05/03/2024` parses as both
DD-MM-YYYY and MM-DD-YYYY), the auto-detection heuristic now uses the
user's locale preference as a tie-breaker instead of relying on array
order
- Adds `getLocaleDateFormat()` helper that maps locale strings to their
expected date format (US → MM-DD-YYYY, most others → DD-MM-YYYY, CJK →
YYYY-MM-DD)
- Passes locale from Inertia shared props to both transaction and
balance import flows

Closes #100

## Test plan
- [x] Added 15 Vitest tests for `getLocaleDateFormat` and
`autoDetectDateFormat` with locale tie-breaking
- [ ] Manual test: Import CSV with ambiguous dates (day ≤ 12) using a
non-US locale, verify DD-MM-YYYY is preferred
- [ ] Manual test: Import CSV with unambiguous dates (day > 12), verify
locale does NOT override correct detection
2026-02-12 09:08:52 +01:00
Víctor Falcón 2fefb64710 Fix CI: Update bun.lock and fix linting errors 2025-12-01 15:16:06 +01:00
Víctor Falcón a4ed4e73c1 Add multi-column description mapping support
- Allow description field to map to multiple columns
- Update ColumnMapping type to accept string or string[] for description
- Join multiple description columns with newlines
- Add validation for multi-column descriptions
- Add test asset for multi-description CSV files
2025-12-01 10:30:11 +01:00
Víctor Falcón dcb78d2252 Update transaction amount to bigint 2025-11-15 20:53:47 +01:00
Víctor Falcón bec18b925b Add account balances 2025-11-15 20:27:18 +01:00
Víctor Falcón e13a19bdde Add some toast notifications 2025-11-11 11:39:28 +00:00
Víctor Falcón dd0f1380d4 Import CSV 2025-11-08 14:17:11 +00:00