@actual-app/api 6.8.1 → 6.8.2

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.
@@ -4,6 +4,7 @@ import type {
4
4
  CategoryEntity,
5
5
  CategoryGroupEntity,
6
6
  GoCardlessToken,
7
+ TransactionEntity,
7
8
  } from '../../types/models';
8
9
  import type { NewRuleEntity, RuleEntity } from '../../types/models/rule';
9
10
  import type { EmptyObject, StripNever } from '../../types/util';
@@ -121,7 +122,7 @@ type FinanceModals = {
121
122
  month: string;
122
123
  };
123
124
 
124
- 'schedule-edit': { id: string } | null;
125
+ 'schedule-edit': { id: string; transaction?: TransactionEntity } | null;
125
126
 
126
127
  'schedule-link': { transactionIds: string[] } | null;
127
128
 
@@ -201,6 +202,7 @@ type FinanceModals = {
201
202
  'rollover-summary-to-budget-menu': {
202
203
  month: string;
203
204
  onTransfer: () => void;
205
+ onCover: () => void;
204
206
  onHoldBuffer: () => void;
205
207
  onResetHoldBuffer: () => void;
206
208
  };
@@ -217,8 +219,9 @@ type FinanceModals = {
217
219
  showToBeBudgeted?: boolean;
218
220
  };
219
221
  cover: {
220
- categoryId: string;
222
+ title: string;
221
223
  month: string;
224
+ showToBeBudgeted?: boolean;
222
225
  onSubmit: (fromCategoryId: string) => void;
223
226
  };
224
227
  'hold-buffer': {
@@ -1,10 +1,10 @@
1
- import { type Database } from 'better-sqlite3';
1
+ import { type Database } from '@jlongster/sql.js';
2
2
 
3
- export async function init(): unknown;
3
+ export async function init(): Promise<void>;
4
4
 
5
5
  export function _getModule(): SqlJsStatic;
6
6
 
7
- export function prepare(db, sql): unknown;
7
+ export function prepare(db: Database, sql: string): string;
8
8
 
9
9
  export function runQuery(
10
10
  db: Database,
@@ -1,20 +1,8 @@
1
- import { TransactionEntity } from '../../types/models';
1
+ import { NewTransactionEntity, TransactionEntity } from '../../types/models';
2
2
  export declare function batchUpdateTransactions({ added, deleted, updated, learnCategories, detectOrphanPayees, runTransfers, }: {
3
- added?: Array<{
4
- id: string;
5
- payee: unknown;
6
- category: unknown;
7
- }>;
8
- deleted?: Array<{
9
- id: string;
10
- payee: unknown;
11
- }>;
12
- updated?: Array<{
13
- id: string;
14
- payee?: unknown;
15
- account?: unknown;
16
- category?: unknown;
17
- }>;
3
+ added?: Array<Partial<NewTransactionEntity | TransactionEntity>>;
4
+ deleted?: Array<Partial<NewTransactionEntity | TransactionEntity>>;
5
+ updated?: Array<Partial<NewTransactionEntity | TransactionEntity>>;
18
6
  learnCategories?: boolean;
19
7
  detectOrphanPayees?: boolean;
20
8
  runTransfers?: boolean;
@@ -271,6 +271,9 @@ export declare const schema: {
271
271
  show_uncategorized: {
272
272
  type: string;
273
273
  };
274
+ include_current: {
275
+ type: string;
276
+ };
274
277
  selected_categories: {
275
278
  type: string;
276
279
  };
@@ -50,6 +50,10 @@ export declare function transferAvailable({ month, amount, category, }: {
50
50
  amount: number;
51
51
  category: string;
52
52
  }): Promise<void>;
53
+ export declare function coverOverbudgeted({ month, category, }: {
54
+ month: string;
55
+ category: string;
56
+ }): Promise<void>;
53
57
  export declare function transferCategory({ month, amount, from, to, }: {
54
58
  month: string;
55
59
  amount: number;
@@ -4,7 +4,7 @@ export declare const app: {
4
4
  handlers: BudgetHandlers;
5
5
  services: any;
6
6
  unlistenServices: any;
7
- method<Name extends "budget/budget-amount" | "budget/copy-previous-month" | "budget/set-zero" | "budget/set-3month-avg" | "budget/check-templates" | "budget/apply-goal-template" | "budget/overwrite-goal-template" | "budget/cleanup-goal-template" | "budget/hold-for-next-month" | "budget/reset-hold" | "budget/cover-overspending" | "budget/transfer-available" | "budget/transfer-category" | "budget/set-carryover" | "budget/apply-single-template" | "budget/set-n-month-avg" | "budget/copy-single-month">(name: Name, func: BudgetHandlers[Name]): void;
7
+ method<Name extends "budget/budget-amount" | "budget/copy-previous-month" | "budget/set-zero" | "budget/set-3month-avg" | "budget/check-templates" | "budget/apply-goal-template" | "budget/overwrite-goal-template" | "budget/cleanup-goal-template" | "budget/hold-for-next-month" | "budget/reset-hold" | "budget/cover-overspending" | "budget/transfer-available" | "budget/cover-overbudgeted" | "budget/transfer-category" | "budget/set-carryover" | "budget/apply-single-template" | "budget/set-n-month-avg" | "budget/copy-single-month">(name: Name, func: BudgetHandlers[Name]): void;
8
8
  service(func: any): void;
9
9
  combine(...apps: any[]): void;
10
10
  startServices(): void;
@@ -46,6 +46,11 @@ export interface BudgetHandlers {
46
46
  category: string;
47
47
  }) => Promise<void>;
48
48
 
49
+ 'budget/cover-overbudgeted': (arg: {
50
+ month: string;
51
+ category: string;
52
+ }) => Promise<void>;
53
+
49
54
  'budget/transfer-category': (arg: {
50
55
  month: string;
51
56
  amount: number;
@@ -1,16 +1,56 @@
1
+ import { Database } from '@jlongster/sql.js';
1
2
  import { CategoryEntity, CategoryGroupEntity } from '../../types/models';
2
3
  export { toDateRepr, fromDateRepr } from '../models';
3
- export declare function getDatabasePath(): any;
4
- export declare function openDatabase(id?: any): Promise<void>;
5
- export declare function reopenDatabase(): Promise<void>;
4
+ export declare function getDatabasePath(): string;
5
+ export declare function openDatabase(id?: string): Promise<void>;
6
6
  export declare function closeDatabase(): Promise<void>;
7
- export declare function setDatabase(db_: any): void;
8
- export declare function getDatabase(): any;
7
+ export declare function setDatabase(db_: Database): void;
8
+ export declare function getDatabase(): {
9
+ close(): void;
10
+ create_function(name: string, func: (...args: any[]) => any): any;
11
+ each(sql: string, params: import("@jlongster/sql.js").BindParams, callback: import("@jlongster/sql.js").ParamsCallback, done: () => void): any;
12
+ each(sql: string, callback: import("@jlongster/sql.js").ParamsCallback, done: () => void): any;
13
+ exec(sql: string, params?: import("@jlongster/sql.js").BindParams): import("@jlongster/sql.js").QueryExecResult[];
14
+ export(): Uint8Array;
15
+ getRowsModified(): number;
16
+ handleError(): null;
17
+ iterateStatements(sql: string): {
18
+ getRemainingSql(): string;
19
+ next(): import("@jlongster/sql.js").StatementIteratorResult;
20
+ [Symbol.iterator](): Iterator<{
21
+ bind(values?: import("@jlongster/sql.js").BindParams): boolean;
22
+ free(): boolean;
23
+ freemem(): void;
24
+ get(params?: import("@jlongster/sql.js").BindParams): import("@jlongster/sql.js").SqlValue[];
25
+ getAsObject(params?: import("@jlongster/sql.js").BindParams): import("@jlongster/sql.js").ParamsObject;
26
+ getColumnNames(): string[];
27
+ getNormalizedSQL(): string;
28
+ getSQL(): string;
29
+ reset(): void;
30
+ run(values?: import("@jlongster/sql.js").BindParams): void;
31
+ step(): boolean;
32
+ }, any, undefined>;
33
+ };
34
+ prepare(sql: string, params?: import("@jlongster/sql.js").BindParams): {
35
+ bind(values?: import("@jlongster/sql.js").BindParams): boolean;
36
+ free(): boolean;
37
+ freemem(): void;
38
+ get(params?: import("@jlongster/sql.js").BindParams): import("@jlongster/sql.js").SqlValue[];
39
+ getAsObject(params?: import("@jlongster/sql.js").BindParams): import("@jlongster/sql.js").ParamsObject;
40
+ getColumnNames(): string[];
41
+ getNormalizedSQL(): string;
42
+ getSQL(): string;
43
+ reset(): void;
44
+ run(values?: import("@jlongster/sql.js").BindParams): void;
45
+ step(): boolean;
46
+ };
47
+ run(sql: string, params?: import("@jlongster/sql.js").BindParams): any;
48
+ };
9
49
  export declare function loadClock(): Promise<void>;
10
50
  export declare function runQuery(sql: string, params?: Array<string | number>, fetchAll?: false): any;
11
51
  export declare function runQuery(sql: string, params: Array<string | number> | undefined, fetchAll: true): any;
12
- export declare function execQuery(sql: any): void;
13
- export declare function cache(sql: any): any;
52
+ export declare function execQuery(sql: string): void;
53
+ export declare function cache(sql: string): any;
14
54
  export declare function transaction(fn: () => void): void;
15
55
  export declare function asyncTransaction(fn: () => Promise<void>): Promise<void>;
16
56
  export declare function all(sql: any, params?: (string | number)[]): Promise<any>;
@@ -4,7 +4,7 @@ export declare const app: {
4
4
  handlers: Handlers;
5
5
  services: any;
6
6
  unlistenServices: any;
7
- method<Name extends "transaction-update" | "undo" | "redo" | "transactions-batch-update" | "transaction-add" | "transaction-delete" | "transactions-parse-file" | "transactions-export" | "transactions-export-query" | "get-categories" | "get-earliest-transaction" | "get-budget-bounds" | "rollover-budget-month" | "report-budget-month" | "budget-set-type" | "category-create" | "category-update" | "category-move" | "category-delete" | "category-group-create" | "category-group-update" | "category-group-move" | "category-group-delete" | "must-category-transfer" | "payee-create" | "payees-get" | "payees-get-rule-counts" | "payees-merge" | "payees-batch-change" | "payees-check-orphaned" | "payees-get-rules" | "make-filters-from-conditions" | "getCell" | "getCells" | "getCellNamesInSheet" | "debugCell" | "create-query" | "query" | "account-update" | "accounts-get" | "account-properties" | "gocardless-accounts-link" | "simplefin-accounts-link" | "account-create" | "account-close" | "account-reopen" | "account-move" | "secret-set" | "secret-check" | "gocardless-poll-web-token" | "gocardless-status" | "simplefin-status" | "simplefin-accounts" | "gocardless-get-banks" | "gocardless-poll-web-token-stop" | "gocardless-create-web-token" | "accounts-bank-sync" | "transactions-import" | "account-unlink" | "save-global-prefs" | "load-global-prefs" | "save-prefs" | "load-prefs" | "sync-reset" | "sync-repair" | "key-make" | "key-test" | "get-did-bootstrap" | "subscribe-needs-bootstrap" | "subscribe-bootstrap" | "subscribe-get-user" | "subscribe-change-password" | "subscribe-sign-in" | "subscribe-sign-out" | "get-server-version" | "get-server-url" | "set-server-url" | "sync" | "get-budgets" | "get-remote-files" | "reset-budget-cache" | "upload-budget" | "download-budget" | "sync-budget" | "load-budget" | "create-demo-budget" | "close-budget" | "delete-budget" | "create-budget" | "import-budget" | "export-budget" | "upload-file-web" | "backups-get" | "backup-load" | "backup-make" | "get-last-opened-backup" | "app-focused" | "api/batch-budget-start" | "api/batch-budget-end" | "api/load-budget" | "api/download-budget" | "api/start-import" | "api/finish-import" | "api/abort-import" | "api/query" | "api/budget-months" | "api/budget-month" | "api/budget-set-amount" | "api/budget-set-carryover" | "api/transactions-export" | "api/transactions-import" | "api/transactions-add" | "api/transactions-get" | "api/transaction-update" | "api/transaction-delete" | "api/sync" | "api/bank-sync" | "api/accounts-get" | "api/account-create" | "api/account-update" | "api/account-close" | "api/account-reopen" | "api/account-delete" | "api/categories-get" | "api/category-groups-get" | "api/category-group-create" | "api/category-group-update" | "api/category-group-delete" | "api/category-create" | "api/category-update" | "api/category-delete" | "api/payees-get" | "api/payee-create" | "api/payee-update" | "api/payee-delete" | "api/rules-get" | "api/payee-rules-get" | "api/rule-create" | "api/rule-update" | "api/rule-delete" | "budget/budget-amount" | "budget/copy-previous-month" | "budget/set-zero" | "budget/set-3month-avg" | "budget/check-templates" | "budget/apply-goal-template" | "budget/overwrite-goal-template" | "budget/cleanup-goal-template" | "budget/hold-for-next-month" | "budget/reset-hold" | "budget/cover-overspending" | "budget/transfer-available" | "budget/transfer-category" | "budget/set-carryover" | "budget/apply-single-template" | "budget/set-n-month-avg" | "budget/copy-single-month" | "filter-create" | "filter-update" | "filter-delete" | "notes-save" | "report/create" | "report/update" | "report/delete" | "rule-validate" | "rule-add" | "rule-update" | "rule-delete" | "rule-delete-all" | "rule-apply-actions" | "rule-add-payee-rename" | "rules-get" | "rule-get" | "rules-run" | "schedule/create" | "schedule/update" | "schedule/delete" | "schedule/skip-next-date" | "schedule/post-transaction" | "schedule/force-run-service" | "schedule/discover" | "schedule/get-upcoming-dates" | "tools/fix-split-transactions">(name: Name, func: Handlers[Name]): void;
7
+ method<Name extends "transaction-update" | "undo" | "redo" | "transactions-batch-update" | "transaction-add" | "transaction-delete" | "transactions-parse-file" | "transactions-export" | "transactions-export-query" | "get-categories" | "get-earliest-transaction" | "get-budget-bounds" | "rollover-budget-month" | "report-budget-month" | "budget-set-type" | "category-create" | "category-update" | "category-move" | "category-delete" | "category-group-create" | "category-group-update" | "category-group-move" | "category-group-delete" | "must-category-transfer" | "payee-create" | "payees-get" | "payees-get-rule-counts" | "payees-merge" | "payees-batch-change" | "payees-check-orphaned" | "payees-get-rules" | "make-filters-from-conditions" | "getCell" | "getCells" | "getCellNamesInSheet" | "debugCell" | "create-query" | "query" | "account-update" | "accounts-get" | "account-properties" | "gocardless-accounts-link" | "simplefin-accounts-link" | "account-create" | "account-close" | "account-reopen" | "account-move" | "secret-set" | "secret-check" | "gocardless-poll-web-token" | "gocardless-status" | "simplefin-status" | "simplefin-accounts" | "gocardless-get-banks" | "gocardless-poll-web-token-stop" | "gocardless-create-web-token" | "accounts-bank-sync" | "transactions-import" | "account-unlink" | "save-global-prefs" | "load-global-prefs" | "save-prefs" | "load-prefs" | "sync-reset" | "sync-repair" | "key-make" | "key-test" | "get-did-bootstrap" | "subscribe-needs-bootstrap" | "subscribe-bootstrap" | "subscribe-get-user" | "subscribe-change-password" | "subscribe-sign-in" | "subscribe-sign-out" | "get-server-version" | "get-server-url" | "set-server-url" | "sync" | "get-budgets" | "get-remote-files" | "reset-budget-cache" | "upload-budget" | "download-budget" | "sync-budget" | "load-budget" | "create-demo-budget" | "close-budget" | "delete-budget" | "create-budget" | "import-budget" | "export-budget" | "upload-file-web" | "backups-get" | "backup-load" | "backup-make" | "get-last-opened-backup" | "app-focused" | "api/batch-budget-start" | "api/batch-budget-end" | "api/load-budget" | "api/download-budget" | "api/start-import" | "api/finish-import" | "api/abort-import" | "api/query" | "api/budget-months" | "api/budget-month" | "api/budget-set-amount" | "api/budget-set-carryover" | "api/transactions-export" | "api/transactions-import" | "api/transactions-add" | "api/transactions-get" | "api/transaction-update" | "api/transaction-delete" | "api/sync" | "api/bank-sync" | "api/accounts-get" | "api/account-create" | "api/account-update" | "api/account-close" | "api/account-reopen" | "api/account-delete" | "api/categories-get" | "api/category-groups-get" | "api/category-group-create" | "api/category-group-update" | "api/category-group-delete" | "api/category-create" | "api/category-update" | "api/category-delete" | "api/payees-get" | "api/payee-create" | "api/payee-update" | "api/payee-delete" | "api/rules-get" | "api/payee-rules-get" | "api/rule-create" | "api/rule-update" | "api/rule-delete" | "budget/budget-amount" | "budget/copy-previous-month" | "budget/set-zero" | "budget/set-3month-avg" | "budget/check-templates" | "budget/apply-goal-template" | "budget/overwrite-goal-template" | "budget/cleanup-goal-template" | "budget/hold-for-next-month" | "budget/reset-hold" | "budget/cover-overspending" | "budget/transfer-available" | "budget/cover-overbudgeted" | "budget/transfer-category" | "budget/set-carryover" | "budget/apply-single-template" | "budget/set-n-month-avg" | "budget/copy-single-month" | "filter-create" | "filter-update" | "filter-delete" | "notes-save" | "report/create" | "report/update" | "report/delete" | "rule-validate" | "rule-add" | "rule-update" | "rule-delete" | "rule-delete-all" | "rule-apply-actions" | "rule-add-payee-rename" | "rules-get" | "rule-get" | "rules-run" | "schedule/create" | "schedule/update" | "schedule/delete" | "schedule/skip-next-date" | "schedule/post-transaction" | "schedule/force-run-service" | "schedule/discover" | "schedule/get-upcoming-dates" | "tools/fix-split-transactions">(name: Name, func: Handlers[Name]): void;
8
8
  service(func: any): void;
9
9
  combine(...apps: any[]): void;
10
10
  startServices(): void;
@@ -1,4 +1,4 @@
1
- import { Database } from 'better-sqlite3';
1
+ import { Database } from '@jlongster/sql.js';
2
2
  export declare function withMigrationsDir(dir: string, func: () => Promise<void>): Promise<void>;
3
3
  export declare function getMigrationsDir(): string;
4
4
  export declare function getUpMigration(id: any, names: any): any;
@@ -1,3 +1,3 @@
1
- export declare function post(url: any, data: any, headers?: {}): Promise<any>;
1
+ export declare function post(url: any, data: any, headers?: {}, timeout?: any): Promise<any>;
2
2
  export declare function postBinary(url: any, data: any, headers: any): Promise<any>;
3
3
  export declare function get(url: any, opts?: any): Promise<string>;
@@ -31,7 +31,7 @@ export declare const ALLOCATION_METHODS: {
31
31
  remainder: string;
32
32
  };
33
33
  export declare function mapField(field: any, opts?: any): any;
34
- export declare function friendlyOp(op: any, type?: any): "" | "is" | "contains" | "one of" | "not one of" | "is not" | "is approx" | "is between" | "does not contain" | "is after" | "is greater than" | "is after or equals" | "is greater than or equals" | "is before" | "is less than" | "is before or equals" | "is less than or equals" | "is true" | "is false" | "set" | "allocate" | "link schedule" | "and" | "or";
34
+ export declare function friendlyOp(op: any, type?: any): "" | "is" | "contains" | "matches" | "one of" | "not one of" | "is not" | "is approx" | "is between" | "does not contain" | "is after" | "is greater than" | "is after or equals" | "is greater than or equals" | "is before" | "is less than" | "is before or equals" | "is less than or equals" | "is true" | "is false" | "set" | "allocate" | "link schedule" | "and" | "or";
35
35
  export declare function deserializeField(field: any): {
36
36
  field: string;
37
37
  options: {
@@ -88,4 +88,29 @@ export declare function realizeTempTransactions(transactions: TransactionEntity[
88
88
  starting_balance_flag?: boolean;
89
89
  transfer_id?: string;
90
90
  }[];
91
+ export declare function makeAsNonChildTransactions(childTransactionsToUpdate: TransactionEntity[], transactions: TransactionEntity[]): {
92
+ updated: TransactionEntity[];
93
+ deleted: {
94
+ amount: number;
95
+ id: string;
96
+ account: import("../types/models").AccountEntity;
97
+ category?: import("../types/models").CategoryEntity;
98
+ payee?: import("../types/models").PayeeEntity;
99
+ schedule?: import("../types/models").ScheduleEntity;
100
+ subtransactions?: TransactionEntity[];
101
+ sort_order?: number;
102
+ tombstone?: boolean;
103
+ imported_payee?: string;
104
+ date: string;
105
+ notes?: string;
106
+ cleared?: boolean;
107
+ reconciled?: boolean;
108
+ is_parent?: boolean;
109
+ is_child?: boolean;
110
+ parent_id?: string;
111
+ imported_id?: string;
112
+ starting_balance_flag?: boolean;
113
+ transfer_id?: string;
114
+ }[];
115
+ };
91
116
  export {};
@@ -15,6 +15,7 @@ export interface CustomReportEntity {
15
15
  showEmpty: boolean;
16
16
  showOffBudget: boolean;
17
17
  showHiddenCategories: boolean;
18
+ includeCurrentInterval: boolean;
18
19
  showUncategorized: boolean;
19
20
  selectedCategories?: CategoryEntity[];
20
21
  graphType: string;
@@ -24,6 +25,13 @@ export interface CustomReportEntity {
24
25
  tombstone?: boolean;
25
26
  }
26
27
 
28
+ export type balanceTypeOpType =
29
+ | 'totalAssets'
30
+ | 'totalDebts'
31
+ | 'totalTotals'
32
+ | 'netAssets'
33
+ | 'netDebts';
34
+
27
35
  export type SpendingMonthEntity = Record<
28
36
  string | number,
29
37
  {
@@ -49,6 +57,7 @@ export interface SpendingEntity {
49
57
  average: number;
50
58
  thisMonth: number;
51
59
  lastMonth: number;
60
+ lastYear: number;
52
61
  }[];
53
62
  startDate?: string;
54
63
  endDate?: string;
@@ -66,6 +75,8 @@ export interface DataEntity {
66
75
  endDate?: string;
67
76
  totalDebts: number;
68
77
  totalAssets: number;
78
+ netAssets: number;
79
+ netDebts: number;
69
80
  totalTotals: number;
70
81
  }
71
82
 
@@ -82,6 +93,8 @@ export type IntervalEntity = {
82
93
  intervalEndDate?: string;
83
94
  totalAssets: number;
84
95
  totalDebts: number;
96
+ netAssets: number;
97
+ netDebts: number;
85
98
  totalTotals: number;
86
99
  };
87
100
 
@@ -93,6 +106,8 @@ export interface GroupedEntity {
93
106
  totalAssets: number;
94
107
  totalDebts: number;
95
108
  totalTotals: number;
109
+ netAssets: number;
110
+ netDebts: number;
96
111
  categories?: GroupedEntity[];
97
112
  }
98
113
 
@@ -113,6 +128,7 @@ export interface CustomReportData {
113
128
  show_empty: number;
114
129
  show_offbudget: number;
115
130
  show_hidden: number;
131
+ include_current: number;
116
132
  show_uncategorized: number;
117
133
  selected_categories?: CategoryEntity[];
118
134
  graph_type: string;
@@ -24,7 +24,8 @@ export type RuleConditionOp =
24
24
  | 'lt'
25
25
  | 'lte'
26
26
  | 'contains'
27
- | 'doesNotContain';
27
+ | 'doesNotContain'
28
+ | 'matches';
28
29
 
29
30
  export interface RuleConditionEntity {
30
31
  field?: string;
@@ -3,9 +3,9 @@ import { type numberFormats } from '../shared/util';
3
3
  export type FeatureFlag =
4
4
  | 'reportBudget'
5
5
  | 'goalTemplatesEnabled'
6
- | 'customReports'
7
6
  | 'spendingReport'
8
- | 'simpleFinSync';
7
+ | 'simpleFinSync'
8
+ | 'iterableTopologicalSort';
9
9
 
10
10
  export type LocalPrefs = Partial<
11
11
  {
@@ -32,7 +32,7 @@ export interface ServerHandlers {
32
32
  Parameters<typeof batchUpdateTransactions>[0],
33
33
  'detectOrphanPayees'
34
34
  >,
35
- ) => Promise<Awaited<ReturnType<typeof batchUpdateTransactions>>['updated']>;
35
+ ) => Promise<Awaited<ReturnType<typeof batchUpdateTransactions>>>;
36
36
 
37
37
  'transaction-add': (transaction) => Promise<EmptyObject>;
38
38
 
@@ -25745,6 +25745,9 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
25745
25745
  }
25746
25746
  }
25747
25747
  }
25748
+ function regexp(regex, text) {
25749
+ return new RegExp(regex).test(text) ? 1 : 0;
25750
+ }
25748
25751
  function openDatabase(pathOrBuffer) {
25749
25752
  const db = new (better_sqlite3__WEBPACK_IMPORTED_MODULE_0___default())(pathOrBuffer);
25750
25753
  // Define Unicode-aware LOWER and UPPER implementation.
@@ -25757,6 +25760,10 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
25757
25760
  db.function('UNICODE_UPPER', {
25758
25761
  deterministic: true
25759
25762
  }, (arg) => arg?.toUpperCase());
25763
+ // @ts-expect-error @types/better-sqlite3 does not support setting strict 3rd argument
25764
+ db.function('REGEXP', {
25765
+ deterministic: true
25766
+ }, regexp);
25760
25767
  return db;
25761
25768
  }
25762
25769
  function closeDatabase(db) {
@@ -26480,6 +26487,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
26480
26487
  ops: [
26481
26488
  'is',
26482
26489
  'contains',
26490
+ 'matches',
26483
26491
  'oneOf',
26484
26492
  'isNot',
26485
26493
  'doesNotContain',
@@ -26498,6 +26506,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
26498
26506
  ops: [
26499
26507
  'is',
26500
26508
  'contains',
26509
+ 'matches',
26501
26510
  'oneOf',
26502
26511
  'isNot',
26503
26512
  'doesNotContain',
@@ -26509,7 +26518,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
26509
26518
  assert(Array.isArray(value), 'no-empty-array', `oneOf must have an array value (field: ${fieldName}): ${JSON.stringify(value)}`);
26510
26519
  return value.filter(Boolean).map((val) => val.toLowerCase());
26511
26520
  }
26512
- if (op === 'contains' || op === 'doesNotContain') {
26521
+ if (op === 'contains' || op === 'matches' || op === 'doesNotContain') {
26513
26522
  assert(typeof value === 'string' && value.length > 0, 'no-empty-string', `contains must have non-empty string (field: ${fieldName})`);
26514
26523
  }
26515
26524
  return value.toLowerCase();
@@ -27008,7 +27017,8 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
27008
27017
  lt: 1,
27009
27018
  lte: 1,
27010
27019
  contains: 0,
27011
- doesNotContain: 0
27020
+ doesNotContain: 0,
27021
+ matches: 0
27012
27022
  };
27013
27023
  function computeScore(rule) {
27014
27024
  const initialScore = rule.conditions.reduce((score, condition) => {
@@ -27298,7 +27308,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
27298
27308
  startDate: since
27299
27309
  }, {
27300
27310
  'X-ACTUAL-TOKEN': userToken
27301
- });
27311
+ }, 60000);
27302
27312
  if (res.error_code) {
27303
27313
  throw BankSyncError(res.error_type, res.error_code);
27304
27314
  }
@@ -27487,14 +27497,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
27487
27497
  // matched transaction. See the final pass below for the needed
27488
27498
  // fields.
27489
27499
  fuzzyDataset = await _db__WEBPACK_IMPORTED_MODULE_4__.all(`SELECT id, is_parent, date, imported_id, payee, category, notes, reconciled FROM v_transactions
27490
- WHERE
27491
- -- If both ids are set, and we didn't match earlier then skip dedup
27492
- ( imported_id IS NULL OR ? IS NULL )
27493
- -- Look 7 days ahead, 7 days behind
27494
- AND date >= ? AND date <= ? AND amount = ?
27495
- AND account = ?
27496
- `, [
27497
- trans.imported_id || null,
27500
+ WHERE date >= ? AND date <= ? AND amount = ? AND account = ?`, [
27498
27501
  _db__WEBPACK_IMPORTED_MODULE_4__.toDateRepr(_shared_months__WEBPACK_IMPORTED_MODULE_1__.subDays(trans.date, 7)),
27499
27502
  _db__WEBPACK_IMPORTED_MODULE_4__.toDateRepr(_shared_months__WEBPACK_IMPORTED_MODULE_1__.addDays(trans.date, 7)),
27500
27503
  trans.amount || 0,
@@ -28466,6 +28469,10 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
28466
28469
  // Running contains with id will automatically reach into
28467
28470
  // the `name` of the referenced table and do a string match
28468
28471
  return apply(type === 'id' ? field + '.name' : field, '$like', '%' + value + '%');
28472
+ case 'matches':
28473
+ // Running contains with id will automatically reach into
28474
+ // the `name` of the referenced table and do a regex match
28475
+ return apply(type === 'id' ? field + '.name' : field, '$regexp', value);
28469
28476
  case 'doesNotContain':
28470
28477
  // Running contains with id will automatically reach into
28471
28478
  // the `name` of the referenced table and do a string match
@@ -30692,6 +30699,17 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
30692
30699
  ]);
30693
30700
  return `${left} LIKE ${right}`;
30694
30701
  }
30702
+ case '$regexp':
30703
+ {
30704
+ const [left, right] = valArray(state, [
30705
+ lhs,
30706
+ rhs
30707
+ ], [
30708
+ 'string',
30709
+ 'string'
30710
+ ]);
30711
+ return `REGEXP(${right}, ${left})`;
30712
+ }
30695
30713
  case '$notlike':
30696
30714
  {
30697
30715
  const [left, right] = valArray(state, [
@@ -31746,6 +31764,9 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
31746
31764
  show_uncategorized: f('integer', {
31747
31765
  default: 0
31748
31766
  }),
31767
+ include_current: f('integer', {
31768
+ default: 0
31769
+ }),
31749
31770
  selected_categories: f('json'),
31750
31771
  graph_type: f('string', {
31751
31772
  default: 'BarGraph'
@@ -32283,6 +32304,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
32283
32304
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
32284
32305
  /* harmony export */ copyPreviousMonth: () => ( /* binding */copyPreviousMonth),
32285
32306
  /* harmony export */ copySinglePreviousMonth: () => ( /* binding */copySinglePreviousMonth),
32307
+ /* harmony export */ coverOverbudgeted: () => ( /* binding */coverOverbudgeted),
32286
32308
  /* harmony export */ coverOverspending: () => ( /* binding */coverOverspending),
32287
32309
  /* harmony export */ getBudget: () => ( /* binding */getBudget),
32288
32310
  /* harmony export */ getSheetValue: () => ( /* binding */getSheetValue),
@@ -32487,16 +32509,22 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
32487
32509
  const spent1 = await getSheetValue(_shared_months__WEBPACK_IMPORTED_MODULE_0__.sheetForMonth(prevMonth1), 'sum-amount-' + cat.id);
32488
32510
  const spent2 = await getSheetValue(_shared_months__WEBPACK_IMPORTED_MODULE_0__.sheetForMonth(prevMonth2), 'sum-amount-' + cat.id);
32489
32511
  const spent3 = await getSheetValue(_shared_months__WEBPACK_IMPORTED_MODULE_0__.sheetForMonth(prevMonth3), 'sum-amount-' + cat.id);
32490
- const avg = Math.round((spent1 + spent2 + spent3) / 3);
32512
+ let avg = Math.round((spent1 + spent2 + spent3) / 3);
32513
+ if (cat.is_income === 0) {
32514
+ avg *= -1;
32515
+ }
32491
32516
  setBudget({
32492
32517
  category: cat.id,
32493
32518
  month,
32494
- amount: -avg
32519
+ amount: avg
32495
32520
  });
32496
32521
  }
32497
32522
  });
32498
32523
  }
32499
32524
  async function setNMonthAvg({ month, N, category }) {
32525
+ const categoryFromDb = await _db__WEBPACK_IMPORTED_MODULE_2__.first('SELECT is_income FROM v_categories WHERE id = ?', [
32526
+ category
32527
+ ]);
32500
32528
  let prevMonth = _shared_months__WEBPACK_IMPORTED_MODULE_0__.prevMonth(month);
32501
32529
  let sumAmount = 0;
32502
32530
  for (let l = 0; l < N; l++) {
@@ -32504,11 +32532,14 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
32504
32532
  prevMonth = _shared_months__WEBPACK_IMPORTED_MODULE_0__.prevMonth(prevMonth);
32505
32533
  }
32506
32534
  await (0, _sync__WEBPACK_IMPORTED_MODULE_5__.batchMessages)(async () => {
32507
- const avg = Math.round(sumAmount / N);
32535
+ let avg = Math.round(sumAmount / N);
32536
+ if (categoryFromDb.is_income === 0) {
32537
+ avg *= -1;
32538
+ }
32508
32539
  setBudget({
32509
32540
  category,
32510
32541
  month,
32511
- amount: -avg
32542
+ amount: avg
32512
32543
  });
32513
32544
  });
32514
32545
  }
@@ -32563,6 +32594,16 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
32563
32594
  amount: budgeted + amount
32564
32595
  });
32565
32596
  }
32597
+ async function coverOverbudgeted({ month, category }) {
32598
+ const sheetName = _shared_months__WEBPACK_IMPORTED_MODULE_0__.sheetForMonth(month);
32599
+ const toBudget = await getSheetValue(sheetName, 'to-budget');
32600
+ const categoryBudget = await getSheetValue(sheetName, 'budget-' + category);
32601
+ await setBudget({
32602
+ category,
32603
+ month,
32604
+ amount: categoryBudget + toBudget
32605
+ });
32606
+ }
32566
32607
  async function transferCategory({ month, amount, from, to }) {
32567
32608
  const sheetName = _shared_months__WEBPACK_IMPORTED_MODULE_0__.sheetForMonth(month);
32568
32609
  const fromBudgeted = await getSheetValue(sheetName, 'budget-' + from);
@@ -32626,6 +32667,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
32626
32667
  app.method('budget/reset-hold', (0, _mutators__WEBPACK_IMPORTED_MODULE_1__.mutator)((0, _undo__WEBPACK_IMPORTED_MODULE_2__.undoable)(_actions__WEBPACK_IMPORTED_MODULE_3__.resetHold)));
32627
32668
  app.method('budget/cover-overspending', (0, _mutators__WEBPACK_IMPORTED_MODULE_1__.mutator)((0, _undo__WEBPACK_IMPORTED_MODULE_2__.undoable)(_actions__WEBPACK_IMPORTED_MODULE_3__.coverOverspending)));
32628
32669
  app.method('budget/transfer-available', (0, _mutators__WEBPACK_IMPORTED_MODULE_1__.mutator)((0, _undo__WEBPACK_IMPORTED_MODULE_2__.undoable)(_actions__WEBPACK_IMPORTED_MODULE_3__.transferAvailable)));
32670
+ app.method('budget/cover-overbudgeted', (0, _mutators__WEBPACK_IMPORTED_MODULE_1__.mutator)((0, _undo__WEBPACK_IMPORTED_MODULE_2__.undoable)(_actions__WEBPACK_IMPORTED_MODULE_3__.coverOverbudgeted)));
32629
32671
  app.method('budget/transfer-category', (0, _mutators__WEBPACK_IMPORTED_MODULE_1__.mutator)((0, _undo__WEBPACK_IMPORTED_MODULE_2__.undoable)(_actions__WEBPACK_IMPORTED_MODULE_3__.transferCategory)));
32630
32672
  app.method('budget/set-carryover', (0, _mutators__WEBPACK_IMPORTED_MODULE_1__.mutator)((0, _undo__WEBPACK_IMPORTED_MODULE_2__.undoable)(_actions__WEBPACK_IMPORTED_MODULE_3__.setCategoryCarryover)));
32631
32673
  /***/
@@ -35214,7 +35256,6 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
35214
35256
  /* harmony export */ moveCategory: () => ( /* binding */moveCategory),
35215
35257
  /* harmony export */ moveCategoryGroup: () => ( /* binding */moveCategoryGroup),
35216
35258
  /* harmony export */ openDatabase: () => ( /* binding */openDatabase),
35217
- /* harmony export */ reopenDatabase: () => ( /* binding */reopenDatabase),
35218
35259
  /* harmony export */ run: () => ( /* binding */run),
35219
35260
  /* harmony export */ runQuery: () => ( /* binding */runQuery),
35220
35261
  /* harmony export */ select: () => ( /* binding */select),
@@ -35246,8 +35287,8 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
35246
35287
  /* harmony import */ var _sync__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../sync */ "./packages/loot-core/src/server/sync/index.ts");
35247
35288
  /* harmony import */ var _sort__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./sort */ "./packages/loot-core/src/server/db/sort.ts");
35248
35289
  // @ts-strict-ignore
35249
- let dbPath;
35250
- let db;
35290
+ let dbPath = null;
35291
+ let db = null;
35251
35292
  // Util
35252
35293
  function getDatabasePath() {
35253
35294
  return dbPath;
@@ -35260,10 +35301,6 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
35260
35301
  setDatabase(await _platform_server_sqlite__WEBPACK_IMPORTED_MODULE_3__.openDatabase(dbPath));
35261
35302
  // await execQuery('PRAGMA journal_mode = WAL');
35262
35303
  }
35263
- async function reopenDatabase() {
35264
- await _platform_server_sqlite__WEBPACK_IMPORTED_MODULE_3__.closeDatabase(db);
35265
- setDatabase(await _platform_server_sqlite__WEBPACK_IMPORTED_MODULE_3__.openDatabase(dbPath));
35266
- }
35267
35304
  async function closeDatabase() {
35268
35305
  if (db) {
35269
35306
  await _platform_server_sqlite__WEBPACK_IMPORTED_MODULE_3__.closeDatabase(db);
@@ -35666,7 +35703,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
35666
35703
  SELECT p.*, COALESCE(a.name, p.name) AS name FROM payees p
35667
35704
  LEFT JOIN accounts a ON (p.transfer_acct = a.id AND a.tombstone = 0)
35668
35705
  WHERE p.tombstone = 0 AND (p.transfer_acct IS NULL OR a.id IS NOT NULL)
35669
- ORDER BY p.transfer_acct IS NULL DESC, p.name COLLATE NOCASE
35706
+ ORDER BY p.transfer_acct IS NULL DESC, p.name COLLATE NOCASE, a.offbudget, a.sort_order
35670
35707
  `);
35671
35708
  }
35672
35709
  function syncGetOrphanedPayees() {
@@ -37318,8 +37355,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
37318
37355
  deleted,
37319
37356
  learnCategories
37320
37357
  });
37321
- // Return all data updates to the frontend
37322
- return result.updated;
37358
+ return result;
37323
37359
  });
37324
37360
  });
37325
37361
  handlers['transaction-add'] = (0, _mutators__WEBPACK_IMPORTED_MODULE_34__.mutator)(async function (transaction) {
@@ -37795,7 +37831,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
37795
37831
  const institution = {
37796
37832
  name: externalAccount.institution ?? 'Unknown'
37797
37833
  };
37798
- const bank = await _accounts_link__WEBPACK_IMPORTED_MODULE_15__.findOrCreateBank(institution, externalAccount.orgDomain);
37834
+ const bank = await _accounts_link__WEBPACK_IMPORTED_MODULE_15__.findOrCreateBank(institution, externalAccount.orgDomain ?? externalAccount.orgId);
37799
37835
  if (upgradingId) {
37800
37836
  const accRow = await _db__WEBPACK_IMPORTED_MODULE_27__.first('SELECT * FROM accounts WHERE id = ?', [
37801
37837
  upgradingId
@@ -38077,9 +38113,16 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
38077
38113
  error: 'unauthorized'
38078
38114
  };
38079
38115
  }
38080
- return (0, _post__WEBPACK_IMPORTED_MODULE_37__.post)((0, _server_config__WEBPACK_IMPORTED_MODULE_42__.getServer)().SIMPLEFIN_SERVER + '/accounts', {}, {
38081
- 'X-ACTUAL-TOKEN': userToken
38082
- });
38116
+ try {
38117
+ return await (0, _post__WEBPACK_IMPORTED_MODULE_37__.post)((0, _server_config__WEBPACK_IMPORTED_MODULE_42__.getServer)().SIMPLEFIN_SERVER + '/accounts', {}, {
38118
+ 'X-ACTUAL-TOKEN': userToken
38119
+ }, 60000);
38120
+ }
38121
+ catch (error) {
38122
+ return {
38123
+ error_code: 'TIMED_OUT'
38124
+ };
38125
+ }
38083
38126
  };
38084
38127
  handlers['gocardless-get-banks'] = async function (country) {
38085
38128
  const userToken = await _platform_server_asyncStorage__WEBPACK_IMPORTED_MODULE_5__.getItem('user-token');
@@ -38163,7 +38206,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
38163
38206
  else if (err instanceof _errors__WEBPACK_IMPORTED_MODULE_30__.PostError && err.reason !== 'internal') {
38164
38207
  errors.push({
38165
38208
  accountId: acct.id,
38166
- message: `Account “${acct.name}” is not linked properly. Please link it again`
38209
+ message: err.reason ? err.reason : `Account “${acct.name}” is not linked properly. Please link it again.`
38167
38210
  });
38168
38211
  }
38169
38212
  else {
@@ -39646,18 +39689,23 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
39646
39689
  throw new _errors__WEBPACK_IMPORTED_MODULE_1__.PostError(text);
39647
39690
  }
39648
39691
  }
39649
- async function post(url, data, headers = {}) {
39692
+ async function post(url, data, headers = {}, timeout = null) {
39650
39693
  let text;
39651
39694
  let res;
39652
39695
  try {
39696
+ const controller = new AbortController();
39697
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
39698
+ const signal = timeout ? controller.signal : null;
39653
39699
  res = await (0, _platform_server_fetch__WEBPACK_IMPORTED_MODULE_0__.fetch)(url, {
39654
39700
  method: 'POST',
39655
39701
  body: JSON.stringify(data),
39702
+ signal,
39656
39703
  headers: {
39657
39704
  ...headers,
39658
39705
  'Content-Type': 'application/json'
39659
39706
  }
39660
39707
  });
39708
+ clearTimeout(timeoutId);
39661
39709
  text = await res.text();
39662
39710
  }
39663
39711
  catch (err) {
@@ -39856,6 +39904,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
39856
39904
  showOffBudget: row.show_offbudget === 1,
39857
39905
  showHiddenCategories: row.show_hidden === 1,
39858
39906
  showUncategorized: row.show_uncategorized === 1,
39907
+ includeCurrentInterval: row.include_current === 1,
39859
39908
  selectedCategories: row.selected_categories,
39860
39909
  graphType: row.graph_type,
39861
39910
  conditions: row.conditions,
@@ -39879,6 +39928,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
39879
39928
  show_offbudget: report.showOffBudget ? 1 : 0,
39880
39929
  show_hidden: report.showHiddenCategories ? 1 : 0,
39881
39930
  show_uncategorized: report.showUncategorized ? 1 : 0,
39931
+ include_current: report.includeCurrentInterval ? 1 : 0,
39882
39932
  selected_categories: report.selectedCategories,
39883
39933
  graph_type: report.graphType,
39884
39934
  conditions: report.conditions,
@@ -41216,6 +41266,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
41216
41266
  /* harmony export */ Graph: () => ( /* binding */Graph)
41217
41267
  /* harmony export */
41218
41268
  });
41269
+ /* harmony import */ var _prefs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../prefs */ "./packages/loot-core/src/server/prefs.ts");
41219
41270
  // @ts-strict-ignore
41220
41271
  function Graph() {
41221
41272
  const graph = {
@@ -41286,27 +41337,84 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
41286
41337
  }
41287
41338
  return graph;
41288
41339
  }
41289
- function topologicalSortUntil(name, visited, sorted) {
41340
+ function topologicalSort(sourceNodes) {
41341
+ const visited = new Set();
41342
+ const sorted = [];
41343
+ const prefs = (0, _prefs__WEBPACK_IMPORTED_MODULE_0__.getPrefs)();
41344
+ const iterableTopologicalSort = prefs != null ? prefs['flags.iterableTopologicalSort'] : false;
41345
+ sourceNodes.forEach((name) => {
41346
+ if (!visited.has(name)) {
41347
+ if (iterableTopologicalSort) {
41348
+ topologicalSortIterable(name, visited, sorted);
41349
+ }
41350
+ else {
41351
+ topologicalSortUntil(name, visited, sorted, 0);
41352
+ }
41353
+ }
41354
+ });
41355
+ return sorted;
41356
+ }
41357
+ function topologicalSortUntil(name, visited, sorted, level) {
41290
41358
  visited.add(name);
41359
+ if (level > 2500) {
41360
+ console.error('Limit of recursions reached while sorting budget: 2500');
41361
+ return;
41362
+ }
41291
41363
  const iter = adjacent(name).values();
41292
41364
  let cur = iter.next();
41293
41365
  while (!cur.done) {
41294
41366
  if (!visited.has(cur.value)) {
41295
- topologicalSortUntil(cur.value, visited, sorted);
41367
+ topologicalSortUntil(cur.value, visited, sorted, level + 1);
41296
41368
  }
41297
41369
  cur = iter.next();
41298
41370
  }
41299
41371
  sorted.unshift(name);
41300
41372
  }
41301
- function topologicalSort(sourceNodes) {
41302
- const visited = new Set();
41303
- const sorted = [];
41304
- sourceNodes.forEach((name) => {
41305
- if (!visited.has(name)) {
41306
- topologicalSortUntil(name, visited, sorted);
41373
+ function topologicalSortIterable(name, visited, sorted) {
41374
+ const stackTrace = [];
41375
+ stackTrace.push({
41376
+ count: -1,
41377
+ value: name,
41378
+ parent: '',
41379
+ level: 0
41380
+ });
41381
+ while (stackTrace.length > 0) {
41382
+ const current = stackTrace.slice(-1)[0];
41383
+ const adjacents = adjacent(current.value);
41384
+ if (current.count === -1) {
41385
+ current.count = adjacents.size;
41386
+ }
41387
+ if (current.count > 0) {
41388
+ const iter = adjacents.values();
41389
+ let cur = iter.next();
41390
+ while (!cur.done) {
41391
+ if (!visited.has(cur.value)) {
41392
+ stackTrace.push({
41393
+ count: -1,
41394
+ parent: current.value,
41395
+ value: cur.value,
41396
+ level: current.level + 1
41397
+ });
41398
+ }
41399
+ else {
41400
+ current.count--;
41401
+ }
41402
+ cur = iter.next();
41403
+ }
41307
41404
  }
41308
- });
41309
- return sorted;
41405
+ else {
41406
+ if (!visited.has(current.value)) {
41407
+ visited.add(current.value);
41408
+ sorted.unshift(current.value);
41409
+ }
41410
+ const removed = stackTrace.pop();
41411
+ for (let i = 0; i < stackTrace.length; i++) {
41412
+ if (stackTrace[i].value === removed.parent) {
41413
+ stackTrace[i].count--;
41414
+ }
41415
+ }
41416
+ }
41417
+ }
41310
41418
  }
41311
41419
  function generateDOT() {
41312
41420
  const edgeStrings = [];
@@ -41316,9 +41424,9 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
41316
41424
  }
41317
41425
  });
41318
41426
  return `
41319
- digraph G {
41320
- ${edgeStrings.join('\n').replace(/!/g, '_')}
41321
- }
41427
+ digraph G {
41428
+ ${edgeStrings.join('\n').replace(/!/g, '_')}
41429
+ }
41322
41430
  `;
41323
41431
  }
41324
41432
  return graph;
@@ -43749,7 +43857,8 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
43749
43857
  function _yearRange(start, end, inclusive = false) {
43750
43858
  const years = [];
43751
43859
  let year = yearFromDate(start);
43752
- while (date_fns__WEBPACK_IMPORTED_MODULE_14__["default"](_parse(year), _parse(end))) {
43860
+ const endYear = yearFromDate(end);
43861
+ while (date_fns__WEBPACK_IMPORTED_MODULE_14__["default"](_parse(year), _parse(endYear))) {
43753
43862
  years.push(year);
43754
43863
  year = addYears(year, 1);
43755
43864
  }
@@ -43780,7 +43889,8 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
43780
43889
  function _range(start, end, inclusive = false) {
43781
43890
  const months = [];
43782
43891
  let month = monthFromDate(start);
43783
- while (date_fns__WEBPACK_IMPORTED_MODULE_14__["default"](_parse(month), _parse(end))) {
43892
+ const endMonth = monthFromDate(end);
43893
+ while (date_fns__WEBPACK_IMPORTED_MODULE_14__["default"](_parse(month), _parse(endMonth))) {
43784
43894
  months.push(month);
43785
43895
  month = addMonths(month, 1);
43786
43896
  }
@@ -44087,6 +44197,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
44087
44197
  ops: [
44088
44198
  'is',
44089
44199
  'contains',
44200
+ 'matches',
44090
44201
  'oneOf',
44091
44202
  'isNot',
44092
44203
  'doesNotContain',
@@ -44102,6 +44213,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
44102
44213
  ops: [
44103
44214
  'is',
44104
44215
  'contains',
44216
+ 'matches',
44105
44217
  'oneOf',
44106
44218
  'isNot',
44107
44219
  'doesNotContain',
@@ -44144,7 +44256,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
44144
44256
  }));
44145
44257
  const ALLOCATION_METHODS = {
44146
44258
  'fixed-amount': 'a fixed amount',
44147
- 'fixed-percent': 'a fixed percent',
44259
+ 'fixed-percent': 'a fixed percent of the remainder',
44148
44260
  remainder: 'an equal portion of the remainder'
44149
44261
  };
44150
44262
  function mapField(field, opts) {
@@ -44184,6 +44296,8 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
44184
44296
  return 'is between';
44185
44297
  case 'contains':
44186
44298
  return 'contains';
44299
+ case 'matches':
44300
+ return 'matches';
44187
44301
  case 'doesNotContain':
44188
44302
  return 'does not contain';
44189
44303
  case 'gt':
@@ -44442,7 +44556,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
44442
44556
  $and: {
44443
44557
  schedule: schedule.id,
44444
44558
  date: {
44445
- $gte: dateCond && dateCond.op === 'is' ? schedule.next_date : _months__WEBPACK_IMPORTED_MODULE_0__.subDays(schedule.next_date, 7)
44559
+ $gte: dateCond && dateCond.op === 'is' ? schedule.next_date : _months__WEBPACK_IMPORTED_MODULE_0__.subDays(schedule.next_date, 2)
44446
44560
  }
44447
44561
  }
44448
44562
  };
@@ -44686,6 +44800,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
44686
44800
  /* harmony export */ groupTransaction: () => ( /* binding */groupTransaction),
44687
44801
  /* harmony export */ isPreviewId: () => ( /* binding */isPreviewId),
44688
44802
  /* harmony export */ isTemporaryId: () => ( /* binding */isTemporaryId),
44803
+ /* harmony export */ makeAsNonChildTransactions: () => ( /* binding */makeAsNonChildTransactions),
44689
44804
  /* harmony export */ makeChild: () => ( /* binding */makeChild),
44690
44805
  /* harmony export */ realizeTempTransactions: () => ( /* binding */realizeTempTransactions),
44691
44806
  /* harmony export */ recalculateSplit: () => ( /* binding */recalculateSplit),
@@ -44733,6 +44848,18 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
44733
44848
  error: null
44734
44849
  };
44735
44850
  }
44851
+ function makeNonChild(parent, data) {
44852
+ return {
44853
+ amount: 0,
44854
+ ...data,
44855
+ cleared: parent.cleared != null ? parent.cleared : null,
44856
+ reconciled: parent.reconciled != null ? parent.reconciled : null,
44857
+ sort_order: parent.sort_order || null,
44858
+ starting_balance_flag: null,
44859
+ is_child: false,
44860
+ parent_id: null
44861
+ };
44862
+ }
44736
44863
  function recalculateSplit(trans) {
44737
44864
  // Calculate the new total of split transactions and make sure
44738
44865
  // that it equals the parent amount
@@ -44968,6 +45095,35 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
44968
45095
  }))
44969
45096
  ];
44970
45097
  }
45098
+ function makeAsNonChildTransactions(childTransactionsToUpdate, transactions) {
45099
+ const [parentTransaction, ...childTransactions] = transactions;
45100
+ const newNonChildTransactions = childTransactionsToUpdate.map((t) => makeNonChild(parentTransaction, t));
45101
+ const remainingChildTransactions = childTransactions.filter((t) => !newNonChildTransactions.some((updatedTrans) => updatedTrans.id === t.id));
45102
+ const nonChildTransactionsToUpdate = remainingChildTransactions.length === 1 ? [
45103
+ ...newNonChildTransactions,
45104
+ makeNonChild(parentTransaction, remainingChildTransactions[0])
45105
+ ] : newNonChildTransactions;
45106
+ const deleteParentTransaction = remainingChildTransactions.length <= 1;
45107
+ const updatedParentTransaction = {
45108
+ ...parentTransaction,
45109
+ ...!deleteParentTransaction ? {
45110
+ amount: remainingChildTransactions.map((t) => t.amount).reduce((total, amount) => total + amount, 0)
45111
+ } : {}
45112
+ };
45113
+ return {
45114
+ updated: [
45115
+ ...!deleteParentTransaction ? [
45116
+ updatedParentTransaction
45117
+ ] : [],
45118
+ ...nonChildTransactionsToUpdate
45119
+ ],
45120
+ deleted: [
45121
+ ...deleteParentTransaction ? [
45122
+ updatedParentTransaction
45123
+ ] : []
45124
+ ]
45125
+ };
45126
+ }
44971
45127
  /***/
44972
45128
  }),
44973
45129
  /***/ "./packages/loot-core/src/shared/util.ts":
@@ -0,0 +1,5 @@
1
+ BEGIN TRANSACTION;
2
+
3
+ ALTER TABLE custom_reports ADD COLUMN include_current INTEGER DEFAULT 0;
4
+
5
+ COMMIT;
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@actual-app/api",
3
- "version": "6.8.1",
3
+ "version": "6.8.2",
4
4
  "license": "MIT",
5
5
  "description": "An API for Actual",
6
6
  "engines": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@actual-app/api",
3
- "version": "6.8.1",
3
+ "version": "6.8.2",
4
4
  "license": "MIT",
5
5
  "description": "An API for Actual",
6
6
  "engines": {