From f8531a3fa913a2ef35e71116105c8e65ffa6c411 Mon Sep 17 00:00:00 2001 From: "Cong Pham (via MelvinBot)" Date: Sat, 14 Mar 2026 06:42:02 +0000 Subject: [PATCH 1/3] Use getCardSettings to resolve nested paymentBankAccountID in card reconciliation The isExpensifyCardFullySetUp function and CardReconciliationPage both read paymentBankAccountID directly from the root level of card settings. When the backend sends Phase 2 nested format (paymentBankAccountID inside US/CURRENT/GB sub-objects), the root-level check fails, hiding the card reconciliation option and showing "Hmm... it's not here" on the page. Update isExpensifyCardFullySetUp to use getCardSettings() helper which correctly resolves nested settings. Similarly update CardReconciliationPage to use getCardSettings() when reading paymentBankAccountID. Co-authored-by: Cong Pham --- src/libs/CardUtils.ts | 2 +- .../accounting/reconciliation/CardReconciliationPage.tsx | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/libs/CardUtils.ts b/src/libs/CardUtils.ts index 3f723e1127bac..3ed3faa5ba28b 100644 --- a/src/libs/CardUtils.ts +++ b/src/libs/CardUtils.ts @@ -1102,7 +1102,7 @@ function hasIssuedExpensifyCard(workspaceAccountID: number, allCardList: OnyxCol * Check if the Expensify Card is fully set up and a new card can be issued */ function isExpensifyCardFullySetUp(policy?: OnyxEntry, cardSettings?: OnyxEntry): boolean { - return !!(policy?.areExpensifyCardsEnabled && cardSettings?.paymentBankAccountID); + return !!(policy?.areExpensifyCardsEnabled && getCardSettings(cardSettings)?.paymentBankAccountID); } function getCardSettings(cardSettings: OnyxEntry, feedCountry?: string): ExpensifyCardSettingsBase | undefined { diff --git a/src/pages/workspace/accounting/reconciliation/CardReconciliationPage.tsx b/src/pages/workspace/accounting/reconciliation/CardReconciliationPage.tsx index 33097f2403cf0..b041f3dd2f636 100644 --- a/src/pages/workspace/accounting/reconciliation/CardReconciliationPage.tsx +++ b/src/pages/workspace/accounting/reconciliation/CardReconciliationPage.tsx @@ -13,7 +13,7 @@ import useOnyx from '@hooks/useOnyx'; import useThemeStyles from '@hooks/useThemeStyles'; import {getConnectionNameFromRouteParam} from '@libs/AccountingUtils'; import {openPolicyAccountingPage} from '@libs/actions/PolicyConnections'; -import {isExpensifyCardFullySetUp} from '@libs/CardUtils'; +import {getCardSettings, isExpensifyCardFullySetUp} from '@libs/CardUtils'; import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types'; import Navigation from '@navigation/Navigation'; import type {SettingsNavigatorParamList} from '@navigation/types'; @@ -74,13 +74,14 @@ function CardReconciliationPage({policy, route}: CardReconciliationPageProps) { const [currentConnectionName] = useOnyx(`${ONYXKEYS.COLLECTION.EXPENSIFY_CARD_CONTINUOUS_RECONCILIATION_CONNECTION}${effectiveDomainID}`); const [bankAccountList] = useOnyx(ONYXKEYS.BANK_ACCOUNT_LIST); - const paymentBankAccountID = fullySetUpCardSetting.cardSetting?.paymentBankAccountID ?? CONST.DEFAULT_NUMBER_ID; + const resolvedCardSettings = getCardSettings(fullySetUpCardSetting.cardSetting); + const paymentBankAccountID = resolvedCardSettings?.paymentBankAccountID ?? CONST.DEFAULT_NUMBER_ID; const bankAccountTitle = bankAccountList?.[paymentBankAccountID]?.title ?? ''; const {connection} = route.params; const connectionName = getConnectionNameFromRouteParam(connection) as ConnectionName; const autoSync = !!policy?.connections?.[connectionName]?.config?.autoSync?.enabled; - const shouldShow = !!fullySetUpCardSetting.cardSetting?.paymentBankAccountID; + const shouldShow = !!resolvedCardSettings?.paymentBankAccountID; const handleToggleContinuousReconciliation = (value: boolean) => { toggleContinuousReconciliation(effectiveDomainID, value, connectionName, currentConnectionName); From 5ea89d51284323163694a65ea61d25f01c467b35 Mon Sep 17 00:00:00 2001 From: "Cong Pham (via MelvinBot)" Date: Sat, 14 Mar 2026 07:09:07 +0000 Subject: [PATCH 2/3] Fetch card settings on PolicyAccountingPage mount when cards are enabled When navigating directly to the Accounting page without first visiting the Expensify Card page, PRIVATE_EXPENSIFY_CARD_SETTINGS may not be loaded in Onyx. This adds a useEffect that calls openPolicyExpensifyCardsPage to ensure card settings are fetched, so shouldShowCardReconciliationOption evaluates correctly. Co-authored-by: Cong Pham --- .../workspace/accounting/PolicyAccountingPage.tsx | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/pages/workspace/accounting/PolicyAccountingPage.tsx b/src/pages/workspace/accounting/PolicyAccountingPage.tsx index 1d88894ba81fe..4cef621e68764 100644 --- a/src/pages/workspace/accounting/PolicyAccountingPage.tsx +++ b/src/pages/workspace/accounting/PolicyAccountingPage.tsx @@ -21,6 +21,7 @@ import ThreeDotsMenu from '@components/ThreeDotsMenu'; import type ThreeDotsMenuProps from '@components/ThreeDotsMenu/types'; import useEnvironment from '@hooks/useEnvironment'; import useExpensifyCardFeeds from '@hooks/useExpensifyCardFeeds'; +import useWorkspaceAccountID from '@hooks/useWorkspaceAccountID'; import {useMemoizedLazyExpensifyIcons, useMemoizedLazyIllustrations} from '@hooks/useLazyAsset'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; @@ -53,6 +54,7 @@ import Navigation from '@navigation/Navigation'; import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import {openOldDotLink} from '@userActions/Link'; +import {openPolicyExpensifyCardsPage} from '@userActions/Policy/Policy'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; @@ -92,6 +94,7 @@ function PolicyAccountingPage({policy}: PolicyAccountingPageProps) { const integrationToDisconnect = params?.integrationToDisconnect; const shouldDisconnectIntegrationBeforeConnecting = params?.shouldDisconnectIntegrationBeforeConnecting; const policyID = policy?.id; + const workspaceAccountID = useWorkspaceAccountID(policyID); const allCardSettings = useExpensifyCardFeeds(policyID); const isSyncInProgress = isConnectionInProgress(connectionSyncProgress, policy); const icons = useMemoizedLazyExpensifyIcons([ @@ -210,6 +213,13 @@ function PolicyAccountingPage({policy}: PolicyAccountingPageProps) { setDateTimeToRelative(''); }, [getDatetimeToRelative, successfulDate]); + useEffect(() => { + if (!policyID || !policy?.areExpensifyCardsEnabled || !workspaceAccountID) { + return; + } + openPolicyExpensifyCardsPage(policyID, workspaceAccountID); + }, [policyID, policy?.areExpensifyCardsEnabled, workspaceAccountID]); + const integrationSpecificMenuItems = useMemo(() => { const sageIntacctEntityList = policy?.connections?.intacct?.data?.entities ?? []; const netSuiteSubsidiaryList = policy?.connections?.netsuite?.options?.data?.subsidiaryList ?? []; From 74929b2367ccf9a6fdbef671eabde796ac5130ef Mon Sep 17 00:00:00 2001 From: "Cong Pham (via MelvinBot)" Date: Sat, 14 Mar 2026 07:12:05 +0000 Subject: [PATCH 3/3] Fix: Prettier formatting for import order in PolicyAccountingPage Co-authored-by: Cong Pham --- src/pages/workspace/accounting/PolicyAccountingPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/workspace/accounting/PolicyAccountingPage.tsx b/src/pages/workspace/accounting/PolicyAccountingPage.tsx index 4cef621e68764..6da8a62f77657 100644 --- a/src/pages/workspace/accounting/PolicyAccountingPage.tsx +++ b/src/pages/workspace/accounting/PolicyAccountingPage.tsx @@ -21,7 +21,6 @@ import ThreeDotsMenu from '@components/ThreeDotsMenu'; import type ThreeDotsMenuProps from '@components/ThreeDotsMenu/types'; import useEnvironment from '@hooks/useEnvironment'; import useExpensifyCardFeeds from '@hooks/useExpensifyCardFeeds'; -import useWorkspaceAccountID from '@hooks/useWorkspaceAccountID'; import {useMemoizedLazyExpensifyIcons, useMemoizedLazyIllustrations} from '@hooks/useLazyAsset'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; @@ -30,6 +29,7 @@ import usePermissions from '@hooks/usePermissions'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; +import useWorkspaceAccountID from '@hooks/useWorkspaceAccountID'; import useWorkspaceDocumentTitle from '@hooks/useWorkspaceDocumentTitle'; import {isAuthenticationError, isConnectionInProgress, isConnectionUnverified, removePolicyConnection, syncConnection} from '@libs/actions/connections'; import {shouldShowQBOReimbursableExportDestinationAccountError} from '@libs/actions/connections/QuickbooksOnline';