From 7959c53b2a63def81f793f6ae999e86247aa3811 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Muzyk?= Date: Thu, 28 Aug 2025 09:16:53 +0200 Subject: [PATCH 01/10] feat: Show page to link existing accounts on payment attempt --- Mobile-Expensify | 2 +- src/ROUTES.ts | 8 +++---- src/SCREENS.ts | 2 +- src/components/KYCWall/BaseKYCWall.tsx | 11 +++++++++- src/components/SettlementButton/index.tsx | 3 +-- .../ModalStackNavigators/index.tsx | 3 +-- src/libs/Navigation/linkingConfig/config.ts | 4 ++-- src/libs/Navigation/types.ts | 8 ++++--- .../WorkspaceOverviewCurrencyPage.tsx | 2 +- ...onnectExistingBusinessBankAccountPage.tsx} | 22 +++++++++++-------- .../workflows/WorkspaceWorkflowsPage.tsx | 4 ++-- 11 files changed, 41 insertions(+), 28 deletions(-) rename src/pages/workspace/workflows/{WorkspaceWorkflowsConnectExistingBankAccountPage.tsx => ConnectExistingBusinessBankAccountPage.tsx} (77%) diff --git a/Mobile-Expensify b/Mobile-Expensify index 695da4ca8e16..ec9e1c617b1e 160000 --- a/Mobile-Expensify +++ b/Mobile-Expensify @@ -1 +1 @@ -Subproject commit 695da4ca8e160f4b0497db27174f1fc67902a0ad +Subproject commit ec9e1c617b1ee9592045d262b8bf61c1b10a8cdb diff --git a/src/ROUTES.ts b/src/ROUTES.ts index e9d6b1581834..a51dae54a3a0 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -184,6 +184,10 @@ const ROUTES = { return getUrlWithBackToParam(`bank-account/${stepToOpen}?policyID=${policyID}`, backTo); }, }, + CONNECT_EXISTING_BUSINESS_BANK_ACCOUNT: { + route: ':policyID/connect-business-bank-account', + getRoute: (policyID: string) => `${policyID}/connect-business-bank-account` as const, + }, PUBLIC_CONSOLE_DEBUG: { route: 'troubleshoot/console', getRoute: (backTo?: string) => getUrlWithBackToParam(`troubleshoot/console`, backTo), @@ -1302,10 +1306,6 @@ const ROUTES = { return `workspaces/${policyID}/workflows` as const; }, }, - WORKSPACE_WORKFLOWS_CONNECT_EXISTING_BANK_ACCOUNT: { - route: 'workspaces/:policyID/workflows/connect-account', - getRoute: (policyID: string) => `workspaces/${policyID}/workflows/connect-account` as const, - }, WORKSPACE_WORKFLOWS_APPROVALS_NEW: { route: 'workspaces/:policyID/workflows/approvals/new', getRoute: (policyID: string) => `workspaces/${policyID}/workflows/approvals/new` as const, diff --git a/src/SCREENS.ts b/src/SCREENS.ts index 2ce656027183..ca836e5e30b9 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -601,7 +601,6 @@ const SCREENS = { WORKFLOWS_APPROVALS_APPROVER: 'Workspace_Workflows_Approvals_Approver', WORKFLOWS_AUTO_REPORTING_FREQUENCY: 'Workspace_Workflows_Auto_Reporting_Frequency', WORKFLOWS_AUTO_REPORTING_MONTHLY_OFFSET: 'Workspace_Workflows_Auto_Reporting_Monthly_Offset', - WORKFLOWS_CONNECT_EXISTING_BANK_ACCOUNT: 'Workspace_Workflows_Connect_Existing_Bank_Account', DESCRIPTION: 'Workspace_Overview_Description', SHARE: 'Workspace_Overview_Share', NAME: 'Workspace_Overview_Name', @@ -720,6 +719,7 @@ const SCREENS = { ENABLE_PAYMENTS_ROOT: 'EnablePayments_Root', ADD_PERSONAL_BANK_ACCOUNT_ROOT: 'AddPersonalBankAccount_Root', REIMBURSEMENT_ACCOUNT_ROOT: 'Reimbursement_Account_Root', + CONNECT_EXISTING_BUSINESS_BANK_ACCOUNT_ROOT: 'Connect_Existing_Business_Bank_Account_Root', WALLET_STATEMENT_ROOT: 'WalletStatement_Root', SIGN_IN_ROOT: 'SignIn_Root', DETAILS_ROOT: 'Details_Root', diff --git a/src/components/KYCWall/BaseKYCWall.tsx b/src/components/KYCWall/BaseKYCWall.tsx index 00d59d2aa11c..109f4863718f 100644 --- a/src/components/KYCWall/BaseKYCWall.tsx +++ b/src/components/KYCWall/BaseKYCWall.tsx @@ -13,6 +13,7 @@ import Log from '@libs/Log'; import Navigation from '@libs/Navigation/Navigation'; import {hasExpensifyPaymentMethod} from '@libs/PaymentUtils'; import {getBankAccountRoute, getPolicyExpenseChat, isExpenseReport as isExpenseReportReportUtils, isIOUReport} from '@libs/ReportUtils'; +import {getEligibleExistingBusinessBankAccounts} from '@libs/WorkflowUtils'; import {kycWallRef} from '@userActions/PaymentMethods'; import {createWorkspaceFromIOUPayment} from '@userActions/Policy/Policy'; import {setKYCWallSource} from '@userActions/Wallet'; @@ -109,6 +110,8 @@ function KYCWall({ setPositionAddPaymentMenu(position); }, [getAnchorPosition]); + const canLinkExistingBankAccount = (policy?: Policy) => policy !== undefined && getEligibleExistingBusinessBankAccounts(bankAccountList, policy.outputCurrency).length > 0; + const selectPaymentMethod = useCallback( (paymentMethod?: PaymentMethod, policy?: Policy) => { if (paymentMethod) { @@ -154,11 +157,17 @@ function KYCWall({ Navigation.navigate(ROUTES.BANK_ACCOUNT_WITH_STEP_TO_OPEN.getRoute(policyID)); return; } + + if (policy !== undefined && canLinkExistingBankAccount(policy)) { + Navigation.navigate(ROUTES.CONNECT_EXISTING_BUSINESS_BANK_ACCOUNT.getRoute(policy?.id)); + return; + } + const bankAccountRoute = addBankAccountRoute ?? getBankAccountRoute(chatReport); Navigation.navigate(bankAccountRoute); } }, - [addBankAccountRoute, addDebitCardRoute, chatReport, iouReport, onSelectPaymentMethod, formatPhoneNumber, lastPaymentMethod, allReports], + [onSelectPaymentMethod, iouReport, addDebitCardRoute, canLinkExistingBankAccount, addBankAccountRoute, chatReport, allReports, formatPhoneNumber, lastPaymentMethod], ); /** diff --git a/src/components/SettlementButton/index.tsx b/src/components/SettlementButton/index.tsx index 0f2d9729729b..5e0b5071b4ba 100644 --- a/src/components/SettlementButton/index.tsx +++ b/src/components/SettlementButton/index.tsx @@ -471,8 +471,7 @@ function SettlementButton({ const isPaymentMethod = Object.values(CONST.PAYMENT_METHODS).includes(selectedOption as PaymentMethod); const shouldSelectPaymentMethod = (isPaymentMethod ?? lastPaymentPolicy ?? !isEmpty(latestBankItem)) && !shouldShowApproveButton && !shouldHidePaymentOptions; - const selectedPolicy = activeAdminPolicies.find((activePolicy) => activePolicy.id === selectedOption); - + const selectedPolicy = activeAdminPolicies.find((activePolicy) => activePolicy.id === policyIDKey); if (!!selectedPolicy || shouldSelectPaymentMethod) { selectPaymentMethod(event, triggerKYCFlow, selectedOption as PaymentMethod, selectedPolicy); return; diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx index 26a5dbe2fd97..d5c3a79bb7aa 100644 --- a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx +++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx @@ -444,8 +444,7 @@ const SettingsModalStackNavigator = createModalStackNavigator require('../../../../pages/workspace/accounting/qbd/import/QuickbooksDesktopCustomersDisplayedAsPage').default, [SCREENS.WORKSPACE.ACCOUNTING.QUICKBOOKS_DESKTOP_ITEMS]: () => require('../../../../pages/workspace/accounting/qbd/import/QuickbooksDesktopItemsPage').default, - [SCREENS.WORKSPACE.WORKFLOWS_CONNECT_EXISTING_BANK_ACCOUNT]: () => - require('../../../../pages/workspace/workflows/WorkspaceWorkflowsConnectExistingBankAccountPage').default, + [SCREENS.CONNECT_EXISTING_BUSINESS_BANK_ACCOUNT_ROOT]: () => require('@pages/workspace/workflows/ConnectExistingBusinessBankAccountPage').default, [SCREENS.REIMBURSEMENT_ACCOUNT]: () => require('../../../../pages/ReimbursementAccount/ReimbursementAccountPage').default, [SCREENS.SETTINGS.REPORT_CARD_LOST_OR_DAMAGED]: () => require('../../../../pages/settings/Wallet/ReportCardLostPage').default, [SCREENS.KEYBOARD_SHORTCUTS]: () => require('../../../../pages/KeyboardShortcutsPage').default, diff --git a/src/libs/Navigation/linkingConfig/config.ts b/src/libs/Navigation/linkingConfig/config.ts index 41b79adcd688..e56202e76b35 100644 --- a/src/libs/Navigation/linkingConfig/config.ts +++ b/src/libs/Navigation/linkingConfig/config.ts @@ -908,8 +908,8 @@ const config: LinkingOptions['config'] = { [SCREENS.WORKSPACE.REPORT_FIELDS_EDIT_INITIAL_VALUE]: { path: ROUTES.WORKSPACE_EDIT_REPORT_FIELDS_INITIAL_VALUE.route, }, - [SCREENS.WORKSPACE.WORKFLOWS_CONNECT_EXISTING_BANK_ACCOUNT]: { - path: ROUTES.WORKSPACE_WORKFLOWS_CONNECT_EXISTING_BANK_ACCOUNT.route, + [SCREENS.CONNECT_EXISTING_BUSINESS_BANK_ACCOUNT_ROOT]: { + path: ROUTES.CONNECT_EXISTING_BUSINESS_BANK_ACCOUNT.route, exact: true, }, [SCREENS.REIMBURSEMENT_ACCOUNT]: { diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts index ffeea57c986b..0b25a1bd8122 100644 --- a/src/libs/Navigation/types.ts +++ b/src/libs/Navigation/types.ts @@ -1640,6 +1640,10 @@ type ReimbursementAccountNavigatorParamList = { }; }; +type ConnectExistingBankAccountNavigatorParamList = { + [SCREENS.CONNECT_EXISTING_BUSINESS_BANK_ACCOUNT_ROOT]: {policyID?: string}; +}; + type WalletStatementNavigatorParamList = { [SCREENS.WALLET_STATEMENT_ROOT]: { /** The statement year and month as one string, i.e. 202110 */ @@ -1918,9 +1922,6 @@ type WorkspaceSplitNavigatorParamList = { [SCREENS.WORKSPACE.WORKFLOWS_AUTO_REPORTING_MONTHLY_OFFSET]: { policyID: string; }; - [SCREENS.WORKSPACE.WORKFLOWS_CONNECT_EXISTING_BANK_ACCOUNT]: { - policyID: string; - }; [SCREENS.WORKSPACE.INVOICES]: { policyID: string; }; @@ -2340,6 +2341,7 @@ export type { PublicScreensParamList, ReferralDetailsNavigatorParamList, ReimbursementAccountNavigatorParamList, + ConnectExistingBankAccountNavigatorParamList, NewReportWorkspaceSelectionNavigatorParamList, ReportDescriptionNavigatorParamList, ReportDetailsNavigatorParamList, diff --git a/src/pages/workspace/WorkspaceOverviewCurrencyPage.tsx b/src/pages/workspace/WorkspaceOverviewCurrencyPage.tsx index dd40885fc366..25748f128f0a 100644 --- a/src/pages/workspace/WorkspaceOverviewCurrencyPage.tsx +++ b/src/pages/workspace/WorkspaceOverviewCurrencyPage.tsx @@ -52,7 +52,7 @@ function WorkspaceOverviewCurrencyPage({policy}: WorkspaceOverviewCurrencyPagePr if (isCurrencySupportedForGlobalReimbursement(item.currencyCode as CurrencyType, isBetaEnabled(CONST.BETAS.GLOBAL_REIMBURSEMENTS_ON_ND) ?? false)) { const hasValidExistingAccounts = getEligibleExistingBusinessBankAccounts(bankAccountList, item.currencyCode).length > 0; if (hasValidExistingAccounts) { - Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_CONNECT_EXISTING_BANK_ACCOUNT.getRoute(policy.id)); + Navigation.navigate(ROUTES.CONNECT_EXISTING_BUSINESS_BANK_ACCOUNT.getRoute(policy.id)); return; } navigateToBankAccountRoute(policy.id, ROUTES.WORKSPACE_WORKFLOWS.getRoute(policy.id), {forceReplace: true}); diff --git a/src/pages/workspace/workflows/WorkspaceWorkflowsConnectExistingBankAccountPage.tsx b/src/pages/workspace/workflows/ConnectExistingBusinessBankAccountPage.tsx similarity index 77% rename from src/pages/workspace/workflows/WorkspaceWorkflowsConnectExistingBankAccountPage.tsx rename to src/pages/workspace/workflows/ConnectExistingBusinessBankAccountPage.tsx index c04453d2bdee..650103fd490e 100644 --- a/src/pages/workspace/workflows/WorkspaceWorkflowsConnectExistingBankAccountPage.tsx +++ b/src/pages/workspace/workflows/ConnectExistingBusinessBankAccountPage.tsx @@ -10,7 +10,7 @@ import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useThemeStyles from '@hooks/useThemeStyles'; import Navigation from '@navigation/Navigation'; import type {PlatformStackScreenProps} from '@navigation/PlatformStackNavigation/types'; -import type {WorkspaceSplitNavigatorParamList} from '@navigation/types'; +import type {ConnectExistingBankAccountNavigatorParamList} from '@navigation/types'; import PaymentMethodList from '@pages/settings/Wallet/PaymentMethodList'; import type {PaymentMethodPressHandlerParams} from '@pages/settings/Wallet/WalletPage/types'; import {setWorkspaceReimbursement} from '@userActions/Policy/Policy'; @@ -20,9 +20,9 @@ import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; -type WorkspaceWorkflowsConnectExistingBankAccountPageProps = PlatformStackScreenProps; +type ConnectExistingBusinessBankAccountPageProps = PlatformStackScreenProps; -function WorkspaceWorkflowsConnectExistingBankAccountPage({route}: WorkspaceWorkflowsConnectExistingBankAccountPageProps) { +function ConnectExistingBusinessBankAccountPage({route}: ConnectExistingBusinessBankAccountPageProps) { const policyID = route.params?.policyID; const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, {canBeMissing: false}); const policyName = policy?.name ?? ''; @@ -32,24 +32,28 @@ function WorkspaceWorkflowsConnectExistingBankAccountPage({route}: WorkspaceWork const {translate} = useLocalize(); const handleAddBankAccountPress = () => { - navigateToBankAccountRoute(route.params.policyID, ROUTES.WORKSPACE_WORKFLOWS.getRoute(route.params.policyID)); + navigateToBankAccountRoute(policyID, ROUTES.WORKSPACE_WORKFLOWS.getRoute(policyID)); }; const handleItemPress = ({methodID}: PaymentMethodPressHandlerParams) => { + if (policyID === undefined) { + return; + } + const newReimburserEmail = policy?.achAccount?.reimburser ?? policy?.owner ?? ''; setWorkspaceReimbursement({ - policyID: route.params.policyID, + policyID, reimbursementChoice: CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_YES, bankAccountID: methodID ?? CONST.DEFAULT_NUMBER_ID, reimburserEmail: newReimburserEmail, }); - Navigation.setNavigationActionToMicrotaskQueue(() => Navigation.goBack(ROUTES.WORKSPACE_WORKFLOWS.getRoute(policyID))); + Navigation.setNavigationActionToMicrotaskQueue(() => Navigation.closeRHPFlow()); }; return ( 0; if (hasValidExistingUSDAccounts) { - Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_CONNECT_EXISTING_BANK_ACCOUNT.getRoute(route.params.policyID)); + Navigation.navigate(ROUTES.CONNECT_EXISTING_BUSINESS_BANK_ACCOUNT.getRoute(route.params.policyID)); } else { navigateToBankAccountRoute(route.params.policyID, ROUTES.WORKSPACE_WORKFLOWS.getRoute(route.params.policyID)); } @@ -298,7 +298,7 @@ function WorkspaceWorkflowsPage({policy, route}: WorkspaceWorkflowsPageProps) { } if (hasValidExistingAccounts) { - Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_CONNECT_EXISTING_BANK_ACCOUNT.getRoute(route.params.policyID)); + Navigation.navigate(ROUTES.CONNECT_EXISTING_BUSINESS_BANK_ACCOUNT.getRoute(route.params.policyID)); return; } From 08f4d047130c4231843f2d38b43acf218d80ebdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Muzyk?= Date: Thu, 28 Aug 2025 16:12:47 +0200 Subject: [PATCH 02/10] feat: pt2 --- Mobile-Expensify | 2 +- src/ROUTES.ts | 6 +++--- src/components/KYCWall/BaseKYCWall.tsx | 11 +++++++---- src/components/SettlementButton/index.tsx | 8 ++++++++ .../AppNavigator/ModalStackNavigators/index.tsx | 2 +- src/libs/Navigation/linkingConfig/config.ts | 2 +- .../ConnectExistingBusinessBankAccountPage.tsx | 3 +-- src/pages/workspace/WorkspaceOverviewCurrencyPage.tsx | 2 +- .../workspace/workflows/WorkspaceWorkflowsPage.tsx | 4 ++-- 9 files changed, 25 insertions(+), 15 deletions(-) rename src/pages/workspace/{workflows => }/ConnectExistingBusinessBankAccountPage.tsx (96%) diff --git a/Mobile-Expensify b/Mobile-Expensify index ec9e1c617b1e..a98bfef7f41e 160000 --- a/Mobile-Expensify +++ b/Mobile-Expensify @@ -1 +1 @@ -Subproject commit ec9e1c617b1ee9592045d262b8bf61c1b10a8cdb +Subproject commit a98bfef7f41e3856323c249252379f6ac07f9556 diff --git a/src/ROUTES.ts b/src/ROUTES.ts index a51dae54a3a0..7d9dd1708253 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -184,9 +184,9 @@ const ROUTES = { return getUrlWithBackToParam(`bank-account/${stepToOpen}?policyID=${policyID}`, backTo); }, }, - CONNECT_EXISTING_BUSINESS_BANK_ACCOUNT: { - route: ':policyID/connect-business-bank-account', - getRoute: (policyID: string) => `${policyID}/connect-business-bank-account` as const, + BANK_ACCOUNT_CONNECT_EXISTING_BUSINESS_BANK_ACCOUNT: { + route: 'bank-account/:policyID/connect-existing-business-bank-account', + getRoute: (policyID: string) => `bank-account/${policyID}/connect-existing-business-bank-account` as const, }, PUBLIC_CONSOLE_DEBUG: { route: 'troubleshoot/console', diff --git a/src/components/KYCWall/BaseKYCWall.tsx b/src/components/KYCWall/BaseKYCWall.tsx index 109f4863718f..53ff870e2913 100644 --- a/src/components/KYCWall/BaseKYCWall.tsx +++ b/src/components/KYCWall/BaseKYCWall.tsx @@ -110,7 +110,10 @@ function KYCWall({ setPositionAddPaymentMenu(position); }, [getAnchorPosition]); - const canLinkExistingBankAccount = (policy?: Policy) => policy !== undefined && getEligibleExistingBusinessBankAccounts(bankAccountList, policy.outputCurrency).length > 0; + const canLinkExistingBusinessBankAccount = useCallback( + (policy?: Policy) => policy !== undefined && getEligibleExistingBusinessBankAccounts(bankAccountList, policy.outputCurrency).length > 0, + [bankAccountList], + ); const selectPaymentMethod = useCallback( (paymentMethod?: PaymentMethod, policy?: Policy) => { @@ -158,8 +161,8 @@ function KYCWall({ return; } - if (policy !== undefined && canLinkExistingBankAccount(policy)) { - Navigation.navigate(ROUTES.CONNECT_EXISTING_BUSINESS_BANK_ACCOUNT.getRoute(policy?.id)); + if (policy !== undefined && canLinkExistingBusinessBankAccount(policy)) { + Navigation.navigate(ROUTES.BANK_ACCOUNT_CONNECT_EXISTING_BUSINESS_BANK_ACCOUNT.getRoute(policy?.id)); return; } @@ -167,7 +170,7 @@ function KYCWall({ Navigation.navigate(bankAccountRoute); } }, - [onSelectPaymentMethod, iouReport, addDebitCardRoute, canLinkExistingBankAccount, addBankAccountRoute, chatReport, allReports, formatPhoneNumber, lastPaymentMethod], + [onSelectPaymentMethod, iouReport, addDebitCardRoute, canLinkExistingBusinessBankAccount, addBankAccountRoute, chatReport, allReports, formatPhoneNumber, lastPaymentMethod], ); /** diff --git a/src/components/SettlementButton/index.tsx b/src/components/SettlementButton/index.tsx index 5e0b5071b4ba..fc9889ba4678 100644 --- a/src/components/SettlementButton/index.tsx +++ b/src/components/SettlementButton/index.tsx @@ -32,6 +32,7 @@ import { import {shouldRestrictUserBillableActions} from '@libs/SubscriptionUtils'; import {setPersonalBankAccountContinueKYCOnSuccess} from '@userActions/BankAccounts'; import {approveMoneyRequest} from '@userActions/IOU'; +import {getPaymentMethods} from '@userActions/PaymentMethods'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; @@ -130,6 +131,13 @@ function SettlementButton({ const formattedPaymentMethods = formatPaymentMethods(bankAccountList ?? {}, fundList ?? {}, styles); const hasIntentToPay = ((formattedPaymentMethods.length === 1 && isIOUReport(iouReport)) || !!policy?.achAccount) && !lastPaymentMethod; + useEffect(() => { + if (isOffline) { + return; + } + getPaymentMethods(); + }, [isOffline]); + useEffect(() => { if (isLoadingLastPaymentMethod) { return; diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx index d5c3a79bb7aa..b6ee5ba19d03 100644 --- a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx +++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx @@ -444,7 +444,7 @@ const SettingsModalStackNavigator = createModalStackNavigator require('../../../../pages/workspace/accounting/qbd/import/QuickbooksDesktopCustomersDisplayedAsPage').default, [SCREENS.WORKSPACE.ACCOUNTING.QUICKBOOKS_DESKTOP_ITEMS]: () => require('../../../../pages/workspace/accounting/qbd/import/QuickbooksDesktopItemsPage').default, - [SCREENS.CONNECT_EXISTING_BUSINESS_BANK_ACCOUNT_ROOT]: () => require('@pages/workspace/workflows/ConnectExistingBusinessBankAccountPage').default, + [SCREENS.CONNECT_EXISTING_BUSINESS_BANK_ACCOUNT_ROOT]: () => require('@pages/workspace/ConnectExistingBusinessBankAccountPage').default, [SCREENS.REIMBURSEMENT_ACCOUNT]: () => require('../../../../pages/ReimbursementAccount/ReimbursementAccountPage').default, [SCREENS.SETTINGS.REPORT_CARD_LOST_OR_DAMAGED]: () => require('../../../../pages/settings/Wallet/ReportCardLostPage').default, [SCREENS.KEYBOARD_SHORTCUTS]: () => require('../../../../pages/KeyboardShortcutsPage').default, diff --git a/src/libs/Navigation/linkingConfig/config.ts b/src/libs/Navigation/linkingConfig/config.ts index e56202e76b35..9db4b2adec5d 100644 --- a/src/libs/Navigation/linkingConfig/config.ts +++ b/src/libs/Navigation/linkingConfig/config.ts @@ -909,7 +909,7 @@ const config: LinkingOptions['config'] = { path: ROUTES.WORKSPACE_EDIT_REPORT_FIELDS_INITIAL_VALUE.route, }, [SCREENS.CONNECT_EXISTING_BUSINESS_BANK_ACCOUNT_ROOT]: { - path: ROUTES.CONNECT_EXISTING_BUSINESS_BANK_ACCOUNT.route, + path: ROUTES.BANK_ACCOUNT_CONNECT_EXISTING_BUSINESS_BANK_ACCOUNT.route, exact: true, }, [SCREENS.REIMBURSEMENT_ACCOUNT]: { diff --git a/src/pages/workspace/workflows/ConnectExistingBusinessBankAccountPage.tsx b/src/pages/workspace/ConnectExistingBusinessBankAccountPage.tsx similarity index 96% rename from src/pages/workspace/workflows/ConnectExistingBusinessBankAccountPage.tsx rename to src/pages/workspace/ConnectExistingBusinessBankAccountPage.tsx index 650103fd490e..1c26394710a8 100644 --- a/src/pages/workspace/workflows/ConnectExistingBusinessBankAccountPage.tsx +++ b/src/pages/workspace/ConnectExistingBusinessBankAccountPage.tsx @@ -17,7 +17,6 @@ import {setWorkspaceReimbursement} from '@userActions/Policy/Policy'; import {navigateToBankAccountRoute} from '@userActions/ReimbursementAccount'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; -import ROUTES from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; type ConnectExistingBusinessBankAccountPageProps = PlatformStackScreenProps; @@ -32,7 +31,7 @@ function ConnectExistingBusinessBankAccountPage({route}: ConnectExistingBusiness const {translate} = useLocalize(); const handleAddBankAccountPress = () => { - navigateToBankAccountRoute(policyID, ROUTES.WORKSPACE_WORKFLOWS.getRoute(policyID)); + navigateToBankAccountRoute(policyID); }; const handleItemPress = ({methodID}: PaymentMethodPressHandlerParams) => { diff --git a/src/pages/workspace/WorkspaceOverviewCurrencyPage.tsx b/src/pages/workspace/WorkspaceOverviewCurrencyPage.tsx index 25748f128f0a..54444b7542f2 100644 --- a/src/pages/workspace/WorkspaceOverviewCurrencyPage.tsx +++ b/src/pages/workspace/WorkspaceOverviewCurrencyPage.tsx @@ -52,7 +52,7 @@ function WorkspaceOverviewCurrencyPage({policy}: WorkspaceOverviewCurrencyPagePr if (isCurrencySupportedForGlobalReimbursement(item.currencyCode as CurrencyType, isBetaEnabled(CONST.BETAS.GLOBAL_REIMBURSEMENTS_ON_ND) ?? false)) { const hasValidExistingAccounts = getEligibleExistingBusinessBankAccounts(bankAccountList, item.currencyCode).length > 0; if (hasValidExistingAccounts) { - Navigation.navigate(ROUTES.CONNECT_EXISTING_BUSINESS_BANK_ACCOUNT.getRoute(policy.id)); + Navigation.navigate(ROUTES.BANK_ACCOUNT_CONNECT_EXISTING_BUSINESS_BANK_ACCOUNT.getRoute(policy.id)); return; } navigateToBankAccountRoute(policy.id, ROUTES.WORKSPACE_WORKFLOWS.getRoute(policy.id), {forceReplace: true}); diff --git a/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx b/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx index ea7bc4e629a4..8a9eff8cd5c5 100644 --- a/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx +++ b/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx @@ -119,7 +119,7 @@ function WorkspaceWorkflowsPage({policy, route}: WorkspaceWorkflowsPageProps) { updateGeneralSettings(policy.id, policy.name, CONST.CURRENCY.USD); const hasValidExistingUSDAccounts = getEligibleExistingBusinessBankAccounts(bankAccountList, CONST.CURRENCY.USD).length > 0; if (hasValidExistingUSDAccounts) { - Navigation.navigate(ROUTES.CONNECT_EXISTING_BUSINESS_BANK_ACCOUNT.getRoute(route.params.policyID)); + Navigation.navigate(ROUTES.BANK_ACCOUNT_CONNECT_EXISTING_BUSINESS_BANK_ACCOUNT.getRoute(route.params.policyID)); } else { navigateToBankAccountRoute(route.params.policyID, ROUTES.WORKSPACE_WORKFLOWS.getRoute(route.params.policyID)); } @@ -298,7 +298,7 @@ function WorkspaceWorkflowsPage({policy, route}: WorkspaceWorkflowsPageProps) { } if (hasValidExistingAccounts) { - Navigation.navigate(ROUTES.CONNECT_EXISTING_BUSINESS_BANK_ACCOUNT.getRoute(route.params.policyID)); + Navigation.navigate(ROUTES.BANK_ACCOUNT_CONNECT_EXISTING_BUSINESS_BANK_ACCOUNT.getRoute(route.params.policyID)); return; } From 5a4fc0db0aed8ff379b1771520baf1f5b80d900f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Muzyk?= Date: Wed, 17 Sep 2025 14:18:24 +0200 Subject: [PATCH 03/10] fix: TS fix --- src/libs/Navigation/linkingConfig/RELATIONS/WORKSPACE_TO_RHP.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libs/Navigation/linkingConfig/RELATIONS/WORKSPACE_TO_RHP.ts b/src/libs/Navigation/linkingConfig/RELATIONS/WORKSPACE_TO_RHP.ts index a7e55d3ecf8f..a30064fdc142 100755 --- a/src/libs/Navigation/linkingConfig/RELATIONS/WORKSPACE_TO_RHP.ts +++ b/src/libs/Navigation/linkingConfig/RELATIONS/WORKSPACE_TO_RHP.ts @@ -33,7 +33,6 @@ const WORKSPACE_TO_RHP: Partial Date: Wed, 17 Sep 2025 14:20:37 +0200 Subject: [PATCH 04/10] drop Mobile-Expensify changes --- Mobile-Expensify | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mobile-Expensify b/Mobile-Expensify index 21739bc2201e..bd6dd2630266 160000 --- a/Mobile-Expensify +++ b/Mobile-Expensify @@ -1 +1 @@ -Subproject commit 21739bc2201e85dc3bbbe98e4105480e5047da22 +Subproject commit bd6dd2630266c122f52cd51e7cfa2d9a0a409bb9 From b9df26cd0be51557c1c51cba2cf8c8076bddf077 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Muzyk?= Date: Fri, 19 Sep 2025 09:49:36 +0200 Subject: [PATCH 05/10] fix: immediately display correct BA number when connecting from expense view --- src/components/SettlementButton/index.tsx | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/components/SettlementButton/index.tsx b/src/components/SettlementButton/index.tsx index f3b37d9d5e0d..04d15a7771ef 100644 --- a/src/components/SettlementButton/index.tsx +++ b/src/components/SettlementButton/index.tsx @@ -435,7 +435,9 @@ function SettlementButton({ return lastPaymentPolicy.name; } - const bankAccountToDisplay = hasIntentToPay ? (formattedPaymentMethods.at(0) as BankAccount) : bankAccount; + const bankAccountToDisplay = hasIntentToPay + ? ((formattedPaymentMethods.find((method) => method.methodID === policy?.achAccount?.bankAccountID) ?? formattedPaymentMethods.at(0)) as BankAccount) + : bankAccount; if (lastPaymentMethod === CONST.IOU.PAYMENT_TYPE.EXPENSIFY || (hasIntentToPay && isInvoiceReportUtil(iouReport))) { if (!personalBankAccountList.length) { return; @@ -453,6 +455,13 @@ function SettlementButton({ return; } + const bankAccountConnectedToPolicy = (formattedPaymentMethods.find((method) => method.methodID === policy?.achAccount?.bankAccountID) as BankAccount)?.accountData?.accountNumber; + if (bankAccountConnectedToPolicy) { + return translate('paymentMethodList.bankAccountLastFour', { + lastFour: bankAccountConnectedToPolicy.slice(-4), + }); + } + return translate('paymentMethodList.bankAccountLastFour', {lastFour: bankAccountToDisplay?.accountData?.accountNumber?.slice(-4)}); } From 6c774ae8abab992f8f37c25f8b4c024a4ced9eb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Muzyk?= Date: Mon, 22 Sep 2025 15:53:34 +0200 Subject: [PATCH 06/10] fix: skip showing existing account --- Mobile-Expensify | 2 +- src/components/KYCWall/BaseKYCWall.tsx | 24 +++++++++++++++++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/Mobile-Expensify b/Mobile-Expensify index b5b56a63eccc..59f6f8e6bfdd 160000 --- a/Mobile-Expensify +++ b/Mobile-Expensify @@ -1 +1 @@ -Subproject commit b5b56a63eccc2182a149947ce58a3d7d05576200 +Subproject commit 59f6f8e6bfdd611cf40e749d8d4e0bac5dc9ecdf diff --git a/src/components/KYCWall/BaseKYCWall.tsx b/src/components/KYCWall/BaseKYCWall.tsx index 53ff870e2913..c5598231263e 100644 --- a/src/components/KYCWall/BaseKYCWall.tsx +++ b/src/components/KYCWall/BaseKYCWall.tsx @@ -12,10 +12,12 @@ import getClickedTargetLocation from '@libs/getClickedTargetLocation'; import Log from '@libs/Log'; import Navigation from '@libs/Navigation/Navigation'; import {hasExpensifyPaymentMethod} from '@libs/PaymentUtils'; +import {hasInProgressVBBA} from '@libs/ReimbursementAccountUtils'; import {getBankAccountRoute, getPolicyExpenseChat, isExpenseReport as isExpenseReportReportUtils, isIOUReport} from '@libs/ReportUtils'; import {getEligibleExistingBusinessBankAccounts} from '@libs/WorkflowUtils'; import {kycWallRef} from '@userActions/PaymentMethods'; import {createWorkspaceFromIOUPayment} from '@userActions/Policy/Policy'; +import {navigateToBankAccountRoute} from '@userActions/ReimbursementAccount'; import {setKYCWallSource} from '@userActions/Wallet'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; @@ -57,6 +59,7 @@ function KYCWall({ const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT, {canBeMissing: true}); const [chatReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${chatReportID}`, {canBeMissing: true}); const [allReports] = useOnyx(ONYXKEYS.COLLECTION.REPORT, {canBeMissing: true}); + const [reimbursementAccountDraft] = useOnyx(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM_DRAFT, {canBeMissing: true}); const {formatPhoneNumber} = useLocalize(); @@ -161,6 +164,13 @@ function KYCWall({ return; } + // If user has a setup in progress we do not show them the option to connect existing account + const isNonUSDWorkspace = policy?.outputCurrency !== CONST.CURRENCY.USD; + if (policy !== undefined && hasInProgressVBBA(reimbursementAccount?.achData, isNonUSDWorkspace, reimbursementAccountDraft?.country ?? '')) { + navigateToBankAccountRoute(policy?.id); + return; + } + if (policy !== undefined && canLinkExistingBusinessBankAccount(policy)) { Navigation.navigate(ROUTES.BANK_ACCOUNT_CONNECT_EXISTING_BUSINESS_BANK_ACCOUNT.getRoute(policy?.id)); return; @@ -170,7 +180,19 @@ function KYCWall({ Navigation.navigate(bankAccountRoute); } }, - [onSelectPaymentMethod, iouReport, addDebitCardRoute, canLinkExistingBusinessBankAccount, addBankAccountRoute, chatReport, allReports, formatPhoneNumber, lastPaymentMethod], + [ + onSelectPaymentMethod, + iouReport, + addDebitCardRoute, + reimbursementAccount?.achData, + reimbursementAccountDraft?.country, + canLinkExistingBusinessBankAccount, + addBankAccountRoute, + chatReport, + allReports, + formatPhoneNumber, + lastPaymentMethod, + ], ); /** From ce1a8704b5f32b35bdac340d210614ff40fcd0f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Muzyk?= Date: Mon, 22 Sep 2025 15:59:41 +0200 Subject: [PATCH 07/10] submodule --- Mobile-Expensify | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mobile-Expensify b/Mobile-Expensify index 59f6f8e6bfdd..b5b56a63eccc 160000 --- a/Mobile-Expensify +++ b/Mobile-Expensify @@ -1 +1 @@ -Subproject commit 59f6f8e6bfdd611cf40e749d8d4e0bac5dc9ecdf +Subproject commit b5b56a63eccc2182a149947ce58a3d7d05576200 From 72ad38418215b7bf34ba519bc735e185c94c3c3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Muzyk?= Date: Wed, 24 Sep 2025 13:54:36 +0200 Subject: [PATCH 08/10] fix: CR fixes --- src/ROUTES.ts | 4 ++-- src/components/KYCWall/BaseKYCWall.tsx | 2 +- src/components/SettlementButton/index.tsx | 5 ++--- src/libs/Navigation/types.ts | 4 +++- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/ROUTES.ts b/src/ROUTES.ts index 830d2d997c27..03e1dd899a63 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -163,8 +163,8 @@ const ROUTES = { }, }, BANK_ACCOUNT_CONNECT_EXISTING_BUSINESS_BANK_ACCOUNT: { - route: 'bank-account/:policyID/connect-existing-business-bank-account', - getRoute: (policyID: string) => `bank-account/${policyID}/connect-existing-business-bank-account` as const, + route: 'bank-account/connect-existing-business-bank-account', + getRoute: (policyID: string) => `bank-account/connect-existing-business-bank-account?policyID=${policyID}` as const, }, PUBLIC_CONSOLE_DEBUG: { route: 'troubleshoot/console', diff --git a/src/components/KYCWall/BaseKYCWall.tsx b/src/components/KYCWall/BaseKYCWall.tsx index c5598231263e..44576a734c2c 100644 --- a/src/components/KYCWall/BaseKYCWall.tsx +++ b/src/components/KYCWall/BaseKYCWall.tsx @@ -167,7 +167,7 @@ function KYCWall({ // If user has a setup in progress we do not show them the option to connect existing account const isNonUSDWorkspace = policy?.outputCurrency !== CONST.CURRENCY.USD; if (policy !== undefined && hasInProgressVBBA(reimbursementAccount?.achData, isNonUSDWorkspace, reimbursementAccountDraft?.country ?? '')) { - navigateToBankAccountRoute(policy?.id); + navigateToBankAccountRoute(policy.id); return; } diff --git a/src/components/SettlementButton/index.tsx b/src/components/SettlementButton/index.tsx index 97d587ec6047..2805c3d0d08e 100644 --- a/src/components/SettlementButton/index.tsx +++ b/src/components/SettlementButton/index.tsx @@ -456,10 +456,9 @@ function SettlementButton({ return; } - const bankAccountConnectedToPolicy = (formattedPaymentMethods.find((method) => method.methodID === policy?.achAccount?.bankAccountID) as BankAccount)?.accountData?.accountNumber; - if (bankAccountConnectedToPolicy) { + if (bankAccountToDisplay?.accountData?.accountNumber) { return translate('paymentMethodList.bankAccountLastFour', { - lastFour: bankAccountConnectedToPolicy.slice(-4), + lastFour: bankAccountToDisplay.accountData.accountNumber.slice(-4), }); } diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts index ef19593e0a84..c7581e39fad7 100644 --- a/src/libs/Navigation/types.ts +++ b/src/libs/Navigation/types.ts @@ -1693,7 +1693,9 @@ type ReimbursementAccountEnterSignerInfoNavigatorParamList = { }; type ConnectExistingBankAccountNavigatorParamList = { - [SCREENS.CONNECT_EXISTING_BUSINESS_BANK_ACCOUNT_ROOT]: {policyID?: string}; + [SCREENS.CONNECT_EXISTING_BUSINESS_BANK_ACCOUNT_ROOT]: { + policyID: string; + }; }; type WalletStatementNavigatorParamList = { From 49688839974e485baf5d16a3f436f90a9321b72c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Muzyk?= Date: Fri, 26 Sep 2025 15:18:34 +0200 Subject: [PATCH 09/10] fix: filter accounts by currency --- .../settings/Wallet/PaymentMethodList.tsx | 21 +++++++++++++++++-- ...ConnectExistingBusinessBankAccountPage.tsx | 2 ++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/pages/settings/Wallet/PaymentMethodList.tsx b/src/pages/settings/Wallet/PaymentMethodList.tsx index 5495fcb77a31..c1c37570c824 100644 --- a/src/pages/settings/Wallet/PaymentMethodList.tsx +++ b/src/pages/settings/Wallet/PaymentMethodList.tsx @@ -95,6 +95,9 @@ type PaymentMethodListProps = { /** Type of payment method to filter by */ filterType?: ValueOf; + /* Currency of payment method to filter by */ + filterCurrency?: string; + /** Whether to show the default badge for the payment method */ shouldHideDefaultBadge?: boolean; }; @@ -185,6 +188,7 @@ function PaymentMethodList({ onAddBankAccountPress = () => {}, itemIconRight, filterType, + filterCurrency, shouldHideDefaultBadge = false, }: PaymentMethodListProps) { const styles = useThemeStyles(); @@ -322,8 +326,20 @@ function PaymentMethodList({ ); } - if (filterType) { - combinedPaymentMethods = combinedPaymentMethods.filter((paymentMethod) => (paymentMethod as BankAccount).accountData?.type === filterType); + if (filterType ?? filterCurrency) { + combinedPaymentMethods = combinedPaymentMethods.filter((paymentMethod) => { + const account = paymentMethod as BankAccount; + + if (filterType && account.accountData?.type !== filterType) { + return false; + } + + if (filterCurrency && account.bankCurrency !== filterCurrency) { + return false; + } + + return true; + }); } combinedPaymentMethods = combinedPaymentMethods.map((paymentMethod) => { @@ -362,6 +378,7 @@ function PaymentMethodList({ styles, isOffline, filterType, + filterCurrency, isLoadingCardList, cardList, illustrations, diff --git a/src/pages/workspace/ConnectExistingBusinessBankAccountPage.tsx b/src/pages/workspace/ConnectExistingBusinessBankAccountPage.tsx index 1c26394710a8..ca2948917548 100644 --- a/src/pages/workspace/ConnectExistingBusinessBankAccountPage.tsx +++ b/src/pages/workspace/ConnectExistingBusinessBankAccountPage.tsx @@ -25,6 +25,7 @@ function ConnectExistingBusinessBankAccountPage({route}: ConnectExistingBusiness const policyID = route.params?.policyID; const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, {canBeMissing: false}); const policyName = policy?.name ?? ''; + const policyCurrency = policy?.outputCurrency ?? ''; const {shouldUseNarrowLayout} = useResponsiveLayout(); const styles = useThemeStyles(); @@ -68,6 +69,7 @@ function ConnectExistingBusinessBankAccountPage({route}: ConnectExistingBusiness listItemStyle={shouldUseNarrowLayout ? styles.ph5 : styles.ph8} itemIconRight={Expensicons.ArrowRight} filterType={CONST.BANK_ACCOUNT.TYPE.BUSINESS} + filterCurrency={policyCurrency} shouldHideDefaultBadge /> From 0d7aa984cd0ee96cef7f656296a2b1e1514eecf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Muzyk?= Date: Mon, 29 Sep 2025 08:59:39 +0200 Subject: [PATCH 10/10] fix: simplify condition --- src/pages/settings/Wallet/PaymentMethodList.tsx | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/pages/settings/Wallet/PaymentMethodList.tsx b/src/pages/settings/Wallet/PaymentMethodList.tsx index db587808f2b9..a85620bff5b3 100644 --- a/src/pages/settings/Wallet/PaymentMethodList.tsx +++ b/src/pages/settings/Wallet/PaymentMethodList.tsx @@ -330,15 +330,7 @@ function PaymentMethodList({ combinedPaymentMethods = combinedPaymentMethods.filter((paymentMethod) => { const account = paymentMethod as BankAccount; - if (filterType && account.accountData?.type !== filterType) { - return false; - } - - if (filterCurrency && account.bankCurrency !== filterCurrency) { - return false; - } - - return true; + return (!!filterType && account.accountData?.type === filterType) || (!!filterCurrency && account.bankCurrency === filterCurrency); }); }