Fix/vat parent accounts (#438)

* feat(enable-banking): add support for account selection and syncing

- Updated StoredAccount interface to include an 'enabled' flag for account syncing preferences.
- Enhanced ensureFiscalPeriod function to handle overlapping fiscal periods with posted entries and opening balances.
- Added tests for fiscal period validation and account syncing logic.
- Implemented AccountPickerDialog component for user account selection.
- Created API routes for PATCH /accounts and POST /sync to manage account syncing.
- Introduced 'pending_selection' status for bank connections to allow user account selection before syncing.
- Updated database migration to support new connection status and backfill existing accounts with enabled=true.

* feat(enable-banking): implement account selection and consent event logging

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Mattsson
2026-05-11 17:12:00 +02:00
committed by GitHub
co-authored by Claude Opus 4.7
parent d0fbc2b616
commit a53a119a2e
20 changed files with 1761 additions and 112 deletions
@@ -143,7 +143,29 @@ export const GET = withCronContext('cron.bank_sync', async (_request, ctx) => {
.toISOString()
.split('T')[0]
const accounts = (connection.accounts_data as StoredAccount[] || []).map(a => ({ ...a }))
// Keep the full list for the DB write-back so we don't drop accounts
// the user has opted out of. Sync only the enabled subset (treating
// undefined as enabled for back-compat with older rows).
const allAccounts = (connection.accounts_data as StoredAccount[] || []).map(a => ({ ...a }))
const accounts = allAccounts.filter(a => a.enabled !== false)
if (accounts.length === 0) {
ctx.log.info('all accounts disabled — skipping sync', {
connectionId: connection.id,
totalAccounts: allAccounts.length,
})
results.push({
connectionId: connection.id,
userId: connection.user_id,
bankName: connection.bank_name,
imported: 0,
duplicates: 0,
errors: 0,
status: 'synced',
daysUntilExpiry: daysLeft,
})
continue
}
// Detect SIE overlap — skip auto-categorization if the sync range
// overlaps with a completed SIE import to prevent double-booking
@@ -194,11 +216,12 @@ export const GET = withCronContext('cron.bank_sync', async (_request, ctx) => {
}
}
// Successful sync: update connection and clear any previous error state
// Successful sync: update connection and clear any previous error state.
// Write allAccounts (not accounts) so disabled accounts stay in the row.
await supabase
.from('bank_connections')
.update({
accounts_data: accounts,
accounts_data: allAccounts,
last_synced_at: new Date().toISOString(),
...(connection.error_message ? { error_message: null } : {}),
})