From c088d0ea39ab23455e2df240b8648f5731d6dde3 Mon Sep 17 00:00:00 2001 From: Hans Date: Sun, 22 Feb 2026 22:08:37 +0700 Subject: [PATCH 1/6] update RBR of admin logic --- .../useNavigationTabBarIndicatorChecks.ts | 2 +- src/libs/actions/PaymentMethods.ts | 47 ++++++++++++++++--- src/pages/settings/InitialSettingsPage.tsx | 5 +- 3 files changed, 43 insertions(+), 11 deletions(-) diff --git a/src/hooks/useNavigationTabBarIndicatorChecks.ts b/src/hooks/useNavigationTabBarIndicatorChecks.ts index 29eb5d1898191..7efe512dfeff5 100644 --- a/src/hooks/useNavigationTabBarIndicatorChecks.ts +++ b/src/hooks/useNavigationTabBarIndicatorChecks.ts @@ -72,7 +72,7 @@ function useNavigationTabBarIndicatorChecks(): NavigationTabBarChecksResult { // we only care if a single error / info condition exists anywhere. const accountChecks: Partial> = { [CONST.INDICATOR_STATUS.HAS_USER_WALLET_ERRORS]: Object.keys(userWallet?.errors ?? {}).length > 0, - [CONST.INDICATOR_STATUS.HAS_PAYMENT_METHOD_ERROR]: hasPaymentMethodError(bankAccountList, fundList, allCards), + [CONST.INDICATOR_STATUS.HAS_PAYMENT_METHOD_ERROR]: hasPaymentMethodError(bankAccountList, fundList, allCards, session, policies), [CONST.INDICATOR_STATUS.HAS_SUBSCRIPTION_ERRORS]: hasSubscriptionRedDotError( stripeCustomerId, retryBillingSuccessful, diff --git a/src/libs/actions/PaymentMethods.ts b/src/libs/actions/PaymentMethods.ts index 117edc0e6a9b9..cf131ea1d5bd6 100644 --- a/src/libs/actions/PaymentMethods.ts +++ b/src/libs/actions/PaymentMethods.ts @@ -1,5 +1,5 @@ import type {RefObject} from 'react'; -import type {OnyxEntry, OnyxUpdate} from 'react-native-onyx'; +import type {OnyxCollection, OnyxEntry, OnyxUpdate} from 'react-native-onyx'; import Onyx from 'react-native-onyx'; import type {ValueOf} from 'type-fest'; import type {KYCWallRef} from '@components/KYCWall/types'; @@ -18,6 +18,7 @@ import * as CardUtils from '@libs/CardUtils'; import GoogleTagManager from '@libs/GoogleTagManager'; import Log from '@libs/Log'; import Navigation from '@libs/Navigation/Navigation'; +import {isPolicyMember} from '@libs/PolicyUtils'; import {getCardForSubscriptionBilling} from '@libs/SubscriptionUtils'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; @@ -25,7 +26,9 @@ import type {Route} from '@src/ROUTES'; import INPUT_IDS from '@src/types/form/AddPaymentCardForm'; import type {BankAccountList, CardList, FundList} from '@src/types/onyx'; import type PaymentMethod from '@src/types/onyx/PaymentMethod'; +import type Policy from '@src/types/onyx/Policy'; import type {OnyxData} from '@src/types/onyx/Request'; +import type Session from '@src/types/onyx/Session'; import type {FilterMethodPaymentType} from '@src/types/onyx/WalletTransfer'; /** @@ -409,13 +412,45 @@ function dismissSuccessfulTransferBalancePage() { } /** - * Looks through each payment method to see if there is an existing error - * + * Looks through each payment method to see if there is an existing error. + * When session and policies are provided, card list errors are only counted if the current user + * is a member of that card's workspace (for company cards) or always counted for personal cards. + * Only cards with non-empty errors are considered (error cards). */ -function hasPaymentMethodError(bankList: OnyxEntry, fundList: OnyxEntry, cardList: OnyxEntry): boolean { - const combinedPaymentMethods = {...bankList, ...fundList, ...cardList}; +function hasPaymentMethodError( + bankList: OnyxEntry, + fundList: OnyxEntry, + cardList: OnyxEntry, + session?: OnyxEntry, + policies?: OnyxCollection, +): boolean { + const hasBankOrFundError = Object.values({...(bankList ?? {}), ...(fundList ?? {})}).some((item) => Object.keys(item?.errors ?? {}).length > 0); + + const currentUserLogin = session?.email; + + if (!currentUserLogin || !policies) { + return hasBankOrFundError; + } + + const cardsWithErrors = Object.values(cardList ?? {}).filter((card) => Object.keys(card?.errors ?? {}).length > 0); + + const policyList = Object.values(policies ?? {}).filter(Boolean); + const hasRelevantCardError = cardsWithErrors.some((card) => { + if (CardUtils.isPersonalCard(card)) { + return true; + } + if (!currentUserLogin || !policies) { + return true; + } + const workspaceAccountID = Number(card?.fundID); + if (Number.isNaN(workspaceAccountID)) { + return true; + } + const policy = policyList.find((p) => p?.workspaceAccountID === workspaceAccountID); + return !!policy && isPolicyMember(policy, currentUserLogin); + }); - return Object.values(combinedPaymentMethods).some((item) => Object.keys(item.errors ?? {}).length); + return hasRelevantCardError || hasBankOrFundError; } type PaymentListKey = diff --git a/src/pages/settings/InitialSettingsPage.tsx b/src/pages/settings/InitialSettingsPage.tsx index 949e85b397da6..9f4b1ab52d098 100755 --- a/src/pages/settings/InitialSettingsPage.tsx +++ b/src/pages/settings/InitialSettingsPage.tsx @@ -153,18 +153,15 @@ function InitialSettingsPage({currentUserPersonalDetails}: InitialSettingsPagePr const shouldDisplayLHB = !shouldUseNarrowLayout; const { - all: {shouldShowRBR}, personalCard: {shouldShowRBR: shouldShowRBRForPersonalCard}, } = useCardFeedErrors(); - const hasPendingCardAction = hasPendingExpensifyCardAction(allCards, privatePersonalDetails); let walletBrickRoadIndicator; if ( - hasPaymentMethodError(bankAccountList, fundList, allCards) || + hasPaymentMethodError(bankAccountList, fundList, allCards, session, policies) || !isEmptyObject(userWallet?.errors) || !isEmptyObject(walletTerms?.errors) || !isEmptyObject(unsharedBankAccount?.errors) || - shouldShowRBR || shouldShowRBRForPersonalCard ) { walletBrickRoadIndicator = CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR; From 92668bcf9f8b35c12e213897dadf1a3c72443873 Mon Sep 17 00:00:00 2001 From: Hans Date: Mon, 23 Feb 2026 13:26:00 +0700 Subject: [PATCH 2/6] cleanup --- src/libs/actions/PaymentMethods.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/libs/actions/PaymentMethods.ts b/src/libs/actions/PaymentMethods.ts index cf131ea1d5bd6..370b731d3609f 100644 --- a/src/libs/actions/PaymentMethods.ts +++ b/src/libs/actions/PaymentMethods.ts @@ -439,13 +439,8 @@ function hasPaymentMethodError( if (CardUtils.isPersonalCard(card)) { return true; } - if (!currentUserLogin || !policies) { - return true; - } + const workspaceAccountID = Number(card?.fundID); - if (Number.isNaN(workspaceAccountID)) { - return true; - } const policy = policyList.find((p) => p?.workspaceAccountID === workspaceAccountID); return !!policy && isPolicyMember(policy, currentUserLogin); }); From aa3f3361219a6aa50ae300b90bcd0670b7290649 Mon Sep 17 00:00:00 2001 From: Hans Date: Mon, 23 Feb 2026 13:27:54 +0700 Subject: [PATCH 3/6] update hasPaymentMethodError logic --- src/libs/actions/PaymentMethods.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/actions/PaymentMethods.ts b/src/libs/actions/PaymentMethods.ts index 370b731d3609f..189545ad77c97 100644 --- a/src/libs/actions/PaymentMethods.ts +++ b/src/libs/actions/PaymentMethods.ts @@ -444,8 +444,8 @@ function hasPaymentMethodError( const policy = policyList.find((p) => p?.workspaceAccountID === workspaceAccountID); return !!policy && isPolicyMember(policy, currentUserLogin); }); - - return hasRelevantCardError || hasBankOrFundError; + // If there is card with errors, we should display the RBR if user is a member of the workspace. + return hasRelevantCardError && hasBankOrFundError; } type PaymentListKey = From acc3a7ec1c694e9cd1ca33661598a0476efe1e31 Mon Sep 17 00:00:00 2001 From: Hans Date: Mon, 23 Feb 2026 13:55:19 +0700 Subject: [PATCH 4/6] correct RBR logic --- src/libs/actions/PaymentMethods.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libs/actions/PaymentMethods.ts b/src/libs/actions/PaymentMethods.ts index 189545ad77c97..cb9fd4941bab9 100644 --- a/src/libs/actions/PaymentMethods.ts +++ b/src/libs/actions/PaymentMethods.ts @@ -18,7 +18,7 @@ import * as CardUtils from '@libs/CardUtils'; import GoogleTagManager from '@libs/GoogleTagManager'; import Log from '@libs/Log'; import Navigation from '@libs/Navigation/Navigation'; -import {isPolicyMember} from '@libs/PolicyUtils'; +import {isPolicyUser} from '@libs/PolicyUtils'; import {getCardForSubscriptionBilling} from '@libs/SubscriptionUtils'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; @@ -442,10 +442,10 @@ function hasPaymentMethodError( const workspaceAccountID = Number(card?.fundID); const policy = policyList.find((p) => p?.workspaceAccountID === workspaceAccountID); - return !!policy && isPolicyMember(policy, currentUserLogin); + return !!policy && isPolicyUser(policy, currentUserLogin); }); // If there is card with errors, we should display the RBR if user is a member of the workspace. - return hasRelevantCardError && hasBankOrFundError; + return hasRelevantCardError || hasBankOrFundError; } type PaymentListKey = From 624cece03a68d17a3c5010ea5755bfca8fea6828 Mon Sep 17 00:00:00 2001 From: Hans Date: Mon, 23 Feb 2026 14:49:21 +0700 Subject: [PATCH 5/6] update early return --- src/libs/actions/PaymentMethods.ts | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/libs/actions/PaymentMethods.ts b/src/libs/actions/PaymentMethods.ts index cb9fd4941bab9..358609186b0ed 100644 --- a/src/libs/actions/PaymentMethods.ts +++ b/src/libs/actions/PaymentMethods.ts @@ -425,13 +425,7 @@ function hasPaymentMethodError( policies?: OnyxCollection, ): boolean { const hasBankOrFundError = Object.values({...(bankList ?? {}), ...(fundList ?? {})}).some((item) => Object.keys(item?.errors ?? {}).length > 0); - const currentUserLogin = session?.email; - - if (!currentUserLogin || !policies) { - return hasBankOrFundError; - } - const cardsWithErrors = Object.values(cardList ?? {}).filter((card) => Object.keys(card?.errors ?? {}).length > 0); const policyList = Object.values(policies ?? {}).filter(Boolean); @@ -439,7 +433,6 @@ function hasPaymentMethodError( if (CardUtils.isPersonalCard(card)) { return true; } - const workspaceAccountID = Number(card?.fundID); const policy = policyList.find((p) => p?.workspaceAccountID === workspaceAccountID); return !!policy && isPolicyUser(policy, currentUserLogin); From 137bf894e10eab1721ec3a28d067c9c8d7bad4b6 Mon Sep 17 00:00:00 2001 From: Hans Date: Thu, 26 Feb 2026 14:12:43 +0700 Subject: [PATCH 6/6] We shouldn't display debug tabview if there is no message --- src/components/Navigation/DebugTabView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Navigation/DebugTabView.tsx b/src/components/Navigation/DebugTabView.tsx index ab510ae46cda1..45ff08d3e93d2 100644 --- a/src/components/Navigation/DebugTabView.tsx +++ b/src/components/Navigation/DebugTabView.tsx @@ -156,7 +156,7 @@ function DebugTabView({selectedTab, chatTabBrickRoad}: DebugTabViewProps) { } }, [selectedTab, chatTabBrickRoad, orderedReportIDs, reportAttributes, status, reimbursementAccount, policyIDWithErrors]); - if (!([NAVIGATION_TABS.INBOX, NAVIGATION_TABS.SETTINGS, NAVIGATION_TABS.WORKSPACES] as string[]).includes(selectedTab ?? '') || !indicator) { + if (!([NAVIGATION_TABS.INBOX, NAVIGATION_TABS.SETTINGS, NAVIGATION_TABS.WORKSPACES] as string[]).includes(selectedTab ?? '') || !indicator || !message) { return null; }