@zeniai/client-epic-state 5.1.91 → 5.1.92-beta0NB

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 (93) hide show
  1. package/lib/entity/accountRecon/accountReconReducer.js +4 -0
  2. package/lib/entity/accountRecon/accountReconState.d.ts +4 -1
  3. package/lib/entity/accountRecon/accountReconState.js +1 -0
  4. package/lib/entity/snackbar/snackbarApiError.d.ts +8 -0
  5. package/lib/entity/snackbar/snackbarApiError.js +15 -0
  6. package/lib/entity/snackbar/snackbarTypes.d.ts +1 -1
  7. package/lib/entity/snackbar/snackbarTypes.js +1 -0
  8. package/lib/epic.d.ts +4 -1
  9. package/lib/epic.js +4 -1
  10. package/lib/esm/entity/accountRecon/accountReconReducer.js +4 -0
  11. package/lib/esm/entity/accountRecon/accountReconState.js +1 -0
  12. package/lib/esm/entity/snackbar/snackbarApiError.js +11 -0
  13. package/lib/esm/entity/snackbar/snackbarTypes.js +1 -0
  14. package/lib/esm/epic.js +4 -1
  15. package/lib/esm/index.js +4 -4
  16. package/lib/esm/view/expenseAutomationView/epics/accountRecon/confirmStatementMappingEpic.js +43 -0
  17. package/lib/esm/view/expenseAutomationView/epics/accountRecon/parseCombinedStatementEpic.js +31 -0
  18. package/lib/esm/view/expenseAutomationView/epics/accountRecon/parseStatementEpic.js +15 -18
  19. package/lib/esm/view/expenseAutomationView/epics/accountRecon/updateCombinedStatementInfoEpic.js +68 -0
  20. package/lib/esm/view/expenseAutomationView/epics/accountRecon/updateStatementInfoEpic.js +10 -10
  21. package/lib/esm/view/expenseAutomationView/epics/accountRecon/uploadAccountStatementDocumentAIHelper.js +12 -4
  22. package/lib/esm/view/expenseAutomationView/epics/accountRecon/uploadAccountStatementEpic.js +8 -2
  23. package/lib/esm/view/expenseAutomationView/helpers/mapStatementUpdateLocalDataToRequestBody.js +20 -5
  24. package/lib/esm/view/expenseAutomationView/payload/reconciliationPayload.js +135 -0
  25. package/lib/esm/view/expenseAutomationView/reducers/reconciliationViewReducer.js +119 -16
  26. package/lib/esm/view/expenseAutomationView/selectors/reconciliationViewSelector.js +28 -7
  27. package/lib/esm/view/expenseAutomationView/selectors/statementParseViewSelector.js +43 -10
  28. package/lib/esm/view/expenseAutomationView/types/reconciliationViewState.js +15 -1
  29. package/lib/esm/view/invoicing/createCreditNote/createCreditNoteEpic.js +2 -0
  30. package/lib/esm/view/invoicing/createInvoice/createInvoiceEpic.js +2 -0
  31. package/lib/esm/view/invoicing/discountAction/discountActionEpic.js +6 -3
  32. package/lib/esm/view/invoicing/dunningAction/dunningActionEpic.js +6 -3
  33. package/lib/esm/view/invoicing/editInvoicingCatalogItemDetailView/editInvoicingCatalogItemDetailViewPayload.js +5 -4
  34. package/lib/esm/view/invoicing/editInvoicingCatalogItemDetailView/saveInvoicingCatalogItemEpic.js +3 -0
  35. package/lib/esm/view/invoicing/editInvoicingCouponDetailView/saveInvoicingCouponEpic.js +2 -0
  36. package/lib/esm/view/invoicing/editInvoicingCustomerDetailView/saveInvoicingCustomerEpic.js +2 -0
  37. package/lib/esm/view/invoicing/editInvoicingSubscriptionDetailView/saveInvoicingSubscriptionEpic.js +2 -0
  38. package/lib/esm/view/invoicing/invoiceAction/invoiceActionEpic.js +7 -3
  39. package/lib/esm/view/invoicing/invoicingQboView/epics/retryInvoicingQboSyncTaskEpic.js +2 -0
  40. package/lib/esm/view/invoicing/invoicingQboView/epics/startInvoicingQboBackfillEpic.js +2 -0
  41. package/lib/esm/view/invoicing/issueCreditNote/issueCreditNoteEpic.js +2 -0
  42. package/lib/esm/view/invoicing/recordPayment/recordPaymentEpic.js +3 -0
  43. package/lib/esm/view/invoicing/settingsView/settingsViewEpics.js +6 -3
  44. package/lib/esm/view/invoicing/settingsView/settingsViewSelector.js +52 -0
  45. package/lib/esm/view/invoicing/subscriptionAction/subscriptionActionEpic.js +6 -3
  46. package/lib/esm/view/vendorTabView/vendorTabViewReducer.js +1 -1
  47. package/lib/index.d.ts +7 -7
  48. package/lib/index.js +51 -46
  49. package/lib/view/expenseAutomationView/epics/accountRecon/confirmStatementMappingEpic.d.ts +34 -0
  50. package/lib/view/expenseAutomationView/epics/accountRecon/confirmStatementMappingEpic.js +47 -0
  51. package/lib/view/expenseAutomationView/epics/accountRecon/parseCombinedStatementEpic.d.ts +26 -0
  52. package/lib/view/expenseAutomationView/epics/accountRecon/parseCombinedStatementEpic.js +35 -0
  53. package/lib/view/expenseAutomationView/epics/accountRecon/parseStatementEpic.d.ts +21 -1
  54. package/lib/view/expenseAutomationView/epics/accountRecon/parseStatementEpic.js +15 -18
  55. package/lib/view/expenseAutomationView/epics/accountRecon/updateCombinedStatementInfoEpic.d.ts +27 -0
  56. package/lib/view/expenseAutomationView/epics/accountRecon/updateCombinedStatementInfoEpic.js +72 -0
  57. package/lib/view/expenseAutomationView/epics/accountRecon/updateStatementInfoEpic.js +10 -10
  58. package/lib/view/expenseAutomationView/epics/accountRecon/uploadAccountStatementDocumentAIHelper.d.ts +1 -1
  59. package/lib/view/expenseAutomationView/epics/accountRecon/uploadAccountStatementDocumentAIHelper.js +12 -4
  60. package/lib/view/expenseAutomationView/epics/accountRecon/uploadAccountStatementEpic.js +7 -1
  61. package/lib/view/expenseAutomationView/helpers/mapStatementUpdateLocalDataToRequestBody.d.ts +1 -0
  62. package/lib/view/expenseAutomationView/helpers/mapStatementUpdateLocalDataToRequestBody.js +20 -4
  63. package/lib/view/expenseAutomationView/helpers/transactionCategorizationLocalDataHelper.d.ts +1 -1
  64. package/lib/view/expenseAutomationView/payload/reconciliationPayload.d.ts +109 -4
  65. package/lib/view/expenseAutomationView/payload/reconciliationPayload.js +143 -0
  66. package/lib/view/expenseAutomationView/reducers/reconciliationViewReducer.d.ts +32 -4
  67. package/lib/view/expenseAutomationView/reducers/reconciliationViewReducer.js +121 -18
  68. package/lib/view/expenseAutomationView/selectorTypes/reconciliationViewSelectorTypes.d.ts +5 -1
  69. package/lib/view/expenseAutomationView/selectors/reconciliationViewSelector.d.ts +3 -1
  70. package/lib/view/expenseAutomationView/selectors/reconciliationViewSelector.js +29 -7
  71. package/lib/view/expenseAutomationView/selectors/statementParseViewSelector.d.ts +3 -2
  72. package/lib/view/expenseAutomationView/selectors/statementParseViewSelector.js +44 -10
  73. package/lib/view/expenseAutomationView/types/reconciliationViewState.d.ts +74 -1
  74. package/lib/view/expenseAutomationView/types/reconciliationViewState.js +19 -1
  75. package/lib/view/invoicing/createCreditNote/createCreditNoteEpic.js +2 -0
  76. package/lib/view/invoicing/createInvoice/createInvoiceEpic.js +2 -0
  77. package/lib/view/invoicing/discountAction/discountActionEpic.js +5 -2
  78. package/lib/view/invoicing/dunningAction/dunningActionEpic.js +5 -2
  79. package/lib/view/invoicing/editInvoicingCatalogItemDetailView/editInvoicingCatalogItemDetailViewPayload.js +5 -4
  80. package/lib/view/invoicing/editInvoicingCatalogItemDetailView/saveInvoicingCatalogItemEpic.js +3 -0
  81. package/lib/view/invoicing/editInvoicingCouponDetailView/saveInvoicingCouponEpic.js +2 -0
  82. package/lib/view/invoicing/editInvoicingCustomerDetailView/saveInvoicingCustomerEpic.js +2 -0
  83. package/lib/view/invoicing/editInvoicingSubscriptionDetailView/saveInvoicingSubscriptionEpic.js +2 -0
  84. package/lib/view/invoicing/invoiceAction/invoiceActionEpic.js +6 -2
  85. package/lib/view/invoicing/invoicingQboView/epics/retryInvoicingQboSyncTaskEpic.js +2 -0
  86. package/lib/view/invoicing/invoicingQboView/epics/startInvoicingQboBackfillEpic.js +2 -0
  87. package/lib/view/invoicing/issueCreditNote/issueCreditNoteEpic.js +2 -0
  88. package/lib/view/invoicing/recordPayment/recordPaymentEpic.js +3 -0
  89. package/lib/view/invoicing/settingsView/settingsViewEpics.js +5 -2
  90. package/lib/view/invoicing/settingsView/settingsViewSelector.d.ts +41 -1
  91. package/lib/view/invoicing/settingsView/settingsViewSelector.js +55 -1
  92. package/lib/view/invoicing/subscriptionAction/subscriptionActionEpic.js +5 -2
  93. package/package.json +1 -1
@@ -1,6 +1,7 @@
1
1
  import { convertToPeriod, } from '../../../commonStateTypes/timePeriod';
2
2
  import { toTransactionsToReviewPayload, } from '../../../entity/accountRecon/accountReconPayload';
3
3
  import { toMatchedTransactionPayload, } from '../../../entity/transaction/payloadTypes/reconciliationTransactionPayloads';
4
+ import { toStatementBalanceSourceStrict, } from '../types/reconciliationViewState';
4
5
  export function createSaveReconciliationPayloadBasedOnActionAndMethod(state, selectedPeriod, localData, accountReconciliationEntity, action, method) {
5
6
  const { balance, initialClearedBalance } = accountReconciliationEntity;
6
7
  const { expenseAutomationReconciliationViewState: { selectedAccountId, reconTabsState: { reconcile: { localData: { selectedTransactionIds }, }, }, }, } = state;
@@ -67,10 +68,60 @@ function createReviewTransactionPayload(accountReconciliationEntity) {
67
68
  });
68
69
  return reviewTransactionsPayload;
69
70
  }
71
+ export function isParseStatementCombinedResponsePayload(payload) {
72
+ return ('statement_uploads' in payload &&
73
+ Array.isArray(payload.statement_uploads) &&
74
+ payload.statement_uploads.length > 0 &&
75
+ // Batch group GET nests each upload under statement_upload — exclude that shape.
76
+ 'statement_upload' in (payload.statement_uploads[0] ?? {}) === false);
77
+ }
78
+ export function isUpdateStatementInfoCombinedResponsePayload(payload) {
79
+ return ('statement_uploads' in payload &&
80
+ Array.isArray(payload.statement_uploads) &&
81
+ payload.statement_uploads.length > 0);
82
+ }
70
83
  export function isStatementDateConflictResponse(response) {
71
84
  return response.status.code === 409 && response.error_code != null;
72
85
  }
86
+ function transformConfirmedCombinedStatementUploadsToState(statementUploads) {
87
+ return (statementUploads ?? []).map((statementUpload) => ({
88
+ accountId: statementUpload.account_id,
89
+ isCombinedStatementAnchor: statementUpload.is_combined_statement_anchor,
90
+ ledgerIdentifiers: statementUpload.ledger_identifiers ?? [],
91
+ statementUploadId: statementUpload.statement_upload_id,
92
+ }));
93
+ }
94
+ function transformCombinedStatementDetailsToState(details) {
95
+ if (details == null) {
96
+ return undefined;
97
+ }
98
+ return {
99
+ combinedStatementGroupId: details.combined_statement_group_id,
100
+ isMappingConfirmed: details.is_mapping_confirmed,
101
+ accounts: (details.accounts ?? []).map((account) => ({
102
+ ledgerIdentifier: account.ledger_identifier,
103
+ accountName: account.account_name,
104
+ accountType: account.account_type,
105
+ maskedAccountNumber: account.masked_account_number,
106
+ openingBalance: account.opening_balance,
107
+ closingBalance: account.closing_balance,
108
+ transactionCount: account.transaction_count,
109
+ isUploadContext: account.is_upload_context,
110
+ existingStatementStatus: account.existing_statement_status ?? null,
111
+ suggestion: account.suggestion != null
112
+ ? {
113
+ accountId: account.suggestion.account_id,
114
+ accountName: account.suggestion.account_name,
115
+ matchedBy: account.suggestion.matched_by,
116
+ matchConfidence: account.suggestion.match_confidence,
117
+ }
118
+ : null,
119
+ })),
120
+ statementUploads: transformConfirmedCombinedStatementUploadsToState(details.statement_uploads),
121
+ };
122
+ }
73
123
  function transformStatementUploadPayloadToState(statementUploadPayload) {
124
+ const balanceSource = toStatementBalanceSourceStrict(statementUploadPayload.statement_meta.balance_source);
74
125
  return {
75
126
  account: {
76
127
  accountId: statementUploadPayload.account.account_id,
@@ -96,6 +147,13 @@ function transformStatementUploadPayloadToState(statementUploadPayload) {
96
147
  statementUploadId: statementUploadPayload.statement_meta.statement_upload_id,
97
148
  totalDeposits: statementUploadPayload.statement_meta.total_deposits,
98
149
  totalPayments: statementUploadPayload.statement_meta.total_payments,
150
+ isCombinedStatement: statementUploadPayload.statement_meta.is_combined_statement ??
151
+ undefined,
152
+ isCombinedStatementAnchor: statementUploadPayload.statement_meta.is_combined_statement_anchor ??
153
+ undefined,
154
+ combinedStatementGroupId: statementUploadPayload.statement_meta.combined_statement_group_id ??
155
+ undefined,
156
+ ...(balanceSource != null ? { balanceSource } : {}),
99
157
  },
100
158
  statementTransactions: (statementUploadPayload.statement_transactions ?? []).map((txn) => ({
101
159
  amount: txn.amount,
@@ -117,6 +175,7 @@ function transformStatementUploadPayloadToState(statementUploadPayload) {
117
175
  transactionMemo: txn.transaction_memo,
118
176
  })),
119
177
  aiSummary: transformAiSummaryPayloadToState(statementUploadPayload.ai_summary),
178
+ combinedStatementDetails: transformCombinedStatementDetailsToState(statementUploadPayload.combined_statement_details),
120
179
  };
121
180
  }
122
181
  function transformPreviousReconciliationInfoToState(payload) {
@@ -177,11 +236,71 @@ export function transformStatementDateConflictToState(response) {
177
236
  };
178
237
  }
179
238
  export function transformParseStatementPayloadToState(payload) {
239
+ if (isParseStatementCombinedResponsePayload(payload) === true) {
240
+ const statementUploads = payload.statement_uploads.map(transformStatementUploadPayloadToState);
241
+ const anchorUpload = statementUploads.find((upload) => upload.statementMeta.isCombinedStatementAnchor === true) ?? statementUploads[0];
242
+ return {
243
+ statementUpload: anchorUpload,
244
+ statementUploads,
245
+ };
246
+ }
180
247
  return {
181
248
  statementUpload: transformStatementUploadPayloadToState(payload.statement_upload),
182
249
  };
183
250
  }
251
+ export function transformCombinedStatementGroupPayloadToState(payload) {
252
+ const groupId = payload.combined_statement_group_id;
253
+ const statementUploads = (payload.statement_uploads ?? []).map((entry) => {
254
+ const upload = transformStatementUploadPayloadToState(entry.statement_upload);
255
+ if ((upload.statementMeta.combinedStatementGroupId == null ||
256
+ upload.statementMeta.combinedStatementGroupId === '') &&
257
+ groupId !== '') {
258
+ return {
259
+ ...upload,
260
+ statementMeta: {
261
+ ...upload.statementMeta,
262
+ combinedStatementGroupId: groupId,
263
+ },
264
+ };
265
+ }
266
+ return upload;
267
+ });
268
+ if (statementUploads.length === 0) {
269
+ throw new Error('Combined statement response has no statement uploads');
270
+ }
271
+ const anchorUpload = statementUploads.find((upload) => upload.statementMeta.isCombinedStatementAnchor === true) ?? statementUploads[0];
272
+ return {
273
+ statementUpload: anchorUpload,
274
+ statementUploads,
275
+ };
276
+ }
277
+ export function isConfirmStatementMappingConflictResponse(response) {
278
+ return response.status.code === 409;
279
+ }
280
+ export function transformConfirmStatementMappingPayloadToState(payload) {
281
+ return transformConfirmedCombinedStatementUploadsToState(payload.statement_uploads);
282
+ }
283
+ export function transformConfirmStatementMappingConflictToState(response) {
284
+ if (isConfirmStatementMappingConflictResponse(response) === false) {
285
+ return null;
286
+ }
287
+ return {
288
+ collidingAccountId: response.colliding_account_id != null
289
+ ? response.colliding_account_id
290
+ : undefined,
291
+ collidingLedgerIdentifiers: response.colliding_ledger_identifiers ?? [],
292
+ previousReconciliationInfo: transformPreviousReconciliationInfoToState(response.previous_reconciliation_info),
293
+ };
294
+ }
184
295
  export function transformUpdateStatementInfoPayloadToState(payload) {
296
+ if (isUpdateStatementInfoCombinedResponsePayload(payload) === true) {
297
+ const statementUploads = payload.statement_uploads.map(transformStatementUploadPayloadToState);
298
+ const anchorUpload = statementUploads.find((upload) => upload.statementMeta.isCombinedStatementAnchor === true) ?? statementUploads[0];
299
+ return {
300
+ statementUpload: anchorUpload,
301
+ statementUploads,
302
+ };
303
+ }
185
304
  return {
186
305
  statementUpload: transformStatementUploadPayloadToState(payload.statement_upload),
187
306
  };
@@ -221,3 +340,19 @@ export function transformStatementUpdateStateToPayload(localData) {
221
340
  export function toStatementUpdateRequestBody(localData) {
222
341
  return transformStatementUpdateStateToPayload(localData);
223
342
  }
343
+ export function transformBulkStatementUpdateStateToPayload(updates) {
344
+ return {
345
+ statement_uploads: updates.map(({ localData, statementUploadId }) => {
346
+ const body = transformStatementUpdateStateToPayload(localData);
347
+ return {
348
+ statement_upload_id: statementUploadId,
349
+ statement_meta: body.statement_meta,
350
+ statement_transactions: body.statement_transactions,
351
+ };
352
+ }),
353
+ };
354
+ }
355
+ /** Bulk PUT body for combined multi-account Confirm & Save. */
356
+ export function toBulkStatementUpdateRequestBody(updates) {
357
+ return transformBulkStatementUpdateStateToPayload(updates);
358
+ }
@@ -430,7 +430,7 @@ const expenseAutomationReconciliationView = createSlice({
430
430
  }
431
431
  },
432
432
  uploadAccountStatement: (draft, action) => {
433
- const { accountId, selectedPeriod } = action.payload;
433
+ const { accountId, selectedPeriod, statementAccountScope } = action.payload;
434
434
  const accountRecon = draft.accountReconciliationRecordsBySelectedPeriod[toMonthYearPeriodId(selectedPeriod)]?.reconciliationByAccountID[accountId];
435
435
  if (accountRecon != null) {
436
436
  accountRecon.statementUploadStatus = {
@@ -455,6 +455,22 @@ const expenseAutomationReconciliationView = createSlice({
455
455
  fetchState: 'Not-Started',
456
456
  error: undefined,
457
457
  };
458
+ accountRecon.combinedStatementGroupId = undefined;
459
+ accountRecon.confirmedCombinedStatementUploads = undefined;
460
+ accountRecon.confirmStatementMappingStatus = {
461
+ fetchState: 'Not-Started',
462
+ error: undefined,
463
+ };
464
+ accountRecon.confirmStatementMappingConflict = null;
465
+ if (accountRecon.localData != null) {
466
+ accountRecon.localData.statementUpdateLocalDataByUploadId = undefined;
467
+ }
468
+ if (statementAccountScope != null) {
469
+ accountRecon.localData = {
470
+ ...accountRecon.localData,
471
+ statementAccountScope,
472
+ };
473
+ }
458
474
  }
459
475
  },
460
476
  uploadAccountStatementSuccess: (draft, action) => {
@@ -517,8 +533,15 @@ const expenseAutomationReconciliationView = createSlice({
517
533
  fetchState: 'Not-Started',
518
534
  error: undefined,
519
535
  };
536
+ accountRecon.combinedStatementGroupId = undefined;
537
+ accountRecon.confirmedCombinedStatementUploads = undefined;
538
+ accountRecon.confirmStatementMappingStatus = {
539
+ fetchState: 'Not-Started',
540
+ error: undefined,
541
+ };
542
+ accountRecon.confirmStatementMappingConflict = null;
520
543
  if (accountRecon.localData != null) {
521
- accountRecon.localData.statementUpdateLocalData = undefined;
544
+ accountRecon.localData.statementUpdateLocalDataByUploadId = undefined;
522
545
  }
523
546
  }
524
547
  },
@@ -544,6 +567,17 @@ const expenseAutomationReconciliationView = createSlice({
544
567
  };
545
568
  }
546
569
  },
570
+ parseCombinedStatement: (draft, action) => {
571
+ const { accountId, selectedPeriod } = action.payload;
572
+ const accountRecon = draft.accountReconciliationRecordsBySelectedPeriod[toMonthYearPeriodId(selectedPeriod)]?.reconciliationByAccountID[accountId];
573
+ if (accountRecon != null) {
574
+ accountRecon.parsedStatementData = undefined;
575
+ accountRecon.statementParseStatus = {
576
+ fetchState: 'In-Progress',
577
+ error: undefined,
578
+ };
579
+ }
580
+ },
547
581
  parseStatementSuccess: (draft, action) => {
548
582
  const { accountId, selectedPeriod } = action.payload;
549
583
  const accountRecon = draft.accountReconciliationRecordsBySelectedPeriod[toMonthYearPeriodId(selectedPeriod)]?.reconciliationByAccountID[accountId];
@@ -598,7 +632,7 @@ const expenseAutomationReconciliationView = createSlice({
598
632
  accountRecon.statementProcessingFailed = false;
599
633
  accountRecon.statementParseInProgress = true;
600
634
  if (accountRecon.localData != null) {
601
- accountRecon.localData.statementUpdateLocalData = undefined;
635
+ accountRecon.localData.statementUpdateLocalDataByUploadId = undefined;
602
636
  }
603
637
  }
604
638
  },
@@ -644,19 +678,18 @@ const expenseAutomationReconciliationView = createSlice({
644
678
  parsedStatementData;
645
679
  },
646
680
  updateStatementUpdateLocalData: (draft, action) => {
647
- const { accountId, selectedPeriod, statementUpdateLocalData } = action.payload;
681
+ const { accountId, selectedPeriod, statementUpdateLocalData, statementUploadId, } = action.payload;
648
682
  const accountRecon = draft.accountReconciliationRecordsBySelectedPeriod[toMonthYearPeriodId(selectedPeriod)]?.reconciliationByAccountID[accountId];
649
- if (accountRecon != null) {
650
- if (accountRecon.localData == null) {
651
- accountRecon.localData = {
652
- statementUpdateLocalData,
653
- };
654
- }
655
- else {
656
- accountRecon.localData.statementUpdateLocalData =
657
- statementUpdateLocalData;
658
- }
683
+ if (accountRecon == null || statementUploadId === '') {
684
+ return;
659
685
  }
686
+ if (accountRecon.localData == null) {
687
+ accountRecon.localData = {};
688
+ }
689
+ accountRecon.localData.statementUpdateLocalDataByUploadId = {
690
+ ...accountRecon.localData.statementUpdateLocalDataByUploadId,
691
+ [statementUploadId]: statementUpdateLocalData,
692
+ };
660
693
  },
661
694
  submitStatementUpdate: (draft, action) => {
662
695
  const { accountId, selectedPeriod } = action.payload;
@@ -670,6 +703,17 @@ const expenseAutomationReconciliationView = createSlice({
670
703
  accountRecon.statementDateConflict = null;
671
704
  }
672
705
  },
706
+ submitCombinedStatementUpdate: (draft, action) => {
707
+ const { accountId, selectedPeriod } = action.payload;
708
+ const accountRecon = draft.accountReconciliationRecordsBySelectedPeriod[toMonthYearPeriodId(selectedPeriod)]?.reconciliationByAccountID[accountId];
709
+ if (accountRecon != null) {
710
+ accountRecon.statementUpdateStatus = {
711
+ fetchState: 'In-Progress',
712
+ error: undefined,
713
+ };
714
+ accountRecon.statementDateConflict = null;
715
+ }
716
+ },
673
717
  submitStatementUpdateSuccess: (draft, action) => {
674
718
  const { accountId, selectedPeriod } = action.payload;
675
719
  const accountRecon = draft.accountReconciliationRecordsBySelectedPeriod[toMonthYearPeriodId(selectedPeriod)]?.reconciliationByAccountID[accountId];
@@ -684,7 +728,7 @@ const expenseAutomationReconciliationView = createSlice({
684
728
  accountRecon.statementProcessingStartedAtMs = undefined;
685
729
  accountRecon.statementProcessingTotalDurationSeconds = undefined;
686
730
  if (accountRecon.localData != null) {
687
- accountRecon.localData.statementUpdateLocalData = undefined;
731
+ accountRecon.localData.statementUpdateLocalDataByUploadId = undefined;
688
732
  }
689
733
  }
690
734
  },
@@ -706,6 +750,52 @@ const expenseAutomationReconciliationView = createSlice({
706
750
  accountRecon.statementDateConflict = null;
707
751
  }
708
752
  },
753
+ confirmStatementMapping: (draft, action) => {
754
+ const { accountId, selectedPeriod } = action.payload;
755
+ const accountRecon = draft.accountReconciliationRecordsBySelectedPeriod[toMonthYearPeriodId(selectedPeriod)]?.reconciliationByAccountID[accountId];
756
+ if (accountRecon != null) {
757
+ accountRecon.confirmStatementMappingStatus = {
758
+ fetchState: 'In-Progress',
759
+ error: undefined,
760
+ };
761
+ accountRecon.confirmStatementMappingConflict = null;
762
+ }
763
+ },
764
+ confirmStatementMappingSuccess: (draft, action) => {
765
+ const { accountId, selectedPeriod, statementUploads } = action.payload;
766
+ const accountRecon = draft.accountReconciliationRecordsBySelectedPeriod[toMonthYearPeriodId(selectedPeriod)]?.reconciliationByAccountID[accountId];
767
+ if (accountRecon != null) {
768
+ accountRecon.confirmStatementMappingStatus = {
769
+ fetchState: 'Completed',
770
+ error: undefined,
771
+ };
772
+ accountRecon.confirmStatementMappingConflict = null;
773
+ accountRecon.confirmedCombinedStatementUploads = statementUploads;
774
+ const combinedStatementDetails = accountRecon.parsedStatementData?.statementUpload
775
+ .combinedStatementDetails;
776
+ if (combinedStatementDetails != null) {
777
+ combinedStatementDetails.isMappingConfirmed = true;
778
+ }
779
+ const combinedStatementGroupId = combinedStatementDetails?.combinedStatementGroupId ??
780
+ accountRecon.parsedStatementData?.statementUpload.statementMeta
781
+ .combinedStatementGroupId;
782
+ if (combinedStatementGroupId != null &&
783
+ combinedStatementGroupId !== '') {
784
+ accountRecon.combinedStatementGroupId = combinedStatementGroupId;
785
+ }
786
+ }
787
+ },
788
+ confirmStatementMappingFailure: (draft, action) => {
789
+ const { accountId, selectedPeriod, mappingConflict } = action.payload;
790
+ const accountRecon = draft.accountReconciliationRecordsBySelectedPeriod[toMonthYearPeriodId(selectedPeriod)]?.reconciliationByAccountID[accountId];
791
+ if (accountRecon != null) {
792
+ accountRecon.confirmStatementMappingStatus = {
793
+ fetchState: 'Error',
794
+ error: action.payload.error,
795
+ };
796
+ accountRecon.confirmStatementMappingConflict = mappingConflict ?? null;
797
+ }
798
+ },
709
799
  updateAccountReconciliationLocalData: (draft, action) => {
710
800
  const { accountId, selectedPeriod, localData } = action.payload;
711
801
  const oldLocalData = draft.accountReconciliationRecordsBySelectedPeriod[toMonthYearPeriodId(selectedPeriod)].reconciliationByAccountID[accountId].localData;
@@ -816,7 +906,7 @@ const expenseAutomationReconciliationView = createSlice({
816
906
  },
817
907
  });
818
908
  // Export actions
819
- export const { fetchReconciliation, fetchReconciliationFailure, fetchReconciliationSuccess, saveReconciliationDetail, saveReconciliationDetailFailure, updateSelectedAccountId, setConnectionInProgressForAccount, setStatementParseInProgress, setStatementProcessingDismissedToBackground, updateStatementProcessingBackgroundCompletedSteps, updateReconcileTabLocalData, updateReconcileTabListSortState, updateReconcileTabListScrollState, saveReconciliationDetailSuccess, updateSelectedTab, updateBalancesLocalData, initialiseLocalDataForSelectedAccountId, clearExpenseAutomationReconciliationView, updateSelectedDrawerAccountId, updateStatementProcessingFailed, updateReviewTabSortState, initializeReconciliationReviewTabLocalData, updateReviewTabLocalData, saveReconciliationReview, updateSaveReconciliationReviewFetchStatus, updateReconListScrollPosition, updateAccountReconciliationLocalData, deleteAccountStatement, deleteAccountStatementSuccess, deleteAccountStatementFailure, excludeAccountFromReconciliation, excludeAccountFromReconciliationSuccess, excludeAccountFromReconciliationFailure, includeAccountInReconciliation, includeAccountInReconciliationSuccess, includeAccountInReconciliationFailure, uploadAccountStatement, uploadAccountStatementSuccess, uploadAccountStatementFailure, parseStatement, parseStatementSuccess, parseStatementFailure, reparseStatement, reparseStatementSuccess, reparseStatementFailure, resetReparseStatementStatus, updateParsedStatementData, updateStatementUpdateLocalData, submitStatementUpdate, submitStatementUpdateSuccess, submitStatementUpdateFailure, clearStatementDateConflict, updateStatementUploadChosen, updateNodeCollapseState, } = expenseAutomationReconciliationView.actions;
909
+ export const { fetchReconciliation, fetchReconciliationFailure, fetchReconciliationSuccess, saveReconciliationDetail, saveReconciliationDetailFailure, updateSelectedAccountId, setConnectionInProgressForAccount, setStatementParseInProgress, setStatementProcessingDismissedToBackground, updateStatementProcessingBackgroundCompletedSteps, updateReconcileTabLocalData, updateReconcileTabListSortState, updateReconcileTabListScrollState, saveReconciliationDetailSuccess, updateSelectedTab, updateBalancesLocalData, initialiseLocalDataForSelectedAccountId, clearExpenseAutomationReconciliationView, updateSelectedDrawerAccountId, updateStatementProcessingFailed, updateReviewTabSortState, initializeReconciliationReviewTabLocalData, updateReviewTabLocalData, saveReconciliationReview, updateSaveReconciliationReviewFetchStatus, updateReconListScrollPosition, updateAccountReconciliationLocalData, deleteAccountStatement, deleteAccountStatementSuccess, deleteAccountStatementFailure, excludeAccountFromReconciliation, excludeAccountFromReconciliationSuccess, excludeAccountFromReconciliationFailure, includeAccountInReconciliation, includeAccountInReconciliationSuccess, includeAccountInReconciliationFailure, uploadAccountStatement, uploadAccountStatementSuccess, uploadAccountStatementFailure, parseStatement, parseCombinedStatement, parseStatementSuccess, parseStatementFailure, reparseStatement, reparseStatementSuccess, reparseStatementFailure, resetReparseStatementStatus, updateParsedStatementData, updateStatementUpdateLocalData, submitStatementUpdate, submitCombinedStatementUpdate, submitStatementUpdateSuccess, submitStatementUpdateFailure, clearStatementDateConflict, confirmStatementMapping, confirmStatementMappingSuccess, confirmStatementMappingFailure, updateStatementUploadChosen, updateNodeCollapseState, } = expenseAutomationReconciliationView.actions;
820
910
  // Export reducer
821
911
  export default expenseAutomationReconciliationView.reducer;
822
912
  function isEntityStatementParsing(reconciliation) {
@@ -830,6 +920,7 @@ function isEntityStatementParseTerminal(reconciliation) {
830
920
  statusCode === 'parsing_failed' ||
831
921
  statusCode === 'validation_failed' ||
832
922
  statusCode === 'processing_failed' ||
923
+ statusCode === 'parsed_awaiting_mapping' ||
833
924
  statusCode === 'deleting' ||
834
925
  statusCode === 'deleted');
835
926
  }
@@ -965,6 +1056,13 @@ function updateAllReconciliation(draft, accounts, selectedPeriod, reconciliation
965
1056
  error: undefined,
966
1057
  },
967
1058
  statementDateConflict: oldRecord?.statementDateConflict ?? null,
1059
+ confirmStatementMappingStatus: oldRecord?.confirmStatementMappingStatus ?? {
1060
+ fetchState: 'Not-Started',
1061
+ error: undefined,
1062
+ },
1063
+ confirmStatementMappingConflict: oldRecord?.confirmStatementMappingConflict ?? null,
1064
+ confirmedCombinedStatementUploads: oldRecord?.confirmedCombinedStatementUploads,
1065
+ combinedStatementGroupId: oldRecord?.combinedStatementGroupId,
968
1066
  localData: {
969
1067
  ...oldRecord?.localData,
970
1068
  accountSource: account?.reconciliation_source != null
@@ -1063,6 +1161,11 @@ const updateReconciliationByAccountIDOnIncludeAccount = (draft, accountId, recon
1063
1161
  statementParseStatus: { fetchState: 'Not-Started', error: undefined },
1064
1162
  reparseStatementStatus: { fetchState: 'Not-Started', error: undefined },
1065
1163
  statementDateConflict: null,
1164
+ confirmStatementMappingStatus: {
1165
+ fetchState: 'Not-Started',
1166
+ error: undefined,
1167
+ },
1168
+ confirmStatementMappingConflict: null,
1066
1169
  localData: {},
1067
1170
  accountDetectionReason: undefined,
1068
1171
  };
@@ -245,8 +245,23 @@ export const getExpenseAutomationReconciliationView = createSelector((state) =>
245
245
  }
246
246
  const accountReconState = accountReconForMonthYearPeriod.reconciliationByAccountID[accountID];
247
247
  const rawParsedStatementData = accountReconState.parsedStatementData;
248
- const statementUpdateLocalData = accountReconState.localData?.statementUpdateLocalData;
249
- const parsedStatementDataForView = getParsedStatementDataForView(rawParsedStatementData, statementUpdateLocalData);
248
+ const statementUpdateLocalDataByUploadId = accountReconState.localData?.statementUpdateLocalDataByUploadId;
249
+ const statementAccountScope = accountReconState.localData?.statementAccountScope;
250
+ const parsedStatementDataForView = getParsedStatementDataForView(rawParsedStatementData, statementUpdateLocalDataByUploadId, statementAccountScope);
251
+ const rawStatementUploads = rawParsedStatementData?.statementUploads != null &&
252
+ rawParsedStatementData.statementUploads.length > 0
253
+ ? rawParsedStatementData.statementUploads
254
+ : rawParsedStatementData?.statementUpload != null
255
+ ? [rawParsedStatementData.statementUpload]
256
+ : [];
257
+ const allCitationTransactions = rawStatementUploads.flatMap((statementUpload) => statementUpload.statementTransactions);
258
+ const statementTransactionPeriodById = rawStatementUploads.length > 0
259
+ ? Object.assign({}, ...rawStatementUploads.map((statementUpload) => {
260
+ const uploadId = statementUpload.statementMeta.statementUploadId;
261
+ const localMeta = statementUpdateLocalDataByUploadId?.[uploadId]?.statementMeta;
262
+ return getStatementTransactionPeriodById(statementUpload.statementTransactions, statementUpload.statementMeta, localMeta);
263
+ }))
264
+ : undefined;
250
265
  reconList[accountID] = {
251
266
  accountConnectionStatus: accountConnectionStatus.status,
252
267
  paymentAccountId: accountConnectionStatus.paymentAccountId,
@@ -257,6 +272,10 @@ export const getExpenseAutomationReconciliationView = createSelector((state) =>
257
272
  statementParseStatus: accountReconState.statementParseStatus,
258
273
  reparseStatementStatus: accountReconState.reparseStatementStatus,
259
274
  statementDateConflict: accountReconState.statementDateConflict,
275
+ confirmStatementMappingStatus: accountReconState.confirmStatementMappingStatus,
276
+ confirmStatementMappingConflict: accountReconState.confirmStatementMappingConflict,
277
+ confirmedCombinedStatementUploads: accountReconState.confirmedCombinedStatementUploads,
278
+ combinedStatementGroupId: accountReconState.combinedStatementGroupId,
260
279
  statementUpdateStatus: accountReconState.statementUpdateStatus,
261
280
  statementUploadStatus: accountReconState.statementUploadStatus,
262
281
  localData: accountReconState.localData,
@@ -267,11 +286,8 @@ export const getExpenseAutomationReconciliationView = createSelector((state) =>
267
286
  statementProcessingTotalDurationSeconds: accountReconState.statementProcessingTotalDurationSeconds,
268
287
  statementProcessingFailed: accountReconState.statementProcessingFailed,
269
288
  parsedStatementData: parsedStatementDataForView,
270
- allCitationTransactions: rawParsedStatementData?.statementUpload?.statementTransactions,
271
- statementTransactionPeriodById: rawParsedStatementData?.statementUpload != null
272
- ? getStatementTransactionPeriodById(rawParsedStatementData.statementUpload.statementTransactions, rawParsedStatementData.statementUpload.statementMeta, accountReconState.localData?.statementUpdateLocalData
273
- ?.statementMeta)
274
- : undefined,
289
+ allCitationTransactions,
290
+ statementTransactionPeriodById,
275
291
  transactionFetchState: reduceAnyFetchState([
276
292
  accountReconState.transactionFetchState,
277
293
  accountListState.byReportId.accountList,
@@ -341,6 +357,8 @@ export const getExpenseAutomationReconciliationView = createSelector((state) =>
341
357
  statementParseStatus: { fetchState: 'Not-Started' },
342
358
  reparseStatementStatus: { fetchState: 'Not-Started' },
343
359
  statementDateConflict: null,
360
+ confirmStatementMappingStatus: { fetchState: 'Not-Started' },
361
+ confirmStatementMappingConflict: null,
344
362
  localData: {},
345
363
  connectionInProgress: false,
346
364
  statementParseInProgress: false,
@@ -457,6 +475,9 @@ export const getExpenseAutomationReconciliationView = createSelector((state) =>
457
475
  });
458
476
  export const getReparseStatementStatusByAccountId = (state, accountId) => getExpenseAutomationReconciliationView(state)
459
477
  .accountReconciliationsByAccountID[accountId]?.reparseStatementStatus;
478
+ export function getLedgerAccountsForCombinedStatementMapping(accountReconciliationsByAccountID) {
479
+ return Object.values(accountReconciliationsByAccountID).map((accountReconciliation) => accountReconciliation.accountReconEntity.account);
480
+ }
460
481
  export const isAccountReconReport = (reportId) => {
461
482
  return reportId.endsWith('reconciliation');
462
483
  };
@@ -1,4 +1,17 @@
1
1
  import { date } from '../../../zeniDayJS';
2
+ export function getStatementUploadsFromParsedData(parsedStatementData) {
3
+ if (parsedStatementData == null) {
4
+ return [];
5
+ }
6
+ if (parsedStatementData.statementUploads != null &&
7
+ parsedStatementData.statementUploads.length > 0) {
8
+ return parsedStatementData.statementUploads;
9
+ }
10
+ if (parsedStatementData.statementUpload != null) {
11
+ return [parsedStatementData.statementUpload];
12
+ }
13
+ return [];
14
+ }
2
15
  export const getEffectiveStatementPeriod = (parsedMeta, localMeta) => ({
3
16
  statementStartDate: localMeta?.statementStartDate != null && localMeta.statementStartDate !== ''
4
17
  ? localMeta.statementStartDate
@@ -25,24 +38,44 @@ export const filterStatementTransactionsByPeriod = (transactions, statementPerio
25
38
  }
26
39
  return transactions.filter((transaction) => isStatementTransactionInPeriod(transaction.transactionDate, statementStartDate, statementEndDate));
27
40
  };
28
- export const getParsedStatementDataForView = (parsedStatementData, statementUpdateLocalData) => {
41
+ const getStatementUploadForView = (statementUpload, statementUpdateLocalData) => {
42
+ const parsedMeta = statementUpload.statementMeta;
43
+ const localMeta = statementUpdateLocalData?.statementMeta;
44
+ const effectiveMeta = localMeta ?? parsedMeta;
45
+ const statementPeriod = getEffectiveStatementPeriod(parsedMeta, localMeta);
46
+ return {
47
+ ...statementUpload,
48
+ statementMeta: effectiveMeta,
49
+ statementTransactions: filterStatementTransactionsByPeriod(statementUpload.statementTransactions, statementPeriod),
50
+ };
51
+ };
52
+ export const getParsedStatementDataForView = (parsedStatementData, statementUpdateLocalDataByUploadId, statementAccountScope) => {
29
53
  if (parsedStatementData == null) {
30
54
  return undefined;
31
55
  }
56
+ const statementUploads = getStatementUploadsFromParsedData(parsedStatementData);
57
+ if (statementUploads.length === 0) {
58
+ return undefined;
59
+ }
60
+ if (statementAccountScope === 'multi_account') {
61
+ const viewedUploads = statementUploads.map((statementUpload) => {
62
+ const uploadId = statementUpload.statementMeta.statementUploadId;
63
+ return getStatementUploadForView(statementUpload, statementUpdateLocalDataByUploadId?.[uploadId]);
64
+ });
65
+ const anchorUploadId = parsedStatementData.statementUpload.statementMeta.statementUploadId;
66
+ const viewedAnchor = viewedUploads.find((upload) => upload.statementMeta.statementUploadId === anchorUploadId) ?? viewedUploads[0];
67
+ return {
68
+ statementUpload: viewedAnchor,
69
+ statementUploads: viewedUploads,
70
+ };
71
+ }
32
72
  const statementUpload = parsedStatementData.statementUpload;
33
73
  if (statementUpload == null) {
34
74
  return undefined;
35
75
  }
36
- const parsedMeta = statementUpload.statementMeta;
37
- const localMeta = statementUpdateLocalData?.statementMeta;
38
- const effectiveMeta = localMeta ?? parsedMeta;
39
- const statementPeriod = getEffectiveStatementPeriod(parsedMeta, localMeta);
76
+ const uploadId = statementUpload.statementMeta.statementUploadId;
40
77
  return {
41
- statementUpload: {
42
- ...statementUpload,
43
- statementMeta: effectiveMeta,
44
- statementTransactions: filterStatementTransactionsByPeriod(statementUpload.statementTransactions, statementPeriod),
45
- },
78
+ statementUpload: getStatementUploadForView(statementUpload, statementUpdateLocalDataByUploadId?.[uploadId]),
46
79
  };
47
80
  };
48
81
  export const getStatementTransactionPeriodById = (allParsedTransactions, parsedMeta, localMeta) => {
@@ -1,4 +1,11 @@
1
- import { stringToUnion } from '../../../commonStateTypes/stringToUnion';
1
+ import { stringToUnion, stringToUnionStrict, } from '../../../commonStateTypes/stringToUnion';
2
+ const ALL_STATEMENT_BALANCE_SOURCES = [
3
+ 'ocr',
4
+ 'prior_recon',
5
+ 'default_zero',
6
+ ];
7
+ export const toStatementBalanceSource = (v) => stringToUnion(v, ALL_STATEMENT_BALANCE_SOURCES);
8
+ export const toStatementBalanceSourceStrict = (v) => stringToUnionStrict(v ?? '', ALL_STATEMENT_BALANCE_SOURCES);
2
9
  export function toReconciliationViewSummary(payload) {
3
10
  return {
4
11
  accounts: {
@@ -59,3 +66,10 @@ const RECON_REVIEW_SORT_KEYS = [
59
66
  ];
60
67
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
61
68
  const toReconReviewSortKey = (v) => stringToUnion(v, RECON_REVIEW_SORT_KEYS);
69
+ const ALL_STATEMENT_ACCOUNT_SCOPES = [
70
+ 'single_account',
71
+ 'multi_account',
72
+ ];
73
+ export const toStatementAccountScope = (v) => stringToUnion(v, ALL_STATEMENT_ACCOUNT_SCOPES);
74
+ export const toStatementAccountScopeStrict = (v) => stringToUnionStrict(v ?? '', ALL_STATEMENT_ACCOUNT_SCOPES);
75
+ export const STATEMENT_ACCOUNT_SCOPES = ALL_STATEMENT_ACCOUNT_SCOPES;
@@ -1,6 +1,7 @@
1
1
  import { from } from 'rxjs';
2
2
  import { catchError, filter, mergeMap } from 'rxjs/operators';
3
3
  import { updateInvoicingCreditNotes } from '../../../entity/invoicing/creditNote/creditNoteReducer';
4
+ import { apiErrorSnackbarVariables } from '../../../entity/snackbar/snackbarApiError';
4
5
  import { openSnackbar } from '../../../entity/snackbar/snackbarReducer';
5
6
  import { createZeniAPIStatus, isSuccessResponse } from '../../../responsePayload';
6
7
  import { localDataToCreateCreditNotePayload, } from './createCreditNotePayload';
@@ -29,6 +30,7 @@ export const createCreditNoteEpic = (actions$, state$, zeniAPI) => actions$.pipe
29
30
  messageSection: 'invoicing_credit_note_saved',
30
31
  messageText: 'failed',
31
32
  type: 'error',
33
+ variables: apiErrorSnackbarVariables(response.status),
32
34
  }),
33
35
  ]);
34
36
  }), catchError((error) => from([
@@ -3,6 +3,7 @@ import { catchError, filter, mergeMap } from 'rxjs/operators';
3
3
  import { updateAddresses } from '../../../entity/address/addressReducer';
4
4
  import { extractInvoicingInvoiceAddresses } from '../../../entity/invoicing/invoice/invoicePayload';
5
5
  import { updateInvoices } from '../../../entity/invoicing/invoice/invoiceReducer';
6
+ import { apiErrorSnackbarVariables } from '../../../entity/snackbar/snackbarApiError';
6
7
  import { openSnackbar } from '../../../entity/snackbar/snackbarReducer';
7
8
  import { createZeniAPIStatus, isSuccessResponse } from '../../../responsePayload';
8
9
  import { addInvoiceToList } from '../invoiceList/invoiceListReducer';
@@ -36,6 +37,7 @@ export const createInvoiceEpic = (actions$, _state$, zeniAPI) => actions$.pipe(f
36
37
  messageSection: 'invoicing_invoice_saved',
37
38
  messageText: 'failed',
38
39
  type: 'error',
40
+ variables: apiErrorSnackbarVariables(response.status),
39
41
  }),
40
42
  ]);
41
43
  }), catchError((error) => from([
@@ -1,8 +1,9 @@
1
1
  import { from } from 'rxjs';
2
2
  import { catchError, filter, mergeMap } from 'rxjs/operators';
3
3
  import { updateInvoicingCoupons } from '../../../entity/invoicing/coupon/couponReducer';
4
+ import { apiErrorSnackbarVariables } from '../../../entity/snackbar/snackbarApiError';
4
5
  import { openSnackbar } from '../../../entity/snackbar/snackbarReducer';
5
- import { createZeniAPIStatus, isSuccessResponse } from '../../../responsePayload';
6
+ import { createZeniAPIStatus, isSuccessResponse, } from '../../../responsePayload';
6
7
  import { runInvoicingDiscountAction, runInvoicingDiscountActionFailure, runInvoicingDiscountActionSuccess, } from './discountActionReducer';
7
8
  /** Snackbar copy per action kind; unlisted kinds run without one. */
8
9
  const SNACKBAR_SECTION_BY_KIND = {
@@ -14,13 +15,15 @@ export const runInvoicingDiscountActionEpic = (actions$, _state$, zeniAPI) => ac
14
15
  const { action: kind, id } = action.payload;
15
16
  const requestBody = { action: kind };
16
17
  const snackbarSection = SNACKBAR_SECTION_BY_KIND[kind];
17
- const snackbar = (messageText) => snackbarSection == null
18
+ /** `status` surfaces the platform's error text; omit it to keep the generic copy. */
19
+ const snackbar = (messageText, status) => snackbarSection == null
18
20
  ? []
19
21
  : [
20
22
  openSnackbar({
21
23
  messageSection: snackbarSection,
22
24
  messageText,
23
25
  type: messageText === 'success' ? 'success' : 'error',
26
+ variables: apiErrorSnackbarVariables(status),
24
27
  }),
25
28
  ];
26
29
  const apiUrl = `${zeniAPI.apiEndPoints.invoicingMicroServiceBaseUrl}/1.0/discounts/${encodeURIComponent(id)}/actions`;
@@ -39,7 +42,7 @@ export const runInvoicingDiscountActionEpic = (actions$, _state$, zeniAPI) => ac
39
42
  error: response.status,
40
43
  id,
41
44
  }),
42
- ...snackbar('failed'),
45
+ ...snackbar('failed', response.status),
43
46
  ]);
44
47
  }), catchError((error) => from([
45
48
  runInvoicingDiscountActionFailure({