From 7010ab1eb6ee9a098eadd5e1a3c258d84536e230 Mon Sep 17 00:00:00 2001 From: Matt Fiddaman Date: Mon, 18 Nov 2024 20:38:45 +0000 Subject: [PATCH] add simplefin batch sync to api (#3821) --- .../loot-core/src/client/actions/account.ts | 2 +- packages/loot-core/src/server/api.ts | 40 ++++++++++++++++--- packages/loot-core/src/server/main.ts | 23 +++++++---- .../loot-core/src/types/server-handlers.d.ts | 12 +++--- upcoming-release-notes/3821.md | 6 +++ 5 files changed, 64 insertions(+), 19 deletions(-) create mode 100644 upcoming-release-notes/3821.md diff --git a/packages/loot-core/src/client/actions/account.ts b/packages/loot-core/src/client/actions/account.ts index 54330402abc..579366b38b5 100644 --- a/packages/loot-core/src/client/actions/account.ts +++ b/packages/loot-core/src/client/actions/account.ts @@ -204,7 +204,7 @@ export function syncAccounts(id?: string) { // Perform sync operation const res = await send('accounts-bank-sync', { - id: accountId, + ids: [accountId], }); const success = handleSyncResponse( diff --git a/packages/loot-core/src/server/api.ts b/packages/loot-core/src/server/api.ts index a2e9348fdc9..72ae7b35d84 100644 --- a/packages/loot-core/src/server/api.ts +++ b/packages/loot-core/src/server/api.ts @@ -248,13 +248,41 @@ handlers['api/sync'] = async function () { }; handlers['api/bank-sync'] = async function (args) { - const { errors } = await handlers['accounts-bank-sync']({ - id: args?.accountId, - }); + const batchSync = args?.accountId == null; + const allErrors = []; + + if (!batchSync) { + const { errors } = await handlers['accounts-bank-sync']({ + ids: [args.accountId], + }); + + allErrors.push(errors); + } else { + const accountsData = await handlers['accounts-get'](); + const accountIdsToSync = accountsData.map(a => a.id); + const simpleFinAccounts = accountsData.filter( + a => a.account_sync_source === 'simpleFin', + ); + const simpleFinAccountIds = simpleFinAccounts.map(a => a.id); + + if (simpleFinAccounts.length > 1) { + const res = await handlers['simplefin-batch-sync']({ + ids: simpleFinAccountIds, + }); + + res.forEach(a => allErrors.push(...a.res.errors)); + } + + const { errors } = await handlers['accounts-bank-sync']({ + ids: accountIdsToSync.filter(a => !simpleFinAccountIds.includes(a)), + }); + + allErrors.push(...errors); + } - const [firstError] = errors; - if (firstError) { - throw new Error(getBankSyncError(firstError)); + const errors = allErrors.filter(e => e != null); + if (errors.length > 0) { + throw new Error(getBankSyncError(errors[0])); } }; diff --git a/packages/loot-core/src/server/main.ts b/packages/loot-core/src/server/main.ts index d2801148e4b..aadde848273 100644 --- a/packages/loot-core/src/server/main.ts +++ b/packages/loot-core/src/server/main.ts @@ -1099,17 +1099,22 @@ function handleSyncError(err, acct) { }; } -handlers['accounts-bank-sync'] = async function ({ id }) { +handlers['accounts-bank-sync'] = async function ({ ids = [] }) { const [[, userId], [, userKey]] = await asyncStorage.multiGet([ 'user-id', 'user-key', ]); + const accounts = await db.runQuery( - `SELECT a.*, b.bank_id as bankId FROM accounts a - LEFT JOIN banks b ON a.bank = b.id - WHERE a.tombstone = 0 AND a.closed = 0 ${id ? 'AND a.id = ?' : ''} - ORDER BY a.offbudget, a.sort_order`, - id ? [id] : [], + ` + SELECT a.*, b.bank_id as bankId + FROM accounts a + LEFT JOIN banks b ON a.bank = b.id + WHERE a.tombstone = 0 AND a.closed = 0 + ${ids.length ? `AND a.id IN (${ids.map(() => '?').join(', ')})` : ''} + ORDER BY a.offbudget, a.sort_order + `, + ids, true, ); @@ -1162,7 +1167,11 @@ handlers['simplefin-batch-sync'] = async function ({ ids = [] }) { const accounts = await db.runQuery( `SELECT a.*, b.bank_id as bankId FROM accounts a LEFT JOIN banks b ON a.bank = b.id - WHERE a.tombstone = 0 AND a.closed = 0 ${ids.length ? `AND a.id IN (${ids.map(() => '?').join(', ')})` : ''} + WHERE + a.tombstone = 0 + AND a.closed = 0 + AND a.account_sync_source = 'simpleFin' + ${ids.length ? `AND a.id IN (${ids.map(() => '?').join(', ')})` : ''} ORDER BY a.offbudget, a.sort_order`, ids.length ? ids : [], true, diff --git a/packages/loot-core/src/types/server-handlers.d.ts b/packages/loot-core/src/types/server-handlers.d.ts index 338b5e2f3f1..1ae73ef66fd 100644 --- a/packages/loot-core/src/types/server-handlers.d.ts +++ b/packages/loot-core/src/types/server-handlers.d.ts @@ -196,10 +196,12 @@ export interface ServerHandlers { 'simplefin-batch-sync': ({ ids }: { ids: string[] }) => Promise< { accountId: string; - errors; - newTransactions; - matchedTransactions; - updatedAccounts; + res: { + errors; + newTransactions; + matchedTransactions; + updatedAccounts; + }; }[] >; @@ -223,7 +225,7 @@ export interface ServerHandlers { | { error: 'failed' } >; - 'accounts-bank-sync': (arg: { id?: string }) => Promise<{ + 'accounts-bank-sync': (arg: { ids?: AccountEntity['id'][] }) => Promise<{ errors; newTransactions; matchedTransactions; diff --git a/upcoming-release-notes/3821.md b/upcoming-release-notes/3821.md new file mode 100644 index 00000000000..82685535180 --- /dev/null +++ b/upcoming-release-notes/3821.md @@ -0,0 +1,6 @@ +--- +category: Enhancements +authors: [matt-fidd] +--- + +Implement SimpleFin batch sync in the API