diff --git a/packages/loot-core/src/server/api.ts b/packages/loot-core/src/server/api.ts index c2aab6d12cce63ec0903f00436b5b5104a49c79f..c36da3398918b37c82e2770e763bc19045e3960b 100644 --- a/packages/loot-core/src/server/api.ts +++ b/packages/loot-core/src/server/api.ts @@ -101,6 +101,12 @@ async function validateExpenseCategory(debug, id) { } } +function checkFileOpen() { + if (!(prefs.getPrefs() || {}).id) { + throw APIError('No budget file is open'); + } +} + let batchPromise = null; handlers['api/batch-budget-start'] = async function () { @@ -225,6 +231,8 @@ handlers['api/start-import'] = async function ({ budgetName }) { }; handlers['api/finish-import'] = async function () { + checkFileOpen(); + sheet.get().markCacheDirty(); // We always need to fully reload the app. Importing doesn't touch @@ -245,6 +253,8 @@ handlers['api/finish-import'] = async function () { handlers['api/abort-import'] = async function () { if (IMPORT_MODE) { + checkFileOpen(); + let { id } = prefs.getPrefs(); await handlers['close-budget'](); @@ -256,15 +266,18 @@ handlers['api/abort-import'] = async function () { }; handlers['api/query'] = async function ({ query }) { + checkFileOpen(); return aqlQuery(query); }; handlers['api/budget-months'] = async function () { + checkFileOpen(); let { start, end } = await handlers['get-budget-bounds'](); return monthUtils.range(start, end); }; handlers['api/budget-month'] = async function ({ month }) { + checkFileOpen(); await validateMonth(month); let groups = await db.getCategoriesGrouped(); @@ -326,6 +339,7 @@ handlers['api/budget-set-amount'] = withMutation(async function ({ categoryId, amount, }) { + checkFileOpen(); return handlers['budget/budget-amount']({ month, category: categoryId, @@ -338,6 +352,7 @@ handlers['api/budget-set-carryover'] = withMutation(async function ({ categoryId, flag, }) { + checkFileOpen(); await validateMonth(month); await validateExpenseCategory('budget-set-carryover', categoryId); return handlers['budget/set-carryover']({ @@ -352,6 +367,7 @@ handlers['api/transactions-export'] = async function ({ categoryGroups, payees, }) { + checkFileOpen(); return handlers['transactions-export']({ transactions, categoryGroups, @@ -363,6 +379,7 @@ handlers['api/transactions-import'] = withMutation(async function ({ accountId, transactions, }) { + checkFileOpen(); return handlers['transactions-import']({ accountId, transactions }); }); @@ -370,6 +387,7 @@ handlers['api/transactions-add'] = withMutation(async function ({ accountId, transactions, }) { + checkFileOpen(); await addTransactions(accountId, transactions, { runTransfers: false }); return 'ok'; }); @@ -379,6 +397,7 @@ handlers['api/transactions-get'] = async function ({ startDate, endDate, }) { + checkFileOpen(); let { data } = await aqlQuery( q('transactions') .filter({ @@ -402,6 +421,7 @@ handlers['api/transaction-update'] = withMutation(async function ({ id, fields, }) { + checkFileOpen(); let { data } = await aqlQuery( q('transactions').filter({ id }).select('*').options({ splits: 'grouped' }), ); @@ -416,6 +436,7 @@ handlers['api/transaction-update'] = withMutation(async function ({ }); handlers['api/transaction-delete'] = withMutation(async function ({ id }) { + checkFileOpen(); let { data } = await aqlQuery( q('transactions').filter({ id }).select('*').options({ splits: 'grouped' }), ); @@ -430,6 +451,7 @@ handlers['api/transaction-delete'] = withMutation(async function ({ id }) { }); handlers['api/accounts-get'] = async function () { + checkFileOpen(); let accounts = await db.getAccounts(); return accounts.map(account => accountModel.toExternal(account)); }; @@ -438,6 +460,7 @@ handlers['api/account-create'] = withMutation(async function ({ account, initialBalance = null, }) { + checkFileOpen(); return handlers['account-create']({ name: account.name, type: account.type, @@ -450,6 +473,7 @@ handlers['api/account-create'] = withMutation(async function ({ }); handlers['api/account-update'] = withMutation(async function ({ id, fields }) { + checkFileOpen(); return db.updateAccount({ id, ...accountModel.fromExternal(fields) }); }); @@ -458,6 +482,7 @@ handlers['api/account-close'] = withMutation(async function ({ transferAccountId, transferCategoryId, }) { + checkFileOpen(); return handlers['account-close']({ id, transferAccountId, @@ -466,16 +491,19 @@ handlers['api/account-close'] = withMutation(async function ({ }); handlers['api/account-reopen'] = withMutation(async function ({ id }) { + checkFileOpen(); return handlers['account-reopen']({ id }); }); handlers['api/account-delete'] = withMutation(async function ({ id }) { + checkFileOpen(); return handlers['account-close']({ id, forced: true }); }); handlers['api/categories-get'] = async function ({ grouped, }: { grouped? } = {}) { + checkFileOpen(); let result = await handlers['get-categories'](); return grouped ? result.grouped.map(categoryGroupModel.toExternal) @@ -485,6 +513,7 @@ handlers['api/categories-get'] = async function ({ handlers['api/category-group-create'] = withMutation(async function ({ group, }) { + checkFileOpen(); return handlers['category-group-create']({ name: group.name }); }); @@ -492,6 +521,7 @@ handlers['api/category-group-update'] = withMutation(async function ({ id, fields, }) { + checkFileOpen(); return handlers['category-group-update']({ id, ...categoryGroupModel.fromExternal(fields), @@ -502,6 +532,7 @@ handlers['api/category-group-delete'] = withMutation(async function ({ id, transferCategoryId, }) { + checkFileOpen(); return handlers['category-group-delete']({ id, transferId: transferCategoryId, @@ -509,6 +540,7 @@ handlers['api/category-group-delete'] = withMutation(async function ({ }); handlers['api/category-create'] = withMutation(async function ({ category }) { + checkFileOpen(); return handlers['category-create']({ name: category.name, groupId: category.group_id, @@ -517,6 +549,7 @@ handlers['api/category-create'] = withMutation(async function ({ category }) { }); handlers['api/category-update'] = withMutation(async function ({ id, fields }) { + checkFileOpen(); return handlers['category-update']({ id, ...categoryModel.fromExternal(fields), @@ -527,6 +560,7 @@ handlers['api/category-delete'] = withMutation(async function ({ id, transferCategoryId, }) { + checkFileOpen(); return handlers['category-delete']({ id, transferId: transferCategoryId, @@ -534,21 +568,25 @@ handlers['api/category-delete'] = withMutation(async function ({ }); handlers['api/payees-get'] = async function () { + checkFileOpen(); let payees = await handlers['payees-get'](); return payees.map(payeeModel.toExternal); }; handlers['api/payee-create'] = withMutation(async function ({ payee }) { + checkFileOpen(); return handlers['payee-create']({ name: payee.name }); }); handlers['api/payee-update'] = withMutation(async function ({ id, fields }) { + checkFileOpen(); return handlers['payees-batch-change']({ updated: [{ id, ...payeeModel.fromExternal(fields) }], }); }); handlers['api/payee-delete'] = withMutation(async function ({ id }) { + checkFileOpen(); return handlers['payees-batch-change']({ deleted: [{ id }] }); }); diff --git a/upcoming-release-notes/1073.md b/upcoming-release-notes/1073.md new file mode 100644 index 0000000000000000000000000000000000000000..6cc62e817432ebc816a410ad37f8ca75139a0083 --- /dev/null +++ b/upcoming-release-notes/1073.md @@ -0,0 +1,6 @@ +--- +category: Maintenance +authors: [j-f1] +--- + +Add a clear error to the API when no budget is open, but you attempted to perform an action that requires a budget to be open.