@mx-cartographer/experiences 9.4.39 → 9.4.40
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.
- package/CHANGELOG.md +4 -0
- package/dist/core/stores/GlobalStore.es.js +12 -8
- package/dist/core/stores/GlobalStore.es.js.map +1 -1
- package/dist/core/stores/RecurringTransactionsStore.d.ts +1 -0
- package/dist/core/stores/RecurringTransactionsStore.es.js +40 -36
- package/dist/core/stores/RecurringTransactionsStore.es.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
## [9.4.40] - 09-24-2026
|
|
2
|
+
|
|
3
|
+
- **FIXED** - double error reporting from Recurring Transactions. Its errors now surface only through `onCaptureException`, and `GlobalStore.captureException` falls back to `console.error` when the host provides no handler (MEW-4169)
|
|
4
|
+
|
|
1
5
|
## [9.4.39] - 09-23-2026
|
|
2
6
|
|
|
3
7
|
- **FIXED** - Trends category rows no longer show a nonzero total with "0 transactions" and no chevron. (MEW-4021)
|
|
@@ -8,7 +8,7 @@ import { CategoryStore as w } from "./CategoryStore.es.js";
|
|
|
8
8
|
import { ConnectStore as d } from "./ConnectStore.es.js";
|
|
9
9
|
import { DebtsStore as u } from "./DebtsStore.es.js";
|
|
10
10
|
import { FinstrongStore as b } from "./FinstrongStore.es.js";
|
|
11
|
-
import { DefaultAppConfig as
|
|
11
|
+
import { DefaultAppConfig as S } from "../constants/DefaultConfig.es.js";
|
|
12
12
|
import { GlobalUiStore as y } from "./GlobalUiStore.es.js";
|
|
13
13
|
import { GlobalCopyStore as C } from "./GlobalCopyStore.es.js";
|
|
14
14
|
import { GoalStore as U } from "./GoalStore.es.js";
|
|
@@ -24,8 +24,8 @@ import { TransactionStore as M } from "./TransactionStore.es.js";
|
|
|
24
24
|
import { TrendsStore as V } from "./TrendsStore.es.js";
|
|
25
25
|
import { UserStore as W } from "./UserStore.es.js";
|
|
26
26
|
import { autorun as v, makeAutoObservable as z } from "mobx";
|
|
27
|
-
var
|
|
28
|
-
appConfig =
|
|
27
|
+
var ht = class {
|
|
28
|
+
appConfig = S;
|
|
29
29
|
endpoint = "/";
|
|
30
30
|
sessionToken = "";
|
|
31
31
|
onCaptureException;
|
|
@@ -55,7 +55,7 @@ var St = class {
|
|
|
55
55
|
userStore;
|
|
56
56
|
globalUiStore;
|
|
57
57
|
insightsV2Store;
|
|
58
|
-
constructor(t =
|
|
58
|
+
constructor(t = S, o = "/", r, e, i) {
|
|
59
59
|
this.appConfig = t, this.endpoint = o, this.sessionToken = t.options.session_token ?? "", this.onCaptureException = i, this.onError = r, this.onStoreUpdate = e, this.accountStore = new p(this), this.appDataStore = new c(this), this.analyticsStore = new m(this), this.beatStore = new f(this), this.budgetsStore = new l(this), this.cashflowStore = new g(this), this.categoryStore = new w(this), this.connectStore = new d(this), this.copyStore = new C(this), this.debtsStore = new u(this), this.finstrongStore = new b(this), this.goalStore = new U(this), this.helpStore = new D(this), this.holdingStore = new A(this), this.merchantStore = new E(this), this.netWorthStore = new x(this), this.notificationStore = new k(this), this.recurringTransactionsStore = new G(this), this.settingsStore = new I(this), this.transactionStore = new M(this), this.trendsStore = new V(this), this.userStore = new W(this), this.globalUiStore = new y(this), this.insightsV2Store = new T(this), z(this), v(() => {
|
|
60
60
|
const { transactions: s } = this.transactionStore;
|
|
61
61
|
this.emitUpdate({ transactions: s });
|
|
@@ -65,7 +65,11 @@ var St = class {
|
|
|
65
65
|
return this.globalUiStore.isInitialized;
|
|
66
66
|
}
|
|
67
67
|
captureException = (t, o) => {
|
|
68
|
-
this.onCaptureException
|
|
68
|
+
if (this.onCaptureException) {
|
|
69
|
+
this.onCaptureException(t, o);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
console.error("Unreported error:", t, o);
|
|
69
73
|
};
|
|
70
74
|
emitUpdate = (t) => {
|
|
71
75
|
this.onStoreUpdate?.(t);
|
|
@@ -78,12 +82,12 @@ var St = class {
|
|
|
78
82
|
this.userStore.loadUserFeatures()
|
|
79
83
|
]);
|
|
80
84
|
};
|
|
81
|
-
loadData = async ({ accounts: t, appData: o, associatedBeats: r, categories: e, institutions: i, transactionRules: s, transactions: a, userFeatures: n, merchantBudgets:
|
|
82
|
-
(!o || !n) && await this.loadConfigData(), o && this.appDataStore.setAppData(o), n && this.userStore.setUserFeatures(n), t && (await this.accountStore.loadMembers(), i && this.accountStore.setInstitutions(i), this.accountStore.setAccounts(t)), r && this.transactionStore.setAssociatedBeats(r), e && this.categoryStore.setCategories(e), a && this.transactionStore.setTransactions(a), s && this.transactionStore.setTransactionRules(s),
|
|
85
|
+
loadData = async ({ accounts: t, appData: o, associatedBeats: r, categories: e, institutions: i, transactionRules: s, transactions: a, userFeatures: n, merchantBudgets: h } = {}) => {
|
|
86
|
+
(!o || !n) && await this.loadConfigData(), o && this.appDataStore.setAppData(o), n && this.userStore.setUserFeatures(n), t && (await this.accountStore.loadMembers(), i && this.accountStore.setInstitutions(i), this.accountStore.setAccounts(t)), r && this.transactionStore.setAssociatedBeats(r), e && this.categoryStore.setCategories(e), a && this.transactionStore.setTransactions(a), s && this.transactionStore.setTransactionRules(s), h && this.budgetsStore.setMerchantBudgets(h);
|
|
83
87
|
};
|
|
84
88
|
};
|
|
85
89
|
export {
|
|
86
|
-
|
|
90
|
+
ht as GlobalStore
|
|
87
91
|
};
|
|
88
92
|
|
|
89
93
|
//# sourceMappingURL=GlobalStore.es.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GlobalStore.es.js","names":[],"sources":["../../../src/core/stores/GlobalStore.ts"],"sourcesContent":["import { autorun, makeAutoObservable } from 'mobx'\n\nimport { DefaultAppConfig } from '../constants/DefaultConfig'\n\nimport {\n AccountStore,\n AnalyticsStore,\n AppDataStore,\n BeatStore,\n BudgetsStore,\n CashflowStore,\n CategoryStore,\n ConnectStore,\n DebtsStore,\n FinstrongStore,\n GlobalCopyStore,\n GlobalUiStore,\n GoalStore,\n HelpStore,\n HoldingStore,\n InsightsV2Store,\n MerchantStore,\n NetWorthStore,\n NotificationStore,\n RecurringTransactionsStore,\n SettingsStore,\n TransactionStore,\n TrendsStore,\n UserStore,\n} from '../stores'\n\nimport type {\n Account,\n Category,\n Institution,\n Member,\n AppConfig,\n AppData,\n Beat,\n GlobalCaptureException,\n GlobalErrorHandler,\n MerchantBudget,\n Tag,\n Tagging,\n Transaction,\n TransactionRule,\n UserFeature,\n} from '../types'\n\ninterface LoadDataProps {\n accounts?: Account[]\n appData?: AppData\n associatedBeats?: Beat[]\n categories?: Category[]\n institutions?: Institution[]\n members?: Member[]\n merchantBudgets?: MerchantBudget[]\n taggings?: Tagging[]\n tags?: Tag[]\n transactionRules?: TransactionRule[]\n transactions?: Transaction[]\n userFeatures?: UserFeature[]\n}\n\ntype OnStoreUpdate = (update: ObservedUpdate) => void\ntype ObservedUpdate = {\n transactions: Transaction[]\n}\nexport class GlobalStore {\n // Global properties\n appConfig: AppConfig = DefaultAppConfig\n endpoint: string = '/'\n sessionToken: string = ''\n onCaptureException?: GlobalCaptureException\n onError?: GlobalErrorHandler\n onStoreUpdate?: OnStoreUpdate\n\n // Data Stores\n accountStore: AccountStore\n appDataStore: AppDataStore\n analyticsStore: AnalyticsStore\n beatStore: BeatStore\n budgetsStore: BudgetsStore\n cashflowStore: CashflowStore\n categoryStore: CategoryStore\n connectStore: ConnectStore\n copyStore: GlobalCopyStore\n debtsStore: DebtsStore\n finstrongStore: FinstrongStore\n goalStore: GoalStore\n helpStore: HelpStore\n holdingStore: HoldingStore\n merchantStore: MerchantStore\n netWorthStore: NetWorthStore\n notificationStore: NotificationStore\n recurringTransactionsStore: RecurringTransactionsStore\n settingsStore: SettingsStore\n transactionStore: TransactionStore\n trendsStore: TrendsStore\n userStore: UserStore\n\n // UI Stores\n globalUiStore: GlobalUiStore\n insightsV2Store: InsightsV2Store\n\n constructor(\n appConfig: AppConfig = DefaultAppConfig,\n endpoint: string = '/',\n onError?: GlobalErrorHandler,\n onStoreUpdate?: OnStoreUpdate,\n onCaptureException?: GlobalCaptureException,\n ) {\n this.appConfig = appConfig\n this.endpoint = endpoint\n this.sessionToken = appConfig.options.session_token ?? ''\n this.onCaptureException = onCaptureException\n this.onError = onError\n this.onStoreUpdate = onStoreUpdate\n\n this.accountStore = new AccountStore(this)\n this.appDataStore = new AppDataStore(this)\n this.analyticsStore = new AnalyticsStore(this)\n this.beatStore = new BeatStore(this)\n this.budgetsStore = new BudgetsStore(this)\n this.cashflowStore = new CashflowStore(this)\n this.categoryStore = new CategoryStore(this)\n this.connectStore = new ConnectStore(this)\n this.copyStore = new GlobalCopyStore(this)\n this.debtsStore = new DebtsStore(this)\n this.finstrongStore = new FinstrongStore(this)\n this.goalStore = new GoalStore(this)\n this.helpStore = new HelpStore(this)\n this.holdingStore = new HoldingStore(this)\n this.merchantStore = new MerchantStore(this)\n this.netWorthStore = new NetWorthStore(this)\n this.notificationStore = new NotificationStore(this)\n this.recurringTransactionsStore = new RecurringTransactionsStore(this)\n this.settingsStore = new SettingsStore(this)\n this.transactionStore = new TransactionStore(this)\n this.trendsStore = new TrendsStore(this)\n this.userStore = new UserStore(this)\n\n this.globalUiStore = new GlobalUiStore(this)\n this.insightsV2Store = new InsightsV2Store(this)\n\n makeAutoObservable(this)\n\n // detects a change based on an observed value\n autorun(() => {\n // destructure or assign new variables to observe changes to them\n // in this case we are observing changes to `transactions`\n const { transactions } = this.transactionStore\n this.emitUpdate({\n transactions,\n })\n })\n }\n\n get isInitialized() {\n return this.globalUiStore.isInitialized\n }\n\n captureException = (error: unknown, context?: Record<string, string>) => {\n this.onCaptureException
|
|
1
|
+
{"version":3,"file":"GlobalStore.es.js","names":[],"sources":["../../../src/core/stores/GlobalStore.ts"],"sourcesContent":["import { autorun, makeAutoObservable } from 'mobx'\n\nimport { DefaultAppConfig } from '../constants/DefaultConfig'\n\nimport {\n AccountStore,\n AnalyticsStore,\n AppDataStore,\n BeatStore,\n BudgetsStore,\n CashflowStore,\n CategoryStore,\n ConnectStore,\n DebtsStore,\n FinstrongStore,\n GlobalCopyStore,\n GlobalUiStore,\n GoalStore,\n HelpStore,\n HoldingStore,\n InsightsV2Store,\n MerchantStore,\n NetWorthStore,\n NotificationStore,\n RecurringTransactionsStore,\n SettingsStore,\n TransactionStore,\n TrendsStore,\n UserStore,\n} from '../stores'\n\nimport type {\n Account,\n Category,\n Institution,\n Member,\n AppConfig,\n AppData,\n Beat,\n GlobalCaptureException,\n GlobalErrorHandler,\n MerchantBudget,\n Tag,\n Tagging,\n Transaction,\n TransactionRule,\n UserFeature,\n} from '../types'\n\ninterface LoadDataProps {\n accounts?: Account[]\n appData?: AppData\n associatedBeats?: Beat[]\n categories?: Category[]\n institutions?: Institution[]\n members?: Member[]\n merchantBudgets?: MerchantBudget[]\n taggings?: Tagging[]\n tags?: Tag[]\n transactionRules?: TransactionRule[]\n transactions?: Transaction[]\n userFeatures?: UserFeature[]\n}\n\ntype OnStoreUpdate = (update: ObservedUpdate) => void\ntype ObservedUpdate = {\n transactions: Transaction[]\n}\nexport class GlobalStore {\n // Global properties\n appConfig: AppConfig = DefaultAppConfig\n endpoint: string = '/'\n sessionToken: string = ''\n onCaptureException?: GlobalCaptureException\n onError?: GlobalErrorHandler\n onStoreUpdate?: OnStoreUpdate\n\n // Data Stores\n accountStore: AccountStore\n appDataStore: AppDataStore\n analyticsStore: AnalyticsStore\n beatStore: BeatStore\n budgetsStore: BudgetsStore\n cashflowStore: CashflowStore\n categoryStore: CategoryStore\n connectStore: ConnectStore\n copyStore: GlobalCopyStore\n debtsStore: DebtsStore\n finstrongStore: FinstrongStore\n goalStore: GoalStore\n helpStore: HelpStore\n holdingStore: HoldingStore\n merchantStore: MerchantStore\n netWorthStore: NetWorthStore\n notificationStore: NotificationStore\n recurringTransactionsStore: RecurringTransactionsStore\n settingsStore: SettingsStore\n transactionStore: TransactionStore\n trendsStore: TrendsStore\n userStore: UserStore\n\n // UI Stores\n globalUiStore: GlobalUiStore\n insightsV2Store: InsightsV2Store\n\n constructor(\n appConfig: AppConfig = DefaultAppConfig,\n endpoint: string = '/',\n onError?: GlobalErrorHandler,\n onStoreUpdate?: OnStoreUpdate,\n onCaptureException?: GlobalCaptureException,\n ) {\n this.appConfig = appConfig\n this.endpoint = endpoint\n this.sessionToken = appConfig.options.session_token ?? ''\n this.onCaptureException = onCaptureException\n this.onError = onError\n this.onStoreUpdate = onStoreUpdate\n\n this.accountStore = new AccountStore(this)\n this.appDataStore = new AppDataStore(this)\n this.analyticsStore = new AnalyticsStore(this)\n this.beatStore = new BeatStore(this)\n this.budgetsStore = new BudgetsStore(this)\n this.cashflowStore = new CashflowStore(this)\n this.categoryStore = new CategoryStore(this)\n this.connectStore = new ConnectStore(this)\n this.copyStore = new GlobalCopyStore(this)\n this.debtsStore = new DebtsStore(this)\n this.finstrongStore = new FinstrongStore(this)\n this.goalStore = new GoalStore(this)\n this.helpStore = new HelpStore(this)\n this.holdingStore = new HoldingStore(this)\n this.merchantStore = new MerchantStore(this)\n this.netWorthStore = new NetWorthStore(this)\n this.notificationStore = new NotificationStore(this)\n this.recurringTransactionsStore = new RecurringTransactionsStore(this)\n this.settingsStore = new SettingsStore(this)\n this.transactionStore = new TransactionStore(this)\n this.trendsStore = new TrendsStore(this)\n this.userStore = new UserStore(this)\n\n this.globalUiStore = new GlobalUiStore(this)\n this.insightsV2Store = new InsightsV2Store(this)\n\n makeAutoObservable(this)\n\n // detects a change based on an observed value\n autorun(() => {\n // destructure or assign new variables to observe changes to them\n // in this case we are observing changes to `transactions`\n const { transactions } = this.transactionStore\n this.emitUpdate({\n transactions,\n })\n })\n }\n\n get isInitialized() {\n return this.globalUiStore.isInitialized\n }\n\n captureException = (error: unknown, context?: Record<string, string>) => {\n if (this.onCaptureException) {\n this.onCaptureException(error, context)\n return\n }\n console.error('Unreported error:', error, context)\n }\n\n // emits change triggered in the autorun\n emitUpdate = (change: ObservedUpdate) => {\n this.onStoreUpdate?.(change)\n }\n\n loadConfigData = async () => {\n await Promise.all([\n // Load copy, config and user data\n this.copyStore.loadCopy(),\n this.appDataStore.loadAppData(),\n this.accountStore.refreshMembers(),\n this.userStore.loadUserFeatures(),\n ])\n }\n\n loadData = async ({\n accounts,\n appData,\n associatedBeats,\n categories,\n institutions,\n transactionRules,\n transactions,\n userFeatures,\n merchantBudgets,\n }: LoadDataProps = {}) => {\n if (!appData || !userFeatures) {\n await this.loadConfigData()\n }\n\n // Keep for backwards compatibility for Insights\n if (appData) {\n this.appDataStore.setAppData(appData)\n }\n\n if (userFeatures) {\n this.userStore.setUserFeatures(userFeatures)\n }\n\n if (accounts) {\n await this.accountStore.loadMembers()\n if (institutions) {\n this.accountStore.setInstitutions(institutions)\n }\n this.accountStore.setAccounts(accounts)\n }\n\n if (associatedBeats) {\n this.transactionStore.setAssociatedBeats(associatedBeats)\n }\n\n if (categories) {\n this.categoryStore.setCategories(categories)\n }\n\n if (transactions) {\n this.transactionStore.setTransactions(transactions)\n }\n\n if (transactionRules) {\n this.transactionStore.setTransactionRules(transactionRules)\n }\n\n if (merchantBudgets) {\n this.budgetsStore.setMerchantBudgets(merchantBudgets)\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -159,6 +159,7 @@ export declare class RecurringTransactionsStore {
|
|
|
159
159
|
* @param transaction - The transaction to unlink.
|
|
160
160
|
*/
|
|
161
161
|
markRecurrenceAsUnpaid: (transaction: Transaction) => Promise<void>;
|
|
162
|
+
private captureError;
|
|
162
163
|
setAlert: (message: string, severity?: RecurringAlertProps["severity"]) => {
|
|
163
164
|
message: string;
|
|
164
165
|
severity: import('@mui/types').OverridableStringUnion<import('@mui/material').AlertColor, import('@mui/material').AlertPropsColorOverrides> | undefined;
|
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
import { RepeatingTransactionsApi as
|
|
2
|
-
import { RecurrenceStatus as n, RecurrenceType as
|
|
3
|
-
import { augmentRepeatingTransactions as
|
|
1
|
+
import { RepeatingTransactionsApi as l } from "../api/RepeatingTransactionsApi.es.js";
|
|
2
|
+
import { RecurrenceStatus as n, RecurrenceType as c } from "../types/RepeatingTransaction.es.js";
|
|
3
|
+
import { augmentRepeatingTransactions as o, buildAllRecurrences as m } from "../utils/RecurringTransactionsUtil.es.js";
|
|
4
4
|
import { endOfMonth as R } from "date-fns/endOfMonth";
|
|
5
5
|
import { isBefore as T } from "date-fns/isBefore";
|
|
6
6
|
import { startOfMonth as f } from "date-fns/startOfMonth";
|
|
7
|
-
import { startOfToday as
|
|
7
|
+
import { startOfToday as s } from "date-fns/startOfToday";
|
|
8
8
|
import { isSameDay as g } from "date-fns/isSameDay";
|
|
9
9
|
import { isWithinInterval as h } from "date-fns/isWithinInterval";
|
|
10
|
-
import { subDays as
|
|
11
|
-
import { makeAutoObservable as
|
|
12
|
-
import { isAfter as
|
|
13
|
-
var d = (e, t) => h(t.expectedDate, e),
|
|
10
|
+
import { subDays as y } from "date-fns/subDays";
|
|
11
|
+
import { makeAutoObservable as S, runInAction as u } from "mobx";
|
|
12
|
+
import { isAfter as p } from "date-fns/isAfter";
|
|
13
|
+
var d = (e, t) => h(t.expectedDate, e), a = (e, t) => e + t.amount, U = class {
|
|
14
14
|
globalStore;
|
|
15
|
-
api = new
|
|
15
|
+
api = new l("/", "");
|
|
16
16
|
repeatingTransactions = [];
|
|
17
17
|
isDataLoaded = !1;
|
|
18
18
|
selectedDay;
|
|
19
19
|
dateRange = {
|
|
20
|
-
start: f(
|
|
21
|
-
end: R(
|
|
20
|
+
start: f(s()),
|
|
21
|
+
end: R(s())
|
|
22
22
|
};
|
|
23
23
|
selectedRepeatingTransactionGuid = null;
|
|
24
24
|
selectedRecurrence = null;
|
|
@@ -27,7 +27,7 @@ var d = (e, t) => h(t.expectedDate, e), s = (e, t) => e + t.amount, U = class {
|
|
|
27
27
|
severity: void 0
|
|
28
28
|
};
|
|
29
29
|
constructor(e) {
|
|
30
|
-
this.globalStore = e, this.api = new
|
|
30
|
+
this.globalStore = e, this.api = new l(e.endpoint, e.sessionToken, e.onError), S(this, {
|
|
31
31
|
recurrencesForRange: !1,
|
|
32
32
|
upcomingExpensesForRange: !1,
|
|
33
33
|
upcomingIncomeForRange: !1,
|
|
@@ -39,16 +39,16 @@ var d = (e, t) => h(t.expectedDate, e), s = (e, t) => e + t.amount, U = class {
|
|
|
39
39
|
return this.globalStore.copyStore.copy.recurring;
|
|
40
40
|
}
|
|
41
41
|
get detailedRepeatingTransactions() {
|
|
42
|
-
return
|
|
42
|
+
return o(this.globalStore.accountStore.visibleAccounts, this.repeatingTransactions, this.globalStore.transactionStore.transactions);
|
|
43
43
|
}
|
|
44
44
|
recurrencesForRange = (e) => {
|
|
45
45
|
const t = this.globalStore.accountStore.visibleAccounts;
|
|
46
46
|
return m(this.detailedRepeatingTransactions, e).filter((r) => t.some((i) => i.guid === r.accountGuid && !i.is_excluded_from_accounts)).filter((r) => h(r.expectedDate, e));
|
|
47
47
|
};
|
|
48
|
-
upcomingExpensesForRange = (e) => this.recurrencesForRange(e).filter((t) => t.type ===
|
|
49
|
-
incomeForRange = (e) => this.recurrencesForRange(e).filter((t) => t.type ===
|
|
48
|
+
upcomingExpensesForRange = (e) => this.recurrencesForRange(e).filter((t) => t.type === c.Expense && t.status === n.Upcoming);
|
|
49
|
+
incomeForRange = (e) => this.recurrencesForRange(e).filter((t) => t.type === c.Income);
|
|
50
50
|
upcomingIncomeForRange = (e) => this.incomeForRange(e).filter((t) => t.status === n.Upcoming);
|
|
51
|
-
nextIncomeForRange = (e) => this.upcomingIncomeForRange(e).find((t) =>
|
|
51
|
+
nextIncomeForRange = (e) => this.upcomingIncomeForRange(e).find((t) => p(t.expectedDate, s()));
|
|
52
52
|
get recurrences() {
|
|
53
53
|
return this.recurrencesForRange(this.dateRange);
|
|
54
54
|
}
|
|
@@ -56,22 +56,22 @@ var d = (e, t) => h(t.expectedDate, e), s = (e, t) => e + t.amount, U = class {
|
|
|
56
56
|
return this.recurrences.filter((e) => e.status === n.Paid || e.status === n.Missed);
|
|
57
57
|
}
|
|
58
58
|
get upcomingRecurrences() {
|
|
59
|
-
return this.recurrences.filter((e) =>
|
|
59
|
+
return this.recurrences.filter((e) => p(e.expectedDate, y(s(), 3)) && T(e.expectedDate, this.dateRange.end) && e.status === n.Upcoming);
|
|
60
60
|
}
|
|
61
61
|
get expenses() {
|
|
62
|
-
return this.recurrences.filter((e) => e.type ===
|
|
62
|
+
return this.recurrences.filter((e) => e.type === c.Expense);
|
|
63
63
|
}
|
|
64
64
|
get upcomingExpenses() {
|
|
65
65
|
return this.expenses.filter((e) => e.status === n.Upcoming);
|
|
66
66
|
}
|
|
67
67
|
get income() {
|
|
68
|
-
return this.recurrences.filter((e) => e.type ===
|
|
68
|
+
return this.recurrences.filter((e) => e.type === c.Income);
|
|
69
69
|
}
|
|
70
70
|
get upcomingIncome() {
|
|
71
71
|
return this.income.filter((e) => e.status === n.Upcoming);
|
|
72
72
|
}
|
|
73
73
|
get nextIncomeRecurrence() {
|
|
74
|
-
return this.upcomingIncome.find((e) =>
|
|
74
|
+
return this.upcomingIncome.find((e) => p(e.expectedDate, s()));
|
|
75
75
|
}
|
|
76
76
|
get currentMonthExpenses() {
|
|
77
77
|
return this.expenses.filter((e) => d(this.dateRange, e));
|
|
@@ -80,25 +80,25 @@ var d = (e, t) => h(t.expectedDate, e), s = (e, t) => e + t.amount, U = class {
|
|
|
80
80
|
return this.income.filter((e) => d(this.dateRange, e));
|
|
81
81
|
}
|
|
82
82
|
get expenseTotal() {
|
|
83
|
-
return this.currentMonthExpenses.reduce(
|
|
83
|
+
return this.currentMonthExpenses.reduce(a, 0);
|
|
84
84
|
}
|
|
85
85
|
get paidExpenseTotal() {
|
|
86
|
-
return this.currentMonthExpenses.filter((e) => e.status === n.Paid).reduce(
|
|
86
|
+
return this.currentMonthExpenses.filter((e) => e.status === n.Paid).reduce(a, 0);
|
|
87
87
|
}
|
|
88
88
|
get missedExpenseTotal() {
|
|
89
|
-
return this.currentMonthExpenses.filter((e) => e.status === n.Missed).reduce(
|
|
89
|
+
return this.currentMonthExpenses.filter((e) => e.status === n.Missed).reduce(a, 0);
|
|
90
90
|
}
|
|
91
91
|
get upcomingExpenseTotal() {
|
|
92
|
-
return this.currentMonthExpenses.filter((e) => e.status === n.Upcoming).reduce(
|
|
92
|
+
return this.currentMonthExpenses.filter((e) => e.status === n.Upcoming).reduce(a, 0);
|
|
93
93
|
}
|
|
94
94
|
get incomeTotal() {
|
|
95
|
-
return this.currentMonthIncome.reduce(
|
|
95
|
+
return this.currentMonthIncome.reduce(a, 0);
|
|
96
96
|
}
|
|
97
97
|
get paidIncomeTotal() {
|
|
98
|
-
return this.currentMonthIncome.filter((e) => e.status === n.Paid).reduce(
|
|
98
|
+
return this.currentMonthIncome.filter((e) => e.status === n.Paid).reduce(a, 0);
|
|
99
99
|
}
|
|
100
100
|
get upcomingIncomeTotal() {
|
|
101
|
-
return this.currentMonthIncome.filter((e) => e.status === n.Upcoming).reduce(
|
|
101
|
+
return this.currentMonthIncome.filter((e) => e.status === n.Upcoming).reduce(a, 0);
|
|
102
102
|
}
|
|
103
103
|
get selectedDayRecurrences() {
|
|
104
104
|
return this.selectedDay && this.recurrences.filter((e) => this.selectedDay && g(e.occurredOnDate || e.expectedDate, this.selectedDay));
|
|
@@ -127,7 +127,7 @@ var d = (e, t) => h(t.expectedDate, e), s = (e, t) => e + t.amount, U = class {
|
|
|
127
127
|
const e = await this.api.getRepeatingTransactions();
|
|
128
128
|
this.setRepeatingTransactions(e);
|
|
129
129
|
} catch (e) {
|
|
130
|
-
|
|
130
|
+
this.captureError("getRepeatingTransactions", e);
|
|
131
131
|
}
|
|
132
132
|
};
|
|
133
133
|
addRepeatingTransaction = async (e, t) => {
|
|
@@ -137,19 +137,19 @@ var d = (e, t) => h(t.expectedDate, e), s = (e, t) => e + t.amount, U = class {
|
|
|
137
137
|
...t,
|
|
138
138
|
repeating_transaction_guid: r.guid
|
|
139
139
|
}), u(() => {
|
|
140
|
-
this.repeatingTransactions = [...this.repeatingTransactions, ...
|
|
140
|
+
this.repeatingTransactions = [...this.repeatingTransactions, ...o(this.globalStore.accountStore.visibleAccounts, [r], this.globalStore.transactionStore.transactions)];
|
|
141
141
|
}), this.setAlert(this.copy.add_repeating_transaction_success, "success"), !0;
|
|
142
142
|
} catch (r) {
|
|
143
|
-
return
|
|
143
|
+
return this.captureError("addRepeatingTransaction", r), this.setAlert(this.copy.add_repeating_transaction_error, "error"), !1;
|
|
144
144
|
}
|
|
145
145
|
};
|
|
146
146
|
deleteRepeatingTransaction = async (e) => {
|
|
147
147
|
try {
|
|
148
148
|
return await this.api.deleteRepeatingTransaction(e), u(() => {
|
|
149
|
-
this.repeatingTransactions =
|
|
149
|
+
this.repeatingTransactions = this.repeatingTransactions.filter((t) => t.guid !== e);
|
|
150
150
|
}), this.setAlert(this.copy.remove_repeating_transaction_success, "success"), !0;
|
|
151
151
|
} catch (t) {
|
|
152
|
-
return
|
|
152
|
+
return this.captureError("deleteRepeatingTransaction", t), this.setAlert(this.copy.remove_repeating_transaction_error, "error"), !1;
|
|
153
153
|
}
|
|
154
154
|
};
|
|
155
155
|
updateRepeatingTransaction = async (e) => {
|
|
@@ -158,12 +158,12 @@ var d = (e, t) => h(t.expectedDate, e), s = (e, t) => e + t.amount, U = class {
|
|
|
158
158
|
return r < 0 ? !1 : (u(() => {
|
|
159
159
|
this.repeatingTransactions = [
|
|
160
160
|
...this.repeatingTransactions.slice(0, r),
|
|
161
|
-
...
|
|
161
|
+
...o(this.globalStore.accountStore.visibleAccounts, [t], this.globalStore.transactionStore.transactions),
|
|
162
162
|
...this.repeatingTransactions.slice(r + 1)
|
|
163
163
|
];
|
|
164
164
|
}), this.setAlert(this.copy.update_repeating_transaction_success, "success"), !0);
|
|
165
165
|
} catch (t) {
|
|
166
|
-
return
|
|
166
|
+
return this.captureError("updateRepeatingTransaction", t), this.setAlert(this.copy.update_repeating_transaction_error, "error"), !1;
|
|
167
167
|
}
|
|
168
168
|
};
|
|
169
169
|
markRecurrenceAsPaid = async (e, t) => {
|
|
@@ -173,7 +173,7 @@ var d = (e, t) => h(t.expectedDate, e), s = (e, t) => e + t.amount, U = class {
|
|
|
173
173
|
repeating_transaction_guid: e
|
|
174
174
|
}), await this.loadRepeatingTransactions(), this.setSelectedRecurrence(null), this.setAlert(this.copy.link_transaction_success, "success");
|
|
175
175
|
} catch (r) {
|
|
176
|
-
|
|
176
|
+
this.captureError("markRecurrenceAsPaid", r), this.setAlert(this.copy.link_transaction_error, "error");
|
|
177
177
|
}
|
|
178
178
|
};
|
|
179
179
|
markRecurrenceAsUnpaid = async (e) => {
|
|
@@ -183,9 +183,13 @@ var d = (e, t) => h(t.expectedDate, e), s = (e, t) => e + t.amount, U = class {
|
|
|
183
183
|
repeating_transaction_guid: null
|
|
184
184
|
}), await this.loadRepeatingTransactions(), this.setSelectedRecurrence(null), this.setAlert(this.copy.unlink_transaction_success, "success");
|
|
185
185
|
} catch (t) {
|
|
186
|
-
|
|
186
|
+
this.captureError("markRecurrenceAsUnpaid", t), this.setAlert(this.copy.unlink_transaction_error, "error");
|
|
187
187
|
}
|
|
188
188
|
};
|
|
189
|
+
captureError = (e, t) => this.globalStore.captureException(t, {
|
|
190
|
+
store: "RecurringTransactionsStore",
|
|
191
|
+
action: e
|
|
192
|
+
});
|
|
189
193
|
setAlert = (e, t = void 0) => this.alert = {
|
|
190
194
|
message: e,
|
|
191
195
|
severity: t
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RecurringTransactionsStore.es.js","names":[],"sources":["../../../src/core/stores/RecurringTransactionsStore.ts"],"sourcesContent":["import { type AlertProps } from '@mui/material'\nimport { makeAutoObservable, runInAction } from 'mobx'\nimport { endOfMonth } from 'date-fns/endOfMonth'\nimport { isAfter } from 'date-fns/isAfter'\nimport { isBefore } from 'date-fns/isBefore'\nimport { isSameDay } from 'date-fns/isSameDay'\nimport { isWithinInterval } from 'date-fns/isWithinInterval'\nimport { startOfMonth } from 'date-fns/startOfMonth'\nimport { startOfToday } from 'date-fns/startOfToday'\nimport { subDays } from 'date-fns/subDays'\n\nimport { RepeatingTransactionsApi } from '../api'\nimport {\n type Recurrence,\n type RecurringCopy,\n type RepeatingTransaction,\n type Transaction,\n RecurrenceStatus,\n RecurrenceType,\n type DateRange,\n} from '../types'\nimport {\n augmentRepeatingTransactions,\n buildAllRecurrences,\n} from '../utils/RecurringTransactionsUtil'\n\nimport { GlobalStore } from './GlobalStore'\n\nconst currentMonthFilter = (date: DateRange, recurrence: Recurrence) =>\n isWithinInterval(recurrence.expectedDate, date)\n\nconst recurrenceTotalReducer = (total: number, recurrence: Recurrence) => total + recurrence.amount\n\ninterface RecurringAlertProps {\n message: string\n severity: AlertProps['severity']\n}\n\nexport class RecurringTransactionsStore {\n globalStore: GlobalStore\n api = new RepeatingTransactionsApi('/', '')\n\n repeatingTransactions: RepeatingTransaction[] = []\n isDataLoaded: boolean = false\n\n selectedDay: Date | undefined\n dateRange: DateRange = { start: startOfMonth(startOfToday()), end: endOfMonth(startOfToday()) }\n selectedRepeatingTransactionGuid: string | null = null\n selectedRecurrence: Recurrence | null = null\n\n alert: RecurringAlertProps = { message: '', severity: undefined }\n\n constructor(globalStore: GlobalStore) {\n this.globalStore = globalStore\n this.api = new RepeatingTransactionsApi(\n globalStore.endpoint,\n globalStore.sessionToken,\n globalStore.onError,\n )\n\n // The *ForRange helpers are parameterized computeds: they must stay plain\n // methods (not actions) so observable reads inside them remain tracked when\n // invoked from an observer/derivation. makeAutoObservable would otherwise\n // annotate them as actions, which do not track reads.\n makeAutoObservable(this, {\n recurrencesForRange: false,\n upcomingExpensesForRange: false,\n upcomingIncomeForRange: false,\n incomeForRange: false,\n nextIncomeForRange: false,\n })\n }\n\n get copy(): RecurringCopy {\n return this.globalStore.copyStore.copy.recurring\n }\n\n get detailedRepeatingTransactions(): RepeatingTransaction[] {\n return augmentRepeatingTransactions(\n this.globalStore.accountStore.visibleAccounts,\n this.repeatingTransactions,\n this.globalStore.transactionStore.transactions,\n )\n }\n\n /**\n * Returns all recurrences built from repeating transactions and filtered by\n * accounts, scoped to the supplied date range. This is the range-parameterized\n * core used by both the shared getters (which pass this.dateRange) and by\n * consumers such as Cash Flow that need their own independent window without\n * mutating the shared dateRange.\n */\n recurrencesForRange = (dateRange: DateRange): Recurrence[] => {\n const accounts = this.globalStore.accountStore.visibleAccounts\n\n return buildAllRecurrences(this.detailedRepeatingTransactions, dateRange)\n .filter((r) => accounts.some((a) => a.guid === r.accountGuid && !a.is_excluded_from_accounts))\n .filter((r) => isWithinInterval(r.expectedDate, dateRange))\n }\n\n /**\n * Returns the upcoming expense recurrences scoped to the supplied date range.\n */\n upcomingExpensesForRange = (dateRange: DateRange): Recurrence[] => {\n return this.recurrencesForRange(dateRange).filter(\n (recurrence: Recurrence) =>\n recurrence.type === RecurrenceType.Expense &&\n recurrence.status === RecurrenceStatus.Upcoming,\n )\n }\n\n /**\n * Returns the income recurrences scoped to the supplied date range.\n */\n incomeForRange = (dateRange: DateRange): Recurrence[] => {\n return this.recurrencesForRange(dateRange).filter(\n (recurrence: Recurrence) => recurrence.type === RecurrenceType.Income,\n )\n }\n\n /**\n * Returns the upcoming income recurrences scoped to the supplied date range.\n */\n upcomingIncomeForRange = (dateRange: DateRange): Recurrence[] => {\n return this.incomeForRange(dateRange).filter(\n (recurrence: Recurrence) => recurrence.status === RecurrenceStatus.Upcoming,\n )\n }\n\n /**\n * Returns the next upcoming income recurrence scoped to the supplied range.\n */\n nextIncomeForRange = (dateRange: DateRange): Recurrence | undefined => {\n return this.upcomingIncomeForRange(dateRange).find((r) =>\n isAfter(r.expectedDate, startOfToday()),\n )\n }\n\n /**\n * Returns all recurrences built from repeating transactions and filtered by accounts.\n */\n get recurrences(): Recurrence[] {\n return this.recurrencesForRange(this.dateRange)\n }\n\n /**\n * Returns all recurrences that have occurred in the past, including those that are paid or missed\n */\n get pastRecurrences(): Recurrence[] {\n return this.recurrences.filter(\n (recurrence: Recurrence) =>\n recurrence.status === RecurrenceStatus.Paid ||\n recurrence.status === RecurrenceStatus.Missed,\n )\n }\n\n /**\n * Returns all recurrences that are expected to occur through the end of the month\n * or should have occurred in the last 3 days.\n */\n get upcomingRecurrences(): Recurrence[] {\n return this.recurrences.filter(\n (r) =>\n isAfter(r.expectedDate, subDays(startOfToday(), 3)) &&\n isBefore(r.expectedDate, this.dateRange.end) &&\n r.status === RecurrenceStatus.Upcoming,\n )\n }\n\n /**\n * Returns all expense recurrences.\n */\n get expenses(): Recurrence[] {\n return this.recurrences.filter(\n (recurrence: Recurrence) => recurrence.type === RecurrenceType.Expense,\n )\n }\n\n /**\n * Returns the upcoming expense recurrences.\n */\n get upcomingExpenses(): Recurrence[] {\n return this.expenses.filter(\n (recurrence: Recurrence) => recurrence.status === RecurrenceStatus.Upcoming,\n )\n }\n\n /**\n * Returns all income recurrences.\n */\n get income(): Recurrence[] {\n return this.recurrences.filter(\n (recurrence: Recurrence) => recurrence.type === RecurrenceType.Income,\n )\n }\n\n /**\n * Returns the upcoming income recurrences.\n */\n get upcomingIncome(): Recurrence[] {\n return this.income.filter(\n (recurrence: Recurrence) => recurrence.status === RecurrenceStatus.Upcoming,\n )\n }\n\n get nextIncomeRecurrence() {\n return this.upcomingIncome.find((r) => isAfter(r.expectedDate, startOfToday()))\n }\n\n /**\n * Returns the expense recurrences for the current month.\n */\n get currentMonthExpenses(): Recurrence[] {\n return this.expenses.filter((recurrence: Recurrence) =>\n currentMonthFilter(this.dateRange, recurrence),\n )\n }\n\n /**\n * Returns the income recurrences for the current month.\n */\n get currentMonthIncome(): Recurrence[] {\n return this.income.filter((recurrence: Recurrence) =>\n currentMonthFilter(this.dateRange, recurrence),\n )\n }\n\n /**\n * Calculates the total amount of all expenses for the current month.\n */\n get expenseTotal(): number {\n return this.currentMonthExpenses.reduce(recurrenceTotalReducer, 0)\n }\n\n /**\n * Calculates the total amount of all paid expenses for the current month.\n */\n get paidExpenseTotal(): number {\n return this.currentMonthExpenses\n .filter((recurrence: Recurrence) => recurrence.status === RecurrenceStatus.Paid)\n .reduce(recurrenceTotalReducer, 0)\n }\n\n /**\n * Calculates the total amount of all missed expenses for the current month.\n */\n get missedExpenseTotal(): number {\n return this.currentMonthExpenses\n .filter((recurrence: Recurrence) => recurrence.status === RecurrenceStatus.Missed)\n .reduce(recurrenceTotalReducer, 0)\n }\n\n /**\n * Calculates the total amount of all upcoming expenses for the current month.\n */\n get upcomingExpenseTotal(): number {\n return this.currentMonthExpenses\n .filter((recurrence: Recurrence) => recurrence.status === RecurrenceStatus.Upcoming)\n .reduce(recurrenceTotalReducer, 0)\n }\n\n /**\n * Calculates the total amount of all income for the current month.\n */\n get incomeTotal(): number {\n return this.currentMonthIncome.reduce(recurrenceTotalReducer, 0)\n }\n\n /**\n * Calculates the total amount of all paid income for the current month.\n */\n get paidIncomeTotal(): number {\n return this.currentMonthIncome\n .filter((recurrence: Recurrence) => recurrence.status === RecurrenceStatus.Paid)\n .reduce(recurrenceTotalReducer, 0)\n }\n\n /**\n * Calculates the total amount of all upcoming income for the current month.\n */\n get upcomingIncomeTotal(): number {\n return this.currentMonthIncome\n .filter((recurrence: Recurrence) => recurrence.status === RecurrenceStatus.Upcoming)\n .reduce(recurrenceTotalReducer, 0)\n }\n\n /**\n * Get the recurrences for the currently selected day.\n */\n get selectedDayRecurrences(): Recurrence[] | undefined {\n return (\n this.selectedDay &&\n this.recurrences.filter(\n (recurrence: Recurrence) =>\n this.selectedDay &&\n isSameDay(recurrence.occurredOnDate || recurrence.expectedDate, this.selectedDay),\n )\n )\n }\n\n get selectedRepeatingTransaction(): RepeatingTransaction | undefined {\n return this.selectedRepeatingTransactionGuid\n ? this.detailedRepeatingTransactions.find(\n (rt) => rt.guid === this.selectedRepeatingTransactionGuid,\n )\n : undefined\n }\n\n setSelectedRepeatingTransactionGuid = (guid: string | null) =>\n (this.selectedRepeatingTransactionGuid = guid)\n\n setSelectedRecurrence = (recurrence: Recurrence | null) => (this.selectedRecurrence = recurrence)\n\n setRepeatingTransactions = (repeating: RepeatingTransaction[]) => {\n this.repeatingTransactions = repeating\n this.isDataLoaded = true\n }\n\n /**\n * Set the date range for filtering recurrences.\n * @param dateRange - The date range to set.\n */\n setDateRange = (dateRange: DateRange) => (this.dateRange = dateRange)\n\n /**\n * Set the currently selected day.\n * @param day - The day to select.\n */\n setSelectedDay = (day: Date) => {\n this.selectedDay = this.selectedDay && isSameDay(day, this.selectedDay) ? undefined : day\n }\n\n loadRepeatingTransactionData = async () => {\n await Promise.all([\n this.globalStore.accountStore.loadAccountData(),\n this.globalStore.categoryStore.loadCategories(),\n this.globalStore.transactionStore.loadTransactionData(),\n ])\n await this.loadRepeatingTransactions()\n }\n\n /**\n * Load repeating transactions and augment them with additional data.\n */\n loadRepeatingTransactions = async () => {\n try {\n const repeatingTransactions = await this.api.getRepeatingTransactions()\n this.setRepeatingTransactions(repeatingTransactions)\n } catch (error) {\n console.error('Error occurred while getting repeating transactions:', error)\n this.globalStore.captureException(error, { store: 'RecurringTransactionsStore' })\n }\n }\n\n /**\n * Add a new repeating transaction and link it to the associated transaction.\n * @param repeatingTransaction - The repeating transaction to add.\n * @param transaction - The transaction associated with the repeating transaction.\n */\n addRepeatingTransaction = async (\n repeatingTransaction: RepeatingTransaction,\n transaction: Transaction,\n ): Promise<boolean> => {\n try {\n const newRepeating = await this.api.addRepeatingTransaction(repeatingTransaction)\n\n await this.globalStore.transactionStore.updateTransaction({\n ...transaction,\n repeating_transaction_guid: newRepeating.guid,\n })\n\n runInAction(() => {\n this.repeatingTransactions = [\n ...this.repeatingTransactions,\n ...augmentRepeatingTransactions(\n this.globalStore.accountStore.visibleAccounts,\n [newRepeating],\n this.globalStore.transactionStore.transactions,\n ),\n ]\n })\n\n this.setAlert(this.copy.add_repeating_transaction_success, 'success')\n\n return true\n } catch (error) {\n console.error('Error occurred while adding repeating transaction:', error)\n this.globalStore.captureException(error, { store: 'RecurringTransactionsStore' })\n this.setAlert(this.copy.add_repeating_transaction_error, 'error')\n\n return false\n }\n }\n\n /**\n * Delete a repeating transaction by its GUID.\n * @param guid - The GUID of the repeating transaction to delete.\n */\n deleteRepeatingTransaction = async (guid: string): Promise<boolean> => {\n try {\n await this.api.deleteRepeatingTransaction(guid)\n\n runInAction(() => {\n this.repeatingTransactions = [\n ...this.repeatingTransactions.filter((rt) => rt.guid !== guid),\n ]\n })\n\n this.setAlert(this.copy.remove_repeating_transaction_success, 'success')\n\n return true\n } catch (error) {\n console.error('Error occurred while deleting repeating transaction:', error)\n this.globalStore.captureException(error, { store: 'RecurringTransactionsStore' })\n this.setAlert(this.copy.remove_repeating_transaction_error, 'error')\n\n return false\n }\n }\n\n /**\n * Update an existing repeating transaction.\n * @param transaction - The repeating transaction to update.\n */\n updateRepeatingTransaction = async (transaction: RepeatingTransaction): Promise<boolean> => {\n try {\n const updatedTransaction = await this.api.updateRepeatingTransaction(transaction)\n\n const index = this.repeatingTransactions.findIndex(\n (rt) => rt.guid === updatedTransaction.guid,\n )\n if (index < 0) return false\n\n runInAction(() => {\n this.repeatingTransactions = [\n ...this.repeatingTransactions.slice(0, index),\n ...augmentRepeatingTransactions(\n this.globalStore.accountStore.visibleAccounts,\n [updatedTransaction],\n this.globalStore.transactionStore.transactions,\n ),\n ...this.repeatingTransactions.slice(index + 1),\n ]\n })\n\n this.setAlert(this.copy.update_repeating_transaction_success, 'success')\n\n return true\n } catch (error) {\n console.error('Error occurred while updating repeating transaction:', error)\n this.globalStore.captureException(error, { store: 'RecurringTransactionsStore' })\n this.setAlert(this.copy.update_repeating_transaction_error, 'error')\n\n return false\n }\n }\n\n /**\n * Mark a recurrence as paid by linking a transaction to the repeating transaction.\n * @param repeatingTransactionGuid - The GUID of the repeating transaction.\n * @param transaction - The transaction to link.\n */\n markRecurrenceAsPaid = async (repeatingTransactionGuid: string, transaction: Transaction) => {\n try {\n await this.globalStore.transactionStore.updateTransaction({\n ...transaction,\n repeating_transaction_guid: repeatingTransactionGuid,\n })\n\n await this.loadRepeatingTransactions()\n this.setSelectedRecurrence(null)\n this.setAlert(this.copy.link_transaction_success, 'success')\n } catch (error) {\n console.error('Error occurred while marking recurrence as paid:', error)\n this.globalStore.captureException(error, { store: 'RecurringTransactionsStore' })\n this.setAlert(this.copy.link_transaction_error, 'error')\n }\n }\n\n /**\n * Mark a recurrence as unpaid by unlinking the associated transaction from the repeating transaction.\n * @param transaction - The transaction to unlink.\n */\n markRecurrenceAsUnpaid = async (transaction: Transaction) => {\n try {\n await this.globalStore.transactionStore.updateTransaction({\n ...transaction,\n repeating_transaction_guid: null,\n })\n\n await this.loadRepeatingTransactions()\n this.setSelectedRecurrence(null)\n this.setAlert(this.copy.unlink_transaction_success, 'success')\n } catch (error) {\n console.error('Error occurred while marking recurrence as unpaid:', error)\n this.globalStore.captureException(error, { store: 'RecurringTransactionsStore' })\n this.setAlert(this.copy.unlink_transaction_error, 'error')\n }\n }\n\n setAlert = (message: string, severity: RecurringAlertProps['severity'] = undefined) =>\n (this.alert = { message, severity })\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"RecurringTransactionsStore.es.js","names":[],"sources":["../../../src/core/stores/RecurringTransactionsStore.ts"],"sourcesContent":["import { type AlertProps } from '@mui/material'\nimport { makeAutoObservable, runInAction } from 'mobx'\nimport { endOfMonth } from 'date-fns/endOfMonth'\nimport { isAfter } from 'date-fns/isAfter'\nimport { isBefore } from 'date-fns/isBefore'\nimport { isSameDay } from 'date-fns/isSameDay'\nimport { isWithinInterval } from 'date-fns/isWithinInterval'\nimport { startOfMonth } from 'date-fns/startOfMonth'\nimport { startOfToday } from 'date-fns/startOfToday'\nimport { subDays } from 'date-fns/subDays'\n\nimport { RepeatingTransactionsApi } from '../api'\nimport {\n type Recurrence,\n type RecurringCopy,\n type RepeatingTransaction,\n type Transaction,\n RecurrenceStatus,\n RecurrenceType,\n type DateRange,\n} from '../types'\nimport {\n augmentRepeatingTransactions,\n buildAllRecurrences,\n} from '../utils/RecurringTransactionsUtil'\n\nimport { GlobalStore } from './GlobalStore'\n\nconst currentMonthFilter = (date: DateRange, recurrence: Recurrence) =>\n isWithinInterval(recurrence.expectedDate, date)\n\nconst recurrenceTotalReducer = (total: number, recurrence: Recurrence) => total + recurrence.amount\n\ninterface RecurringAlertProps {\n message: string\n severity: AlertProps['severity']\n}\n\nexport class RecurringTransactionsStore {\n globalStore: GlobalStore\n api = new RepeatingTransactionsApi('/', '')\n\n repeatingTransactions: RepeatingTransaction[] = []\n isDataLoaded: boolean = false\n\n selectedDay: Date | undefined\n dateRange: DateRange = { start: startOfMonth(startOfToday()), end: endOfMonth(startOfToday()) }\n selectedRepeatingTransactionGuid: string | null = null\n selectedRecurrence: Recurrence | null = null\n\n alert: RecurringAlertProps = { message: '', severity: undefined }\n\n constructor(globalStore: GlobalStore) {\n this.globalStore = globalStore\n this.api = new RepeatingTransactionsApi(\n globalStore.endpoint,\n globalStore.sessionToken,\n globalStore.onError,\n )\n\n // The *ForRange helpers are parameterized computeds: they must stay plain\n // methods (not actions) so observable reads inside them remain tracked when\n // invoked from an observer/derivation. makeAutoObservable would otherwise\n // annotate them as actions, which do not track reads.\n makeAutoObservable(this, {\n recurrencesForRange: false,\n upcomingExpensesForRange: false,\n upcomingIncomeForRange: false,\n incomeForRange: false,\n nextIncomeForRange: false,\n })\n }\n\n get copy(): RecurringCopy {\n return this.globalStore.copyStore.copy.recurring\n }\n\n get detailedRepeatingTransactions(): RepeatingTransaction[] {\n return augmentRepeatingTransactions(\n this.globalStore.accountStore.visibleAccounts,\n this.repeatingTransactions,\n this.globalStore.transactionStore.transactions,\n )\n }\n\n /**\n * Returns all recurrences built from repeating transactions and filtered by\n * accounts, scoped to the supplied date range. This is the range-parameterized\n * core used by both the shared getters (which pass this.dateRange) and by\n * consumers such as Cash Flow that need their own independent window without\n * mutating the shared dateRange.\n */\n recurrencesForRange = (dateRange: DateRange): Recurrence[] => {\n const accounts = this.globalStore.accountStore.visibleAccounts\n\n return buildAllRecurrences(this.detailedRepeatingTransactions, dateRange)\n .filter((r) => accounts.some((a) => a.guid === r.accountGuid && !a.is_excluded_from_accounts))\n .filter((r) => isWithinInterval(r.expectedDate, dateRange))\n }\n\n /**\n * Returns the upcoming expense recurrences scoped to the supplied date range.\n */\n upcomingExpensesForRange = (dateRange: DateRange): Recurrence[] => {\n return this.recurrencesForRange(dateRange).filter(\n (recurrence: Recurrence) =>\n recurrence.type === RecurrenceType.Expense &&\n recurrence.status === RecurrenceStatus.Upcoming,\n )\n }\n\n /**\n * Returns the income recurrences scoped to the supplied date range.\n */\n incomeForRange = (dateRange: DateRange): Recurrence[] => {\n return this.recurrencesForRange(dateRange).filter(\n (recurrence: Recurrence) => recurrence.type === RecurrenceType.Income,\n )\n }\n\n /**\n * Returns the upcoming income recurrences scoped to the supplied date range.\n */\n upcomingIncomeForRange = (dateRange: DateRange): Recurrence[] => {\n return this.incomeForRange(dateRange).filter(\n (recurrence: Recurrence) => recurrence.status === RecurrenceStatus.Upcoming,\n )\n }\n\n /**\n * Returns the next upcoming income recurrence scoped to the supplied range.\n */\n nextIncomeForRange = (dateRange: DateRange): Recurrence | undefined => {\n return this.upcomingIncomeForRange(dateRange).find((r) =>\n isAfter(r.expectedDate, startOfToday()),\n )\n }\n\n /**\n * Returns all recurrences built from repeating transactions and filtered by accounts.\n */\n get recurrences(): Recurrence[] {\n return this.recurrencesForRange(this.dateRange)\n }\n\n /**\n * Returns all recurrences that have occurred in the past, including those that are paid or missed\n */\n get pastRecurrences(): Recurrence[] {\n return this.recurrences.filter(\n (recurrence: Recurrence) =>\n recurrence.status === RecurrenceStatus.Paid ||\n recurrence.status === RecurrenceStatus.Missed,\n )\n }\n\n /**\n * Returns all recurrences that are expected to occur through the end of the month\n * or should have occurred in the last 3 days.\n */\n get upcomingRecurrences(): Recurrence[] {\n return this.recurrences.filter(\n (r) =>\n isAfter(r.expectedDate, subDays(startOfToday(), 3)) &&\n isBefore(r.expectedDate, this.dateRange.end) &&\n r.status === RecurrenceStatus.Upcoming,\n )\n }\n\n /**\n * Returns all expense recurrences.\n */\n get expenses(): Recurrence[] {\n return this.recurrences.filter(\n (recurrence: Recurrence) => recurrence.type === RecurrenceType.Expense,\n )\n }\n\n /**\n * Returns the upcoming expense recurrences.\n */\n get upcomingExpenses(): Recurrence[] {\n return this.expenses.filter(\n (recurrence: Recurrence) => recurrence.status === RecurrenceStatus.Upcoming,\n )\n }\n\n /**\n * Returns all income recurrences.\n */\n get income(): Recurrence[] {\n return this.recurrences.filter(\n (recurrence: Recurrence) => recurrence.type === RecurrenceType.Income,\n )\n }\n\n /**\n * Returns the upcoming income recurrences.\n */\n get upcomingIncome(): Recurrence[] {\n return this.income.filter(\n (recurrence: Recurrence) => recurrence.status === RecurrenceStatus.Upcoming,\n )\n }\n\n get nextIncomeRecurrence() {\n return this.upcomingIncome.find((r) => isAfter(r.expectedDate, startOfToday()))\n }\n\n /**\n * Returns the expense recurrences for the current month.\n */\n get currentMonthExpenses(): Recurrence[] {\n return this.expenses.filter((recurrence: Recurrence) =>\n currentMonthFilter(this.dateRange, recurrence),\n )\n }\n\n /**\n * Returns the income recurrences for the current month.\n */\n get currentMonthIncome(): Recurrence[] {\n return this.income.filter((recurrence: Recurrence) =>\n currentMonthFilter(this.dateRange, recurrence),\n )\n }\n\n /**\n * Calculates the total amount of all expenses for the current month.\n */\n get expenseTotal(): number {\n return this.currentMonthExpenses.reduce(recurrenceTotalReducer, 0)\n }\n\n /**\n * Calculates the total amount of all paid expenses for the current month.\n */\n get paidExpenseTotal(): number {\n return this.currentMonthExpenses\n .filter((recurrence: Recurrence) => recurrence.status === RecurrenceStatus.Paid)\n .reduce(recurrenceTotalReducer, 0)\n }\n\n /**\n * Calculates the total amount of all missed expenses for the current month.\n */\n get missedExpenseTotal(): number {\n return this.currentMonthExpenses\n .filter((recurrence: Recurrence) => recurrence.status === RecurrenceStatus.Missed)\n .reduce(recurrenceTotalReducer, 0)\n }\n\n /**\n * Calculates the total amount of all upcoming expenses for the current month.\n */\n get upcomingExpenseTotal(): number {\n return this.currentMonthExpenses\n .filter((recurrence: Recurrence) => recurrence.status === RecurrenceStatus.Upcoming)\n .reduce(recurrenceTotalReducer, 0)\n }\n\n /**\n * Calculates the total amount of all income for the current month.\n */\n get incomeTotal(): number {\n return this.currentMonthIncome.reduce(recurrenceTotalReducer, 0)\n }\n\n /**\n * Calculates the total amount of all paid income for the current month.\n */\n get paidIncomeTotal(): number {\n return this.currentMonthIncome\n .filter((recurrence: Recurrence) => recurrence.status === RecurrenceStatus.Paid)\n .reduce(recurrenceTotalReducer, 0)\n }\n\n /**\n * Calculates the total amount of all upcoming income for the current month.\n */\n get upcomingIncomeTotal(): number {\n return this.currentMonthIncome\n .filter((recurrence: Recurrence) => recurrence.status === RecurrenceStatus.Upcoming)\n .reduce(recurrenceTotalReducer, 0)\n }\n\n /**\n * Get the recurrences for the currently selected day.\n */\n get selectedDayRecurrences(): Recurrence[] | undefined {\n return (\n this.selectedDay &&\n this.recurrences.filter(\n (recurrence: Recurrence) =>\n this.selectedDay &&\n isSameDay(recurrence.occurredOnDate || recurrence.expectedDate, this.selectedDay),\n )\n )\n }\n\n get selectedRepeatingTransaction(): RepeatingTransaction | undefined {\n return this.selectedRepeatingTransactionGuid\n ? this.detailedRepeatingTransactions.find(\n (rt) => rt.guid === this.selectedRepeatingTransactionGuid,\n )\n : undefined\n }\n\n setSelectedRepeatingTransactionGuid = (guid: string | null) =>\n (this.selectedRepeatingTransactionGuid = guid)\n\n setSelectedRecurrence = (recurrence: Recurrence | null) => (this.selectedRecurrence = recurrence)\n\n setRepeatingTransactions = (repeating: RepeatingTransaction[]) => {\n this.repeatingTransactions = repeating\n this.isDataLoaded = true\n }\n\n /**\n * Set the date range for filtering recurrences.\n * @param dateRange - The date range to set.\n */\n setDateRange = (dateRange: DateRange) => (this.dateRange = dateRange)\n\n /**\n * Set the currently selected day.\n * @param day - The day to select.\n */\n setSelectedDay = (day: Date) => {\n this.selectedDay = this.selectedDay && isSameDay(day, this.selectedDay) ? undefined : day\n }\n\n loadRepeatingTransactionData = async () => {\n await Promise.all([\n this.globalStore.accountStore.loadAccountData(),\n this.globalStore.categoryStore.loadCategories(),\n this.globalStore.transactionStore.loadTransactionData(),\n ])\n await this.loadRepeatingTransactions()\n }\n\n /**\n * Load repeating transactions and augment them with additional data.\n */\n loadRepeatingTransactions = async () => {\n try {\n const repeatingTransactions = await this.api.getRepeatingTransactions()\n this.setRepeatingTransactions(repeatingTransactions)\n } catch (error) {\n this.captureError('getRepeatingTransactions', error)\n }\n }\n\n /**\n * Add a new repeating transaction and link it to the associated transaction.\n * @param repeatingTransaction - The repeating transaction to add.\n * @param transaction - The transaction associated with the repeating transaction.\n */\n addRepeatingTransaction = async (\n repeatingTransaction: RepeatingTransaction,\n transaction: Transaction,\n ): Promise<boolean> => {\n try {\n const newRepeating = await this.api.addRepeatingTransaction(repeatingTransaction)\n\n await this.globalStore.transactionStore.updateTransaction({\n ...transaction,\n repeating_transaction_guid: newRepeating.guid,\n })\n\n runInAction(() => {\n this.repeatingTransactions = [\n ...this.repeatingTransactions,\n ...augmentRepeatingTransactions(\n this.globalStore.accountStore.visibleAccounts,\n [newRepeating],\n this.globalStore.transactionStore.transactions,\n ),\n ]\n })\n\n this.setAlert(this.copy.add_repeating_transaction_success, 'success')\n\n return true\n } catch (error) {\n this.captureError('addRepeatingTransaction', error)\n this.setAlert(this.copy.add_repeating_transaction_error, 'error')\n\n return false\n }\n }\n\n /**\n * Delete a repeating transaction by its GUID.\n * @param guid - The GUID of the repeating transaction to delete.\n */\n deleteRepeatingTransaction = async (guid: string): Promise<boolean> => {\n try {\n await this.api.deleteRepeatingTransaction(guid)\n\n runInAction(() => {\n this.repeatingTransactions = this.repeatingTransactions.filter((rt) => rt.guid !== guid)\n })\n\n this.setAlert(this.copy.remove_repeating_transaction_success, 'success')\n\n return true\n } catch (error) {\n this.captureError('deleteRepeatingTransaction', error)\n this.setAlert(this.copy.remove_repeating_transaction_error, 'error')\n\n return false\n }\n }\n\n /**\n * Update an existing repeating transaction.\n * @param transaction - The repeating transaction to update.\n */\n updateRepeatingTransaction = async (transaction: RepeatingTransaction): Promise<boolean> => {\n try {\n const updatedTransaction = await this.api.updateRepeatingTransaction(transaction)\n\n const index = this.repeatingTransactions.findIndex(\n (rt) => rt.guid === updatedTransaction.guid,\n )\n if (index < 0) return false\n\n runInAction(() => {\n this.repeatingTransactions = [\n ...this.repeatingTransactions.slice(0, index),\n ...augmentRepeatingTransactions(\n this.globalStore.accountStore.visibleAccounts,\n [updatedTransaction],\n this.globalStore.transactionStore.transactions,\n ),\n ...this.repeatingTransactions.slice(index + 1),\n ]\n })\n\n this.setAlert(this.copy.update_repeating_transaction_success, 'success')\n\n return true\n } catch (error) {\n this.captureError('updateRepeatingTransaction', error)\n this.setAlert(this.copy.update_repeating_transaction_error, 'error')\n\n return false\n }\n }\n\n /**\n * Mark a recurrence as paid by linking a transaction to the repeating transaction.\n * @param repeatingTransactionGuid - The GUID of the repeating transaction.\n * @param transaction - The transaction to link.\n */\n markRecurrenceAsPaid = async (repeatingTransactionGuid: string, transaction: Transaction) => {\n try {\n await this.globalStore.transactionStore.updateTransaction({\n ...transaction,\n repeating_transaction_guid: repeatingTransactionGuid,\n })\n\n await this.loadRepeatingTransactions()\n this.setSelectedRecurrence(null)\n this.setAlert(this.copy.link_transaction_success, 'success')\n } catch (error) {\n this.captureError('markRecurrenceAsPaid', error)\n this.setAlert(this.copy.link_transaction_error, 'error')\n }\n }\n\n /**\n * Mark a recurrence as unpaid by unlinking the associated transaction from the repeating transaction.\n * @param transaction - The transaction to unlink.\n */\n markRecurrenceAsUnpaid = async (transaction: Transaction) => {\n try {\n await this.globalStore.transactionStore.updateTransaction({\n ...transaction,\n repeating_transaction_guid: null,\n })\n\n await this.loadRepeatingTransactions()\n this.setSelectedRecurrence(null)\n this.setAlert(this.copy.unlink_transaction_success, 'success')\n } catch (error) {\n this.captureError('markRecurrenceAsUnpaid', error)\n this.setAlert(this.copy.unlink_transaction_error, 'error')\n }\n }\n\n private captureError = (action: string, error: unknown) =>\n this.globalStore.captureException(error, { store: 'RecurringTransactionsStore', action })\n\n setAlert = (message: string, severity: RecurringAlertProps['severity'] = undefined) =>\n (this.alert = { message, severity })\n}\n"],"mappings":"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"}
|