diff --git a/packages/api/methods.test.ts b/packages/api/methods.test.ts index 4a3cc09001..9a9e2fb9ed 100644 --- a/packages/api/methods.test.ts +++ b/packages/api/methods.test.ts @@ -251,7 +251,7 @@ describe('API CRUD operations', () => { ); }); - //apis: createAccount, getAccounts, updateAccount, closeAccount, deleteAccount, reopenAccount + //apis: createAccount, getAccounts, updateAccount, closeAccount, deleteAccount, reopenAccount, getAccountBalance test('Accounts: successfully complete account operators', async () => { const accountId1 = await api.createAccount( { name: 'test-account1', offbudget: true }, @@ -272,6 +272,9 @@ describe('API CRUD operations', () => { ]), ); + expect(await api.getAccountBalance(accountId1)).toEqual(1000); + expect(await api.getAccountBalance(accountId2)).toEqual(0); + await api.updateAccount(accountId1, { offbudget: false }); await api.closeAccount(accountId1, accountId2, null); await api.deleteAccount(accountId2); @@ -569,6 +572,11 @@ describe('API CRUD operations', () => { }); expect(addResult).toBe('ok'); + expect(await api.getAccountBalance(accountId)).toEqual(200); + expect( + await api.getAccountBalance(accountId, new Date(2023, 10, 2)), + ).toEqual(0); + // confirm added transactions exist let transactions = await api.getTransactions( accountId, diff --git a/packages/api/methods.ts b/packages/api/methods.ts index 63f23ae30d..cc25bfe3e4 100644 --- a/packages/api/methods.ts +++ b/packages/api/methods.ts @@ -125,6 +125,10 @@ export function deleteAccount(id) { return send('api/account-delete', { id }); } +export function getAccountBalance(id, cutoff?) { + return send('api/account-balance', { id, cutoff }); +} + export function getCategoryGroups() { return send('api/category-groups-get'); } diff --git a/packages/loot-core/src/server/api.ts b/packages/loot-core/src/server/api.ts index d50cf08e61..fe670152ad 100644 --- a/packages/loot-core/src/server/api.ts +++ b/packages/loot-core/src/server/api.ts @@ -538,6 +538,14 @@ handlers['api/account-delete'] = withMutation(async function ({ id }) { return handlers['account-close']({ id, forced: true }); }); +handlers['api/account-balance'] = withMutation(async function ({ + id, + cutoff = new Date(), +}) { + checkFileOpen(); + return handlers['account-balance']({ id, cutoff }); +}); + handlers['api/categories-get'] = async function ({ grouped, }: { grouped? } = {}) { diff --git a/packages/loot-core/src/server/main.ts b/packages/loot-core/src/server/main.ts index c85fb31169..634293646e 100644 --- a/packages/loot-core/src/server/main.ts +++ b/packages/loot-core/src/server/main.ts @@ -13,6 +13,7 @@ import { logger } from '../platform/server/log'; import * as sqlite from '../platform/server/sqlite'; import { isNonProductionEnvironment } from '../shared/environment'; import * as monthUtils from '../shared/months'; +import { dayFromDate } from '../shared/months'; import { q, Query } from '../shared/query'; import { amountToInteger, stringToInteger } from '../shared/util'; import { type Budget } from '../types/budget'; @@ -578,6 +579,14 @@ handlers['accounts-get'] = async function () { return db.getAccounts(); }; +handlers['account-balance'] = async function ({ id, cutoff }) { + const { balance } = await db.first( + 'SELECT sum(amount) as balance FROM transactions WHERE acct = ? AND isParent = 0 AND tombstone = 0 AND date <= ?', + [id, db.toDateRepr(dayFromDate(cutoff))], + ); + return balance ? balance : 0; +}; + handlers['account-properties'] = async function ({ id }) { const { balance } = await db.first( 'SELECT sum(amount) as balance FROM transactions WHERE acct = ? AND isParent = 0 AND tombstone = 0', diff --git a/packages/loot-core/src/types/api-handlers.d.ts b/packages/loot-core/src/types/api-handlers.d.ts index 7be7f4119e..edd89582dd 100644 --- a/packages/loot-core/src/types/api-handlers.d.ts +++ b/packages/loot-core/src/types/api-handlers.d.ts @@ -114,6 +114,11 @@ export interface ApiHandlers { 'api/account-delete': (arg: { id }) => Promise; + 'api/account-balance': (arg: { + id: string; + cutoff?: Date; + }) => Promise; + 'api/categories-get': (arg: { grouped; }) => Promise>; diff --git a/upcoming-release-notes/2930.md b/upcoming-release-notes/2930.md new file mode 100644 index 0000000000..dbe12f5253 --- /dev/null +++ b/upcoming-release-notes/2930.md @@ -0,0 +1,6 @@ +--- +category: Features +authors: [psybers] +--- + +Add getAccountBalance() API.