From a2ac241cd350942adc7df6c735cf0b0d0b408448 Mon Sep 17 00:00:00 2001 From: null Date: Sat, 6 Jun 2026 15:51:56 -0500 Subject: [PATCH] refactor(sync): centralize sync constants in bankSyncConfigService, wire through config/UI --- client/components/admin/BankSyncAdminCard.jsx | 34 +++++++++++-------- client/components/data/BankSyncSection.jsx | 12 ++++--- routes/dataSources.js | 4 +-- services/bankSyncConfigService.js | 7 +++- services/bankSyncService.js | 13 +++---- 5 files changed, 39 insertions(+), 31 deletions(-) diff --git a/client/components/admin/BankSyncAdminCard.jsx b/client/components/admin/BankSyncAdminCard.jsx index 283e070..da239ec 100644 --- a/client/components/admin/BankSyncAdminCard.jsx +++ b/client/components/admin/BankSyncAdminCard.jsx @@ -32,7 +32,7 @@ export default function BankSyncAdminCard() { const [saving, setSaving] = useState(false); const [enabled, setEnabled] = useState(false); const [syncInterval, setSyncInterval] = useState(4); - const [syncDays, setSyncDays] = useState(90); + const [syncDays, setSyncDays] = useState(30); useEffect(() => { api.bankSyncConfig() @@ -40,7 +40,7 @@ export default function BankSyncAdminCard() { setConfig(d); setEnabled(!!d.enabled); setSyncInterval(d.sync_interval_hours ?? 4); - setSyncDays(d.sync_days ?? 90); + setSyncDays(d.sync_days ?? 30); }) .catch(err => setLoadError(err.message || 'Failed to load bank sync config')) .finally(() => setLoading(false)); @@ -49,12 +49,13 @@ export default function BankSyncAdminCard() { const handleSave = async () => { const hours = parseFloat(syncInterval); const days = parseInt(syncDays, 10); + const maxDays = config?.sync_days_max ?? 45; if (!Number.isFinite(hours) || hours < 0.5 || hours > 168) { toast.error('Sync interval must be between 0.5 and 168 hours.'); return; } - if (!Number.isFinite(days) || days < 1 || days > 45) { - toast.error('Routine sync lookback must be 1–45 days. SimpleFIN Bridge enforces a 45-day hard limit — values above 45 return errors.'); + if (!Number.isFinite(days) || days < 1 || days > maxDays) { + toast.error(`Routine sync lookback must be 1–${maxDays} days. SimpleFIN Bridge enforces a ${maxDays}-day hard limit — values above ${maxDays} return errors.`); return; } setSaving(true); @@ -63,7 +64,7 @@ export default function BankSyncAdminCard() { setConfig(result); setEnabled(!!result.enabled); setSyncInterval(result.sync_interval_hours ?? 4); - setSyncDays(result.sync_days ?? 90); + setSyncDays(result.sync_days ?? 30); toast.success('Bank sync settings saved.'); } catch (err) { toast.error(err.message || 'Failed to update bank sync setting.'); @@ -96,6 +97,8 @@ export default function BankSyncAdminCard() { || parseFloat(syncInterval) !== config?.sync_interval_hours || parseInt(syncDays, 10) !== config?.sync_days; const worker = config?.worker; + const seedDays = config?.seed_days ?? 44; + const maxDays = config?.sync_days_max ?? 45; return ( @@ -161,12 +164,13 @@ export default function BankSyncAdminCard() {

Initial connect & backfill

- 6 days + {seedDays} days

- The first sync (and any manual backfill) always fetches the maximum 60 days of history - to build a complete transaction picture. This is fixed — SimpleFIN Bridge enforces a - strict 60-day hard limit and will return possible errors. + The first sync (and any manual backfill) fetches up to {seedDays} days of + history to build a complete transaction picture. This is fixed — SimpleFIN Bridge enforces a + strict {maxDays}-day hard limit, so this stays one day under it to avoid + latency-related errors.

@@ -184,10 +188,10 @@ export default function BankSyncAdminCard() { setSyncDays(Math.min(45, Math.max(1, parseInt(e.target.value, 10) || 30)))} + onChange={e => setSyncDays(Math.min(maxDays, Math.max(1, parseInt(e.target.value, 10) || 30)))} className="w-20 text-sm text-right" /> days @@ -195,11 +199,11 @@ export default function BankSyncAdminCard() { {/* Amber warning at the SimpleFIN limit */} - {parseInt(syncDays, 10) >= 45 && ( + {parseInt(syncDays, 10) >= maxDays && (

- 45 days is SimpleFIN Bridge's maximum. Requests at this limit may occasionally + {maxDays} days is SimpleFIN Bridge's maximum. Requests at this limit may occasionally fail due to request latency — 30 days or less is recommended for reliable routine syncs.

@@ -209,8 +213,8 @@ export default function BankSyncAdminCard() {
- SimpleFIN Bridge enforces a 45-day maximum on all requests. - Any value above 45 will cause sync errors for all users. + SimpleFIN Bridge enforces a {maxDays}-day maximum on all requests. + Any value above {maxDays} will cause sync errors for all users.
diff --git a/client/components/data/BankSyncSection.jsx b/client/components/data/BankSyncSection.jsx index cfc4144..f751433 100644 --- a/client/components/data/BankSyncSection.jsx +++ b/client/components/data/BankSyncSection.jsx @@ -289,7 +289,8 @@ function AccountRow({ account, sourceId, expanded, onToggleExpand, onToggleMonit export default function BankSyncSection({ onConnectionChange, cardProps = {} }) { const [enabled, setEnabled] = useState(null); - const [syncDays, setSyncDays] = useState(90); + const [syncDays, setSyncDays] = useState(30); + const [seedDays, setSeedDays] = useState(44); const [connections, setConnections] = useState([]); const [accountsBySource, setAccountsBySource] = useState({}); const [accountsLoading, setAccountsLoading] = useState({}); @@ -377,7 +378,8 @@ export default function BankSyncSection({ onConnectionChange, cardProps = {} }) api.dataSources({ type: 'provider_sync' }), ]); setEnabled(status.enabled); - setSyncDays(status.sync_days ?? 90); + setSyncDays(status.sync_days ?? 30); + setSeedDays(status.seed_days ?? 44); const conns = Array.isArray(sources) ? sources.filter(s => s.provider === 'simplefin') : []; setConnections(conns); onConnectionChange?.(conns[0] || null); @@ -484,7 +486,7 @@ export default function BankSyncSection({ onConnectionChange, cardProps = {} }) if (result.errlist) { toast.warning(`Backfill complete — ${result.transactionsNew} new transaction(s). Some connections need attention: ${result.errlist}`); } else { - toast.success(`Backfill complete — ${result.transactionsNew} new transaction(s) pulled from the last 90 days.`); + toast.success(`Backfill complete — ${result.transactionsNew} new transaction(s) pulled from the last ${seedDays} days.`); } await load(); } catch (err) { @@ -632,11 +634,11 @@ export default function BankSyncSection({ onConnectionChange, cardProps = {} }) onClick={() => handleBackfill(conn.id)} disabled={syncing === conn.id || backfilling === conn.id} className="h-8 text-xs gap-1.5 text-muted-foreground" - title="Pull up to 90 days of transaction history" + title={`Pull up to ${seedDays} days of transaction history`} > {backfilling === conn.id ? <>Backfilling… - : <>90d Backfill} + : <>{seedDays}d Backfill}