@zeniai/client-epic-state 5.1.3-betaAS1 → 5.1.3-betaVR1

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 (40) hide show
  1. package/lib/commonPayloadTypes/commonPayload.d.ts +4 -25
  2. package/lib/esm/index.js +4 -8
  3. package/lib/esm/view/expenseAutomationView/helpers/transactionCategorizationLocalDataHelper.js +200 -0
  4. package/lib/esm/view/expenseAutomationView/reducers/transactionsViewReducer.js +96 -2
  5. package/lib/esm/view/spendManagement/billPay/internationalWireVerification/epics/fetchIntlVerificationFormEpic.js +3 -7
  6. package/lib/esm/view/spendManagement/billPay/internationalWireVerification/epics/initializeIntlVerificationFormEpic.js +34 -33
  7. package/lib/esm/view/spendManagement/billPay/internationalWireVerification/epics/submitIntlVerificationEpic.js +7 -2
  8. package/lib/esm/view/spendManagement/billPay/internationalWireVerification/internationalWireVerificationPayload.js +8 -55
  9. package/lib/esm/view/spendManagement/billPay/internationalWireVerification/internationalWireVerificationReducer.js +6 -5
  10. package/lib/esm/view/spendManagement/billPay/internationalWireVerification/internationalWireVerificationSelector.js +15 -39
  11. package/lib/index.d.ts +6 -11
  12. package/lib/index.js +41 -54
  13. package/lib/view/expenseAutomationView/helpers/transactionCategorizationLocalDataHelper.d.ts +36 -1
  14. package/lib/view/expenseAutomationView/helpers/transactionCategorizationLocalDataHelper.js +205 -1
  15. package/lib/view/expenseAutomationView/reducers/transactionsViewReducer.d.ts +28 -2
  16. package/lib/view/expenseAutomationView/reducers/transactionsViewReducer.js +96 -2
  17. package/lib/view/expenseAutomationView/types/transactionsViewState.d.ts +39 -0
  18. package/lib/view/spendManagement/billPay/internationalWireVerification/epics/fetchIntlVerificationFormEpic.d.ts +3 -3
  19. package/lib/view/spendManagement/billPay/internationalWireVerification/epics/fetchIntlVerificationFormEpic.js +2 -6
  20. package/lib/view/spendManagement/billPay/internationalWireVerification/epics/initializeIntlVerificationFormEpic.d.ts +1 -2
  21. package/lib/view/spendManagement/billPay/internationalWireVerification/epics/initializeIntlVerificationFormEpic.js +33 -32
  22. package/lib/view/spendManagement/billPay/internationalWireVerification/epics/submitIntlVerificationEpic.js +7 -2
  23. package/lib/view/spendManagement/billPay/internationalWireVerification/internationalWireVerificationPayload.d.ts +1 -24
  24. package/lib/view/spendManagement/billPay/internationalWireVerification/internationalWireVerificationPayload.js +9 -59
  25. package/lib/view/spendManagement/billPay/internationalWireVerification/internationalWireVerificationReducer.js +5 -4
  26. package/lib/view/spendManagement/billPay/internationalWireVerification/internationalWireVerificationSelector.js +15 -39
  27. package/lib/view/spendManagement/billPay/internationalWireVerification/internationalWireVerificationState.d.ts +1 -20
  28. package/package.json +2 -2
  29. package/lib/esm/view/spendManagement/billPay/internationalWireVerification/internationalWireOnboardingDetailsToLocalData.js +0 -146
  30. package/lib/esm/view/spendManagement/billPay/internationalWireVerification/internationalWireVerificationFieldConstants.js +0 -40
  31. package/lib/esm/view/spendManagement/billPay/internationalWireVerification/internationalWireVerificationLocalDataHelpers.js +0 -86
  32. package/lib/esm/view/spendManagement/billPay/internationalWireVerification/internationalWireVerificationSubmitPayload.js +0 -154
  33. package/lib/view/spendManagement/billPay/internationalWireVerification/internationalWireOnboardingDetailsToLocalData.d.ts +0 -4
  34. package/lib/view/spendManagement/billPay/internationalWireVerification/internationalWireOnboardingDetailsToLocalData.js +0 -150
  35. package/lib/view/spendManagement/billPay/internationalWireVerification/internationalWireVerificationFieldConstants.d.ts +0 -38
  36. package/lib/view/spendManagement/billPay/internationalWireVerification/internationalWireVerificationFieldConstants.js +0 -43
  37. package/lib/view/spendManagement/billPay/internationalWireVerification/internationalWireVerificationLocalDataHelpers.d.ts +0 -27
  38. package/lib/view/spendManagement/billPay/internationalWireVerification/internationalWireVerificationLocalDataHelpers.js +0 -96
  39. package/lib/view/spendManagement/billPay/internationalWireVerification/internationalWireVerificationSubmitPayload.d.ts +0 -32
  40. package/lib/view/spendManagement/billPay/internationalWireVerification/internationalWireVerificationSubmitPayload.js +0 -159
@@ -10,31 +10,10 @@ export interface AllowedValueWithCodeOptionalPayload {
10
10
  export declare function isAllowedValueWithCodePayload(allowedValueWithCodePayload: any): allowedValueWithCodePayload is AllowedValueWithCodePayload;
11
11
  export declare function isAllowedValueWithCodeOptionalPayload(allowedValueWithCodePayload: any): allowedValueWithCodePayload is AllowedValueWithCodeOptionalPayload;
12
12
  export declare function toAllowedValueWithCode(allowedValueWithCodePayload: AllowedValueWithCodePayload): AllowedValueWithCode;
13
- export interface LabelValueCodeDescriptionPayload {
14
- code: string;
15
- description: string;
16
- }
17
- export interface LabelValueFileOptionPayload {
18
- file_id: string;
19
- option?: string;
20
- }
21
- export interface LabelValuePersonNamePayload {
22
- first_name?: string;
23
- last_name?: string;
24
- }
25
- export interface LabelValuePersonPayload {
26
- company_role?: string;
27
- date_of_birth?: string;
28
- email?: string;
29
- name?: LabelValuePersonNamePayload;
30
- nationality?: string;
31
- ownership_percentage?: number;
32
- proof_of_address?: LabelValueFileOptionPayload[];
33
- proof_of_identity?: LabelValueFileOptionPayload[];
34
- ssn?: string;
35
- }
36
- export type LabelValueCodesValuesPayload = string | string[] | LabelValueCodeDescriptionPayload | LabelValueCodeDescriptionPayload[] | LabelValueFileOptionPayload | LabelValueFileOptionPayload[] | LabelValuePersonPayload | LabelValuePersonPayload[];
37
13
  export interface LabelValueCodesPayload {
38
14
  label: string;
39
- values: LabelValueCodesValuesPayload;
15
+ values: {
16
+ code: string;
17
+ description: string;
18
+ }[] | string[];
40
19
  }
package/lib/esm/index.js CHANGED
@@ -172,7 +172,7 @@ import { clearExpenseAutomationFluxAnalysisView, fetchFluxAnalysisView, reviewFl
172
172
  import { clearJeScheduleLocalData as clearExpenseAutomationJEScheduleLocalData, clearExpenseAutomationJESchedulesView, fetchJeSchedulesPage as fetchExpenseAutomationJESchedulesPage, ignoreRecommendedJeSchedule as ignoreExpenseAutomationJESchedule, initializeAccountSettingsView as initializeJeAccountSettingsView, initializeJeScheduleLocalData, removeJeScheduleTransactionKey, retryJeSchedule as retryExpenseAutomationJESchedule, saveAccountSettings as saveJeAccountSettings, saveAccountSettingsLocalData as saveJeAccountSettingsLocalData, updateJESchedulesUIState as updateExpenseAutomationJESchedulesUIState, updateJeScheduleLocalDataById, updateJeScheduleTransactionKeys, } from './view/expenseAutomationView/reducers/jeSchedulesViewReducer';
173
173
  import { acknowledgeBulkUploadConfirmMatchComplete, bulkUploadAutomatchingTimedOut, bulkUploadReceipts, bulkUploadReceiptsFailure, bulkUploadReceiptsSuccess, clearBulkUpload, clearBulkUploadBatchDetailsForScopeChange, clearManualSearchResults, clearMissingReceiptsTabNavigation, confirmBulkUploadMatch, confirmBulkUploadMatchFailure, confirmBulkUploadMatchSuccess, fetchBulkUploadBatchDetails, fetchBulkUploadBatchDetailsFailure, fetchBulkUploadBatchDetailsSuccess, fetchBulkUploadBatches, fetchBulkUploadBatchesFailure, fetchBulkUploadBatchesSuccess, fetchCompletedTransactions, fetchCompletedTransactionsFailure, fetchCompletedTransactionsSuccess, fetchMissingReceipts as fetchExpenseAutomationMissingReceipts, fetchMoreBatchDetails, fetchMoreBatchDetailsComplete, fetchMoreBatchDetailsFailure, markBatchDetailRefreshAttempted, markMissingReceiptAsDone as markExpenseAutomationMissingReceiptAsDone, pusherBatchStatusUpdate, refreshBatchDetailsForBatchId, requestMissingReceiptsTabNavigation, restoreBulkUploadAutomatchingOnMount, restoreBulkUploadMatchingState, searchTransactionsForManualMatch, searchTransactionsForManualMatchFailure, searchTransactionsForManualMatchSuccess, setBulkUploadCompletedSubTab, setBulkUploadResultsTab, setBulkUploadSortConfig, setBulkUploadUploadedFileCount, storeBatchDetails, updateBulkUploadProgress, updateMissingReceiptUploadState as updateExpenseAutomationMissingReceiptUploadState, updateMissingReceiptsUIState as updateExpenseAutomationMissingReceiptsUIState, uploadMissingReceiptSuccess as uploadExpenseAutomationMissingReceiptSuccess, } from './view/expenseAutomationView/reducers/missingReceiptsViewReducer';
174
174
  import { deleteAccountStatement, excludeAccountFromReconciliation, fetchReconciliation as fetchReconciliationView, includeAccountInReconciliation, saveReconciliationDetail as saveExpenseAutomationReconciliationDetail, saveReconciliationReview as saveExpenseAutomationReconciliationReview, setConnectionInProgressForAccount as setConnectionInProgressForAccountReconciliation, setStatementParseInProgress, updateAccountReconciliationLocalData as updateExpenseAutomationAccountReconciliationLocalData, updateSelectedAccountId as updateExpenseAutomationAccountReconciliationSelectedAccountId, updateSelectedTab as updateExpenseAutomationAccountReconciliationSelectedTab, updateReconListScrollPosition as updateExpenseAutomationReconListScrollPosition, updateReviewTabSortState as updateExpenseAutomationReconReviewTabListSortState, updateReviewTabLocalData as updateExpenseAutomationReconReviewTabLocalData, updateReconcileTabListScrollState as updateExpenseAutomationReconcileTabListScrollState, updateReconcileTabListSortState as updateExpenseAutomationReconcileTabListSortState, updateReconcileTabLocalData as updateExpenseAutomationReconcileTabLocalData, updateSelectedDrawerAccountId as updateExpenseAutomationSelectedDrawerAccountId, updateNodeCollapseState, updateStatementUploadChosen, uploadAccountStatement, } from './view/expenseAutomationView/reducers/reconciliationViewReducer';
175
- import { backgroundRefetchReviewTab, clearExpenseAutomationTransactionsView, fetchTransactionCategorization, fetchTransactionCategorizationFailure, fetchTransactionCategorizationView, initializeTransactionCategorizationViewLocalData, markCategoryClassRecommendationsFailureForCategorization, markTransactionAsNotMiscategorized, removeTransactionFromAllTabs, saveTransactionCategorization, saveTransactionCategorizationLocalData, setAllItemsToCategoryClassInLocalDataForCategorization, setEntityRecommendationForLineIdsForCategorization, syncTransactionCategorizationFromDetailSave, updateCurrentSelectedTransactionCategorizationTab, updateSelectedCheckboxTransactionIds, updateSelectedCustomerForTransaction, updateSelectedTransactionId, updateSelectedVendorForTransaction, updateTransactionCategorization, updateTransactionCategorizationCompletedSubTab, updateTransactionCategorizationSaveStatus, updateTransactionCategorizationUIState, updateTransactionCategorizationUploadReceiptState, updateTransactionFilters, uploadTransactionCategorizationReceiptSuccess, } from './view/expenseAutomationView/reducers/transactionsViewReducer';
175
+ import { backgroundRefetchReviewTab, clearExpenseAutomationTransactionsView, fetchTransactionCategorization, applyFieldToEmptyLinesForCategorization, clearLastEditedFieldForApplyToEmptyForCategorization, fetchTransactionCategorizationFailure, fetchTransactionCategorizationView, initializeTransactionCategorizationViewLocalData, markCategoryClassRecommendationsFailureForCategorization, markTransactionAsNotMiscategorized, removeTransactionFromAllTabs, saveTransactionCategorization, saveTransactionCategorizationLocalData, setAllItemsToCategoryClassInLocalDataForCategorization, setEntityRecommendationForLineIdsForCategorization, setLastEditedFieldForApplyToEmptyForCategorization, syncTransactionCategorizationFromDetailSave, updateCurrentSelectedTransactionCategorizationTab, updateSelectedCheckboxTransactionIds, updateSelectedCustomerForTransaction, updateSelectedTransactionId, updateSelectedVendorForTransaction, updateTransactionCategorization, updateTransactionCategorizationCompletedSubTab, updateTransactionCategorizationSaveStatus, updateTransactionCategorizationUIState, updateTransactionCategorizationUploadReceiptState, updateTransactionFilters, uploadTransactionCategorizationReceiptSuccess, } from './view/expenseAutomationView/reducers/transactionsViewReducer';
176
176
  import { getExpenseAutomationFluxAnalysisView } from './view/expenseAutomationView/selectors/fluxAnalysisViewSelector';
177
177
  import { getExpenseAutomationReconciliationView, isAccountReconReport, } from './view/expenseAutomationView/selectors/reconciliationViewSelector';
178
178
  import { getExpenseAutomationTransactionView, getLastTransferEntryReplacement, } from './view/expenseAutomationView/selectors/transactionCategorizationSelector';
@@ -183,6 +183,7 @@ import { BATCH_FILE_STATUSES, isUnmatchedTabFileStatus, toBatchFileStatus, toBat
183
183
  import { toMissingReceiptsSortKey as toExpenseAutomationMissingReceiptsSortKey, } from './view/expenseAutomationView/types/missingReceiptsViewState';
184
184
  import { toReconciliationTabsType, } from './view/expenseAutomationView/types/reconciliationViewState';
185
185
  import { toTransactionsTabKey as toExpenseAutomationTransactionsTabKey, toTransactionsSortKey, } from './view/expenseAutomationView/types/transactionsViewState';
186
+ import { isLineFieldEmpty } from './view/expenseAutomationView/helpers/transactionCategorizationLocalDataHelper';
186
187
  import { clearFeatureNotificationView, fetchRegisteredInterests, notifyMeForFeature, } from './view/featureNotificationView/featureNotificationViewReducer';
187
188
  import { getFeatureNotificationView, getRegisteredInterests, getRegisteredInterestsByFeature, isFeatureInterestRegistered, } from './view/featureNotificationView/featureNotificationViewSelector';
188
189
  import downloadFile from './view/fileView/fileDownloadHelpers';
@@ -290,7 +291,6 @@ import { convertAmountToHomeCurrency, discardBillUpdatesInLocalStore, discardOut
290
291
  import { checkIfCreatorIsApprover, getEditBillDetail, toPaymentToOption, } from './view/spendManagement/billPay/editBillView/editBillViewSelector';
291
292
  import { clearInternationalWire, createPaymentInstrument, createPaymentInstrumentUpdateStatus, deletePaymentInstrument, fetchInternationalWireDynamicForm, initializeDynamicForm, initializeInternationalWireLocalData, updateInternationalWireLocalStoreData, } from './view/spendManagement/billPay/internationalWire/internationalWireReducer';
292
293
  import { getInternationalWireView, } from './view/spendManagement/billPay/internationalWire/internationalWireSelector';
293
- import { InternationalWireVerificationFormOrder, sortVerificationFormFields, } from './view/spendManagement/billPay/internationalWireVerification/internationalWireVerificationPayload';
294
294
  import { fetchInternationalVerificationForm, submitInternationalVerificationForm, updateVerificationFormLocalData, } from './view/spendManagement/billPay/internationalWireVerification/internationalWireVerificationReducer';
295
295
  import { getIntlWireVerificationView, } from './view/spendManagement/billPay/internationalWireVerification/internationalWireVerificationSelector';
296
296
  import { fetchBillAttachment, fetchMagicLinkBankNameByRouting, fetchMagicLinkBankNameBySwift, fetchMagicLinkTenant, saveBankAccount, saveMagicLinkAddressInLocalStore, updateMagicLinkBankAccountLocalStoreData, updateMagicLinkInternationalBankAccountLocalStoreData, } from './view/spendManagement/billPay/magicLinkView/magicLinkViewReducer';
@@ -459,7 +459,7 @@ export {
459
459
  BATCH_FILE_STATUSES, isUnmatchedTabFileStatus, DEFAULT_COMPLETED_SUB_TAB, toBatchFileStatus, toBatchStatusValue, toBulkUploadPhase, toBulkUploadResultsTab, toBulkUploadSortKey, toCompletedSubTab, toMatchSource, toMissingReceiptsTab, toExpenseAutomationJEScheduleMainTab, toExpenseAutomationJEScheduleSortKey, getExpenseAutomationView, toExpenseAutomationMissingReceiptsSortKey, toExpenseAutomationTransactionsTabKey, toExpenseAutomationViewType, uploadExpenseAutomationMissingReceiptSuccess, markExpenseAutomationMissingReceiptAsDone, fetchAllExpenseAutomationTabs, refreshExpenseAutomationCurrentTab, updateCurrentSelectedTransactionCategorizationTab, updateTransactionCategorizationCompletedSubTab, fetchExpenseAutomationMissingReceipts,
460
460
  // Bulk Upload Actions
461
461
  bulkUploadReceipts, bulkUploadAutomatchingTimedOut, bulkUploadReceiptsSuccess, bulkUploadReceiptsFailure, restoreBulkUploadAutomatchingOnMount, restoreBulkUploadMatchingState, updateBulkUploadProgress, pusherBatchStatusUpdate, requestMissingReceiptsTabNavigation, clearMissingReceiptsTabNavigation, fetchBulkUploadBatchDetails, fetchBulkUploadBatchDetailsSuccess, fetchBulkUploadBatchDetailsFailure, storeBatchDetails, fetchMoreBatchDetails, fetchMoreBatchDetailsComplete, fetchMoreBatchDetailsFailure, fetchBulkUploadBatches, fetchBulkUploadBatchesSuccess, fetchBulkUploadBatchesFailure, clearBulkUploadBatchDetailsForScopeChange, markBatchDetailRefreshAttempted, refreshBatchDetailsForBatchId, confirmBulkUploadMatch, confirmBulkUploadMatchSuccess, confirmBulkUploadMatchFailure, setBulkUploadResultsTab, setBulkUploadCompletedSubTab, setBulkUploadSortConfig, setBulkUploadUploadedFileCount, clearBulkUpload, searchTransactionsForManualMatch, searchTransactionsForManualMatchSuccess, searchTransactionsForManualMatchFailure, clearManualSearchResults, acknowledgeBulkUploadConfirmMatchComplete, fetchCompletedTransactions, fetchCompletedTransactionsSuccess, fetchCompletedTransactionsFailure, fetchFluxAnalysisView, clearExpenseAutomationFluxAnalysisView, updateOperatingExpensesIdsForReview as updateFluxOperatingExpensesIdsForReview, updateSelectedSectionIdsForReview as updateFluxAnalysisSelectedSectionIdsForReview, reviewFluxAnalysisView, updateExpenseAutomationMissingReceiptUploadState, updateExpenseAutomationMissingReceiptsUIState, updateTransactionCategorizationUploadReceiptState, uploadTransactionCategorizationReceiptSuccess, getExpenseAutomationFluxAnalysisView, updateCurrentSelectedView, updateCurrentSelectedPeriod, getExpenseAutomationTransactionView, getLastTransferEntryReplacement, updateFluxAnalysisViewUIState, updateFluxAnalysisViewPageMetaData, MAX_SELECTION_LIMIT, checkIfAllLineItemsAreCategoryClassFilled, getLineItemsByTransactionIdsFromLocalData, isAnyItemWithUncategorizedExpenseAccount, excludeAccountFromReconciliation, includeAccountInReconciliation, saveExpenseAutomationReconciliationDetail, updateExpenseAutomationReconcileTabListScrollState, updateExpenseAutomationReconReviewTabListSortState, updateExpenseAutomationReconcileTabListSortState, updateExpenseAutomationReconcileTabLocalData, updateExpenseAutomationAccountReconciliationSelectedTab, updateExpenseAutomationAccountReconciliationSelectedAccountId, getExpenseAutomationReconciliationView, fetchReconciliationView, uploadAccountStatementIntoDocumentAI, updateExpenseAutomationReconListScrollPosition, setConnectionInProgressForAccountReconciliation, getAccountReconByAccountIdAndSelectedPeriod, toReconciliationTabsType, isAccountReconReport, updateExpenseAutomationReconReviewTabLocalData, updateExpenseAutomationSelectedDrawerAccountId, saveExpenseAutomationReconciliationReview, updateExpenseAutomationAccountReconciliationLocalData, toReconciliationAccountSource, deleteAccountStatement, uploadAccountStatement, updateNodeCollapseState, updateStatementUploadChosen, isReviewTransactionBankTransferType, isReviewTransactionBillPaymentType, isReviewTransactionCreditCardPaymentType, isReviewTransactionDepositType, isReviewTransactionExpenseType, isReviewTransactionCreditCardCreditType, setStatementParseInProgress, };
462
- export { fetchTransactionCategorization, fetchTransactionCategorizationView, updateTransactionCategorizationUIState, updateTransactionFilters, updateSelectedCheckboxTransactionIds, markCategoryClassRecommendationsFailureForCategorization, setEntityRecommendationForLineIdsForCategorization, initializeTransactionCategorizationViewLocalData, setAllItemsToCategoryClassInLocalDataForCategorization, saveTransactionCategorizationLocalData, fetchTransactionCategorizationFailure, saveTransactionCategorization, updateTransactionCategorization, updateTransactionCategorizationSaveStatus, markTransactionAsNotMiscategorized, updateSelectedVendorForTransaction, updateSelectedCustomerForTransaction, updateSelectedTransactionId, syncTransactionCategorizationFromDetailSave, backgroundRefetchReviewTab, createTransferEntry, createTransferEntryFailure, createTransferEntryReplacedTransaction, createTransferEntrySuccess, resetCreateTransferEntryStatus, clearTransferEntryRouteReplacement, fetchAccountsForTransferFlow, removeTransactionFromAllTabs, clearExpenseAutomationTransactionsView, toTransactionsSortKey, };
462
+ export { fetchTransactionCategorization, fetchTransactionCategorizationView, updateTransactionCategorizationUIState, updateTransactionFilters, updateSelectedCheckboxTransactionIds, markCategoryClassRecommendationsFailureForCategorization, setEntityRecommendationForLineIdsForCategorization, setLastEditedFieldForApplyToEmptyForCategorization, applyFieldToEmptyLinesForCategorization, clearLastEditedFieldForApplyToEmptyForCategorization, initializeTransactionCategorizationViewLocalData, setAllItemsToCategoryClassInLocalDataForCategorization, saveTransactionCategorizationLocalData, fetchTransactionCategorizationFailure, saveTransactionCategorization, updateTransactionCategorization, updateTransactionCategorizationSaveStatus, markTransactionAsNotMiscategorized, updateSelectedVendorForTransaction, updateSelectedCustomerForTransaction, updateSelectedTransactionId, syncTransactionCategorizationFromDetailSave, backgroundRefetchReviewTab, createTransferEntry, createTransferEntryFailure, createTransferEntryReplacedTransaction, createTransferEntrySuccess, resetCreateTransferEntryStatus, clearTransferEntryRouteReplacement, fetchAccountsForTransferFlow, removeTransactionFromAllTabs, clearExpenseAutomationTransactionsView, toTransactionsSortKey, isLineFieldEmpty, };
463
463
  export { TOP_EX_TIME_PERIODS };
464
464
  export { toTimeframeTick, mapTimePeriodtoTimeframeTick, toTimePeriod, toAbsoluteDay, toMonthYearPeriodId, convertToPeriod, };
465
465
  export { toVendorSpendTrendFilterTabsTypeStrict, } from './entity/vendorExpense/vendorExpenseSelector';
@@ -642,11 +642,7 @@ export { pushToastNotification, getLastNotificationTime, getNotifications, };
642
642
  export { getReferralListView, getInviteFormView, toReferralListViewSortKeyType, StatusTypes, AmountStatusTypes, fetchReferrals, sendReferralInvite, clearReferrals, saveReferralFormDataInLocalStore, updateReferralListSortUiState, resendReferralInvite, fetchRewardsPlan, getRewardsPlanCard, updateReferViewed, };
643
643
  export { ALL_WEEK_DAYS, SEMI_WEEKLY_REQUIRED_DAYS_COUNT, getMinAllowedEndDate, getRecurringEndDateFromCount, toDayOfWeek, toRecurringFrequency, };
644
644
  export { fetchCockpitContext, fetchCompanyTaskManagerView, fetchTaskManagerMetrics, getCompanyTaskManagerView, createTaskFromTaskGroupTemplate, };
645
- export { InternationalWireVerificationFormOrder, sortVerificationFormFields, fetchInternationalVerificationForm, submitInternationalVerificationForm, updateVerificationFormLocalData, getIntlWireVerificationView, };
646
- export { InternationalWireVerificationBooleanWithSubfieldsFieldNameList, InternationalWireVerificationBooleanWithSubfieldsFieldNames, InternationalWireVerificationControllingPersonFieldName, InternationalWireVerificationFormFieldNames, InternationalWireVerificationStakeHolderFieldName, InternationalWireVerificationSubfieldNames, } from './view/spendManagement/billPay/internationalWireVerification/internationalWireVerificationFieldConstants';
647
- export { IntlWireVerificationLocalDataSuffix, toIntlWireVerificationFormDetails, toIntlWireVerificationSubmitPayload, } from './view/spendManagement/billPay/internationalWireVerification/internationalWireVerificationSubmitPayload';
648
- export { getStakeHolderOwnerIndicesFromLocalData, } from './view/spendManagement/billPay/internationalWireVerification/internationalWireVerificationLocalDataHelpers';
649
- export { toVerificationFormLocalDataFromOnboardingDetails, } from './view/spendManagement/billPay/internationalWireVerification/internationalWireOnboardingDetailsToLocalData';
645
+ export { fetchInternationalVerificationForm, submitInternationalVerificationForm, updateVerificationFormLocalData, getIntlWireVerificationView, };
650
646
  export { fetchExpressPayInitialDetails, updateExpressPayFormLocalData, submitExpressPay, resetExpressPayLocalData, getExpressPayView, };
651
647
  export { acceptTreasuryTerms, fetchTreasurySetupView, clearTreasurySetupView, fetchTreasuryFunds, updatePortfolioAllocation, fetchPortfolioAllocation, updateFundAllocationLocalData, updateTreasuryPromoIntroClosedByOutsideClick, updateTreasuryPromoRemindMeLaterClicked, updateTreasuryVideoViewed, getTreasurySetupViewDetails, getTreasuryFundsMaximumYield, };
652
648
  // ── AI Accountant Entity ──
@@ -764,3 +764,203 @@ export const hasTransactionLocalDataChanges = (transaction, transactionReviewLoc
764
764
  }
765
765
  return false;
766
766
  };
767
+ // =========================================================================
768
+ // Apply-to-Empty-Lines helpers
769
+ //
770
+ // Drives the contextual "Apply <value> to <count> empty <field>" banner on
771
+ // the Transaction Categorization List page (Pending Review tab). The banner
772
+ // triggers when the user fills in Category / Class / per-line Vendor on one
773
+ // line of a multi-line transaction; the helpers below compute which sibling
774
+ // lines are eligible (per-field, INDEPENDENT) and mutate only that field
775
+ // when the user clicks Apply.
776
+ //
777
+ // Empty-field detection mirrors the existing categorization auto-fill rules:
778
+ // - Category empty when `account.qboId == null` OR the account is one of
779
+ // the company's uncategorized accounts.
780
+ // - Class empty when `class.qboId == null` AND `class.classId == null`.
781
+ // - Vendor empty when the line carries no `lineEntity` / `vendor` /
782
+ // `customer`. Only `journal_entry` / `deposit` transactions surface
783
+ // a per-line vendor — for other transaction types vendor is
784
+ // transaction-level and the banner is not offered.
785
+ // =========================================================================
786
+ const PER_LINE_VENDOR_TRANSACTION_TYPES = [
787
+ 'journal_entry',
788
+ 'deposit',
789
+ ];
790
+ /**
791
+ * Returns true iff the *specific field* is empty on this line. The three
792
+ * fields are evaluated INDEPENDENTLY — eligibility for a Category Apply
793
+ * depends solely on the line's category emptiness, irrespective of class
794
+ * / vendor on the same line.
795
+ */
796
+ export const isLineFieldEmpty = (line, field, transactionType, uncategorizedAccounts, isUncategorizedExpenseCategoryEnabled = false) => {
797
+ switch (field) {
798
+ case 'category': {
799
+ const categoryId = line.account?.qboId ?? line.account?.accountId;
800
+ if (categoryId == null) {
801
+ return true;
802
+ }
803
+ if (uncategorizedAccounts == null) {
804
+ return false;
805
+ }
806
+ return isAccountUncategorized(uncategorizedAccounts, categoryId, isUncategorizedExpenseCategoryEnabled === true ? ['income'] : undefined);
807
+ }
808
+ case 'class': {
809
+ // Class has no separate "uncategorized" concept — empty iff both
810
+ // candidate ids are missing. Mirrors the existing auto-fill check
811
+ // at L564 above (`record.class?.qboId == null`) plus the legacy
812
+ // detail-page emptiness convention (qboId OR classId).
813
+ return line.class?.qboId == null && line.class?.classId == null;
814
+ }
815
+ case 'vendor': {
816
+ if (transactionType == null ||
817
+ PER_LINE_VENDOR_TRANSACTION_TYPES.includes(transactionType) === false) {
818
+ // Vendor is transaction-scoped (header) for non-JE / non-deposit
819
+ // transactions, so per-line vendor emptiness is meaningless and
820
+ // we never offer the Apply banner there.
821
+ return false;
822
+ }
823
+ return (line.lineEntity == null && line.vendor == null && line.customer == null);
824
+ }
825
+ default:
826
+ return false;
827
+ }
828
+ };
829
+ /**
830
+ * Computes the eligible empty-line ids for a given field+transaction.
831
+ * Excludes the source line (the one the user edited) since the user
832
+ * already filled THAT line — the banner is about propagating to siblings.
833
+ */
834
+ const computeEligibleEmptyLineIds = (localData, field, sourceLineId, uncategorizedAccounts, isUncategorizedExpenseCategoryEnabled = false) => {
835
+ const eligibleIds = [];
836
+ for (const lineId of localData.sortedLineItems) {
837
+ if (lineId === sourceLineId) {
838
+ continue;
839
+ }
840
+ const line = localData.lineItemById[lineId];
841
+ if (line == null) {
842
+ continue;
843
+ }
844
+ if (isLineFieldEmpty(line, field, localData.transactionType, uncategorizedAccounts, isUncategorizedExpenseCategoryEnabled)) {
845
+ eligibleIds.push(lineId);
846
+ }
847
+ }
848
+ return eligibleIds;
849
+ };
850
+ /**
851
+ * Replaces (not merges) the apply-to-empty banner state on the local
852
+ * data. Called by the categorization watch handler whenever the user
853
+ * changes Category / Class / per-line Vendor on a line. Returns a fresh
854
+ * copy of the local data; if no sibling lines have the corresponding
855
+ * field empty, the banner is hidden by leaving `applyToEmptyState` null.
856
+ */
857
+ export const toSetLastEditedFieldForApplyToEmpty = (transactionLocalData, field, sourceLineId, value, uncategorizedAccounts, isUncategorizedExpenseCategoryEnabled = false) => {
858
+ const eligibleEmptyLineIds = computeEligibleEmptyLineIds(transactionLocalData, field, sourceLineId, uncategorizedAccounts, isUncategorizedExpenseCategoryEnabled);
859
+ if (eligibleEmptyLineIds.length === 0) {
860
+ // No siblings to fill — drop any prior banner so we don't leave a
861
+ // stale proposal up.
862
+ return {
863
+ ...transactionLocalData,
864
+ applyToEmptyState: null,
865
+ };
866
+ }
867
+ const next = {
868
+ field,
869
+ sourceLineId,
870
+ valueLabel: value.valueLabel,
871
+ eligibleEmptyLineIds,
872
+ account: value.account,
873
+ classBase: value.classBase,
874
+ entity: value.entity,
875
+ };
876
+ return {
877
+ ...transactionLocalData,
878
+ applyToEmptyState: next,
879
+ };
880
+ };
881
+ /**
882
+ * Mutates ONLY the banner's field on each line whose field is currently
883
+ * empty (re-checked against live state). Other lines and other fields are
884
+ * untouched. Mirrors the per-field, INDEPENDENT rule from the PRD.
885
+ *
886
+ * After applying, the banner state is cleared. Returns a fresh copy of
887
+ * the local data.
888
+ */
889
+ export const toApplyFieldToEmptyLines = (transactionLocalData, uncategorizedAccounts, isUncategorizedExpenseCategoryEnabled = false) => {
890
+ const state = transactionLocalData.applyToEmptyState;
891
+ if (state == null) {
892
+ return transactionLocalData;
893
+ }
894
+ const newLineItems = {};
895
+ for (const lineId of transactionLocalData.sortedLineItems) {
896
+ const line = transactionLocalData.lineItemById[lineId];
897
+ if (line == null) {
898
+ continue;
899
+ }
900
+ // Re-check emptiness against the current line state — the user could
901
+ // have manually filled some of these in between the set and apply.
902
+ if (lineId !== state.sourceLineId &&
903
+ state.eligibleEmptyLineIds.includes(lineId) &&
904
+ isLineFieldEmpty(line, state.field, transactionLocalData.transactionType, uncategorizedAccounts, isUncategorizedExpenseCategoryEnabled)) {
905
+ const updated = { ...line };
906
+ switch (state.field) {
907
+ case 'category':
908
+ if (state.account != null) {
909
+ updated.account = state.account;
910
+ }
911
+ break;
912
+ case 'class':
913
+ if (state.classBase != null) {
914
+ updated.class = state.classBase;
915
+ }
916
+ break;
917
+ case 'vendor':
918
+ if (state.entity != null) {
919
+ updated.lineEntity = state.entity;
920
+ // Mirror the legacy split-by-type behavior (see
921
+ // `setEntityRecommendationForLineIdInLocalData` -> entity
922
+ // shape). Keep `vendor` / `customer` legs in sync so
923
+ // downstream save flows that read either side stay correct.
924
+ if (state.entity.type === 'vendor') {
925
+ // VendorBase has {id, name, logo?} — no qboId field.
926
+ updated.vendor = {
927
+ id: state.entity.id,
928
+ name: state.entity.name,
929
+ logo: state.entity.logo,
930
+ };
931
+ updated.customer = undefined;
932
+ }
933
+ else if (state.entity.type === 'customer') {
934
+ updated.customer = {
935
+ id: state.entity.id,
936
+ name: state.entity.name,
937
+ logo: state.entity.logo,
938
+ qboId: state.entity.qboId,
939
+ };
940
+ updated.vendor = undefined;
941
+ }
942
+ }
943
+ break;
944
+ default:
945
+ break;
946
+ }
947
+ newLineItems[lineId] = updated;
948
+ }
949
+ else {
950
+ newLineItems[lineId] = line;
951
+ }
952
+ }
953
+ return {
954
+ ...transactionLocalData,
955
+ lineItemById: newLineItems,
956
+ applyToEmptyState: null,
957
+ };
958
+ };
959
+ /**
960
+ * Clears the apply-to-empty banner state. Used by Dismiss as well as on
961
+ * save / discard / transaction-context-change.
962
+ */
963
+ export const toClearApplyToEmpty = (transactionLocalData) => ({
964
+ ...transactionLocalData,
965
+ applyToEmptyState: null,
966
+ });
@@ -3,7 +3,7 @@ import recordGet from 'lodash/get';
3
3
  import uniq from 'lodash/uniq';
4
4
  import { toMonthYearPeriodId, } from '../../../commonStateTypes/timePeriod';
5
5
  import { isVendorTransaction } from '../../../entity/transaction/stateTypes/vendorTransaction';
6
- import { filterAutoTabLineItems, mergeTabSpecificLineItems, removeTransactionFromTabView, setEntityRecommendationForLineIdInLocalData, shouldAutoSelectAndAdd, toSetAllLineItemsToCategoryClass, toTransactionDetailLocalData, } from '../helpers/transactionCategorizationLocalDataHelper';
6
+ import { filterAutoTabLineItems, mergeTabSpecificLineItems, removeTransactionFromTabView, setEntityRecommendationForLineIdInLocalData, shouldAutoSelectAndAdd, toApplyFieldToEmptyLines, toClearApplyToEmpty, toSetAllLineItemsToCategoryClass, toSetLastEditedFieldForApplyToEmpty, toTransactionDetailLocalData, } from '../helpers/transactionCategorizationLocalDataHelper';
7
7
  import { DEFAULT_COMPLETED_SUB_TAB, } from '../types/completedSubTab';
8
8
  import { TRANSACTIONS_TABS, } from '../types/transactionsViewState';
9
9
  export const initialTransactionTabViewState = {
@@ -1052,7 +1052,101 @@ const expenseAutomationTransactionsView = createSlice({
1052
1052
  }
1053
1053
  },
1054
1054
  },
1055
+ /**
1056
+ * Records the user's most-recent Category / Class / per-line Vendor
1057
+ * edit on a multi-line transaction, computes the sibling lines whose
1058
+ * SAME field is currently empty, and stores the result on
1059
+ * `applyToEmptyState`. The categorization list row reads that state
1060
+ * to render the "Apply <value> to <count> empty <field>" banner.
1061
+ */
1062
+ setLastEditedFieldForApplyToEmptyForCategorization: {
1063
+ prepare(selectedTab, transactionId, field, sourceLineId, value, uncategorizedAccounts, isUncategorizedExpenseCategoryEnabled) {
1064
+ return {
1065
+ payload: {
1066
+ selectedTab,
1067
+ transactionId,
1068
+ field,
1069
+ sourceLineId,
1070
+ value,
1071
+ uncategorizedAccounts,
1072
+ isUncategorizedExpenseCategoryEnabled,
1073
+ },
1074
+ };
1075
+ },
1076
+ reducer(draft, action) {
1077
+ const { selectedTab, transactionId, field, sourceLineId, value, uncategorizedAccounts, isUncategorizedExpenseCategoryEnabled, } = action.payload;
1078
+ const transactionLocalData = recordGet(draft.transactionCategorizationView[selectedTab]
1079
+ .transactionReviewLocalDataById, transactionId, undefined);
1080
+ if (transactionLocalData == null) {
1081
+ return;
1082
+ }
1083
+ const next = toSetLastEditedFieldForApplyToEmpty(transactionLocalData.transactionReviewLocalData, field, sourceLineId, value, uncategorizedAccounts, isUncategorizedExpenseCategoryEnabled);
1084
+ draft.transactionCategorizationView[selectedTab].transactionReviewLocalDataById[transactionId] = {
1085
+ transactionId,
1086
+ transactionReviewLocalData: next,
1087
+ };
1088
+ },
1089
+ },
1090
+ /**
1091
+ * Applies the value tracked in `applyToEmptyState` to the eligible
1092
+ * empty lines (re-checked at apply time) and clears the banner. Only
1093
+ * the banner's field is mutated — every other field on those lines
1094
+ * is preserved.
1095
+ */
1096
+ applyFieldToEmptyLinesForCategorization: {
1097
+ prepare(selectedTab, transactionId, uncategorizedAccounts, isUncategorizedExpenseCategoryEnabled) {
1098
+ return {
1099
+ payload: {
1100
+ selectedTab,
1101
+ transactionId,
1102
+ uncategorizedAccounts,
1103
+ isUncategorizedExpenseCategoryEnabled,
1104
+ },
1105
+ };
1106
+ },
1107
+ reducer(draft, action) {
1108
+ const { selectedTab, transactionId, uncategorizedAccounts, isUncategorizedExpenseCategoryEnabled, } = action.payload;
1109
+ const transactionLocalData = recordGet(draft.transactionCategorizationView[selectedTab]
1110
+ .transactionReviewLocalDataById, transactionId, undefined);
1111
+ if (transactionLocalData == null) {
1112
+ return;
1113
+ }
1114
+ const next = toApplyFieldToEmptyLines(transactionLocalData.transactionReviewLocalData, uncategorizedAccounts, isUncategorizedExpenseCategoryEnabled);
1115
+ draft.transactionCategorizationView[selectedTab].transactionReviewLocalDataById[transactionId] = {
1116
+ transactionId,
1117
+ transactionReviewLocalData: next,
1118
+ };
1119
+ // Mark the transaction dirty so the existing Save flow picks up
1120
+ // the propagated edits.
1121
+ const dirtyIds = draft.transactionCategorizationView[selectedTab]
1122
+ .transactionIdsWithUnsavedData;
1123
+ if (dirtyIds.includes(transactionId) === false) {
1124
+ dirtyIds.push(transactionId);
1125
+ }
1126
+ },
1127
+ },
1128
+ /**
1129
+ * Clears the apply-to-empty banner state. Used by Dismiss and any
1130
+ * transaction-context change (save / discard / unmount).
1131
+ */
1132
+ clearLastEditedFieldForApplyToEmptyForCategorization: {
1133
+ prepare(selectedTab, transactionId) {
1134
+ return { payload: { selectedTab, transactionId } };
1135
+ },
1136
+ reducer(draft, action) {
1137
+ const { selectedTab, transactionId } = action.payload;
1138
+ const transactionLocalData = recordGet(draft.transactionCategorizationView[selectedTab]
1139
+ .transactionReviewLocalDataById, transactionId, undefined);
1140
+ if (transactionLocalData == null) {
1141
+ return;
1142
+ }
1143
+ draft.transactionCategorizationView[selectedTab].transactionReviewLocalDataById[transactionId] = {
1144
+ transactionId,
1145
+ transactionReviewLocalData: toClearApplyToEmpty(transactionLocalData.transactionReviewLocalData),
1146
+ };
1147
+ },
1148
+ },
1055
1149
  },
1056
1150
  });
1057
- export const { fetchTransactionCategorization, updateTransactionCategorizationUIState, updateTransactionFilters, initializeTransactionCategorizationViewLocalData, saveTransactionCategorizationLocalData, fetchTransactionCategorizationFailure, saveTransactionCategorization, updateTransactionCategorization, updateCurrentSelectedTransactionCategorizationTab, updateTransactionCategorizationCompletedSubTab, updateTransactionCategorizationSaveStatus, markTransactionAsNotMiscategorized, updateStatusForTransactionNotMiscategorizedUpdateForCategorization, updateSelectedVendorForTransaction, updateSelectedCustomerForTransaction, setAllItemsToCategoryClassInLocalDataForCategorization, updateTotalCountForTransactionCategorization, updateParentTotalCountForTab, fetchTransactionCategorizationSuccess, resetOtherTabsFetchState, fetchTransactionCategorizationView, updateSelectedCheckboxTransactionIds, clearExpenseAutomationTransactionsViewPerTabView, clearExpenseAutomationTransactionsView, setEntityRecommendationForLineIdsForCategorization, markCategoryClassRecommendationsInProgressForCategorization, markCategoryClassRecommendationsCompletedForCategorization, markCategoryClassRecommendationsFailureForCategorization, updateSelectedTransactionId, syncTransactionCategorizationFromDetailSave, backgroundRefetchReviewTab, removeTransactionFromAllTabs, updateTransactionCategorizationUploadReceiptState, uploadTransactionCategorizationReceiptSuccess, } = expenseAutomationTransactionsView.actions;
1151
+ export const { fetchTransactionCategorization, updateTransactionCategorizationUIState, updateTransactionFilters, initializeTransactionCategorizationViewLocalData, saveTransactionCategorizationLocalData, fetchTransactionCategorizationFailure, saveTransactionCategorization, updateTransactionCategorization, updateCurrentSelectedTransactionCategorizationTab, updateTransactionCategorizationCompletedSubTab, updateTransactionCategorizationSaveStatus, markTransactionAsNotMiscategorized, updateStatusForTransactionNotMiscategorizedUpdateForCategorization, updateSelectedVendorForTransaction, updateSelectedCustomerForTransaction, setAllItemsToCategoryClassInLocalDataForCategorization, updateTotalCountForTransactionCategorization, updateParentTotalCountForTab, fetchTransactionCategorizationSuccess, resetOtherTabsFetchState, fetchTransactionCategorizationView, updateSelectedCheckboxTransactionIds, clearExpenseAutomationTransactionsViewPerTabView, clearExpenseAutomationTransactionsView, setEntityRecommendationForLineIdsForCategorization, markCategoryClassRecommendationsInProgressForCategorization, markCategoryClassRecommendationsCompletedForCategorization, markCategoryClassRecommendationsFailureForCategorization, updateSelectedTransactionId, syncTransactionCategorizationFromDetailSave, backgroundRefetchReviewTab, removeTransactionFromAllTabs, updateTransactionCategorizationUploadReceiptState, uploadTransactionCategorizationReceiptSuccess, setLastEditedFieldForApplyToEmptyForCategorization, applyFieldToEmptyLinesForCategorization, clearLastEditedFieldForApplyToEmptyForCategorization, } = expenseAutomationTransactionsView.actions;
1058
1152
  export default expenseAutomationTransactionsView.reducer;
@@ -1,9 +1,8 @@
1
1
  import { from, of } from 'rxjs';
2
2
  import { catchError, filter, mergeMap, switchMap } from 'rxjs/operators';
3
3
  import { createZeniAPIStatus, isSuccessResponse, } from '../../../../../responsePayload';
4
- import { toVerificationFormLocalDataFromOnboardingDetails } from '../internationalWireOnboardingDetailsToLocalData';
5
- import { fetchInternationalVerificationForm, updateInternationalVerificationForm, updateVerificationFormFailure, updateVerificationFormLocalData, } from '../internationalWireVerificationReducer';
6
- export const fetchIntlVerificationFormEpic = (actions$, state$, zeniAPI) => actions$.pipe(filter(fetchInternationalVerificationForm.match), switchMap((action) => {
4
+ import { fetchInternationalVerificationForm, initializeIntlVerificationForm, updateInternationalVerificationForm, updateVerificationFormFailure, } from '../internationalWireVerificationReducer';
5
+ export const fetchIntlVerificationFormEpic = (actions$, _state$, zeniAPI) => actions$.pipe(filter(fetchInternationalVerificationForm.match), switchMap((action) => {
7
6
  const query = {
8
7
  region: 'US',
9
8
  legal_type: 'BUSINESS',
@@ -12,14 +11,11 @@ export const fetchIntlVerificationFormEpic = (actions$, state$, zeniAPI) => acti
12
11
  .getJSON(`${zeniAPI.apiEndPoints.payMicroServiceBaseUrl}/1.0/international-wire/onboarding-fields?query=${encodeURIComponent(JSON.stringify(query))}`)
13
12
  .pipe(mergeMap((response) => {
14
13
  if (isSuccessResponse(response) && response.data != null) {
15
- const onboardingDataFromCompanyInfo = state$.value.companyState.companiesById[action.payload.companyId]
16
- ?.companyBillPayInfo?.internationalWireOnboardingDetails;
17
- const localData = toVerificationFormLocalDataFromOnboardingDetails(onboardingDataFromCompanyInfo, response.data.labels);
18
14
  return from([
19
15
  updateInternationalVerificationForm({
20
16
  internationalWireFormPayload: response.data.labels,
21
17
  }),
22
- updateVerificationFormLocalData(localData),
18
+ initializeIntlVerificationForm(action.payload.companyId, response.data.labels),
23
19
  ]);
24
20
  }
25
21
  else {
@@ -1,38 +1,39 @@
1
- import { empty, from } from 'rxjs';
1
+ import { from } from 'rxjs';
2
2
  import { filter, mergeMap } from 'rxjs/operators';
3
- import { getCurrentTenant } from '../../../../../entity/tenant/tenantSelector';
4
- import { fetchBillPaySetupViewSuccess } from '../../billPaySetupView/billPaySetupViewReducer';
5
- import { toVerificationFormLocalDataFromOnboardingDetails } from '../internationalWireOnboardingDetailsToLocalData';
6
3
  import { initializeIntlVerificationForm, updateVerificationFormLocalData, } from '../internationalWireVerificationReducer';
7
- const hasSavedPersonSubfieldData = (localData) => Object.keys(localData).some((key) => /^stake_holder_\d+_/.test(key) ||
8
- (key.startsWith('controlling_person_') && key !== 'controlling_person'));
9
- export const initializeIntlVerificationFormEpic = (actions$, state$) => actions$.pipe(filter((action) => initializeIntlVerificationForm.match(action) ||
10
- fetchBillPaySetupViewSuccess.match(action)), mergeMap((action) => {
4
+ export const initializeIntlVerificationFormEpic = (actions$, state$) => actions$.pipe(filter(initializeIntlVerificationForm.match), mergeMap((action) => {
5
+ const { companyId, internationalWireFormPayload } = action.payload;
6
+ const actions = [];
11
7
  const state = state$.value;
12
- const formFieldLabels = state.internationalWireVerificationState.verificationFormFieldLabels;
13
- if (Object.keys(formFieldLabels).length === 0) {
14
- return empty();
15
- }
16
- const companyId = initializeIntlVerificationForm.match(action) ?
17
- action.payload.companyId
18
- : getCurrentTenant(state)?.companyId;
19
- if (companyId == null) {
20
- return empty();
21
- }
22
- const onboardingDataFromCompanyInfo = state.companyState.companiesById[companyId]?.companyBillPayInfo
23
- ?.internationalWireOnboardingDetails;
24
- const localDataFromCompany = toVerificationFormLocalDataFromOnboardingDetails(onboardingDataFromCompanyInfo, formFieldLabels);
25
- const existingLocalData = state.internationalWireVerificationState.verificationFormLocalData;
26
- if (fetchBillPaySetupViewSuccess.match(action)) {
27
- if (!hasSavedPersonSubfieldData(localDataFromCompany) ||
28
- hasSavedPersonSubfieldData(existingLocalData)) {
29
- return empty();
8
+ const onboardingDataFromCompanyInfo = state.companyState.companiesById[companyId].companyBillPayInfo
9
+ .internationalWireOnboardingDetails;
10
+ const localData = {};
11
+ Object.keys(internationalWireFormPayload).forEach((formFieldKey) => {
12
+ const values = onboardingDataFromCompanyInfo != null
13
+ ? onboardingDataFromCompanyInfo[formFieldKey]?.values
14
+ : undefined;
15
+ if (values != null) {
16
+ localData[formFieldKey] =
17
+ internationalWireFormPayload[formFieldKey].type === 'enum'
18
+ ? internationalWireFormPayload[formFieldKey]
19
+ .is_multiple_values_allowed === false
20
+ ? typeof values[0] === 'object' && 'code' in values[0]
21
+ ? values[0].code
22
+ : ''
23
+ : values.map((value) => typeof value === 'object' && 'code' in value
24
+ ? value.code
25
+ : '')
26
+ : values[0];
30
27
  }
31
- }
32
- return from([
33
- updateVerificationFormLocalData({
34
- ...existingLocalData,
35
- ...localDataFromCompany,
36
- }),
37
- ]);
28
+ else {
29
+ localData[formFieldKey] =
30
+ internationalWireFormPayload[formFieldKey].type === 'enum' &&
31
+ internationalWireFormPayload[formFieldKey]
32
+ .is_multiple_values_allowed === true
33
+ ? []
34
+ : '';
35
+ }
36
+ });
37
+ actions.push(updateVerificationFormLocalData(localData));
38
+ return from(actions);
38
39
  }));
@@ -3,7 +3,6 @@ import { catchError, filter, mergeMap, switchMap } from 'rxjs/operators';
3
3
  import { updateInternationalWireOnboardingStatus } from '../../../../../entity/company/companyReducer';
4
4
  import { openSnackbar } from '../../../../../entity/snackbar/snackbarReducer';
5
5
  import { createZeniAPIStatus, isSuccessResponse, } from '../../../../../responsePayload';
6
- import { toIntlWireVerificationSubmitPayload } from '../internationalWireVerificationSubmitPayload';
7
6
  import { submitInternationalVerificationForm, updateVerificationFormSubmissionStatus, } from '../internationalWireVerificationReducer';
8
7
  export const submitIntlVerificationEpic = (actions$, state$, zeniAPI) => actions$.pipe(filter(submitInternationalVerificationForm.match), switchMap((action) => {
9
8
  const { internationalWireVerificationState } = state$.value;
@@ -11,7 +10,7 @@ export const submitIntlVerificationEpic = (actions$, state$, zeniAPI) => actions
11
10
  const localData = internationalWireVerificationState.verificationFormLocalData;
12
11
  if (localData != null) {
13
12
  return zeniAPI
14
- .postAndGetJSON(`${zeniAPI.apiEndPoints.payMicroServiceBaseUrl}/1.0/international-wire/onboarding`, toIntlWireVerificationSubmitPayload(localData))
13
+ .postAndGetJSON(`${zeniAPI.apiEndPoints.payMicroServiceBaseUrl}/1.0/international-wire/onboarding`, toIntlWireVerificationPayload(localData))
15
14
  .pipe(mergeMap((response) => {
16
15
  const actions = [];
17
16
  if (isSuccessResponse(response) && response.data != null) {
@@ -55,3 +54,9 @@ export const submitIntlVerificationEpic = (actions$, state$, zeniAPI) => actions
55
54
  return from([]);
56
55
  }
57
56
  }));
57
+ const toIntlWireVerificationPayload = (localData) => {
58
+ return {
59
+ is_applicant_declaration: true,
60
+ form_details: localData,
61
+ };
62
+ };
@@ -1,62 +1,15 @@
1
- import { InternationalWireVerificationReadonlyHideableFieldNames, InternationalWireVerificationFormFieldNames, } from './internationalWireVerificationFieldConstants';
2
- import { hasBusinessOwnershipValueInLocalData } from './internationalWireVerificationLocalDataHelpers';
3
- export const InternationalWireVerificationFormOrder = [
4
- InternationalWireVerificationFormFieldNames.certificateOfGoodStanding,
5
- InternationalWireVerificationFormFieldNames.businessOwnership,
6
- InternationalWireVerificationFormFieldNames.companyProofOfAddress,
7
- InternationalWireVerificationFormFieldNames.companyOfficerProofOfAddress,
8
- InternationalWireVerificationFormFieldNames.companyRegistrationDate,
9
- InternationalWireVerificationFormFieldNames.annualTurnover,
10
- InternationalWireVerificationFormFieldNames.expectedTransactionVolume,
11
- InternationalWireVerificationFormFieldNames.employeeCount,
12
- InternationalWireVerificationFormFieldNames.intendedUseOfAccount,
13
- InternationalWireVerificationFormFieldNames.transactionCountries,
14
- InternationalWireVerificationFormFieldNames.stakeHolder,
15
- InternationalWireVerificationFormFieldNames.controllingPerson,
16
- ];
17
- const toFieldValues = (fieldValues) => fieldValues?.map(({ code, description }) => ({ code, description })) ?? [];
18
- const toSubField = (subfield) => ({
19
- label: subfield.label,
20
- placeholder: subfield.field_hint_text ?? '',
21
- type: subfield.type,
22
- fieldValues: toFieldValues(subfield.field_values),
23
- isMultipleOptionsSupported: subfield.is_multiple_options_supported,
24
- options: subfield.options,
25
- });
26
1
  export const toDynamicFormField = (key, payload) => ({
27
2
  name: key,
28
3
  label: payload.label,
29
4
  placeholder: payload.field_hint_text ?? '',
30
5
  isMultipleValuesAllowed: payload.is_multiple_values_allowed ?? false,
31
6
  type: payload.type,
32
- fieldValues: toFieldValues(payload.field_values),
33
- isMultipleOptionsSupported: payload.is_multiple_options_supported,
34
- options: payload.options,
35
- requirements: payload.requirements,
36
- default: payload.default,
37
- subfields: payload.subfields != null
38
- ? Object.fromEntries(Object.entries(payload.subfields).map(([subfieldKey, subfield]) => [
39
- subfieldKey,
40
- toSubField(subfield),
41
- ]))
42
- : undefined,
7
+ fieldValues: payload.field_values != null && payload.field_values.length > 0
8
+ ? payload.field_values.map((fieldValue) => {
9
+ return {
10
+ code: fieldValue.code,
11
+ description: fieldValue.description,
12
+ };
13
+ })
14
+ : [],
43
15
  });
44
- const readonlyHideableVerificationFormFieldNames = new Set(InternationalWireVerificationReadonlyHideableFieldNames);
45
- export const filterVerificationFormFieldsForReadonlyView = (fields, localData, isReadonly) => {
46
- if (!isReadonly || hasBusinessOwnershipValueInLocalData(localData)) {
47
- return fields;
48
- }
49
- return fields.filter((field) => !readonlyHideableVerificationFormFieldNames.has(field.name));
50
- };
51
- export const sortVerificationFormFields = (fields) => {
52
- const orderIndex = new Map(InternationalWireVerificationFormOrder.map((name, index) => [name, index]));
53
- return fields.slice().sort((a, b) => {
54
- const aIndex = orderIndex.get(a.name) ?? InternationalWireVerificationFormOrder.length;
55
- const bIndex = orderIndex.get(b.name) ?? InternationalWireVerificationFormOrder.length;
56
- if (aIndex !== bIndex) {
57
- return aIndex - bIndex;
58
- }
59
- return a.name.localeCompare(b.name);
60
- });
61
- };
62
- export const toVerificationFormFields = (internationalWireFormPayload) => sortVerificationFormFields(Object.keys(internationalWireFormPayload).map((key) => toDynamicFormField(key, internationalWireFormPayload[key])));