@actual-app/api 6.8.2 → 6.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/@types/jest.config.d.ts +7 -7
  2. package/@types/loot-core/client/constants.d.ts +2 -0
  3. package/@types/loot-core/client/state-types/index.d.ts +1 -1
  4. package/@types/loot-core/client/state-types/modals.d.ts +27 -8
  5. package/@types/loot-core/client/state-types/notifications.d.ts +18 -1
  6. package/@types/loot-core/client/state-types/prefs.d.ts +9 -4
  7. package/@types/loot-core/client/state-types/queries.d.ts +8 -0
  8. package/@types/loot-core/server/accounts/parse-file.d.ts +1 -0
  9. package/@types/loot-core/server/accounts/rules.d.ts +2 -2
  10. package/@types/loot-core/server/accounts/sync.d.ts +12 -1
  11. package/@types/loot-core/server/accounts/transaction-rules.d.ts +1 -3
  12. package/@types/loot-core/server/accounts/transactions.d.ts +3 -5
  13. package/@types/loot-core/server/api-models.d.ts +21 -6
  14. package/@types/loot-core/server/aql/schema/index.d.ts +41 -3
  15. package/@types/loot-core/server/budget/actions.d.ts +2 -1
  16. package/@types/loot-core/server/budget/statements.d.ts +9 -0
  17. package/@types/loot-core/server/budget/template-notes.d.ts +5 -0
  18. package/@types/loot-core/server/budget/types/templates.d.ts +82 -0
  19. package/@types/loot-core/server/cloud-storage.d.ts +0 -1
  20. package/@types/loot-core/server/dashboard/app.d.ts +12 -0
  21. package/@types/loot-core/server/dashboard/types/handlers.d.ts +24 -0
  22. package/@types/loot-core/server/db/index.d.ts +4 -2
  23. package/@types/loot-core/server/db/types.d.ts +9 -0
  24. package/@types/loot-core/server/encryption-internals.d.ts +0 -1
  25. package/@types/loot-core/server/encryption-internals.web.d.ts +0 -1
  26. package/@types/loot-core/server/encryption.d.ts +0 -1
  27. package/@types/loot-core/server/errors.d.ts +2 -0
  28. package/@types/loot-core/server/importers/actual.d.ts +0 -1
  29. package/@types/loot-core/server/importers/index.d.ts +0 -1
  30. package/@types/loot-core/server/importers/ynab4.d.ts +0 -1
  31. package/@types/loot-core/server/importers/ynab5.d.ts +0 -1
  32. package/@types/loot-core/server/main-app.d.ts +1 -1
  33. package/@types/loot-core/server/models.d.ts +4 -4
  34. package/@types/loot-core/server/prefs.d.ts +7 -2
  35. package/@types/loot-core/server/reports/app.d.ts +46 -0
  36. package/@types/loot-core/server/rules/types/handlers.d.ts +4 -6
  37. package/@types/loot-core/server/sync/make-test-message.d.ts +0 -1
  38. package/@types/loot-core/shared/dashboard.d.ts +2 -0
  39. package/@types/loot-core/shared/months.d.ts +7 -6
  40. package/@types/loot-core/shared/normalisation.d.ts +1 -0
  41. package/@types/loot-core/shared/rules.d.ts +5 -1
  42. package/@types/loot-core/shared/schedules.d.ts +22 -22
  43. package/@types/loot-core/shared/transactions.d.ts +26 -75
  44. package/@types/loot-core/shared/util.d.ts +10 -13
  45. package/@types/loot-core/types/api-handlers.d.ts +29 -3
  46. package/@types/loot-core/types/file.d.ts +2 -0
  47. package/@types/loot-core/types/handlers.d.ts +2 -0
  48. package/@types/loot-core/types/models/category-group.d.ts +6 -2
  49. package/@types/loot-core/types/models/category.d.ts +4 -2
  50. package/@types/loot-core/types/models/dashboard.d.ts +56 -0
  51. package/@types/loot-core/types/models/index.d.ts +1 -0
  52. package/@types/loot-core/types/models/payee.d.ts +6 -7
  53. package/@types/loot-core/types/models/reports.d.ts +12 -5
  54. package/@types/loot-core/types/models/rule.d.ts +100 -7
  55. package/@types/loot-core/types/models/transaction.d.ts +12 -25
  56. package/@types/loot-core/types/prefs.d.ts +50 -26
  57. package/@types/loot-core/types/server-handlers.d.ts +13 -8
  58. package/@types/loot-core/types/util.d.ts +4 -0
  59. package/@types/methods.d.ts +8 -11
  60. package/@types/migrations/1722717601000_reports_move_selected_categories.d.ts +1 -0
  61. package/@types/migrations/1722804019000_create_dashboard_table.d.ts +1 -0
  62. package/dist/app/bundle.api.js +5544 -1857
  63. package/dist/app/query.js +1 -2
  64. package/dist/index.js +3 -3
  65. package/dist/injected.js +2 -2
  66. package/dist/methods.js +65 -41
  67. package/dist/methods.test.js +23 -15
  68. package/dist/migrations/1632571489012_remove_cache.js +1 -1
  69. package/dist/migrations/1720310586000_link_transfer_schedules.sql +19 -0
  70. package/dist/migrations/1720664867241_add_payee_favorite.sql +5 -0
  71. package/dist/migrations/1720665000000_goal_context.sql +6 -0
  72. package/dist/migrations/1722717601000_reports_move_selected_categories.js +39 -0
  73. package/dist/migrations/1722804019000_create_dashboard_table.js +38 -0
  74. package/dist/package.json +2 -2
  75. package/dist/utils.js +2 -3
  76. package/dist/validateNodeVersion.js +1 -2
  77. package/package.json +2 -2
package/dist/app/query.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.q = void 0;
3
+ exports.q = q;
4
4
  class Query {
5
5
  constructor(state) {
6
6
  this.state = {
@@ -86,4 +86,3 @@ class Query {
86
86
  function q(table) {
87
87
  return new Query({ table });
88
88
  }
89
- exports.q = q;
package/dist/index.js CHANGED
@@ -26,7 +26,9 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
26
26
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
27
27
  };
28
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
- exports.shutdown = exports.init = exports.utils = exports.methods = exports.internal = void 0;
29
+ exports.utils = exports.methods = exports.internal = void 0;
30
+ exports.init = init;
31
+ exports.shutdown = shutdown;
30
32
  // @ts-ignore: bundle not available until we build it
31
33
  // eslint-disable-next-line import/extensions
32
34
  const bundle = __importStar(require("./app/bundle.api.js"));
@@ -53,7 +55,6 @@ async function init(config = {}) {
53
55
  injected.override(bundle.lib.send);
54
56
  return bundle.lib;
55
57
  }
56
- exports.init = init;
57
58
  async function shutdown() {
58
59
  if (actualApp) {
59
60
  await actualApp.send('sync');
@@ -61,4 +62,3 @@ async function shutdown() {
61
62
  actualApp = null;
62
63
  }
63
64
  }
64
- exports.shutdown = shutdown;
package/dist/injected.js CHANGED
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  // TODO: comment on why it works this way
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.override = exports.send = void 0;
4
+ exports.send = void 0;
5
+ exports.override = override;
5
6
  function override(sendImplementation) {
6
7
  exports.send = sendImplementation;
7
8
  }
8
- exports.override = override;
package/dist/methods.js CHANGED
@@ -23,7 +23,52 @@ var __importStar = (this && this.__importStar) || function (mod) {
23
23
  return result;
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.deleteRule = exports.updateRule = exports.createRule = exports.getPayeeRules = exports.getRules = exports.deletePayee = exports.updatePayee = exports.createPayee = exports.getPayees = exports.deleteCategory = exports.updateCategory = exports.createCategory = exports.getCategories = exports.deleteCategoryGroup = exports.updateCategoryGroup = exports.createCategoryGroup = exports.getCategoryGroups = exports.deleteAccount = exports.reopenAccount = exports.closeAccount = exports.updateAccount = exports.createAccount = exports.getAccounts = exports.deleteTransaction = exports.updateTransaction = exports.getTransactions = exports.importTransactions = exports.addTransactions = exports.setBudgetCarryover = exports.setBudgetAmount = exports.getBudgetMonth = exports.getBudgetMonths = exports.runQuery = exports.batchBudgetUpdates = exports.runBankSync = exports.sync = exports.downloadBudget = exports.loadBudget = exports.runImport = exports.q = void 0;
26
+ exports.q = void 0;
27
+ exports.runImport = runImport;
28
+ exports.loadBudget = loadBudget;
29
+ exports.downloadBudget = downloadBudget;
30
+ exports.getBudgets = getBudgets;
31
+ exports.sync = sync;
32
+ exports.runBankSync = runBankSync;
33
+ exports.batchBudgetUpdates = batchBudgetUpdates;
34
+ exports.runQuery = runQuery;
35
+ exports.getBudgetMonths = getBudgetMonths;
36
+ exports.getBudgetMonth = getBudgetMonth;
37
+ exports.setBudgetAmount = setBudgetAmount;
38
+ exports.setBudgetCarryover = setBudgetCarryover;
39
+ exports.addTransactions = addTransactions;
40
+ exports.importTransactions = importTransactions;
41
+ exports.getTransactions = getTransactions;
42
+ exports.updateTransaction = updateTransaction;
43
+ exports.deleteTransaction = deleteTransaction;
44
+ exports.getAccounts = getAccounts;
45
+ exports.createAccount = createAccount;
46
+ exports.updateAccount = updateAccount;
47
+ exports.closeAccount = closeAccount;
48
+ exports.reopenAccount = reopenAccount;
49
+ exports.deleteAccount = deleteAccount;
50
+ exports.getAccountBalance = getAccountBalance;
51
+ exports.getCategoryGroups = getCategoryGroups;
52
+ exports.createCategoryGroup = createCategoryGroup;
53
+ exports.updateCategoryGroup = updateCategoryGroup;
54
+ exports.deleteCategoryGroup = deleteCategoryGroup;
55
+ exports.getCategories = getCategories;
56
+ exports.createCategory = createCategory;
57
+ exports.updateCategory = updateCategory;
58
+ exports.deleteCategory = deleteCategory;
59
+ exports.getCommonPayees = getCommonPayees;
60
+ exports.getPayees = getPayees;
61
+ exports.createPayee = createPayee;
62
+ exports.updatePayee = updatePayee;
63
+ exports.deletePayee = deletePayee;
64
+ exports.mergePayees = mergePayees;
65
+ exports.getRules = getRules;
66
+ exports.getPayeeRules = getPayeeRules;
67
+ exports.createRule = createRule;
68
+ exports.updateRule = updateRule;
69
+ exports.deleteRule = deleteRule;
70
+ exports.holdBudgetForNextMonth = holdBudgetForNextMonth;
71
+ exports.resetBudgetHold = resetBudgetHold;
27
72
  const injected = __importStar(require("./injected"));
28
73
  var query_1 = require("./app/query");
29
74
  Object.defineProperty(exports, "q", { enumerable: true, get: function () { return query_1.q; } });
@@ -41,23 +86,21 @@ async function runImport(name, func) {
41
86
  }
42
87
  await send('api/finish-import');
43
88
  }
44
- exports.runImport = runImport;
45
89
  async function loadBudget(budgetId) {
46
90
  return send('api/load-budget', { id: budgetId });
47
91
  }
48
- exports.loadBudget = loadBudget;
49
92
  async function downloadBudget(syncId, { password } = {}) {
50
93
  return send('api/download-budget', { syncId, password });
51
94
  }
52
- exports.downloadBudget = downloadBudget;
95
+ async function getBudgets() {
96
+ return send('api/get-budgets');
97
+ }
53
98
  async function sync() {
54
99
  return send('api/sync');
55
100
  }
56
- exports.sync = sync;
57
101
  async function runBankSync(args) {
58
102
  return send('api/bank-sync', args);
59
103
  }
60
- exports.runBankSync = runBankSync;
61
104
  async function batchBudgetUpdates(func) {
62
105
  await send('api/batch-budget-start');
63
106
  try {
@@ -67,27 +110,21 @@ async function batchBudgetUpdates(func) {
67
110
  await send('api/batch-budget-end');
68
111
  }
69
112
  }
70
- exports.batchBudgetUpdates = batchBudgetUpdates;
71
113
  function runQuery(query) {
72
114
  return send('api/query', { query: query.serialize() });
73
115
  }
74
- exports.runQuery = runQuery;
75
116
  function getBudgetMonths() {
76
117
  return send('api/budget-months');
77
118
  }
78
- exports.getBudgetMonths = getBudgetMonths;
79
119
  function getBudgetMonth(month) {
80
120
  return send('api/budget-month', { month });
81
121
  }
82
- exports.getBudgetMonth = getBudgetMonth;
83
122
  function setBudgetAmount(month, categoryId, value) {
84
123
  return send('api/budget-set-amount', { month, categoryId, amount: value });
85
124
  }
86
- exports.setBudgetAmount = setBudgetAmount;
87
125
  function setBudgetCarryover(month, categoryId, flag) {
88
126
  return send('api/budget-set-carryover', { month, categoryId, flag });
89
127
  }
90
- exports.setBudgetCarryover = setBudgetCarryover;
91
128
  function addTransactions(accountId, transactions, { learnCategories = false, runTransfers = false } = {}) {
92
129
  return send('api/transactions-add', {
93
130
  accountId,
@@ -96,35 +133,27 @@ function addTransactions(accountId, transactions, { learnCategories = false, run
96
133
  runTransfers,
97
134
  });
98
135
  }
99
- exports.addTransactions = addTransactions;
100
136
  function importTransactions(accountId, transactions) {
101
137
  return send('api/transactions-import', { accountId, transactions });
102
138
  }
103
- exports.importTransactions = importTransactions;
104
139
  function getTransactions(accountId, startDate, endDate) {
105
140
  return send('api/transactions-get', { accountId, startDate, endDate });
106
141
  }
107
- exports.getTransactions = getTransactions;
108
142
  function updateTransaction(id, fields) {
109
143
  return send('api/transaction-update', { id, fields });
110
144
  }
111
- exports.updateTransaction = updateTransaction;
112
145
  function deleteTransaction(id) {
113
146
  return send('api/transaction-delete', { id });
114
147
  }
115
- exports.deleteTransaction = deleteTransaction;
116
148
  function getAccounts() {
117
149
  return send('api/accounts-get');
118
150
  }
119
- exports.getAccounts = getAccounts;
120
151
  function createAccount(account, initialBalance) {
121
152
  return send('api/account-create', { account, initialBalance });
122
153
  }
123
- exports.createAccount = createAccount;
124
154
  function updateAccount(id, fields) {
125
155
  return send('api/account-update', { id, fields });
126
156
  }
127
- exports.updateAccount = updateAccount;
128
157
  function closeAccount(id, transferAccountId, transferCategoryId) {
129
158
  return send('api/account-close', {
130
159
  id,
@@ -132,80 +161,75 @@ function closeAccount(id, transferAccountId, transferCategoryId) {
132
161
  transferCategoryId,
133
162
  });
134
163
  }
135
- exports.closeAccount = closeAccount;
136
164
  function reopenAccount(id) {
137
165
  return send('api/account-reopen', { id });
138
166
  }
139
- exports.reopenAccount = reopenAccount;
140
167
  function deleteAccount(id) {
141
168
  return send('api/account-delete', { id });
142
169
  }
143
- exports.deleteAccount = deleteAccount;
170
+ function getAccountBalance(id, cutoff) {
171
+ return send('api/account-balance', { id, cutoff });
172
+ }
144
173
  function getCategoryGroups() {
145
174
  return send('api/category-groups-get');
146
175
  }
147
- exports.getCategoryGroups = getCategoryGroups;
148
176
  function createCategoryGroup(group) {
149
177
  return send('api/category-group-create', { group });
150
178
  }
151
- exports.createCategoryGroup = createCategoryGroup;
152
179
  function updateCategoryGroup(id, fields) {
153
180
  return send('api/category-group-update', { id, fields });
154
181
  }
155
- exports.updateCategoryGroup = updateCategoryGroup;
156
182
  function deleteCategoryGroup(id, transferCategoryId) {
157
183
  return send('api/category-group-delete', { id, transferCategoryId });
158
184
  }
159
- exports.deleteCategoryGroup = deleteCategoryGroup;
160
185
  function getCategories() {
161
186
  return send('api/categories-get', { grouped: false });
162
187
  }
163
- exports.getCategories = getCategories;
164
188
  function createCategory(category) {
165
189
  return send('api/category-create', { category });
166
190
  }
167
- exports.createCategory = createCategory;
168
191
  function updateCategory(id, fields) {
169
192
  return send('api/category-update', { id, fields });
170
193
  }
171
- exports.updateCategory = updateCategory;
172
194
  function deleteCategory(id, transferCategoryId) {
173
195
  return send('api/category-delete', { id, transferCategoryId });
174
196
  }
175
- exports.deleteCategory = deleteCategory;
197
+ function getCommonPayees() {
198
+ return send('api/common-payees-get');
199
+ }
176
200
  function getPayees() {
177
201
  return send('api/payees-get');
178
202
  }
179
- exports.getPayees = getPayees;
180
203
  function createPayee(payee) {
181
204
  return send('api/payee-create', { payee });
182
205
  }
183
- exports.createPayee = createPayee;
184
206
  function updatePayee(id, fields) {
185
207
  return send('api/payee-update', { id, fields });
186
208
  }
187
- exports.updatePayee = updatePayee;
188
209
  function deletePayee(id) {
189
210
  return send('api/payee-delete', { id });
190
211
  }
191
- exports.deletePayee = deletePayee;
212
+ function mergePayees(targetId, mergeIds) {
213
+ return send('api/payees-merge', { targetId, mergeIds });
214
+ }
192
215
  function getRules() {
193
216
  return send('api/rules-get');
194
217
  }
195
- exports.getRules = getRules;
196
218
  function getPayeeRules(id) {
197
219
  return send('api/payee-rules-get', { id });
198
220
  }
199
- exports.getPayeeRules = getPayeeRules;
200
221
  function createRule(rule) {
201
222
  return send('api/rule-create', { rule });
202
223
  }
203
- exports.createRule = createRule;
204
224
  function updateRule(rule) {
205
225
  return send('api/rule-update', { rule });
206
226
  }
207
- exports.updateRule = updateRule;
208
227
  function deleteRule(id) {
209
- return send('api/rule-delete', { id });
228
+ return send('api/rule-delete', id);
229
+ }
230
+ function holdBudgetForNextMonth(month, amount) {
231
+ return send('api/budget-hold-for-next-month', { month, amount });
232
+ }
233
+ function resetBudgetHold(month) {
234
+ return send('api/budget-reset-hold', { month });
210
235
  }
211
- exports.deleteRule = deleteRule;
@@ -61,6 +61,16 @@ describe('API CRUD operations', () => {
61
61
  // load test budget
62
62
  await api.loadBudget(budgetName);
63
63
  });
64
+ // api: getBudgets
65
+ test('getBudgets', async () => {
66
+ const budgets = await api.getBudgets();
67
+ expect(budgets).toEqual(expect.arrayContaining([
68
+ expect.objectContaining({
69
+ id: 'test-budget',
70
+ name: 'Default Test Db',
71
+ }),
72
+ ]));
73
+ });
64
74
  // apis: getCategoryGroups, createCategoryGroup, updateCategoryGroup, deleteCategoryGroup
65
75
  test('CategoryGroups: successfully update category groups', async () => {
66
76
  const month = '2023-10';
@@ -69,28 +79,22 @@ describe('API CRUD operations', () => {
69
79
  const groups = await api.getCategoryGroups();
70
80
  expect(groups).toEqual(expect.arrayContaining([
71
81
  expect.objectContaining({
72
- hidden: 0,
82
+ hidden: false,
73
83
  id: 'fc3825fd-b982-4b72-b768-5b30844cf832',
74
- is_income: 0,
84
+ is_income: false,
75
85
  name: 'Usual Expenses',
76
- sort_order: 16384,
77
- tombstone: 0,
78
86
  }),
79
87
  expect.objectContaining({
80
- hidden: 0,
88
+ hidden: false,
81
89
  id: 'a137772f-cf2f-4089-9432-822d2ddc1466',
82
- is_income: 0,
90
+ is_income: false,
83
91
  name: 'Investments and Savings',
84
- sort_order: 32768,
85
- tombstone: 0,
86
92
  }),
87
93
  expect.objectContaining({
88
- hidden: 0,
94
+ hidden: false,
89
95
  id: '2E1F5BDB-209B-43F9-AF2C-3CE28E380C00',
90
- is_income: 1,
96
+ is_income: true,
91
97
  name: 'Income',
92
- sort_order: 32768,
93
- tombstone: 0,
94
98
  }),
95
99
  ]));
96
100
  // create our test category group
@@ -218,7 +222,7 @@ describe('API CRUD operations', () => {
218
222
  }),
219
223
  ]));
220
224
  });
221
- //apis: createAccount, getAccounts, updateAccount, closeAccount, deleteAccount, reopenAccount
225
+ //apis: createAccount, getAccounts, updateAccount, closeAccount, deleteAccount, reopenAccount, getAccountBalance
222
226
  test('Accounts: successfully complete account operators', async () => {
223
227
  const accountId1 = await api.createAccount({ name: 'test-account1', offbudget: true }, 1000);
224
228
  const accountId2 = await api.createAccount({ name: 'test-account2' }, 0);
@@ -232,6 +236,8 @@ describe('API CRUD operations', () => {
232
236
  }),
233
237
  expect.objectContaining({ id: accountId2, name: 'test-account2' }),
234
238
  ]));
239
+ expect(await api.getAccountBalance(accountId1)).toEqual(1000);
240
+ expect(await api.getAccountBalance(accountId2)).toEqual(0);
235
241
  await api.updateAccount(accountId1, { offbudget: false });
236
242
  await api.closeAccount(accountId1, accountId2, null);
237
243
  await api.deleteAccount(accountId2);
@@ -476,9 +482,9 @@ describe('API CRUD operations', () => {
476
482
  }),
477
483
  ]));
478
484
  // delete rules
479
- await api.deleteRule(rules[1]);
485
+ await api.deleteRule(rules[1].id);
480
486
  expect(await api.getRules()).toHaveLength(1);
481
- await api.deleteRule(rules[0]);
487
+ await api.deleteRule(rules[0].id);
482
488
  expect(await api.getRules()).toHaveLength(0);
483
489
  });
484
490
  // apis: addTransactions, getTransactions, importTransactions, updateTransaction, deleteTransaction
@@ -493,6 +499,8 @@ describe('API CRUD operations', () => {
493
499
  runTransfers: true,
494
500
  });
495
501
  expect(addResult).toBe('ok');
502
+ expect(await api.getAccountBalance(accountId)).toEqual(200);
503
+ expect(await api.getAccountBalance(accountId, new Date(2023, 10, 2))).toEqual(0);
496
504
  // confirm added transactions exist
497
505
  let transactions = await api.getTransactions(accountId, '2023-11-01', '2023-11-30');
498
506
  expect(transactions).toEqual(expect.arrayContaining(newTransaction.map(trans => expect.objectContaining(trans))));
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = runMigration;
3
4
  async function runMigration(db) {
4
5
  function getValue(node) {
5
6
  return node.expr != null ? node.expr : node.cachedValue;
@@ -100,4 +101,3 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
100
101
  VACUUM;
101
102
  `);
102
103
  }
103
- exports.default = runMigration;
@@ -0,0 +1,19 @@
1
+ BEGIN TRANSACTION;
2
+
3
+ UPDATE transactions AS t1
4
+ SET schedule = (
5
+ SELECT t2.schedule FROM transactions AS t2
6
+ WHERE t2.id = t1.transferred_id
7
+ AND t2.schedule IS NOT NULL
8
+ LIMIT 1
9
+ )
10
+ WHERE t1.schedule IS NULL
11
+ AND t1.transferred_id IS NOT NULL
12
+ AND EXISTS (
13
+ SELECT 1 FROM transactions AS t2
14
+ WHERE t2.id = t1.transferred_id
15
+ AND t2.schedule IS NOT NULL
16
+ LIMIT 1
17
+ );
18
+
19
+ COMMIT;
@@ -0,0 +1,5 @@
1
+ BEGIN TRANSACTION;
2
+
3
+ ALTER TABLE payees ADD COLUMN favorite INTEGER DEFAULT 0 DEFAULT FALSE;
4
+
5
+ COMMIT;
@@ -0,0 +1,6 @@
1
+ BEGIN TRANSACTION;
2
+
3
+ ALTER TABLE zero_budgets ADD COLUMN long_goal INTEGER DEFAULT null;
4
+ ALTER TABLE reflect_budgets ADD COLUMN long_goal INTEGER DEFAULT null;
5
+
6
+ COMMIT;
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = runMigration;
4
+ async function runMigration(db) {
5
+ const categories = await db.runQuery('SELECT id FROM categories WHERE tombstone = 0', [], true);
6
+ const customReports = await db.runQuery('SELECT id, selected_categories, conditions FROM custom_reports WHERE tombstone = 0 AND selected_categories IS NOT NULL', [], true);
7
+ // Move all `selected_categories` to `conditions` if possible.. otherwise skip
8
+ for (const report of customReports) {
9
+ const conditions = report.conditions ? JSON.parse(report.conditions) : [];
10
+ const selectedCategories = report.selected_categories
11
+ ? JSON.parse(report.selected_categories)
12
+ : [];
13
+ const selectedCategoryIds = selectedCategories.map(({ id }) => id);
14
+ const areAllCategoriesSelected = !categories.find(({ id }) => !selectedCategoryIds.includes(id));
15
+ // Do nothing if all categories are selected.. we don't need to add a new condition for that
16
+ if (areAllCategoriesSelected) {
17
+ continue;
18
+ }
19
+ // If `conditions` already has a "category" filter - skip the entry
20
+ if (conditions.find(({ field }) => field === 'category')) {
21
+ continue;
22
+ }
23
+ // Append a new condition with the selected category IDs
24
+ await db.runQuery('UPDATE custom_reports SET conditions = ? WHERE id = ?', [
25
+ JSON.stringify([
26
+ ...conditions,
27
+ {
28
+ field: 'category',
29
+ op: 'oneOf',
30
+ value: selectedCategoryIds,
31
+ type: 'id',
32
+ },
33
+ ]),
34
+ report.id,
35
+ ]);
36
+ }
37
+ // Remove all the `selectedCategories` values - we don't need them anymore
38
+ await db.runQuery('UPDATE custom_reports SET selected_categories = NULL WHERE tombstone = 0');
39
+ }
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = runMigration;
4
+ const uuid_1 = require("uuid");
5
+ /* eslint-disable rulesdir/typography */
6
+ async function runMigration(db) {
7
+ db.transaction(() => {
8
+ db.execQuery(`
9
+ CREATE TABLE dashboard
10
+ (id TEXT PRIMARY KEY,
11
+ type TEXT,
12
+ width INTEGER,
13
+ height INTEGER,
14
+ x INTEGER,
15
+ y INTEGER,
16
+ meta TEXT,
17
+ tombstone INTEGER DEFAULT 0);
18
+
19
+ INSERT INTO dashboard (id, type, width, height, x, y)
20
+ VALUES
21
+ ('${(0, uuid_1.v4)()}','net-worth-card', 8, 2, 0, 0),
22
+ ('${(0, uuid_1.v4)()}', 'cash-flow-card', 4, 2, 8, 0);
23
+ `);
24
+ // Add custom reports to the dashboard
25
+ const reports = db.runQuery('SELECT id FROM custom_reports WHERE tombstone = 0 ORDER BY name COLLATE NOCASE ASC', [], true);
26
+ reports.forEach((report, id) => {
27
+ db.runQuery(`INSERT INTO dashboard (id, type, width, height, x, y, meta) VALUES (?, ?, ?, ?, ?, ?, ?)`, [
28
+ (0, uuid_1.v4)(),
29
+ 'custom-report',
30
+ 4,
31
+ 2,
32
+ (id * 4) % 12,
33
+ 2 + Math.floor(id / 3) * 2,
34
+ JSON.stringify({ id: report.id }),
35
+ ]);
36
+ });
37
+ });
38
+ }
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@actual-app/api",
3
- "version": "6.8.2",
3
+ "version": "6.10.0",
4
4
  "license": "MIT",
5
5
  "description": "An API for Actual",
6
6
  "engines": {
@@ -35,6 +35,6 @@
35
35
  "@types/uuid": "^9.0.2",
36
36
  "jest": "^27.5.1",
37
37
  "tsc-alias": "^1.8.8",
38
- "typescript": "^5.0.2"
38
+ "typescript": "^5.5.4"
39
39
  }
40
40
  }
package/dist/utils.js CHANGED
@@ -1,11 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.integerToAmount = exports.amountToInteger = void 0;
3
+ exports.amountToInteger = amountToInteger;
4
+ exports.integerToAmount = integerToAmount;
4
5
  function amountToInteger(n) {
5
6
  return Math.round(n * 100);
6
7
  }
7
- exports.amountToInteger = amountToInteger;
8
8
  function integerToAmount(n) {
9
9
  return parseFloat((n / 100).toFixed(2));
10
10
  }
11
- exports.integerToAmount = integerToAmount;
@@ -23,7 +23,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
23
23
  return result;
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.validateNodeVersion = void 0;
26
+ exports.validateNodeVersion = validateNodeVersion;
27
27
  const compare_versions_1 = require("compare-versions");
28
28
  const packageJson = __importStar(require("./package.json"));
29
29
  function validateNodeVersion() {
@@ -35,4 +35,3 @@ function validateNodeVersion() {
35
35
  }
36
36
  }
37
37
  }
38
- exports.validateNodeVersion = validateNodeVersion;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@actual-app/api",
3
- "version": "6.8.2",
3
+ "version": "6.10.0",
4
4
  "license": "MIT",
5
5
  "description": "An API for Actual",
6
6
  "engines": {
@@ -35,6 +35,6 @@
35
35
  "@types/uuid": "^9.0.2",
36
36
  "jest": "^27.5.1",
37
37
  "tsc-alias": "^1.8.8",
38
- "typescript": "^5.0.2"
38
+ "typescript": "^5.5.4"
39
39
  }
40
40
  }