@zeniai/client-epic-state 5.1.18-betaDI11 → 5.1.18-betaDI12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. package/README.md +3 -1
  2. package/lib/commonStateTypes/viewAndReport/agingReportStateTypes.d.ts +1 -1
  3. package/lib/entity/accountRecon/accountReconPayload.d.ts +22 -0
  4. package/lib/entity/accountRecon/accountReconPayload.js +26 -1
  5. package/lib/entity/accountRecon/accountReconReducer.d.ts +5 -2
  6. package/lib/entity/accountRecon/accountReconReducer.js +36 -2
  7. package/lib/entity/accountRecon/accountReconSelector.d.ts +6 -1
  8. package/lib/entity/accountRecon/accountReconSelector.js +5 -0
  9. package/lib/entity/accountRecon/accountReconState.d.ts +22 -0
  10. package/lib/entity/monthEndCloseChecks/monthEndCloseChecksPayload.d.ts +8 -0
  11. package/lib/entity/monthEndCloseChecks/monthEndCloseChecksPayload.js +10 -0
  12. package/lib/entity/monthEndCloseChecks/monthEndCloseChecksState.d.ts +8 -0
  13. package/lib/entity/task/taskReducer.js +3 -0
  14. package/lib/entity/task/taskState.d.ts +1 -1
  15. package/lib/entity/transaction/payloadTypes/transactionPayload.d.ts +1 -0
  16. package/lib/entity/transaction/payloadTypes/transactionPayload.js +5 -0
  17. package/lib/entity/transaction/stateTypes/transaction.d.ts +1 -0
  18. package/lib/epic.d.ts +7 -2
  19. package/lib/epic.js +7 -2
  20. package/lib/esm/entity/accountRecon/accountReconPayload.js +26 -1
  21. package/lib/esm/entity/accountRecon/accountReconReducer.js +35 -1
  22. package/lib/esm/entity/accountRecon/accountReconSelector.js +5 -0
  23. package/lib/esm/entity/monthEndCloseChecks/monthEndCloseChecksPayload.js +10 -0
  24. package/lib/esm/entity/task/taskReducer.js +3 -0
  25. package/lib/esm/entity/transaction/payloadTypes/transactionPayload.js +5 -0
  26. package/lib/esm/epic.js +7 -2
  27. package/lib/esm/index.js +9 -9
  28. package/lib/esm/view/aiCfoView/aiCfoViewReducer.js +29 -3
  29. package/lib/esm/view/aiCfoView/aiCfoViewSelector.js +11 -0
  30. package/lib/esm/view/aiCfoView/epics/createSessionAndSubmitEpic.js +2 -2
  31. package/lib/esm/view/aiCfoView/epics/fetchSkillsEpic.js +34 -0
  32. package/lib/esm/view/aiCfoView/epics/submitQuestionEpic.js +7 -1
  33. package/lib/esm/view/expenseAutomationView/epics/accountRecon/parseStatementEpic.js +34 -0
  34. package/lib/esm/view/expenseAutomationView/epics/accountRecon/reparseStatementEpic.js +31 -0
  35. package/lib/esm/view/expenseAutomationView/epics/accountRecon/updateStatementInfoEpic.js +57 -0
  36. package/lib/esm/view/expenseAutomationView/epics/fluxAnalysis/fetchFluxAnalysisViewEpic.js +1 -0
  37. package/lib/esm/view/expenseAutomationView/epics/transactionCategorization/fetchTransactionCategorizationEpic.js +49 -11
  38. package/lib/esm/view/expenseAutomationView/epics/transactionCategorization/fetchTransactionCategorizationViewEpic.js +30 -3
  39. package/lib/esm/view/expenseAutomationView/payload/reconciliationPayload.js +153 -0
  40. package/lib/esm/view/expenseAutomationView/reducers/fluxAnalysisViewReducer.js +6 -1
  41. package/lib/esm/view/expenseAutomationView/reducers/reconciliationViewReducer.js +188 -9
  42. package/lib/esm/view/expenseAutomationView/reducers/transactionsViewReducer.js +37 -17
  43. package/lib/esm/view/expenseAutomationView/selectors/fluxAnalysisViewSelector.js +2 -1
  44. package/lib/esm/view/expenseAutomationView/selectors/reconciliationViewSelector.js +27 -0
  45. package/lib/esm/view/expenseAutomationView/types/reconciliationViewState.js +29 -0
  46. package/lib/esm/view/onboardingView/cockpitView/epic/initializeOnboardingCustomerViewUpdateDataEpic.js +4 -16
  47. package/lib/esm/view/onboardingView/cockpitView/onboardingCockpitViewPayload.js +2 -2
  48. package/lib/esm/view/opExByVendor/opExByVendorReducer.js +28 -5
  49. package/lib/esm/view/opExByVendor/opExByVendorSelector.js +1 -0
  50. package/lib/esm/view/opExByVendor/refreshOpExByVendorReportEpic.js +21 -0
  51. package/lib/esm/view/referralView/epics/sendReferralInviteEpic.js +9 -1
  52. package/lib/esm/view/referralView/referralReducer.js +3 -2
  53. package/lib/esm/view/spendManagement/commonSetup/setupViewReducer.js +5 -1
  54. package/lib/esm/view/taskManager/taskDetailView/epics/saveTaskDetailEpic.js +2 -2
  55. package/lib/esm/view/taskManager/taskDetailView/epics/sendCommentMentionNotificationEpic.js +2 -2
  56. package/lib/esm/view/taskManager/taskDetailView/taskDetailSelector.js +1 -1
  57. package/lib/esm/view/taskManager/taskListView/taskListReducer.js +3 -1
  58. package/lib/esm/view/transactionDetail/epics/saveTransactionDetailEpic.js +3 -1
  59. package/lib/esm/view/transactionDetail/epics/saveTransactionHelper.js +11 -2
  60. package/lib/esm/view/transactionDetail/epics/updateTransactionDetailEpic.js +34 -5
  61. package/lib/esm/view/transactionDetail/transactionDetailLocalDataHelper.js +17 -0
  62. package/lib/index.d.ts +14 -14
  63. package/lib/index.js +57 -37
  64. package/lib/view/aiCfoView/aiCfoViewPayload.d.ts +14 -0
  65. package/lib/view/aiCfoView/aiCfoViewReducer.d.ts +8 -4
  66. package/lib/view/aiCfoView/aiCfoViewReducer.js +30 -4
  67. package/lib/view/aiCfoView/aiCfoViewSelector.d.ts +2 -1
  68. package/lib/view/aiCfoView/aiCfoViewSelector.js +12 -0
  69. package/lib/view/aiCfoView/aiCfoViewState.d.ts +15 -0
  70. package/lib/view/aiCfoView/epics/createSessionAndSubmitEpic.js +2 -2
  71. package/lib/view/aiCfoView/epics/fetchSkillsEpic.d.ts +8 -0
  72. package/lib/view/aiCfoView/epics/fetchSkillsEpic.js +38 -0
  73. package/lib/view/aiCfoView/epics/submitQuestionEpic.js +7 -1
  74. package/lib/view/expenseAutomationView/epics/accountRecon/parseStatementEpic.d.ts +6 -0
  75. package/lib/view/expenseAutomationView/epics/accountRecon/parseStatementEpic.js +38 -0
  76. package/lib/view/expenseAutomationView/epics/accountRecon/reparseStatementEpic.d.ts +26 -0
  77. package/lib/view/expenseAutomationView/epics/accountRecon/reparseStatementEpic.js +35 -0
  78. package/lib/view/expenseAutomationView/epics/accountRecon/updateStatementInfoEpic.d.ts +27 -0
  79. package/lib/view/expenseAutomationView/epics/accountRecon/updateStatementInfoEpic.js +61 -0
  80. package/lib/view/expenseAutomationView/epics/fluxAnalysis/fetchFluxAnalysisViewEpic.js +1 -0
  81. package/lib/view/expenseAutomationView/epics/transactionCategorization/fetchTransactionCategorizationEpic.js +47 -9
  82. package/lib/view/expenseAutomationView/epics/transactionCategorization/fetchTransactionCategorizationViewEpic.js +30 -3
  83. package/lib/view/expenseAutomationView/payload/fluxAnalysisPayload.d.ts +8 -0
  84. package/lib/view/expenseAutomationView/payload/reconciliationPayload.d.ts +176 -10
  85. package/lib/view/expenseAutomationView/payload/reconciliationPayload.js +159 -0
  86. package/lib/view/expenseAutomationView/payload/transactionCategorizationPayload.d.ts +7 -0
  87. package/lib/view/expenseAutomationView/reducers/fluxAnalysisViewReducer.d.ts +2 -1
  88. package/lib/view/expenseAutomationView/reducers/fluxAnalysisViewReducer.js +6 -1
  89. package/lib/view/expenseAutomationView/reducers/reconciliationViewReducer.d.ts +53 -3
  90. package/lib/view/expenseAutomationView/reducers/reconciliationViewReducer.js +190 -10
  91. package/lib/view/expenseAutomationView/reducers/transactionsViewReducer.js +37 -17
  92. package/lib/view/expenseAutomationView/selectorTypes/reconciliationViewSelectorTypes.d.ts +7 -1
  93. package/lib/view/expenseAutomationView/selectors/fluxAnalysisViewSelector.js +2 -1
  94. package/lib/view/expenseAutomationView/selectors/reconciliationViewSelector.d.ts +2 -0
  95. package/lib/view/expenseAutomationView/selectors/reconciliationViewSelector.js +29 -1
  96. package/lib/view/expenseAutomationView/types/fluxAnalysisViewState.d.ts +2 -0
  97. package/lib/view/expenseAutomationView/types/reconciliationViewState.d.ts +175 -0
  98. package/lib/view/expenseAutomationView/types/reconciliationViewState.js +30 -0
  99. package/lib/view/onboardingView/cockpitView/epic/initializeOnboardingCustomerViewUpdateDataEpic.js +3 -15
  100. package/lib/view/onboardingView/cockpitView/onboardingCockpitViewPayload.js +2 -2
  101. package/lib/view/opExByVendor/opExByVendorReducer.d.ts +6 -1
  102. package/lib/view/opExByVendor/opExByVendorReducer.js +29 -6
  103. package/lib/view/opExByVendor/opExByVendorSelector.d.ts +1 -0
  104. package/lib/view/opExByVendor/opExByVendorSelector.js +1 -0
  105. package/lib/view/opExByVendor/opExByVendorState.d.ts +1 -0
  106. package/lib/view/opExByVendor/refreshOpExByVendorReportEpic.d.ts +17 -0
  107. package/lib/view/opExByVendor/refreshOpExByVendorReportEpic.js +25 -0
  108. package/lib/view/referralView/epics/sendReferralInviteEpic.js +9 -1
  109. package/lib/view/referralView/referralReducer.d.ts +1 -0
  110. package/lib/view/referralView/referralReducer.js +4 -3
  111. package/lib/view/spendManagement/commonSetup/setupViewReducer.js +5 -1
  112. package/lib/view/taskManager/taskDetailView/epics/saveTaskDetailEpic.js +2 -2
  113. package/lib/view/taskManager/taskDetailView/epics/sendCommentMentionNotificationEpic.d.ts +1 -1
  114. package/lib/view/taskManager/taskDetailView/epics/sendCommentMentionNotificationEpic.js +1 -1
  115. package/lib/view/taskManager/taskDetailView/taskDetail.d.ts +1 -1
  116. package/lib/view/taskManager/taskDetailView/taskDetailSelector.js +1 -1
  117. package/lib/view/taskManager/taskListView/taskListReducer.js +3 -1
  118. package/lib/view/transactionDetail/epics/saveTransactionDetailEpic.js +3 -1
  119. package/lib/view/transactionDetail/epics/saveTransactionHelper.d.ts +1 -1
  120. package/lib/view/transactionDetail/epics/saveTransactionHelper.js +11 -2
  121. package/lib/view/transactionDetail/epics/updateTransactionDetailEpic.d.ts +8 -0
  122. package/lib/view/transactionDetail/epics/updateTransactionDetailEpic.js +36 -6
  123. package/lib/view/transactionDetail/transactionDetailLocalDataHelper.js +17 -0
  124. package/lib/view/transactionDetail/transactionDetailState.d.ts +1 -0
  125. package/lib/view/transactionDetail/transactionDetailTypes.d.ts +1 -0
  126. package/lib/view/vendorFiling1099/vendorFiling1099List/vendorFiling1099ListState.d.ts +1 -1
  127. package/package.json +5 -2
@@ -7,6 +7,131 @@ import { BankStatusCodeType } from '../../../entity/accountRecon/accountReconSta
7
7
  import { CustomerBase } from '../../../entity/customer/customerState';
8
8
  import { VendorBase } from '../../../entity/vendor/vendorState';
9
9
  import { ZeniAPIStatus } from '../../../responsePayload';
10
+ import { ReconciliationSummaryPayload } from '../payload/reconciliationPayload';
11
+ export interface PolygonPoint {
12
+ x: number;
13
+ y: number;
14
+ }
15
+ export interface Citation {
16
+ page: number;
17
+ pageHeight: number;
18
+ pageWidth: number;
19
+ polygon: PolygonPoint[];
20
+ referenceText: string;
21
+ }
22
+ export interface StatementTransaction {
23
+ amount: number;
24
+ citations: Citation[];
25
+ isUserAdded: boolean;
26
+ isUserEdited: boolean;
27
+ statementTransactionId: string;
28
+ transactionDate: string;
29
+ transactionDirection: 'debit' | 'credit';
30
+ transactionMemo: string;
31
+ }
32
+ export interface StatementMeta {
33
+ closingBalance: number;
34
+ openingBalance: number;
35
+ statementDataStatus: {
36
+ code: string;
37
+ label: string;
38
+ };
39
+ statementEndDate: string;
40
+ statementStartDate: string;
41
+ statementStatus: {
42
+ code: string;
43
+ label: string;
44
+ };
45
+ statementUploadId: string;
46
+ totalDeposits: number;
47
+ totalPayments: number;
48
+ }
49
+ export interface AccountInfo {
50
+ accountId: string;
51
+ accountName: string;
52
+ accountType: string;
53
+ currencyCode: string;
54
+ last4Digits: string | null;
55
+ }
56
+ export interface FileInfo {
57
+ fileId: string;
58
+ fileName: string;
59
+ signedUrl: string;
60
+ }
61
+ export interface AiSummaryField {
62
+ code: string;
63
+ label: string;
64
+ }
65
+ export interface PreviousReconciliationInfo {
66
+ endDate: string;
67
+ reconciledAt: string;
68
+ reconciledByUserId: string;
69
+ reconciliationId: string;
70
+ startDate: string;
71
+ }
72
+ export interface AiSummaryChainStatus {
73
+ code: string;
74
+ expectedStartDate: string | null;
75
+ label: string;
76
+ previousReconciliationInfo: PreviousReconciliationInfo | null;
77
+ }
78
+ /**
79
+ * Surfaced when Confirm & Save is rejected with a 409 because the statement
80
+ * period overlaps with / leaves a gap after an already-reconciled period.
81
+ */
82
+ export interface StatementDateConflict {
83
+ errorCode: string;
84
+ expectedStartDate: string | null;
85
+ /** Present for overlap conflicts; GAP-only 409s may omit prior recon info. */
86
+ previousReconciliationInfo?: PreviousReconciliationInfo;
87
+ }
88
+ export interface AiSummary {
89
+ accountIdentified: string | null;
90
+ chainStatus: AiSummaryChainStatus;
91
+ exceptionsDetected: number;
92
+ fieldsCaptured: AiSummaryField[];
93
+ transactionsExtracted: number;
94
+ }
95
+ export interface StatementUpload {
96
+ account: AccountInfo;
97
+ file: FileInfo | null;
98
+ statementMeta: StatementMeta;
99
+ statementTransactions: StatementTransaction[];
100
+ aiSummary?: AiSummary | null;
101
+ }
102
+ export interface ParsedStatementData {
103
+ statementUpload: StatementUpload;
104
+ }
105
+ export interface ReconciliationSummaryAccounts {
106
+ done: number;
107
+ failed: number;
108
+ inProgress: number;
109
+ total: number;
110
+ }
111
+ export interface ReconciliationSummaryAutoMatched {
112
+ matchedTxns: number;
113
+ totalTxns: number;
114
+ }
115
+ export interface ReconciliationSummaryNeedsReview {
116
+ accountCount: number;
117
+ txnCount: number;
118
+ }
119
+ export interface ReconciliationSummaryProgressBar {
120
+ aiPercentageShare: number;
121
+ completePercentage: number;
122
+ humanPercentageShare: number;
123
+ remainingPercentage: number;
124
+ }
125
+ export interface ReconciliationViewSummary {
126
+ accounts: ReconciliationSummaryAccounts;
127
+ accountsToConnectCount: number;
128
+ autoMatched: ReconciliationSummaryAutoMatched;
129
+ needsReview: ReconciliationSummaryNeedsReview;
130
+ timeSavedHours: number;
131
+ timeSavedPercentage: number;
132
+ progressBar?: ReconciliationSummaryProgressBar;
133
+ }
134
+ export declare function toReconciliationViewSummary(payload: ReconciliationSummaryPayload): ReconciliationViewSummary;
10
135
  export declare const RECONCILE_ACTIONS: readonly ["reconcile", "save_reconcile_for_later", "exclude"];
11
136
  export declare const toReconcileActions: (v: string) => "reconcile" | "save_reconcile_for_later" | "exclude";
12
137
  export type ReconcileActionType = ReturnType<typeof toReconcileActions>;
@@ -107,9 +232,11 @@ export interface ReconciliationViewState extends FetchStateAndError {
107
232
  reconTabsState: ReconciliationTabsState;
108
233
  refreshStatus: FetchStateAndError;
109
234
  selectedTab: ReconciliationViewTabType;
235
+ statementProcessingFailed: boolean;
110
236
  statementUploadChosen: boolean;
111
237
  selectedAccountId?: ID;
112
238
  selectedDrawerAccountId?: ID;
239
+ summary?: ReconciliationViewSummary;
113
240
  }
114
241
  export interface BankConnectionStatus {
115
242
  connectionInProgress: boolean;
@@ -120,19 +247,67 @@ export interface AccountReconciliationRecords {
120
247
  accountIDs: ID[];
121
248
  reconciliationByAccountID: Record<ID, AccountReconciliationDataWithTransactionFetchState>;
122
249
  }
250
+ export interface StatementTransactionForUpdate {
251
+ amount: number;
252
+ transactionDate: string;
253
+ transactionDirection: 'debit' | 'credit';
254
+ transactionMemo: string;
255
+ statementTransactionId?: string;
256
+ }
257
+ export interface StatementTransactionsUpdate {
258
+ added: StatementTransactionForUpdate[];
259
+ deletedIds: string[];
260
+ updated: StatementTransactionForUpdate[];
261
+ }
262
+ export interface StatementUpdateLocalData {
263
+ statementMeta: StatementMeta;
264
+ statementTransactions: StatementTransactionsUpdate;
265
+ }
266
+ export interface StatementUpdateLocalDataPayload {
267
+ statement_meta: {
268
+ opening_balance: number;
269
+ statement_end_date: string;
270
+ statement_start_date: string;
271
+ total_deposits: number;
272
+ total_payments: number;
273
+ };
274
+ statement_transactions: {
275
+ added: Array<{
276
+ amount: number;
277
+ transaction_date: string;
278
+ transaction_direction: 'debit' | 'credit';
279
+ transaction_memo: string;
280
+ }>;
281
+ deleted_ids: string[];
282
+ updated: Array<{
283
+ amount: number;
284
+ statement_transaction_id: string;
285
+ transaction_date: string;
286
+ transaction_direction: 'debit' | 'credit';
287
+ transaction_memo: string;
288
+ }>;
289
+ };
290
+ }
123
291
  export interface AccountReconciliationLocalData {
124
292
  accountSource?: ReconciliationAccountSourceType;
293
+ statementUpdateLocalData?: StatementUpdateLocalData;
125
294
  }
126
295
  export interface AccountReconciliationDataWithTransactionFetchState {
127
296
  accountId: ID;
128
297
  localData: AccountReconciliationLocalData;
129
298
  refreshStatus: FetchStateAndError;
299
+ reparseStatementStatus: FetchStateAndError;
300
+ statementDateConflict: StatementDateConflict | null;
130
301
  statementDeleteStatus: FetchStateAndError;
302
+ /** Derived from bank_status.code === 'parsing' for read-only list/drawer banners. */
131
303
  statementParseInProgress: boolean;
304
+ /** Client-driven fetch state for the parseStatement epic (In-Progress/Completed/Error). */
305
+ statementParseStatus: FetchStateAndError;
132
306
  statementUpdateStatus: FetchStateAndError;
133
307
  statementUploadStatus: FetchStateAndError;
134
308
  transactionFetchState: FetchStateAndError;
135
309
  accountDetectionReason?: string;
310
+ parsedStatementData?: ParsedStatementData;
136
311
  reconciliationId?: ID;
137
312
  }
138
313
  export {};
@@ -1,7 +1,37 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.toReconciliationTabsType = exports.toReconcileActions = exports.RECONCILE_ACTIONS = void 0;
4
+ exports.toReconciliationViewSummary = toReconciliationViewSummary;
4
5
  const stringToUnion_1 = require("../../../commonStateTypes/stringToUnion");
6
+ function toReconciliationViewSummary(payload) {
7
+ return {
8
+ accounts: {
9
+ done: payload.accounts.done,
10
+ failed: payload.accounts.failed,
11
+ inProgress: payload.accounts.in_progress,
12
+ total: payload.accounts.total,
13
+ },
14
+ accountsToConnectCount: payload.accounts_to_connect_count,
15
+ autoMatched: {
16
+ matchedTxns: payload.auto_matched.matched_txns,
17
+ totalTxns: payload.auto_matched.total_txns,
18
+ },
19
+ needsReview: {
20
+ accountCount: payload.needs_review.account_count,
21
+ txnCount: payload.needs_review.txn_count,
22
+ },
23
+ timeSavedHours: 0,
24
+ timeSavedPercentage: payload.time_saved_percentage,
25
+ progressBar: payload.progress_bar != null
26
+ ? {
27
+ aiPercentageShare: payload.progress_bar.ai_percentage_share,
28
+ completePercentage: payload.progress_bar.complete_percentage,
29
+ humanPercentageShare: payload.progress_bar.human_percentage_share,
30
+ remainingPercentage: payload.progress_bar.remaining_percentage,
31
+ }
32
+ : undefined,
33
+ };
34
+ }
5
35
  exports.RECONCILE_ACTIONS = [
6
36
  'reconcile',
7
37
  'save_reconcile_for_later',
@@ -116,32 +116,20 @@ const getSelectedProducts = (isDebitCardFlagEnabled, tenant) => {
116
116
  const isBookkeepingEnabled = (0, tenantSelector_1.isTenantBookkeepingEnabled)(tenant);
117
117
  const isOtherProductsEnabled = (0, tenantSelector_1.isOtherProductsEnabledForTenant)(tenant);
118
118
  const isCardsEnabled = (0, tenantSelector_1.isTenantCardsOnly)(tenant);
119
- const isTreasuryEnabled = (0, tenantSelector_1.isTenantTreasuryEnabled)(tenant);
120
119
  if (isCardsEnabled && isBankingOnly) {
121
- const selectedProducts = ['zeni_cards', 'zeni_checking'];
122
- if (isTreasuryEnabled) {
123
- selectedProducts.push('zeni_treasury');
124
- }
125
- return selectedProducts;
120
+ return [];
126
121
  }
127
122
  else if (isBankingOnly) {
128
- const selectedProducts = ['zeni_checking'];
129
- if (isTreasuryEnabled) {
130
- selectedProducts.push('zeni_treasury');
131
- }
132
- return selectedProducts;
123
+ return [];
133
124
  }
134
125
  else if (isCardsEnabled) {
135
- return ['zeni_cards'];
126
+ return [];
136
127
  }
137
128
  else if (isBookkeepingEnabled) {
138
129
  return [
139
130
  'bookkeeping',
140
131
  'zeni_bill_pay',
141
- 'zeni_checking',
142
132
  'zeni_reimbursements',
143
- 'zeni_treasury',
144
- 'zeni_cards',
145
133
  ];
146
134
  }
147
135
  else if (isOtherProductsEnabled) {
@@ -51,9 +51,9 @@ const toOnboardingCustomerPayload = (onboardingCustomer, sendInvite, company, te
51
51
  const isTreasury = selectedProducts.includes('zeni_treasury');
52
52
  if (isBookkeeping) {
53
53
  onboardingCustomerPayload.is_book_keeping_enabled = true;
54
- onboardingCustomerPayload.is_banking_enabled = true;
54
+ onboardingCustomerPayload.is_banking_enabled = isChecking;
55
55
  onboardingCustomerPayload.is_spend_management_enabled = true;
56
- onboardingCustomerPayload.is_card_enabled = true;
56
+ onboardingCustomerPayload.is_card_enabled = isCards;
57
57
  onboardingCustomerPayload.is_treasury_enabled = isTreasury;
58
58
  }
59
59
  else if (isChecking && isCards) {
@@ -3,6 +3,7 @@ import { COABalanceType } from '../../commonStateTypes/coaBalance/coaBalanceType
3
3
  import { FetchState } from '../../commonStateTypes/common';
4
4
  import { SortOrder } from '../../commonStateTypes/selectorTypes/sortOrderTypes';
5
5
  import { ZeniAPIStatus } from '../../responsePayload';
6
+ import { ZeniDate } from '../../zeniDayJS';
6
7
  import { OpexByVendorReportPayload, OpexByVendorReportSummaryPayload } from './opExByVendorPayload';
7
8
  import { OpExByVendorQuery, OpExByVendorState, OpexByVendorSortKey } from './opExByVendorState';
8
9
  export declare const defaultTimeframePeriodsOpExByVendor: {
@@ -52,6 +53,10 @@ export declare const fetchOpExByVendor: import("@reduxjs/toolkit").ActionCreator
52
53
  }, "opExByVendor/clearOpExByVendorSearch">, updateOpExByVendorPageLimit: import("@reduxjs/toolkit").ActionCreatorWithOptionalPayload<number | undefined, "opExByVendor/updateOpExByVendorPageLimit">, updateOpExByVendorSearchString: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
53
54
  searchText: string;
54
55
  timeframe: COABalanceMonthQuarterTimeframe;
55
- }, "opExByVendor/updateOpExByVendorSearchString">;
56
+ }, "opExByVendor/updateOpExByVendorSearchString">, refreshOpExByVendorReport: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"opExByVendor/refreshOpExByVendorReport">, refreshOpExByVendorReportSuccess: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
57
+ lastRefreshSuccessTime: ZeniDate | undefined;
58
+ }, "opExByVendor/refreshOpExByVendorReportSuccess">, refreshOpExByVendorReportFailure: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[error: ZeniAPIStatus<Record<string, unknown>>], {
59
+ error: ZeniAPIStatus<Record<string, unknown>>;
60
+ }, "opExByVendor/refreshOpExByVendorReportFailure", never, never>;
56
61
  declare const _default: import("redux").Reducer<OpExByVendorState>;
57
62
  export default _default;
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  var _a;
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.updateOpExByVendorSearchString = exports.updateOpExByVendorPageLimit = exports.clearOpExByVendorSearch = exports.updateOpExByVendorDownloadState = exports.updateOpExByVendorPageFetchInProgress = exports.updateOpExByVendorSortOrSearchInProgress = exports.updateOpExByVendorSort = exports.updateOpExByVendorAdditionalBalancesSelection = exports.clearOpExByVendor = exports.updateOpExByVendorUIState = exports.updateOpExByVendorTimeFrame = exports.updateOpExByVendorReportSummarySuccess = exports.updateOpExByVendorReportSummaryFailure = exports.fetchOpExByVendorReportSummary = exports.updateOpExByVendorReportSuccessForTimeframe = exports.updateOpExByVendorReportFailureForTimeframe = exports.fetchOpExByVendorReportForTimeframe = exports.updateOpExByVendorReportGenerated = exports.fetchOpExByVendor = exports.initialState = exports.initialSearchStringState = exports.defaultTimeframePeriodsOpExByVendor = void 0;
4
+ exports.refreshOpExByVendorReportFailure = exports.refreshOpExByVendorReportSuccess = exports.refreshOpExByVendorReport = exports.updateOpExByVendorSearchString = exports.updateOpExByVendorPageLimit = exports.clearOpExByVendorSearch = exports.updateOpExByVendorDownloadState = exports.updateOpExByVendorPageFetchInProgress = exports.updateOpExByVendorSortOrSearchInProgress = exports.updateOpExByVendorSort = exports.updateOpExByVendorAdditionalBalancesSelection = exports.clearOpExByVendor = exports.updateOpExByVendorUIState = exports.updateOpExByVendorTimeFrame = exports.updateOpExByVendorReportSummarySuccess = exports.updateOpExByVendorReportSummaryFailure = exports.fetchOpExByVendorReportSummary = exports.updateOpExByVendorReportSuccessForTimeframe = exports.updateOpExByVendorReportFailureForTimeframe = exports.fetchOpExByVendorReportForTimeframe = exports.updateOpExByVendorReportGenerated = exports.fetchOpExByVendor = exports.initialState = exports.initialSearchStringState = exports.defaultTimeframePeriodsOpExByVendor = void 0;
5
5
  const toolkit_1 = require("@reduxjs/toolkit");
6
6
  const coaBalancePayload_1 = require("../../commonPayloadTypes/v2/coaBalancePayload");
7
7
  const viewAndReportPayload_1 = require("../../commonPayloadTypes/viewAndReportPayload");
@@ -26,6 +26,10 @@ exports.initialState = {
26
26
  error: undefined,
27
27
  },
28
28
  },
29
+ refreshStatus: {
30
+ fetchState: 'Not-Started',
31
+ error: undefined,
32
+ },
29
33
  summaryFetchState: {
30
34
  fetchState: 'Not-Started',
31
35
  error: undefined,
@@ -263,12 +267,32 @@ const opexByVendor = (0, toolkit_1.createSlice)({
263
267
  [timeframe]: [],
264
268
  };
265
269
  },
270
+ refreshOpExByVendorReport(draft) {
271
+ draft.refreshStatus = { fetchState: 'In-Progress', error: undefined };
272
+ },
273
+ refreshOpExByVendorReportSuccess(draft, action) {
274
+ draft.refreshStatus = { fetchState: 'Completed', error: undefined };
275
+ if (action.payload.lastRefreshSuccessTime != null) {
276
+ draft.lastRefreshSuccessTime = action.payload.lastRefreshSuccessTime;
277
+ }
278
+ },
279
+ refreshOpExByVendorReportFailure: {
280
+ prepare(error) {
281
+ return { payload: { error } };
282
+ },
283
+ reducer(draft, action) {
284
+ draft.refreshStatus = {
285
+ fetchState: 'Error',
286
+ error: action.payload.error,
287
+ };
288
+ },
289
+ },
266
290
  clearOpExByVendor(draft) {
267
291
  Object.assign(draft, exports.initialState);
268
292
  },
269
293
  },
270
294
  });
271
- _a = opexByVendor.actions, exports.fetchOpExByVendor = _a.fetchOpExByVendor, exports.updateOpExByVendorReportGenerated = _a.updateOpExByVendorReportGenerated, exports.fetchOpExByVendorReportForTimeframe = _a.fetchOpExByVendorReportForTimeframe, exports.updateOpExByVendorReportFailureForTimeframe = _a.updateOpExByVendorReportFailureForTimeframe, exports.updateOpExByVendorReportSuccessForTimeframe = _a.updateOpExByVendorReportSuccessForTimeframe, exports.fetchOpExByVendorReportSummary = _a.fetchOpExByVendorReportSummary, exports.updateOpExByVendorReportSummaryFailure = _a.updateOpExByVendorReportSummaryFailure, exports.updateOpExByVendorReportSummarySuccess = _a.updateOpExByVendorReportSummarySuccess, exports.updateOpExByVendorTimeFrame = _a.updateOpExByVendorTimeFrame, exports.updateOpExByVendorUIState = _a.updateOpExByVendorUIState, exports.clearOpExByVendor = _a.clearOpExByVendor, exports.updateOpExByVendorAdditionalBalancesSelection = _a.updateOpExByVendorAdditionalBalancesSelection, exports.updateOpExByVendorSort = _a.updateOpExByVendorSort, exports.updateOpExByVendorSortOrSearchInProgress = _a.updateOpExByVendorSortOrSearchInProgress, exports.updateOpExByVendorPageFetchInProgress = _a.updateOpExByVendorPageFetchInProgress, exports.updateOpExByVendorDownloadState = _a.updateOpExByVendorDownloadState, exports.clearOpExByVendorSearch = _a.clearOpExByVendorSearch, exports.updateOpExByVendorPageLimit = _a.updateOpExByVendorPageLimit, exports.updateOpExByVendorSearchString = _a.updateOpExByVendorSearchString;
295
+ _a = opexByVendor.actions, exports.fetchOpExByVendor = _a.fetchOpExByVendor, exports.updateOpExByVendorReportGenerated = _a.updateOpExByVendorReportGenerated, exports.fetchOpExByVendorReportForTimeframe = _a.fetchOpExByVendorReportForTimeframe, exports.updateOpExByVendorReportFailureForTimeframe = _a.updateOpExByVendorReportFailureForTimeframe, exports.updateOpExByVendorReportSuccessForTimeframe = _a.updateOpExByVendorReportSuccessForTimeframe, exports.fetchOpExByVendorReportSummary = _a.fetchOpExByVendorReportSummary, exports.updateOpExByVendorReportSummaryFailure = _a.updateOpExByVendorReportSummaryFailure, exports.updateOpExByVendorReportSummarySuccess = _a.updateOpExByVendorReportSummarySuccess, exports.updateOpExByVendorTimeFrame = _a.updateOpExByVendorTimeFrame, exports.updateOpExByVendorUIState = _a.updateOpExByVendorUIState, exports.clearOpExByVendor = _a.clearOpExByVendor, exports.updateOpExByVendorAdditionalBalancesSelection = _a.updateOpExByVendorAdditionalBalancesSelection, exports.updateOpExByVendorSort = _a.updateOpExByVendorSort, exports.updateOpExByVendorSortOrSearchInProgress = _a.updateOpExByVendorSortOrSearchInProgress, exports.updateOpExByVendorPageFetchInProgress = _a.updateOpExByVendorPageFetchInProgress, exports.updateOpExByVendorDownloadState = _a.updateOpExByVendorDownloadState, exports.clearOpExByVendorSearch = _a.clearOpExByVendorSearch, exports.updateOpExByVendorPageLimit = _a.updateOpExByVendorPageLimit, exports.updateOpExByVendorSearchString = _a.updateOpExByVendorSearchString, exports.refreshOpExByVendorReport = _a.refreshOpExByVendorReport, exports.refreshOpExByVendorReportSuccess = _a.refreshOpExByVendorReportSuccess, exports.refreshOpExByVendorReportFailure = _a.refreshOpExByVendorReportFailure;
272
296
  exports.default = opexByVendor.reducer;
273
297
  const doUpdateOpexByVendorReport = (draft, timeframe, reportPayload, queryProps) => {
274
298
  if (reportPayload.status.is_report_generated == null) {
@@ -321,10 +345,9 @@ const doUpdateOpexByVendorReportSummary = (draft, reportPayload) => {
321
345
  const report = (0, viewAndReportPayload_1.mapReportPayloadToReport)(reportPayload);
322
346
  draft.firstMonthOfFY = report.firstMonthOfFY;
323
347
  draft.bookCloseDate = report.bookCloseDate;
324
- draft.lastRefreshSuccessTime =
325
- reportPayload.status.last_refresh_success_time != null
326
- ? (0, zeniDayJS_1.date)(reportPayload.status.last_refresh_success_time)
327
- : undefined;
348
+ if (reportPayload.status.last_refresh_success_time != null) {
349
+ draft.lastRefreshSuccessTime = (0, zeniDayJS_1.date)(reportPayload.status.last_refresh_success_time);
350
+ }
328
351
  draft.totalOpexByVendor = (0, coaBalancePayload_1.combineCOABalanceGrouped)((0, coaBalancePayload_1.mapCOABalanceGroupedPayloadV2ToCOABalanceGrouped)(reportPayload.operating_expenses, reportPayload.currency, 'month'), (0, coaBalancePayload_1.mapCOABalanceGroupedPayloadV2ToCOABalanceGrouped)(reportPayload.operating_expenses, reportPayload.currency, 'quarter'));
329
352
  draft.summaryOpexByVendorKey = mapVendorSummaryBalances(reportPayload.operating_expenses, reportPayload.currency);
330
353
  }
@@ -28,6 +28,7 @@ export interface OpExByVendorReport extends SelectorReport {
28
28
  filter: COABalancesFilter;
29
29
  isReportGenerated: boolean;
30
30
  opexBalances: OpExBalancesByVendor[];
31
+ refreshStatus: FetchStateAndError;
31
32
  reportFetchState: {
32
33
  month: FetchStateAndError;
33
34
  quarter: FetchStateAndError;
@@ -71,6 +71,7 @@ exports.getOpExByVendorReport = (0, toolkit_1.createSelector)((state) => state.o
71
71
  filter,
72
72
  isReportGenerated: opExByVendorState.opExByVendorReportGenerated,
73
73
  lastRefreshSuccessTime: opExByVendorState.lastRefreshSuccessTime,
74
+ refreshStatus: opExByVendorState.refreshStatus,
74
75
  opexBalances,
75
76
  summaryBalances,
76
77
  allTimeframeTicks,
@@ -65,6 +65,7 @@ export interface OpExByVendorState extends Omit<Report, 'dataAvailable'> {
65
65
  quarter: OpexVendorKey[];
66
66
  };
67
67
  opExByVendorReportGenerated: boolean;
68
+ refreshStatus: FetchStateAndError;
68
69
  reportFetchState: {
69
70
  month: FetchStateAndError;
70
71
  quarter: FetchStateAndError;
@@ -0,0 +1,17 @@
1
+ import { ActionsObservable, StateObservable } from 'redux-observable';
2
+ import { RootState } from '../../reducer';
3
+ import { ZeniAPIStatus } from '../../responsePayload';
4
+ import { ZeniAPI } from '../../zeniAPI';
5
+ import { refreshOpExByVendorReport, refreshOpExByVendorReportFailure, refreshOpExByVendorReportSuccess } from './opExByVendorReducer';
6
+ export type ActionType = ReturnType<typeof refreshOpExByVendorReport> | ReturnType<typeof refreshOpExByVendorReportSuccess> | ReturnType<typeof refreshOpExByVendorReportFailure>;
7
+ export declare const refreshOpExByVendorReportEpic: (actions$: ActionsObservable<ActionType>, _state: StateObservable<RootState>, zeniAPI: ZeniAPI) => import("rxjs").Observable<{
8
+ payload: {
9
+ lastRefreshSuccessTime: import("../../zeniDayJS").ZeniDate | undefined;
10
+ };
11
+ type: "opExByVendor/refreshOpExByVendorReportSuccess";
12
+ } | {
13
+ payload: {
14
+ error: ZeniAPIStatus<Record<string, unknown>>;
15
+ };
16
+ type: "opExByVendor/refreshOpExByVendorReportFailure";
17
+ }>;
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.refreshOpExByVendorReportEpic = void 0;
4
+ const rxjs_1 = require("rxjs");
5
+ const operators_1 = require("rxjs/operators");
6
+ const responsePayload_1 = require("../../responsePayload");
7
+ const zeniDayJS_1 = require("../../zeniDayJS");
8
+ const opExByVendorReducer_1 = require("./opExByVendorReducer");
9
+ const refreshOpExByVendorReportEpic = (actions$, _state, zeniAPI) => actions$.pipe((0, operators_1.filter)(opExByVendorReducer_1.refreshOpExByVendorReport.match), (0, operators_1.switchMap)(() => {
10
+ return zeniAPI
11
+ .postAndGetJSON(`${zeniAPI.apiEndPoints.accountMicroServiceBaseUrl}/1.0/reports/operating-expenses-by-vendor/refresh`)
12
+ .pipe((0, operators_1.mergeMap)((response) => {
13
+ if (response.status.code >= 200 && response.status.code < 300) {
14
+ const lastRefreshSuccessTime = response.status.last_refresh_success_time != null
15
+ ? (0, zeniDayJS_1.date)(response.status.last_refresh_success_time)
16
+ : undefined;
17
+ return (0, rxjs_1.of)((0, opExByVendorReducer_1.refreshOpExByVendorReportSuccess)({ lastRefreshSuccessTime }));
18
+ }
19
+ else {
20
+ return (0, rxjs_1.of)((0, opExByVendorReducer_1.refreshOpExByVendorReportFailure)(response.status));
21
+ }
22
+ }), (0, operators_1.catchError)((error) => (0, rxjs_1.of)((0, opExByVendorReducer_1.refreshOpExByVendorReportFailure)((0, responsePayload_1.createZeniAPIStatus)('Unexpected error', 'Refresh OpEx by Vendor REST API call errored out: ' +
23
+ JSON.stringify(error))))));
24
+ }));
25
+ exports.refreshOpExByVendorReportEpic = refreshOpExByVendorReportEpic;
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.sendReferralInviteEpic = void 0;
4
4
  const rxjs_1 = require("rxjs");
5
5
  const operators_1 = require("rxjs/operators");
6
+ const snackbarReducer_1 = require("../../../entity/snackbar/snackbarReducer");
6
7
  const responsePayload_1 = require("../../../responsePayload");
7
8
  const referralReducer_1 = require("../referralReducer");
8
9
  const sendReferralInviteEpic = (actions$, state$, zeniAPI) => actions$.pipe((0, operators_1.filter)(referralReducer_1.sendReferralInvite.match), (0, operators_1.switchMap)(() => {
@@ -16,7 +17,14 @@ const sendReferralInviteEpic = (actions$, state$, zeniAPI) => actions$.pipe((0,
16
17
  .postAndGetJSON(`${zeniAPI.apiEndPoints.tenantMicroServiceBaseUrl}/1.0/company-referrals`, invitePayload)
17
18
  .pipe((0, operators_1.mergeMap)((response) => {
18
19
  if ((0, responsePayload_1.isSuccessStatus)(response)) {
19
- const actions = [(0, referralReducer_1.sendReferralInviteSuccess)()];
20
+ const actions = [
21
+ (0, referralReducer_1.sendReferralInviteSuccess)(),
22
+ (0, snackbarReducer_1.openSnackbar)({
23
+ messageSection: 'referral_invite_sent',
24
+ messageText: 'success',
25
+ type: 'success',
26
+ }),
27
+ ];
20
28
  return actions;
21
29
  }
22
30
  else {
@@ -2,6 +2,7 @@ import { SortOrder } from '../../commonStateTypes/selectorTypes/sortOrderTypes';
2
2
  import { ZeniAPIStatus } from '../../responsePayload';
3
3
  import { FetchRewardsPayload, FetchRewardsPlanPayload } from './referralPayload';
4
4
  import { InviteCompanyLocalData, ReferralListViewSortKey, ReferralViewState } from './referralState';
5
+ export declare const DEFAULT_REFERRER_AMOUNT = 4000;
5
6
  export declare const initialState: ReferralViewState;
6
7
  export declare const fetchReferrals: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[cacheOverride?: any, refreshViewInBackground?: any], {
7
8
  cacheOverride: any;
@@ -1,13 +1,14 @@
1
1
  "use strict";
2
2
  var _a;
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.updateRewardsPlanFailure = exports.updateRewardsPlan = exports.fetchRewardsPlan = exports.clearReferrals = exports.updateReferViewedFailure = exports.updateReferViewedSuccess = exports.updateReferViewed = exports.resendReferralInviteSuccess = exports.resendReferralInvite = exports.sendReferralInviteFailure = exports.sendReferralInviteSuccess = exports.sendReferralInvite = exports.clearReferralFormDataInLocalStore = exports.saveReferralFormDataInLocalStore = exports.updateReferralsFailure = exports.updateReferralListSortUiState = exports.updateReferrals = exports.fetchReferrals = exports.initialState = void 0;
4
+ exports.updateRewardsPlanFailure = exports.updateRewardsPlan = exports.fetchRewardsPlan = exports.clearReferrals = exports.updateReferViewedFailure = exports.updateReferViewedSuccess = exports.updateReferViewed = exports.resendReferralInviteSuccess = exports.resendReferralInvite = exports.sendReferralInviteFailure = exports.sendReferralInviteSuccess = exports.sendReferralInvite = exports.clearReferralFormDataInLocalStore = exports.saveReferralFormDataInLocalStore = exports.updateReferralsFailure = exports.updateReferralListSortUiState = exports.updateReferrals = exports.fetchReferrals = exports.initialState = exports.DEFAULT_REFERRER_AMOUNT = void 0;
5
5
  const toolkit_1 = require("@reduxjs/toolkit");
6
6
  const amount_1 = require("../../commonStateTypes/amount");
7
7
  const zeniDayJS_1 = require("../../zeniDayJS");
8
8
  const zeniUrl_1 = require("../../zeniUrl");
9
9
  const referralPayload_1 = require("./referralPayload");
10
10
  const referralState_1 = require("./referralState");
11
+ exports.DEFAULT_REFERRER_AMOUNT = 4000;
11
12
  exports.initialState = {
12
13
  fetchState: 'Not-Started',
13
14
  error: undefined,
@@ -48,7 +49,7 @@ exports.initialState = {
48
49
  },
49
50
  rewardsPlan: {
50
51
  referrerAmount: {
51
- amount: 0,
52
+ amount: exports.DEFAULT_REFERRER_AMOUNT,
52
53
  currencyCode: 'USD',
53
54
  currencySymbol: '$',
54
55
  },
@@ -57,7 +58,7 @@ exports.initialState = {
57
58
  currencyCode: 'USD',
58
59
  currencySymbol: '$',
59
60
  },
60
- planName: 'PLAN_1000',
61
+ planName: 'PLAN_4000',
61
62
  planId: 'dummy',
62
63
  referralLink: (0, zeniUrl_1.toZeniUrl)(''),
63
64
  },
@@ -115,7 +115,11 @@ const setupView = (0, toolkit_1.createSlice)({
115
115
  saveSetupViewDataInLocalStore(draft, action) {
116
116
  const setupViewLocalData = action.payload;
117
117
  if (setupViewLocalData.companyDetails != null) {
118
- draft.companyDetails.localData = setupViewLocalData.companyDetails;
118
+ const syncToken = setupViewLocalData.companyDetails.syncToken ?? draft.companyDetails.localData?.syncToken;
119
+ draft.companyDetails.localData = {
120
+ ...setupViewLocalData.companyDetails,
121
+ ...(syncToken != null ? { syncToken } : {}),
122
+ };
119
123
  }
120
124
  if (setupViewLocalData.primaryContactDetails != null) {
121
125
  draft.primaryContactDetails.localData =
@@ -19,8 +19,8 @@ const saveTaskDetailEpic = (actions$, state$, zeniAPI) => actions$.pipe((0, oper
19
19
  // fall back to the entity's current group. For a create, use the
20
20
  // taskGroupId from the action payload.
21
21
  const localTaskGroupId = taskId != null
22
- ? state.taskDetailState.editTaskStateById[taskId]?.taskDetailLocalData
23
- .taskGroupId
22
+ ? state.taskDetailState.editTaskStateById[taskId]
23
+ ?.taskDetailLocalData?.taskGroupId
24
24
  : undefined;
25
25
  // Distinguish three cases (PR #3101 review):
26
26
  // - create (taskId == null): use the action payload group.
@@ -17,4 +17,4 @@ export declare const sendCommentMentionNotification: import("@reduxjs/toolkit").
17
17
  performedById: string;
18
18
  }, "taskDetailView/sendCommentMentionNotification", never, never>;
19
19
  export type ActionType = ReturnType<typeof sendCommentMentionNotification>;
20
- export declare const sendCommentMentionNotificationEpic: (actions$: ActionsObservable<ActionType>, _state$: StateObservable<RootState>, zeniAPI: ZeniAPI) => import("rxjs").Observable<unknown>;
20
+ export declare const sendCommentMentionNotificationEpic: (actions$: ActionsObservable<ActionType>, _state$: StateObservable<RootState>, zeniAPI: ZeniAPI) => import("rxjs").Observable<never>;
@@ -37,5 +37,5 @@ const handleSendCommentMentionNotification = ({ taskId, mentionedUserIds, perfor
37
37
  // non-success responses and network errors so a Slack outage
38
38
  // does not pollute the dev console for every @-mention.
39
39
  return rxjs_1.EMPTY;
40
- }), (0, operators_1.catchError)(() => (0, rxjs_1.of)()));
40
+ }), (0, operators_1.catchError)(() => rxjs_1.EMPTY));
41
41
  };
@@ -53,7 +53,7 @@ export interface EditTaskLocalData {
53
53
  recurringStartDate?: ZeniDate;
54
54
  savedRecurringEndDate?: ZeniDate;
55
55
  savedRecurringTasksCount?: number;
56
- taskGroupId?: ID;
56
+ taskGroupId?: ID | null;
57
57
  }
58
58
  export declare const initialTaskDetailLocalData: EditTaskLocalData;
59
59
  export declare const initialTaskDetail: EditTaskDetail;
@@ -38,7 +38,7 @@ const getTaskDetail = (state, taskId) => {
38
38
  const taskEntity = (0, taskSelector_1.getTaskById)(taskState, taskId);
39
39
  subtasks =
40
40
  taskEntity != null
41
- ? (0, taskSelector_1.getTasksByIds)(taskState, taskEntity.subTasksIds)
41
+ ? (0, taskSelector_1.getTasksByIds)(taskState, taskEntity.subTasksIds ?? [])
42
42
  : [];
43
43
  const fileIdsInEntity = taskEntity?.fileIds ?? [];
44
44
  if (taskEntity != null) {
@@ -494,7 +494,9 @@ const taskList = (0, toolkit_1.createSlice)({
494
494
  // never move between tabs on their own.
495
495
  builder.addCase(taskReducer_1.updateTasks, (draft, action) => {
496
496
  action.payload.forEach((taskPayload) => {
497
- if (taskPayload.parent_task_id) {
497
+ // Only re-bucket parents; subtasks (parent_task_id is a non-empty
498
+ // string) are nested under their parent row and don't move tabs.
499
+ if (taskPayload.parent_task_id !== null && taskPayload.parent_task_id !== undefined && taskPayload.parent_task_id !== '') {
498
500
  return;
499
501
  }
500
502
  const taskId = taskPayload.task_id;
@@ -8,6 +8,7 @@ const get_1 = __importDefault(require("lodash/get"));
8
8
  const rxjs_1 = require("rxjs");
9
9
  const operators_1 = require("rxjs/operators");
10
10
  const transactionSelector_1 = require("../../../entity/transaction/transactionSelector");
11
+ const tenantSelector_1 = require("../../../entity/tenant/tenantSelector");
11
12
  const transactionDetailReducer_1 = require("../transactionDetailReducer");
12
13
  const transactionDetailState_1 = require("../transactionDetailState");
13
14
  const saveTransactionHelper_1 = require("./saveTransactionHelper");
@@ -16,12 +17,13 @@ const saveTransactionDetailEpic = (actions$, state$) => actions$.pipe((0, operat
16
17
  const fetchActions = [];
17
18
  const transactionDetailState = state$.value.transactionDetailState;
18
19
  const transactionState = state$.value.transactionState;
20
+ const isAccountingProjectsEnabled = (0, tenantSelector_1.getIsAccountingProjectsEnabled)(state$.value);
19
21
  const key = (0, transactionDetailState_1.getTransactionDetailKey)(transactionId);
20
22
  const detail = (0, get_1.default)(transactionDetailState.transactionDetailById, key, undefined);
21
23
  const transaction = (0, transactionSelector_1.getSupportedTransactionById)(transactionState, key);
22
24
  if (detail != null && transaction != null) {
23
25
  const localData = detail.transactionDetailLocalData;
24
- const transactionSaveUpdates = (0, saveTransactionHelper_1.toTransactionUpdatesFromTransactionDetailLocalData)(localData, transaction, isExpenseAutomationEnabled);
26
+ const transactionSaveUpdates = (0, saveTransactionHelper_1.toTransactionUpdatesFromTransactionDetailLocalData)(localData, transaction, isExpenseAutomationEnabled, isAccountingProjectsEnabled);
25
27
  fetchActions.push((0, transactionDetailReducer_1.updateTransactionDetail)(transactionId, transactionSaveUpdates, isExpenseAutomationEnabled, cotTransactionTracking, isUncategorizedExpenseCategoryEnabled));
26
28
  return (0, rxjs_1.from)(fetchActions);
27
29
  }
@@ -21,7 +21,7 @@ import { TransactionDetailLocalData } from '../transactionDetailTypes';
21
21
  * 4. Only difference between this and Miscategorized will be that we will
22
22
  * additionally fire “Mark as not miscat” for every point above.
23
23
  */
24
- export declare const toTransactionUpdatesFromTransactionDetailLocalData: (transactionDetailLocalData: TransactionDetailLocalData, transaction: SupportedTransaction, isExpenseAutomationEnabled: boolean) => TransactionSaveUpdates;
24
+ export declare const toTransactionUpdatesFromTransactionDetailLocalData: (transactionDetailLocalData: TransactionDetailLocalData, transaction: SupportedTransaction, isExpenseAutomationEnabled: boolean, isAccountingProjectsEnabled?: boolean) => TransactionSaveUpdates;
25
25
  export declare const toRecommendedAccountBase: (amountValue: number, accountBase?: AccountBase, recommendationBase?: RecommendationBase) => RecommendedAccountBase | undefined;
26
26
  export declare const toRecommendedClassBase: (amountValue: number, classBase?: ClassBase, recommendationBase?: RecommendationBase) => RecommendedClassBase | undefined;
27
27
  export declare const isTransactionMiscategorized: (transaction: SupportedTransaction, isExpenseAutomationEnabled: boolean) => boolean;