@zeniai/client-epic-state 5.2.32 → 5.2.34-beta0ND
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/lib/commonPayloadTypes/classesView/reportByClassPayloadV2.d.ts +13 -1
- package/lib/entity/notificationRegistry/notificationRegistryReducer.d.ts +2 -1
- package/lib/entity/notificationRegistry/notificationRegistryReducer.js +20 -9
- package/lib/entity/notificationRegistry/notificationRegistrySelector.d.ts +2 -1
- package/lib/entity/notificationRegistry/notificationRegistrySelector.js +7 -1
- package/lib/entity/notificationRegistry/notificationRegistryState.d.ts +5 -0
- package/lib/entity/notificationRegistry/notificationRegistryState.js +7 -1
- package/lib/entity/sectionClassesViewV2/sectionClassesViewEpic.js +10 -7
- package/lib/entity/sectionClassesViewV2/sectionClassesViewReducer.d.ts +3 -3
- package/lib/entity/sectionProjectView/sectionProjectViewEpic.js +6 -2
- package/lib/entity/sectionProjectView/sectionProjectViewReducer.d.ts +3 -3
- package/lib/entity/sectionProjectView/sectionProjectViewReducer.js +6 -3
- package/lib/epic.js +12 -0
- package/lib/esm/entity/class/classReducer.js +1 -1
- package/lib/esm/entity/notificationRegistry/notificationRegistryReducer.js +20 -9
- package/lib/esm/entity/notificationRegistry/notificationRegistrySelector.js +5 -0
- package/lib/esm/entity/notificationRegistry/notificationRegistryState.js +5 -0
- package/lib/esm/entity/sectionClassesViewV2/sectionClassesViewEpic.js +10 -7
- package/lib/esm/entity/sectionProjectView/sectionProjectViewEpic.js +6 -2
- package/lib/esm/entity/sectionProjectView/sectionProjectViewReducer.js +7 -4
- package/lib/esm/epic.js +12 -0
- package/lib/esm/index.js +6 -6
- package/lib/esm/view/aiCfoView/aiCfoViewReducer.js +268 -1
- package/lib/esm/view/aiCfoView/aiCfoViewSelector.js +50 -0
- package/lib/esm/view/aiCfoView/epics/deleteRoutineEpic.js +35 -0
- package/lib/esm/view/aiCfoView/epics/fetchRoutineRunsEpic.js +37 -0
- package/lib/esm/view/aiCfoView/epics/fetchRoutinesEpic.js +37 -0
- package/lib/esm/view/aiCfoView/epics/runRoutineEpic.js +34 -0
- package/lib/esm/view/aiCfoView/epics/saveRoutineEpic.js +65 -0
- package/lib/esm/view/aiCfoView/epics/setRoutineEnabledEpic.js +28 -0
- package/lib/esm/view/aiCfoView/epics/toRoutine.js +64 -0
- package/lib/esm/view/aiCfoView/epics/toRoutineRun.js +42 -0
- package/lib/esm/view/expenseAutomationView/selectors/fluxAnalysisViewSelector.js +12 -10
- package/lib/esm/view/expenseAutomationView/selectors/jeSchedulesViewSelector.js +3 -11
- package/lib/esm/view/expenseAutomationView/selectors/missingReceiptsSelector.js +10 -11
- package/lib/esm/view/invoicing/editInvoicingCustomerDetailView/editInvoicingCustomerDetailViewPayload.js +4 -0
- package/lib/esm/view/notificationPreferencesView/epics/saveNotificationPreferencesEpic.js +20 -7
- package/lib/esm/view/notificationPreferencesView/notificationPreferencesViewReducer.js +43 -17
- package/lib/esm/view/notificationPreferencesView/notificationPreferencesViewSelector.js +24 -4
- package/lib/esm/view/settingsView/epic/fetchNotificationSettingsEpic.js +12 -2
- package/lib/index.d.ts +8 -8
- package/lib/index.js +63 -41
- package/lib/view/aiCfoView/aiCfoViewPayload.d.ts +90 -0
- package/lib/view/aiCfoView/aiCfoViewReducer.d.ts +164 -123
- package/lib/view/aiCfoView/aiCfoViewReducer.js +270 -3
- package/lib/view/aiCfoView/aiCfoViewSelector.d.ts +13 -1
- package/lib/view/aiCfoView/aiCfoViewSelector.js +55 -0
- package/lib/view/aiCfoView/aiCfoViewState.d.ts +157 -0
- package/lib/view/aiCfoView/epics/deleteRoutineEpic.d.ts +18 -0
- package/lib/view/aiCfoView/epics/deleteRoutineEpic.js +39 -0
- package/lib/view/aiCfoView/epics/fetchRoutineRunsEpic.d.ts +13 -0
- package/lib/view/aiCfoView/epics/fetchRoutineRunsEpic.js +41 -0
- package/lib/view/aiCfoView/epics/fetchRoutinesEpic.d.ts +7 -0
- package/lib/view/aiCfoView/epics/fetchRoutinesEpic.js +41 -0
- package/lib/view/aiCfoView/epics/runRoutineEpic.d.ts +14 -0
- package/lib/view/aiCfoView/epics/runRoutineEpic.js +38 -0
- package/lib/view/aiCfoView/epics/saveRoutineEpic.d.ts +13 -0
- package/lib/view/aiCfoView/epics/saveRoutineEpic.js +69 -0
- package/lib/view/aiCfoView/epics/setRoutineEnabledEpic.d.ts +15 -0
- package/lib/view/aiCfoView/epics/setRoutineEnabledEpic.js +32 -0
- package/lib/view/aiCfoView/epics/toRoutine.d.ts +17 -0
- package/lib/view/aiCfoView/epics/toRoutine.js +69 -0
- package/lib/view/aiCfoView/epics/toRoutineRun.d.ts +12 -0
- package/lib/view/aiCfoView/epics/toRoutineRun.js +47 -0
- package/lib/view/cashFlowClassesView/cashFlowClassesViewPayload.d.ts +4 -4
- package/lib/view/cashFlowProjectView/cashFlowProjectViewPayload.d.ts +4 -4
- package/lib/view/expenseAutomationView/selectors/fluxAnalysisViewSelector.js +12 -10
- package/lib/view/expenseAutomationView/selectors/jeSchedulesViewSelector.js +3 -11
- package/lib/view/expenseAutomationView/selectors/missingReceiptsSelector.js +10 -11
- package/lib/view/invoicing/editInvoicingCustomerDetailView/editInvoicingCustomerDetailViewPayload.d.ts +1 -11
- package/lib/view/invoicing/editInvoicingCustomerDetailView/editInvoicingCustomerDetailViewPayload.js +4 -0
- package/lib/view/invoicing/editInvoicingCustomerDetailView/editInvoicingCustomerDetailViewReducer.d.ts +1 -2
- package/lib/view/invoicing/editInvoicingCustomerDetailView/editInvoicingCustomerDetailViewSelector.d.ts +1 -2
- package/lib/view/invoicing/editInvoicingCustomerDetailView/editInvoicingCustomerDetailViewState.d.ts +15 -1
- package/lib/view/invoicing/invoicingCustomerListView/invoicingCustomerListViewReducer.d.ts +1 -1
- package/lib/view/invoicing/invoicingCustomerListView/invoicingCustomerListViewState.d.ts +1 -1
- package/lib/view/notificationPreferencesView/epics/saveNotificationPreferencesEpic.js +19 -6
- package/lib/view/notificationPreferencesView/notificationPreferencesViewReducer.d.ts +8 -5
- package/lib/view/notificationPreferencesView/notificationPreferencesViewReducer.js +43 -17
- package/lib/view/notificationPreferencesView/notificationPreferencesViewSelector.d.ts +4 -0
- package/lib/view/notificationPreferencesView/notificationPreferencesViewSelector.js +30 -5
- package/lib/view/notificationPreferencesView/notificationPreferencesViewState.d.ts +4 -3
- package/lib/view/profitAndLossProjectView/profitAndLossProjectViewPayload.d.ts +12 -0
- package/lib/view/settingsView/epic/fetchNotificationSettingsEpic.js +12 -2
- package/lib/view/settingsView/settingsViewPayload.d.ts +2 -0
- package/package.json +1 -1
|
@@ -18,8 +18,20 @@ interface ClassCOABalanceGroupedPayloadByClassIdV2 {
|
|
|
18
18
|
export interface SectionByClassCOABalanceGroupedPayloadV2 extends COABalanceGroupedPayloadV2 {
|
|
19
19
|
classes: ClassCOABalanceGroupedPayloadByClassIdV2;
|
|
20
20
|
}
|
|
21
|
+
interface CalculatedClassCOABalanceGroupedPayloadByClassIdV2 {
|
|
22
|
+
[class_Id: string]: COABalanceGroupedPayloadV2;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* A section whose per-class entries carry a time series and nothing else: the
|
|
26
|
+
* backend fills the account-wise map only for the account sections, so the
|
|
27
|
+
* calculated sections (net income, the operating total, change in cash) are
|
|
28
|
+
* grouped by class with no accounts underneath.
|
|
29
|
+
*/
|
|
30
|
+
export interface CalculatedSectionByClassCOABalanceGroupedPayloadV2 extends COABalanceGroupedPayloadV2 {
|
|
31
|
+
classes: CalculatedClassCOABalanceGroupedPayloadByClassIdV2;
|
|
32
|
+
}
|
|
21
33
|
export interface ClassMetadataWithBalancesPayloadV2 {
|
|
22
|
-
classBalances:
|
|
34
|
+
classBalances: COABalanceGroupedPayloadV2;
|
|
23
35
|
classMetadata: ClassMetadataPayload;
|
|
24
36
|
nestedAccountIds: NestedAccountIDHierarchy[];
|
|
25
37
|
nestedClassId: NestedClassID;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { NotificationRegistryPayload } from './notificationRegistryPayload';
|
|
2
|
-
import { NotificationRegistryState } from './notificationRegistryState';
|
|
2
|
+
import { NotificationDomain, NotificationRegistryState } from './notificationRegistryState';
|
|
3
3
|
export declare const initialState: NotificationRegistryState;
|
|
4
4
|
export interface UpdateNotificationRegistryPayload {
|
|
5
5
|
registry: NotificationRegistryPayload | undefined;
|
|
6
6
|
registryEpochAtDispatch: number;
|
|
7
|
+
registriesByDomain?: Partial<Record<NotificationDomain, NotificationRegistryPayload | undefined>>;
|
|
7
8
|
}
|
|
8
9
|
export declare const updateNotificationRegistry: import("@reduxjs/toolkit").ActionCreatorWithPayload<UpdateNotificationRegistryPayload, "notificationRegistry/updateNotificationRegistry">;
|
|
9
10
|
declare const _default: import("redux").Reducer<NotificationRegistryState>;
|
|
@@ -4,6 +4,7 @@ exports.updateNotificationRegistry = exports.initialState = void 0;
|
|
|
4
4
|
const toolkit_1 = require("@reduxjs/toolkit");
|
|
5
5
|
const rootActions_1 = require("../../rootActions");
|
|
6
6
|
const notificationRegistryPayload_1 = require("./notificationRegistryPayload");
|
|
7
|
+
const notificationRegistryState_1 = require("./notificationRegistryState");
|
|
7
8
|
exports.initialState = { registryEpoch: 0 };
|
|
8
9
|
const notificationRegistry = (0, toolkit_1.createSlice)({
|
|
9
10
|
name: 'notificationRegistry',
|
|
@@ -22,16 +23,24 @@ const notificationRegistry = (0, toolkit_1.createSlice)({
|
|
|
22
23
|
// `task_checklist_registry` CLEARS so tenant B doesn't inherit A's
|
|
23
24
|
// Task Checklist section. Guarded by the epoch check above so a stale
|
|
24
25
|
// absent-response can't wipe a fresh registry.
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
const { registriesByDomain } = action.payload;
|
|
27
|
+
// Absent `registriesByDomain` means a pre-domain caller: treat `registry`
|
|
28
|
+
// as the task_checklist snapshot so their behaviour is unchanged.
|
|
29
|
+
const snapshots = registriesByDomain ?? { task_checklist: action.payload.registry };
|
|
30
|
+
draft.registryByDomain = {};
|
|
31
|
+
for (const domain of notificationRegistryState_1.NOTIFICATION_DOMAINS) {
|
|
32
|
+
const payload = snapshots[domain];
|
|
33
|
+
// Full-replace per domain, and an absent snapshot CLEARS that domain so
|
|
34
|
+
// tenant B never inherits A's section. The gates are independent
|
|
35
|
+
// server-side, so one domain clearing must not touch the other.
|
|
36
|
+
if (payload != null) {
|
|
37
|
+
draft.registryByDomain[domain] =
|
|
38
|
+
(0, notificationRegistryPayload_1.mapNotificationRegistryPayloadToRegistry)(payload);
|
|
39
|
+
}
|
|
28
40
|
}
|
|
29
|
-
//
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
// the preferences slice's `mergePreferences`). Do not assume the
|
|
33
|
-
// current payload is partial without also updating this reducer.
|
|
34
|
-
draft.registry = (0, notificationRegistryPayload_1.mapNotificationRegistryPayloadToRegistry)(action.payload.registry);
|
|
41
|
+
// Mirrored for consumers that predate the domain-keyed map.
|
|
42
|
+
draft.registry = draft.registryByDomain.task_checklist;
|
|
43
|
+
return;
|
|
35
44
|
},
|
|
36
45
|
},
|
|
37
46
|
extraReducers: (builder) => {
|
|
@@ -44,6 +53,8 @@ const notificationRegistry = (0, toolkit_1.createSlice)({
|
|
|
44
53
|
// — Cursor Bugbot 67d6918e. Returning `initialState` verbatim would
|
|
45
54
|
// rewind the counter and let a stale in-flight GET restore A's
|
|
46
55
|
// registry over B's.
|
|
56
|
+
// Drops `registry` and `registryByDomain` together: a tenant switch must
|
|
57
|
+
// not leave one domain's section behind.
|
|
47
58
|
return { registryEpoch: draft.registryEpoch + 1 };
|
|
48
59
|
});
|
|
49
60
|
},
|
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
import { NotificationRegistry, NotificationRegistryState } from './notificationRegistryState';
|
|
1
|
+
import { NotificationDomain, NotificationRegistry, NotificationRegistryState } from './notificationRegistryState';
|
|
2
2
|
export declare const getNotificationRegistry: (slice: NotificationRegistryState) => NotificationRegistry | undefined;
|
|
3
|
+
export declare const getNotificationRegistryForDomain: (slice: NotificationRegistryState, domain: NotificationDomain) => NotificationRegistry | undefined;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getNotificationRegistry = void 0;
|
|
3
|
+
exports.getNotificationRegistryForDomain = exports.getNotificationRegistry = void 0;
|
|
4
4
|
// Current behavior: a null / undefined registry means the whole notification
|
|
5
5
|
// section is hidden by consumers. This conflates two distinct states —
|
|
6
6
|
// "user has no saved preferences yet" vs "the Task Checklist feature gate is
|
|
@@ -8,3 +8,9 @@ exports.getNotificationRegistry = void 0;
|
|
|
8
8
|
// them (e.g. an explicit `gate_off` signal from the server) is a follow-up.
|
|
9
9
|
const getNotificationRegistry = (slice) => slice.registry;
|
|
10
10
|
exports.getNotificationRegistry = getNotificationRegistry;
|
|
11
|
+
// `undefined` conflates gate-off with no-preferences-yet; consumers hide the
|
|
12
|
+
// section either way. Falls back to `registry` for task_checklist so state built
|
|
13
|
+
// in the pre-domain shape (consumer mocks, older callers) still resolves.
|
|
14
|
+
const getNotificationRegistryForDomain = (slice, domain) => slice.registryByDomain?.[domain] ??
|
|
15
|
+
(domain === 'task_checklist' ? slice.registry : undefined);
|
|
16
|
+
exports.getNotificationRegistryForDomain = getNotificationRegistryForDomain;
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
export declare const NOTIFICATION_DOMAINS: readonly ["task_checklist", "commenting"];
|
|
2
|
+
export type NotificationDomain = (typeof NOTIFICATION_DOMAINS)[number];
|
|
3
|
+
export declare const DEFAULT_NOTIFICATION_DOMAIN: NotificationDomain;
|
|
4
|
+
export declare const toNotificationDomain: (raw: string) => NotificationDomain;
|
|
1
5
|
export declare const NOTIFICATION_CHANNELS: readonly ["email", "slack", "in_app"];
|
|
2
6
|
export type NotificationChannel = (typeof NOTIFICATION_CHANNELS)[number];
|
|
3
7
|
export declare const toNotificationChannel: (raw: string) => NotificationChannel;
|
|
@@ -30,4 +34,5 @@ export interface NotificationRegistry {
|
|
|
30
34
|
export interface NotificationRegistryState {
|
|
31
35
|
registryEpoch: number;
|
|
32
36
|
registry?: NotificationRegistry;
|
|
37
|
+
registryByDomain?: Partial<Record<NotificationDomain, NotificationRegistry>>;
|
|
33
38
|
}
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.toNotificationFrequency = exports.NOTIFICATION_FREQUENCIES = exports.toNotificationChannel = exports.NOTIFICATION_CHANNELS = void 0;
|
|
3
|
+
exports.toNotificationFrequency = exports.NOTIFICATION_FREQUENCIES = exports.toNotificationChannel = exports.NOTIFICATION_CHANNELS = exports.toNotificationDomain = exports.DEFAULT_NOTIFICATION_DOMAIN = exports.NOTIFICATION_DOMAINS = void 0;
|
|
4
4
|
const stringToUnion_1 = require("../../commonStateTypes/stringToUnion");
|
|
5
|
+
// Wire vocabulary owned by the notifications service, not by this slice.
|
|
6
|
+
exports.NOTIFICATION_DOMAINS = ['task_checklist', 'commenting'];
|
|
7
|
+
// Callers that predate the domain split mean Task Checklist.
|
|
8
|
+
exports.DEFAULT_NOTIFICATION_DOMAIN = 'task_checklist';
|
|
9
|
+
const toNotificationDomain = (raw) => (0, stringToUnion_1.stringToUnion)(raw, exports.NOTIFICATION_DOMAINS);
|
|
10
|
+
exports.toNotificationDomain = toNotificationDomain;
|
|
5
11
|
exports.NOTIFICATION_CHANNELS = ['email', 'slack', 'in_app'];
|
|
6
12
|
const toNotificationChannel = (raw) => (0, stringToUnion_1.stringToUnion)(raw, exports.NOTIFICATION_CHANNELS);
|
|
7
13
|
exports.toNotificationChannel = toNotificationChannel;
|
|
@@ -29,17 +29,20 @@ const updateSectionClassesViewEpic = (actions$) => actions$.pipe((0, operators_1
|
|
|
29
29
|
Object.keys(sectionPayload.classes).forEach((eachClassId) => {
|
|
30
30
|
const classId = classMetadataRecordsByID[eachClassId].nestedClassId;
|
|
31
31
|
const classMetadataPayload = classMetadataRecordsByID[eachClassId].classMetadataPayload;
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
32
|
+
const classPayload = sectionPayload.classes[eachClassId];
|
|
33
|
+
// A calculated section is grouped by class with no accounts under it.
|
|
34
|
+
const classAccounts = 'accounts' in classPayload ? classPayload.accounts : undefined;
|
|
35
|
+
if (classAccounts != null) {
|
|
36
|
+
accountMetadataWithBalancesPayloads.push(...(0, subAccountPayloadHelper_1.getSubAccountsMetadataForAccountList)(classAccounts, accountMetadataRecordsByID, sectionId, { parentClassId: classId, sectionId }));
|
|
37
|
+
}
|
|
38
|
+
const nestedAccountIds = classAccounts != null
|
|
39
|
+
? (0, getNestedAccountIDHierarchyForSection_1.getNestedAccountIDHierarchyForAccounts)(Object.keys(classAccounts), accountsMetadata)
|
|
40
|
+
: [];
|
|
38
41
|
if (classMetadataPayload != null) {
|
|
39
42
|
classMetadataWithBalancesPayloads.push({
|
|
40
43
|
nestedClassId: classId,
|
|
41
44
|
classMetadata: classMetadataPayload,
|
|
42
|
-
classBalances:
|
|
45
|
+
classBalances: classPayload,
|
|
43
46
|
nestedAccountIds,
|
|
44
47
|
});
|
|
45
48
|
}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { SectionByClassCOABalanceGroupedPayloadV2 } from '../../commonPayloadTypes/classesView/reportByClassPayloadV2';
|
|
1
|
+
import { CalculatedSectionByClassCOABalanceGroupedPayloadV2, SectionByClassCOABalanceGroupedPayloadV2 } from '../../commonPayloadTypes/classesView/reportByClassPayloadV2';
|
|
2
2
|
import { CurrencyPayload } from '../../commonPayloadTypes/v2/viewAndReportPayloadv2';
|
|
3
3
|
import { AccountMetadataPayload } from '../account/accountPayload';
|
|
4
4
|
import { ClassMetadataPayload } from '../class/classPayload';
|
|
5
5
|
import { SectionClassesViewStateV2 } from './sectionClassesViewState';
|
|
6
6
|
export declare const initialState: SectionClassesViewStateV2;
|
|
7
|
-
export declare const updateSectionClassesView: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[timeframe: "month" | "year" | "quarter", sectionId: string, reportId: "cash_balance" | "card_balance" | "expense_automation_card" | "operating_expenses" | "operating_expenses_by_classes" | "operating_expenses_by_projects" | "revenue" | "revenue_by_classes" | "revenue_by_projects" | "net_burn_or_income" | "net_burn_or_income_story_card" | "net_burn_or_income_by_classes" | "net_burn_or_income_by_projects" | "cash_position" | "top_expenses" | "profit_and_loss" | "profit_and_loss_by_classes" | "profit_and_loss_by_projects" | "balance_sheet" | "balance_sheet_by_classes" | "balance_sheet_by_projects" | "cash_flow" | "cash_flow_by_classes" | "cash_flow_by_projects" | "dashboard" | "finance_statement" | "transaction_list_of_account" | "transaction_list_missing_receipt" | "transaction_list_of_account_by_class" | "transaction_list_of_account_by_project" | "transaction_detail" | "cash_in_cash_out" | "insights_dashboard" | "company_details" | "class_list" | "account_list" | "account_list_by_type" | "vendor" | "task_card" | "bill_pay" | "reimbursement" | "bill_pay_card" | "reimbursement_card" | "bill_pay_promo_card" | "zeni_accounts" | "zeni_accounts_promo_card" | "zeni_treasury" | "charge_cards" | "other_connection" | "reimbursement_promo_card" | "onboarding" | "operating_expenses_by_vendor" | "operating_expenses_by_vendor_summary" | "vendors_tab" | "accounts_payable_aging" | "accounts_receivable_aging" | "vendor_global_review" | "prepaid_expenses" | "fixed_assets" | "notification" | "rewards_card" | "billing" | "flux_analysis_operating_expense" | "account_reconciliation" | "zeni_credit_promo_card" | "treasury_promo_card" | "excluded_account_reconciliation" | "transfer_accounts" | "credit_card_transfer_accounts", sectionPayload: SectionByClassCOABalanceGroupedPayloadV2, classesMetadataPayload: ClassMetadataPayload[], accountsMetadataPayload: AccountMetadataPayload[], currencyPayload: CurrencyPayload], {
|
|
7
|
+
export declare const updateSectionClassesView: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[timeframe: "month" | "year" | "quarter", sectionId: string, reportId: "cash_balance" | "card_balance" | "expense_automation_card" | "operating_expenses" | "operating_expenses_by_classes" | "operating_expenses_by_projects" | "revenue" | "revenue_by_classes" | "revenue_by_projects" | "net_burn_or_income" | "net_burn_or_income_story_card" | "net_burn_or_income_by_classes" | "net_burn_or_income_by_projects" | "cash_position" | "top_expenses" | "profit_and_loss" | "profit_and_loss_by_classes" | "profit_and_loss_by_projects" | "balance_sheet" | "balance_sheet_by_classes" | "balance_sheet_by_projects" | "cash_flow" | "cash_flow_by_classes" | "cash_flow_by_projects" | "dashboard" | "finance_statement" | "transaction_list_of_account" | "transaction_list_missing_receipt" | "transaction_list_of_account_by_class" | "transaction_list_of_account_by_project" | "transaction_detail" | "cash_in_cash_out" | "insights_dashboard" | "company_details" | "class_list" | "account_list" | "account_list_by_type" | "vendor" | "task_card" | "bill_pay" | "reimbursement" | "bill_pay_card" | "reimbursement_card" | "bill_pay_promo_card" | "zeni_accounts" | "zeni_accounts_promo_card" | "zeni_treasury" | "charge_cards" | "other_connection" | "reimbursement_promo_card" | "onboarding" | "operating_expenses_by_vendor" | "operating_expenses_by_vendor_summary" | "vendors_tab" | "accounts_payable_aging" | "accounts_receivable_aging" | "vendor_global_review" | "prepaid_expenses" | "fixed_assets" | "notification" | "rewards_card" | "billing" | "flux_analysis_operating_expense" | "account_reconciliation" | "zeni_credit_promo_card" | "treasury_promo_card" | "excluded_account_reconciliation" | "transfer_accounts" | "credit_card_transfer_accounts", sectionPayload: SectionByClassCOABalanceGroupedPayloadV2 | CalculatedSectionByClassCOABalanceGroupedPayloadV2, classesMetadataPayload: ClassMetadataPayload[], accountsMetadataPayload: AccountMetadataPayload[], currencyPayload: CurrencyPayload], {
|
|
8
8
|
timeframe: "month" | "year" | "quarter";
|
|
9
9
|
reportId: "cash_balance" | "card_balance" | "expense_automation_card" | "operating_expenses" | "operating_expenses_by_classes" | "operating_expenses_by_projects" | "revenue" | "revenue_by_classes" | "revenue_by_projects" | "net_burn_or_income" | "net_burn_or_income_story_card" | "net_burn_or_income_by_classes" | "net_burn_or_income_by_projects" | "cash_position" | "top_expenses" | "profit_and_loss" | "profit_and_loss_by_classes" | "profit_and_loss_by_projects" | "balance_sheet" | "balance_sheet_by_classes" | "balance_sheet_by_projects" | "cash_flow" | "cash_flow_by_classes" | "cash_flow_by_projects" | "dashboard" | "finance_statement" | "transaction_list_of_account" | "transaction_list_missing_receipt" | "transaction_list_of_account_by_class" | "transaction_list_of_account_by_project" | "transaction_detail" | "cash_in_cash_out" | "insights_dashboard" | "company_details" | "class_list" | "account_list" | "account_list_by_type" | "vendor" | "task_card" | "bill_pay" | "reimbursement" | "bill_pay_card" | "reimbursement_card" | "bill_pay_promo_card" | "zeni_accounts" | "zeni_accounts_promo_card" | "zeni_treasury" | "charge_cards" | "other_connection" | "reimbursement_promo_card" | "onboarding" | "operating_expenses_by_vendor" | "operating_expenses_by_vendor_summary" | "vendors_tab" | "accounts_payable_aging" | "accounts_receivable_aging" | "vendor_global_review" | "prepaid_expenses" | "fixed_assets" | "notification" | "rewards_card" | "billing" | "flux_analysis_operating_expense" | "account_reconciliation" | "zeni_credit_promo_card" | "treasury_promo_card" | "excluded_account_reconciliation" | "transfer_accounts" | "credit_card_transfer_accounts";
|
|
10
10
|
sectionId: string;
|
|
11
|
-
sectionPayload: SectionByClassCOABalanceGroupedPayloadV2;
|
|
11
|
+
sectionPayload: SectionByClassCOABalanceGroupedPayloadV2 | CalculatedSectionByClassCOABalanceGroupedPayloadV2;
|
|
12
12
|
classesMetadataPayload: ClassMetadataPayload[];
|
|
13
13
|
accountsMetadataPayload: AccountMetadataPayload[];
|
|
14
14
|
currencyPayload: CurrencyPayload;
|
|
@@ -18,12 +18,16 @@ const updateSectionProjectViewEpic = (actions$) => actions$.pipe((0, operators_1
|
|
|
18
18
|
const accountMetadataWithBalancesPayloads = [];
|
|
19
19
|
if (sectionPayload.projects != null) {
|
|
20
20
|
Object.keys(sectionPayload.projects).forEach((projectId) => {
|
|
21
|
-
const
|
|
21
|
+
const projectPayload = sectionPayload.projects[projectId];
|
|
22
|
+
// A calculated section is grouped by project with no accounts under it.
|
|
23
|
+
const projectAccounts = 'accounts' in projectPayload ? projectPayload.accounts : undefined;
|
|
22
24
|
const projectsViewParentID = {
|
|
23
25
|
projectId,
|
|
24
26
|
sectionId,
|
|
25
27
|
};
|
|
26
|
-
|
|
28
|
+
if (projectAccounts != null) {
|
|
29
|
+
getSubAccountsMetadataForProjectAccountList(projectAccounts, accountMetadataRecordsByID, sectionId, projectsViewParentID, accountMetadataWithBalancesPayloads);
|
|
30
|
+
}
|
|
27
31
|
});
|
|
28
32
|
}
|
|
29
33
|
if (accountMetadataWithBalancesPayloads.length > 0) {
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { CurrencyPayload } from '../../commonPayloadTypes/v2/viewAndReportPayloadv2';
|
|
2
|
-
import { SectionByProjectCOABalanceGroupedPayloadV2 } from '../../view/profitAndLossProjectView/profitAndLossProjectViewPayload';
|
|
2
|
+
import { CalculatedSectionByProjectCOABalanceGroupedPayloadV2, SectionByProjectCOABalanceGroupedPayloadV2 } from '../../view/profitAndLossProjectView/profitAndLossProjectViewPayload';
|
|
3
3
|
import { AccountMetadataPayload } from '../account/accountPayload';
|
|
4
4
|
import { SectionProjectViewState } from './sectionProjectViewState';
|
|
5
5
|
export declare const initialState: SectionProjectViewState;
|
|
6
|
-
export declare const updateSectionProjectView: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[timeframe: "month" | "year" | "quarter", sectionId: string, reportId: "cash_balance" | "card_balance" | "expense_automation_card" | "operating_expenses" | "operating_expenses_by_classes" | "operating_expenses_by_projects" | "revenue" | "revenue_by_classes" | "revenue_by_projects" | "net_burn_or_income" | "net_burn_or_income_story_card" | "net_burn_or_income_by_classes" | "net_burn_or_income_by_projects" | "cash_position" | "top_expenses" | "profit_and_loss" | "profit_and_loss_by_classes" | "profit_and_loss_by_projects" | "balance_sheet" | "balance_sheet_by_classes" | "balance_sheet_by_projects" | "cash_flow" | "cash_flow_by_classes" | "cash_flow_by_projects" | "dashboard" | "finance_statement" | "transaction_list_of_account" | "transaction_list_missing_receipt" | "transaction_list_of_account_by_class" | "transaction_list_of_account_by_project" | "transaction_detail" | "cash_in_cash_out" | "insights_dashboard" | "company_details" | "class_list" | "account_list" | "account_list_by_type" | "vendor" | "task_card" | "bill_pay" | "reimbursement" | "bill_pay_card" | "reimbursement_card" | "bill_pay_promo_card" | "zeni_accounts" | "zeni_accounts_promo_card" | "zeni_treasury" | "charge_cards" | "other_connection" | "reimbursement_promo_card" | "onboarding" | "operating_expenses_by_vendor" | "operating_expenses_by_vendor_summary" | "vendors_tab" | "accounts_payable_aging" | "accounts_receivable_aging" | "vendor_global_review" | "prepaid_expenses" | "fixed_assets" | "notification" | "rewards_card" | "billing" | "flux_analysis_operating_expense" | "account_reconciliation" | "zeni_credit_promo_card" | "treasury_promo_card" | "excluded_account_reconciliation" | "transfer_accounts" | "credit_card_transfer_accounts", sectionPayload: SectionByProjectCOABalanceGroupedPayloadV2, accountsMetadataPayload: AccountMetadataPayload[], currencyPayload: CurrencyPayload], {
|
|
6
|
+
export declare const updateSectionProjectView: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[timeframe: "month" | "year" | "quarter", sectionId: string, reportId: "cash_balance" | "card_balance" | "expense_automation_card" | "operating_expenses" | "operating_expenses_by_classes" | "operating_expenses_by_projects" | "revenue" | "revenue_by_classes" | "revenue_by_projects" | "net_burn_or_income" | "net_burn_or_income_story_card" | "net_burn_or_income_by_classes" | "net_burn_or_income_by_projects" | "cash_position" | "top_expenses" | "profit_and_loss" | "profit_and_loss_by_classes" | "profit_and_loss_by_projects" | "balance_sheet" | "balance_sheet_by_classes" | "balance_sheet_by_projects" | "cash_flow" | "cash_flow_by_classes" | "cash_flow_by_projects" | "dashboard" | "finance_statement" | "transaction_list_of_account" | "transaction_list_missing_receipt" | "transaction_list_of_account_by_class" | "transaction_list_of_account_by_project" | "transaction_detail" | "cash_in_cash_out" | "insights_dashboard" | "company_details" | "class_list" | "account_list" | "account_list_by_type" | "vendor" | "task_card" | "bill_pay" | "reimbursement" | "bill_pay_card" | "reimbursement_card" | "bill_pay_promo_card" | "zeni_accounts" | "zeni_accounts_promo_card" | "zeni_treasury" | "charge_cards" | "other_connection" | "reimbursement_promo_card" | "onboarding" | "operating_expenses_by_vendor" | "operating_expenses_by_vendor_summary" | "vendors_tab" | "accounts_payable_aging" | "accounts_receivable_aging" | "vendor_global_review" | "prepaid_expenses" | "fixed_assets" | "notification" | "rewards_card" | "billing" | "flux_analysis_operating_expense" | "account_reconciliation" | "zeni_credit_promo_card" | "treasury_promo_card" | "excluded_account_reconciliation" | "transfer_accounts" | "credit_card_transfer_accounts", sectionPayload: SectionByProjectCOABalanceGroupedPayloadV2 | CalculatedSectionByProjectCOABalanceGroupedPayloadV2, accountsMetadataPayload: AccountMetadataPayload[], currencyPayload: CurrencyPayload], {
|
|
7
7
|
timeframe: "month" | "year" | "quarter";
|
|
8
8
|
reportId: "cash_balance" | "card_balance" | "expense_automation_card" | "operating_expenses" | "operating_expenses_by_classes" | "operating_expenses_by_projects" | "revenue" | "revenue_by_classes" | "revenue_by_projects" | "net_burn_or_income" | "net_burn_or_income_story_card" | "net_burn_or_income_by_classes" | "net_burn_or_income_by_projects" | "cash_position" | "top_expenses" | "profit_and_loss" | "profit_and_loss_by_classes" | "profit_and_loss_by_projects" | "balance_sheet" | "balance_sheet_by_classes" | "balance_sheet_by_projects" | "cash_flow" | "cash_flow_by_classes" | "cash_flow_by_projects" | "dashboard" | "finance_statement" | "transaction_list_of_account" | "transaction_list_missing_receipt" | "transaction_list_of_account_by_class" | "transaction_list_of_account_by_project" | "transaction_detail" | "cash_in_cash_out" | "insights_dashboard" | "company_details" | "class_list" | "account_list" | "account_list_by_type" | "vendor" | "task_card" | "bill_pay" | "reimbursement" | "bill_pay_card" | "reimbursement_card" | "bill_pay_promo_card" | "zeni_accounts" | "zeni_accounts_promo_card" | "zeni_treasury" | "charge_cards" | "other_connection" | "reimbursement_promo_card" | "onboarding" | "operating_expenses_by_vendor" | "operating_expenses_by_vendor_summary" | "vendors_tab" | "accounts_payable_aging" | "accounts_receivable_aging" | "vendor_global_review" | "prepaid_expenses" | "fixed_assets" | "notification" | "rewards_card" | "billing" | "flux_analysis_operating_expense" | "account_reconciliation" | "zeni_credit_promo_card" | "treasury_promo_card" | "excluded_account_reconciliation" | "transfer_accounts" | "credit_card_transfer_accounts";
|
|
9
9
|
sectionId: string;
|
|
10
|
-
sectionPayload: SectionByProjectCOABalanceGroupedPayloadV2;
|
|
10
|
+
sectionPayload: SectionByProjectCOABalanceGroupedPayloadV2 | CalculatedSectionByProjectCOABalanceGroupedPayloadV2;
|
|
11
11
|
accountsMetadataPayload: AccountMetadataPayload[];
|
|
12
12
|
currencyPayload: CurrencyPayload;
|
|
13
13
|
}, "sectionProjectView/updateSectionProjectView", never, never>;
|
|
@@ -34,10 +34,13 @@ const sectionProjectView = (0, toolkit_1.createSlice)({
|
|
|
34
34
|
const accountsMetadata = accountsMetadataPayload.map((eachAccount) => (0, accountPayload_1.mapAccountMetadataPayloadToAccountMetadata)(eachAccount));
|
|
35
35
|
Object.keys(sectionPayload.projects).forEach((projectId) => {
|
|
36
36
|
const projectPayload = sectionPayload.projects[projectId];
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
// A calculated section is grouped by project with no accounts under it.
|
|
38
|
+
const projectAccounts = 'accounts' in projectPayload
|
|
39
|
+
? projectPayload.accounts
|
|
40
|
+
: undefined;
|
|
41
|
+
const nestedAccountIds = projectAccounts != null
|
|
42
|
+
? (0, getNestedAccountIDHierarchyForSection_1.getNestedAccountIDHierarchyForAccounts)(Object.keys(projectAccounts), accountsMetadata)
|
|
39
43
|
: [];
|
|
40
|
-
const nestedAccountIds = (0, getNestedAccountIDHierarchyForSection_1.getNestedAccountIDHierarchyForAccounts)(projectAccountIds, accountsMetadata);
|
|
41
44
|
updateSectionProject(draft, timeframe, projectPayload, sectionId, projectId, reportId, currencyPayload, nestedAccountIds);
|
|
42
45
|
});
|
|
43
46
|
}
|
package/lib/epic.js
CHANGED
|
@@ -53,15 +53,21 @@ const acceptMasterTOSEpic_1 = require("./view/aiCfoView/epics/acceptMasterTOSEpi
|
|
|
53
53
|
const createSessionAndSubmitEpic_1 = require("./view/aiCfoView/epics/createSessionAndSubmitEpic");
|
|
54
54
|
const createSessionEpic_1 = require("./view/aiCfoView/epics/createSessionEpic");
|
|
55
55
|
const deleteChatSessionEpic_1 = require("./view/aiCfoView/epics/deleteChatSessionEpic");
|
|
56
|
+
const deleteRoutineEpic_1 = require("./view/aiCfoView/epics/deleteRoutineEpic");
|
|
56
57
|
const deleteSkillEpic_1 = require("./view/aiCfoView/epics/deleteSkillEpic");
|
|
57
58
|
const fetchChatHistoryEpic_1 = require("./view/aiCfoView/epics/fetchChatHistoryEpic");
|
|
58
59
|
const fetchChatSessionsForUserEpic_1 = require("./view/aiCfoView/epics/fetchChatSessionsForUserEpic");
|
|
60
|
+
const fetchRoutineRunsEpic_1 = require("./view/aiCfoView/epics/fetchRoutineRunsEpic");
|
|
61
|
+
const fetchRoutinesEpic_1 = require("./view/aiCfoView/epics/fetchRoutinesEpic");
|
|
59
62
|
const fetchSkillDetailEpic_1 = require("./view/aiCfoView/epics/fetchSkillDetailEpic");
|
|
60
63
|
const fetchSkillVersionBodyEpic_1 = require("./view/aiCfoView/epics/fetchSkillVersionBodyEpic");
|
|
61
64
|
const fetchSkillVersionsEpic_1 = require("./view/aiCfoView/epics/fetchSkillVersionsEpic");
|
|
62
65
|
const fetchSkillsEpic_1 = require("./view/aiCfoView/epics/fetchSkillsEpic");
|
|
63
66
|
const fetchSuggestedQuestionsEpic_1 = require("./view/aiCfoView/epics/fetchSuggestedQuestionsEpic");
|
|
67
|
+
const runRoutineEpic_1 = require("./view/aiCfoView/epics/runRoutineEpic");
|
|
68
|
+
const saveRoutineEpic_1 = require("./view/aiCfoView/epics/saveRoutineEpic");
|
|
64
69
|
const saveSkillEpic_1 = require("./view/aiCfoView/epics/saveSkillEpic");
|
|
70
|
+
const setRoutineEnabledEpic_1 = require("./view/aiCfoView/epics/setRoutineEnabledEpic");
|
|
65
71
|
const setSkillVisibilityEpic_1 = require("./view/aiCfoView/epics/setSkillVisibilityEpic");
|
|
66
72
|
const stopSubmitEpic_1 = require("./view/aiCfoView/epics/stopSubmitEpic");
|
|
67
73
|
const stopSubmitQuestionEpic_1 = require("./view/aiCfoView/epics/stopSubmitQuestionEpic");
|
|
@@ -845,6 +851,7 @@ const ALL_EPICS = [
|
|
|
845
851
|
deletePersonEpic_1.deletePersonEpic,
|
|
846
852
|
deleteRemiApprovalRuleEpic_1.deleteRemiApprovalRuleEpic,
|
|
847
853
|
deleteRemiEpic_1.deleteRemiEpic,
|
|
854
|
+
deleteRoutineEpic_1.deleteRoutineEpic,
|
|
848
855
|
deleteScheduleAccruedDetailEpic_1.deleteScheduleAccruedDetailEpic,
|
|
849
856
|
deleteScheduleDetailEpic_1.deleteScheduleDetailEpic,
|
|
850
857
|
deleteSkillEpic_1.deleteSkillEpic,
|
|
@@ -1169,6 +1176,8 @@ const ALL_EPICS = [
|
|
|
1169
1176
|
fetchReviewCompanyViewEpic_1.fetchReviewCompanyViewEpic,
|
|
1170
1177
|
fetchReviewTransferDetailEpic_1.fetchReviewTransferDetailEpic,
|
|
1171
1178
|
fetchRewardsPlanEpic_1.fetchRewardsPlanEpic,
|
|
1179
|
+
fetchRoutineRunsEpic_1.fetchRoutineRunsEpic,
|
|
1180
|
+
fetchRoutinesEpic_1.fetchRoutinesEpic,
|
|
1172
1181
|
fetchScheduleAccruedDetailsEpic_1.fetchScheduleAccruedDetailsEpic,
|
|
1173
1182
|
fetchScheduleAccruedDetailsPageEpic_1.fetchScheduleAccruedDetailsPageEpic,
|
|
1174
1183
|
fetchScheduleDetailsEpic_1.fetchScheduleDetailsEpic,
|
|
@@ -1347,6 +1356,7 @@ const ALL_EPICS = [
|
|
|
1347
1356
|
runInvoicingInvoiceActionEpic_1.runInvoicingInvoiceActionEpic,
|
|
1348
1357
|
runInvoicingPaymentActionEpic_1.runInvoicingPaymentActionEpic,
|
|
1349
1358
|
runInvoicingSubscriptionActionEpic_1.runInvoicingSubscriptionActionEpic,
|
|
1359
|
+
runRoutineEpic_1.runRoutineEpic,
|
|
1350
1360
|
saveAccountMappingViewEpic_1.saveAccountMappingViewEpic,
|
|
1351
1361
|
saveAccountSettingsViewEpic_1.saveAccountSettingsViewEpic,
|
|
1352
1362
|
saveAPIKeyConnectionEpic_1.saveAPIKeyConnectionEpic,
|
|
@@ -1382,6 +1392,7 @@ const ALL_EPICS = [
|
|
|
1382
1392
|
saveReasonForAuditRuleEpic_1.saveReasonForAuditRuleEpic,
|
|
1383
1393
|
saveRemiDetailEpic_1.saveRemiDetailEpic,
|
|
1384
1394
|
saveRemiSetupApproverViewUpdatesEpic_1.saveRemiSetupApproverViewUpdatesEpic,
|
|
1395
|
+
saveRoutineEpic_1.saveRoutineEpic,
|
|
1385
1396
|
saveScheduleAccruedDetailsEpic_1.saveScheduleAccruedDetailsEpic,
|
|
1386
1397
|
saveScheduleDetailsEpic_1.saveScheduleDetailsEpic,
|
|
1387
1398
|
saveSkillEpic_1.saveSkillEpic,
|
|
@@ -1410,6 +1421,7 @@ const ALL_EPICS = [
|
|
|
1410
1421
|
sendOtpEpic_1.sendOtpEpic,
|
|
1411
1422
|
sendReferralInviteEpic_1.sendReferralInviteEpic,
|
|
1412
1423
|
sessionHeartbeatEpic_1.sessionHeartbeatEpic,
|
|
1424
|
+
setRoutineEnabledEpic_1.setRoutineEnabledEpic,
|
|
1413
1425
|
setSkillVisibilityEpic_1.setSkillVisibilityEpic,
|
|
1414
1426
|
snoozeTaskEpic_1.snoozeTaskEpic,
|
|
1415
1427
|
startInvoicingQboBackfillEpic_1.startInvoicingQboBackfillEpic,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createSlice } from '@reduxjs/toolkit';
|
|
2
2
|
import assignWith from 'lodash/assignWith';
|
|
3
3
|
import recordGet from 'lodash/get';
|
|
4
|
-
import { mapCOABalanceGroupedByPeriodPayloadV2ToCOABalanceGroupedByPeriod } from '../../commonPayloadTypes/v2/coaBalancePayload';
|
|
4
|
+
import { mapCOABalanceGroupedByPeriodPayloadV2ToCOABalanceGroupedByPeriod, } from '../../commonPayloadTypes/v2/coaBalancePayload';
|
|
5
5
|
import { getParentClassId } from '../../commonStateTypes/classesView/getNestedClassIDHierarchyForReport';
|
|
6
6
|
import { clearAll } from '../../rootActions';
|
|
7
7
|
import { mapClassBasePayloadToClass, } from './classPayload';
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createSlice } from '@reduxjs/toolkit';
|
|
2
2
|
import { clearAll } from '../../rootActions';
|
|
3
3
|
import { mapNotificationRegistryPayloadToRegistry, } from './notificationRegistryPayload';
|
|
4
|
+
import { NOTIFICATION_DOMAINS, } from './notificationRegistryState';
|
|
4
5
|
export const initialState = { registryEpoch: 0 };
|
|
5
6
|
const notificationRegistry = createSlice({
|
|
6
7
|
name: 'notificationRegistry',
|
|
@@ -19,16 +20,24 @@ const notificationRegistry = createSlice({
|
|
|
19
20
|
// `task_checklist_registry` CLEARS so tenant B doesn't inherit A's
|
|
20
21
|
// Task Checklist section. Guarded by the epoch check above so a stale
|
|
21
22
|
// absent-response can't wipe a fresh registry.
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
const { registriesByDomain } = action.payload;
|
|
24
|
+
// Absent `registriesByDomain` means a pre-domain caller: treat `registry`
|
|
25
|
+
// as the task_checklist snapshot so their behaviour is unchanged.
|
|
26
|
+
const snapshots = registriesByDomain ?? { task_checklist: action.payload.registry };
|
|
27
|
+
draft.registryByDomain = {};
|
|
28
|
+
for (const domain of NOTIFICATION_DOMAINS) {
|
|
29
|
+
const payload = snapshots[domain];
|
|
30
|
+
// Full-replace per domain, and an absent snapshot CLEARS that domain so
|
|
31
|
+
// tenant B never inherits A's section. The gates are independent
|
|
32
|
+
// server-side, so one domain clearing must not touch the other.
|
|
33
|
+
if (payload != null) {
|
|
34
|
+
draft.registryByDomain[domain] =
|
|
35
|
+
mapNotificationRegistryPayloadToRegistry(payload);
|
|
36
|
+
}
|
|
25
37
|
}
|
|
26
|
-
//
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
// the preferences slice's `mergePreferences`). Do not assume the
|
|
30
|
-
// current payload is partial without also updating this reducer.
|
|
31
|
-
draft.registry = mapNotificationRegistryPayloadToRegistry(action.payload.registry);
|
|
38
|
+
// Mirrored for consumers that predate the domain-keyed map.
|
|
39
|
+
draft.registry = draft.registryByDomain.task_checklist;
|
|
40
|
+
return;
|
|
32
41
|
},
|
|
33
42
|
},
|
|
34
43
|
extraReducers: (builder) => {
|
|
@@ -41,6 +50,8 @@ const notificationRegistry = createSlice({
|
|
|
41
50
|
// — Cursor Bugbot 67d6918e. Returning `initialState` verbatim would
|
|
42
51
|
// rewind the counter and let a stale in-flight GET restore A's
|
|
43
52
|
// registry over B's.
|
|
53
|
+
// Drops `registry` and `registryByDomain` together: a tenant switch must
|
|
54
|
+
// not leave one domain's section behind.
|
|
44
55
|
return { registryEpoch: draft.registryEpoch + 1 };
|
|
45
56
|
});
|
|
46
57
|
},
|
|
@@ -4,3 +4,8 @@
|
|
|
4
4
|
// off for this tenant". Both currently surface as `undefined`. Distinguishing
|
|
5
5
|
// them (e.g. an explicit `gate_off` signal from the server) is a follow-up.
|
|
6
6
|
export const getNotificationRegistry = (slice) => slice.registry;
|
|
7
|
+
// `undefined` conflates gate-off with no-preferences-yet; consumers hide the
|
|
8
|
+
// section either way. Falls back to `registry` for task_checklist so state built
|
|
9
|
+
// in the pre-domain shape (consumer mocks, older callers) still resolves.
|
|
10
|
+
export const getNotificationRegistryForDomain = (slice, domain) => slice.registryByDomain?.[domain] ??
|
|
11
|
+
(domain === 'task_checklist' ? slice.registry : undefined);
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import { stringToUnion } from '../../commonStateTypes/stringToUnion';
|
|
2
|
+
// Wire vocabulary owned by the notifications service, not by this slice.
|
|
3
|
+
export const NOTIFICATION_DOMAINS = ['task_checklist', 'commenting'];
|
|
4
|
+
// Callers that predate the domain split mean Task Checklist.
|
|
5
|
+
export const DEFAULT_NOTIFICATION_DOMAIN = 'task_checklist';
|
|
6
|
+
export const toNotificationDomain = (raw) => stringToUnion(raw, NOTIFICATION_DOMAINS);
|
|
2
7
|
export const NOTIFICATION_CHANNELS = ['email', 'slack', 'in_app'];
|
|
3
8
|
export const toNotificationChannel = (raw) => stringToUnion(raw, NOTIFICATION_CHANNELS);
|
|
4
9
|
export const NOTIFICATION_FREQUENCIES = ['instant', 'daily'];
|
|
@@ -26,17 +26,20 @@ export const updateSectionClassesViewEpic = (actions$) => actions$.pipe(filter(u
|
|
|
26
26
|
Object.keys(sectionPayload.classes).forEach((eachClassId) => {
|
|
27
27
|
const classId = classMetadataRecordsByID[eachClassId].nestedClassId;
|
|
28
28
|
const classMetadataPayload = classMetadataRecordsByID[eachClassId].classMetadataPayload;
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
29
|
+
const classPayload = sectionPayload.classes[eachClassId];
|
|
30
|
+
// A calculated section is grouped by class with no accounts under it.
|
|
31
|
+
const classAccounts = 'accounts' in classPayload ? classPayload.accounts : undefined;
|
|
32
|
+
if (classAccounts != null) {
|
|
33
|
+
accountMetadataWithBalancesPayloads.push(...getSubAccountsMetadataForAccountList(classAccounts, accountMetadataRecordsByID, sectionId, { parentClassId: classId, sectionId }));
|
|
34
|
+
}
|
|
35
|
+
const nestedAccountIds = classAccounts != null
|
|
36
|
+
? getNestedAccountIDHierarchyForAccounts(Object.keys(classAccounts), accountsMetadata)
|
|
37
|
+
: [];
|
|
35
38
|
if (classMetadataPayload != null) {
|
|
36
39
|
classMetadataWithBalancesPayloads.push({
|
|
37
40
|
nestedClassId: classId,
|
|
38
41
|
classMetadata: classMetadataPayload,
|
|
39
|
-
classBalances:
|
|
42
|
+
classBalances: classPayload,
|
|
40
43
|
nestedAccountIds,
|
|
41
44
|
});
|
|
42
45
|
}
|
|
@@ -15,12 +15,16 @@ export const updateSectionProjectViewEpic = (actions$) => actions$.pipe(filter(u
|
|
|
15
15
|
const accountMetadataWithBalancesPayloads = [];
|
|
16
16
|
if (sectionPayload.projects != null) {
|
|
17
17
|
Object.keys(sectionPayload.projects).forEach((projectId) => {
|
|
18
|
-
const
|
|
18
|
+
const projectPayload = sectionPayload.projects[projectId];
|
|
19
|
+
// A calculated section is grouped by project with no accounts under it.
|
|
20
|
+
const projectAccounts = 'accounts' in projectPayload ? projectPayload.accounts : undefined;
|
|
19
21
|
const projectsViewParentID = {
|
|
20
22
|
projectId,
|
|
21
23
|
sectionId,
|
|
22
24
|
};
|
|
23
|
-
|
|
25
|
+
if (projectAccounts != null) {
|
|
26
|
+
getSubAccountsMetadataForProjectAccountList(projectAccounts, accountMetadataRecordsByID, sectionId, projectsViewParentID, accountMetadataWithBalancesPayloads);
|
|
27
|
+
}
|
|
24
28
|
});
|
|
25
29
|
}
|
|
26
30
|
if (accountMetadataWithBalancesPayloads.length > 0) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createSlice } from '@reduxjs/toolkit';
|
|
2
|
-
import { mapCOABalanceGroupedByPeriodPayloadV2ToCOABalanceGroupedByPeriod } from '../../commonPayloadTypes/v2/coaBalancePayload';
|
|
2
|
+
import { mapCOABalanceGroupedByPeriodPayloadV2ToCOABalanceGroupedByPeriod, } from '../../commonPayloadTypes/v2/coaBalancePayload';
|
|
3
3
|
import { clearAll } from '../../rootActions';
|
|
4
4
|
import { mapAccountMetadataPayloadToAccountMetadata, } from '../account/accountPayload';
|
|
5
5
|
import { getNestedAccountIDHierarchyForAccounts } from '../sectionAccountsView/getNestedAccountIDHierarchyForSection';
|
|
@@ -31,10 +31,13 @@ const sectionProjectView = createSlice({
|
|
|
31
31
|
const accountsMetadata = accountsMetadataPayload.map((eachAccount) => mapAccountMetadataPayloadToAccountMetadata(eachAccount));
|
|
32
32
|
Object.keys(sectionPayload.projects).forEach((projectId) => {
|
|
33
33
|
const projectPayload = sectionPayload.projects[projectId];
|
|
34
|
-
|
|
35
|
-
|
|
34
|
+
// A calculated section is grouped by project with no accounts under it.
|
|
35
|
+
const projectAccounts = 'accounts' in projectPayload
|
|
36
|
+
? projectPayload.accounts
|
|
37
|
+
: undefined;
|
|
38
|
+
const nestedAccountIds = projectAccounts != null
|
|
39
|
+
? getNestedAccountIDHierarchyForAccounts(Object.keys(projectAccounts), accountsMetadata)
|
|
36
40
|
: [];
|
|
37
|
-
const nestedAccountIds = getNestedAccountIDHierarchyForAccounts(projectAccountIds, accountsMetadata);
|
|
38
41
|
updateSectionProject(draft, timeframe, projectPayload, sectionId, projectId, reportId, currencyPayload, nestedAccountIds);
|
|
39
42
|
});
|
|
40
43
|
}
|
package/lib/esm/epic.js
CHANGED
|
@@ -50,15 +50,21 @@ import { acceptMasterTOSEpic, } from './view/aiCfoView/epics/acceptMasterTOSEpic
|
|
|
50
50
|
import { createSessionAndSubmitEpic, } from './view/aiCfoView/epics/createSessionAndSubmitEpic';
|
|
51
51
|
import { createSessionEpic, } from './view/aiCfoView/epics/createSessionEpic';
|
|
52
52
|
import { deleteChatSessionEpic, } from './view/aiCfoView/epics/deleteChatSessionEpic';
|
|
53
|
+
import { deleteRoutineEpic } from './view/aiCfoView/epics/deleteRoutineEpic';
|
|
53
54
|
import { deleteSkillEpic } from './view/aiCfoView/epics/deleteSkillEpic';
|
|
54
55
|
import { fetchChatHistoryEpic, } from './view/aiCfoView/epics/fetchChatHistoryEpic';
|
|
55
56
|
import { fetchChatSessionsForUserEpic, } from './view/aiCfoView/epics/fetchChatSessionsForUserEpic';
|
|
57
|
+
import { fetchRoutineRunsEpic } from './view/aiCfoView/epics/fetchRoutineRunsEpic';
|
|
58
|
+
import { fetchRoutinesEpic } from './view/aiCfoView/epics/fetchRoutinesEpic';
|
|
56
59
|
import { fetchSkillDetailEpic } from './view/aiCfoView/epics/fetchSkillDetailEpic';
|
|
57
60
|
import { fetchSkillVersionBodyEpic } from './view/aiCfoView/epics/fetchSkillVersionBodyEpic';
|
|
58
61
|
import { fetchSkillVersionsEpic } from './view/aiCfoView/epics/fetchSkillVersionsEpic';
|
|
59
62
|
import { fetchSkillsEpic, } from './view/aiCfoView/epics/fetchSkillsEpic';
|
|
60
63
|
import { fetchSuggestedQuestionsEpic, } from './view/aiCfoView/epics/fetchSuggestedQuestionsEpic';
|
|
64
|
+
import { runRoutineEpic } from './view/aiCfoView/epics/runRoutineEpic';
|
|
65
|
+
import { saveRoutineEpic } from './view/aiCfoView/epics/saveRoutineEpic';
|
|
61
66
|
import { saveSkillEpic } from './view/aiCfoView/epics/saveSkillEpic';
|
|
67
|
+
import { setRoutineEnabledEpic } from './view/aiCfoView/epics/setRoutineEnabledEpic';
|
|
62
68
|
import { setSkillVisibilityEpic } from './view/aiCfoView/epics/setSkillVisibilityEpic';
|
|
63
69
|
import { stopSubmitEpic, } from './view/aiCfoView/epics/stopSubmitEpic';
|
|
64
70
|
import { stopSubmitQuestionEpic, } from './view/aiCfoView/epics/stopSubmitQuestionEpic';
|
|
@@ -842,6 +848,7 @@ const ALL_EPICS = [
|
|
|
842
848
|
deletePersonEpic,
|
|
843
849
|
deleteRemiApprovalRuleEpic,
|
|
844
850
|
deleteRemiEpic,
|
|
851
|
+
deleteRoutineEpic,
|
|
845
852
|
deleteScheduleAccruedDetailEpic,
|
|
846
853
|
deleteScheduleDetailEpic,
|
|
847
854
|
deleteSkillEpic,
|
|
@@ -1166,6 +1173,8 @@ const ALL_EPICS = [
|
|
|
1166
1173
|
fetchReviewCompanyViewEpic,
|
|
1167
1174
|
fetchReviewTransferDetailEpic,
|
|
1168
1175
|
fetchRewardsPlanEpic,
|
|
1176
|
+
fetchRoutineRunsEpic,
|
|
1177
|
+
fetchRoutinesEpic,
|
|
1169
1178
|
fetchScheduleAccruedDetailsEpic,
|
|
1170
1179
|
fetchScheduleAccruedDetailsPageEpic,
|
|
1171
1180
|
fetchScheduleDetailsEpic,
|
|
@@ -1344,6 +1353,7 @@ const ALL_EPICS = [
|
|
|
1344
1353
|
runInvoicingInvoiceActionEpic,
|
|
1345
1354
|
runInvoicingPaymentActionEpic,
|
|
1346
1355
|
runInvoicingSubscriptionActionEpic,
|
|
1356
|
+
runRoutineEpic,
|
|
1347
1357
|
saveAccountMappingViewEpic,
|
|
1348
1358
|
saveAccountSettingsViewEpic,
|
|
1349
1359
|
saveAPIKeyConnectionEpic,
|
|
@@ -1379,6 +1389,7 @@ const ALL_EPICS = [
|
|
|
1379
1389
|
saveReasonForAuditRuleEpic,
|
|
1380
1390
|
saveRemiDetailEpic,
|
|
1381
1391
|
saveRemiSetupApproverViewUpdatesEpic,
|
|
1392
|
+
saveRoutineEpic,
|
|
1382
1393
|
saveScheduleAccruedDetailsEpic,
|
|
1383
1394
|
saveScheduleDetailsEpic,
|
|
1384
1395
|
saveSkillEpic,
|
|
@@ -1407,6 +1418,7 @@ const ALL_EPICS = [
|
|
|
1407
1418
|
sendOtpEpic,
|
|
1408
1419
|
sendReferralInviteEpic,
|
|
1409
1420
|
sessionHeartbeatEpic,
|
|
1421
|
+
setRoutineEnabledEpic,
|
|
1410
1422
|
setSkillVisibilityEpic,
|
|
1411
1423
|
snoozeTaskEpic,
|
|
1412
1424
|
startInvoicingQboBackfillEpic,
|