From 0ef89ff5a3a4d170496cb9b7bf577d1faaf559b2 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Tue, 2 Dec 2025 23:49:18 +0700 Subject: [PATCH 1/5] fix: Pay with business account is shown when bulk paying negative expense --- src/hooks/useBulkPayOptions.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/hooks/useBulkPayOptions.ts b/src/hooks/useBulkPayOptions.ts index 9a197bad3bdd9..c1833610a9054 100644 --- a/src/hooks/useBulkPayOptions.ts +++ b/src/hooks/useBulkPayOptions.ts @@ -5,6 +5,7 @@ import type {TupleToUnion} from 'type-fest'; import {Bank, Cash, Wallet} from '@components/Icon/Expensicons'; import type {PopoverMenuItem} from '@components/PopoverMenu'; import type {BankAccountMenuItem} from '@components/Search/types'; +import {canIOUBePaid} from '@libs/actions/IOU'; import {isCurrencySupportedForDirectReimbursement} from '@libs/actions/Policy/Policy'; import Navigation from '@libs/Navigation/Navigation'; import {formatPaymentMethods} from '@libs/PaymentUtils'; @@ -78,6 +79,7 @@ function useBulkPayOptions({ const canUseWallet = !isExpenseReport && !isInvoiceReport && isCurrencySupportedWallet; const hasSinglePolicy = !isExpenseReport && activeAdminPolicies.length === 1; const hasMultiplePolicies = !isExpenseReport && activeAdminPolicies.length > 1; + const onlyShowPayElsewhere = canIOUBePaid(iouReport, chatReport, policy, undefined, true); function getLatestBankAccountItem() { if (!policy?.achAccount?.bankAccountID) { @@ -137,6 +139,10 @@ function useBulkPayOptions({ return undefined; } + if (onlyShowPayElsewhere) { + return [paymentMethods[CONST.IOU.PAYMENT_TYPE.ELSEWHERE]]; + } + if (shouldShowBusinessBankAccountOptions) { buttonOptions.push(paymentMethods[CONST.PAYMENT_METHODS.BUSINESS_BANK_ACCOUNT]); } @@ -238,6 +244,7 @@ function useBulkPayOptions({ chatReport, getPaymentSubitems, formattedAmount, + onlyShowPayElsewhere, ]); return { From b176ca6d0d0370fd5338b11ddebd4a4164245953 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Fri, 5 Dec 2025 16:48:29 +0700 Subject: [PATCH 2/5] fix perf comment --- src/hooks/useBulkPayOptions.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/hooks/useBulkPayOptions.ts b/src/hooks/useBulkPayOptions.ts index c1833610a9054..267026cb2bf44 100644 --- a/src/hooks/useBulkPayOptions.ts +++ b/src/hooks/useBulkPayOptions.ts @@ -79,7 +79,10 @@ function useBulkPayOptions({ const canUseWallet = !isExpenseReport && !isInvoiceReport && isCurrencySupportedWallet; const hasSinglePolicy = !isExpenseReport && activeAdminPolicies.length === 1; const hasMultiplePolicies = !isExpenseReport && activeAdminPolicies.length > 1; - const onlyShowPayElsewhere = canIOUBePaid(iouReport, chatReport, policy, undefined, true); + const onlyShowPayElsewhere = useMemo( + () => canIOUBePaid(iouReport, chatReport, policy, undefined, true), + [iouReport, chatReport, policy], + ); function getLatestBankAccountItem() { if (!policy?.achAccount?.bankAccountID) { From aa335dd35d0c7126882ced702e8088967b27113f Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Fri, 5 Dec 2025 16:52:34 +0700 Subject: [PATCH 3/5] merge main --- src/hooks/useBulkPayOptions.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/hooks/useBulkPayOptions.ts b/src/hooks/useBulkPayOptions.ts index 267026cb2bf44..80212d0d81eff 100644 --- a/src/hooks/useBulkPayOptions.ts +++ b/src/hooks/useBulkPayOptions.ts @@ -79,10 +79,7 @@ function useBulkPayOptions({ const canUseWallet = !isExpenseReport && !isInvoiceReport && isCurrencySupportedWallet; const hasSinglePolicy = !isExpenseReport && activeAdminPolicies.length === 1; const hasMultiplePolicies = !isExpenseReport && activeAdminPolicies.length > 1; - const onlyShowPayElsewhere = useMemo( - () => canIOUBePaid(iouReport, chatReport, policy, undefined, true), - [iouReport, chatReport, policy], - ); + const onlyShowPayElsewhere = useMemo(() => canIOUBePaid(iouReport, chatReport, policy, undefined, true), [iouReport, chatReport, policy]); function getLatestBankAccountItem() { if (!policy?.achAccount?.bankAccountID) { From da4a8301858dea253b3f9fb8e9d91e7fdb29d7ef Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Mon, 15 Dec 2025 15:48:35 +0700 Subject: [PATCH 4/5] fix edge case --- src/hooks/useBulkPayOptions.ts | 7 ++----- src/pages/Search/SearchPage.tsx | 12 +++++++++++- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/hooks/useBulkPayOptions.ts b/src/hooks/useBulkPayOptions.ts index 08b4326e26b4b..982478ed38999 100644 --- a/src/hooks/useBulkPayOptions.ts +++ b/src/hooks/useBulkPayOptions.ts @@ -5,7 +5,6 @@ import type {TupleToUnion} from 'type-fest'; import {Bank, Cash, Wallet} from '@components/Icon/Expensicons'; import type {PopoverMenuItem} from '@components/PopoverMenu'; import type {BankAccountMenuItem} from '@components/Search/types'; -import {canIOUBePaid} from '@libs/actions/IOU'; import {isCurrencySupportedForGlobalReimbursement} from '@libs/actions/Policy/Policy'; import Navigation from '@libs/Navigation/Navigation'; import {formatPaymentMethods} from '@libs/PaymentUtils'; @@ -38,6 +37,7 @@ type UseBulkPayOptionProps = { isCurrencySupportedWallet?: boolean; currency: string | undefined; formattedAmount: string; + onlyShowPayElsewhere: boolean; }; type UseBulkPayOptionReturnType = { @@ -55,6 +55,7 @@ function useBulkPayOptions({ isCurrencySupportedWallet, currency, formattedAmount, + onlyShowPayElsewhere, }: UseBulkPayOptionProps): UseBulkPayOptionReturnType { const icons = useMemoizedLazyExpensifyIcons(['Building', 'User'] as const); const {translate} = useLocalize(); @@ -79,10 +80,6 @@ function useBulkPayOptions({ const canUseWallet = !isExpenseReport && !isInvoiceReport && isCurrencySupportedWallet; const hasSinglePolicy = !isExpenseReport && activeAdminPolicies.length === 1; const hasMultiplePolicies = !isExpenseReport && activeAdminPolicies.length > 1; - const onlyShowPayElsewhere = useMemo( - () => !canIOUBePaid(iouReport, chatReport, policy, undefined, false) && canIOUBePaid(iouReport, chatReport, policy, undefined, true), - [iouReport, chatReport, policy], - ); function getLatestBankAccountItem() { if (!policy?.achAccount?.bankAccountID) { diff --git a/src/pages/Search/SearchPage.tsx b/src/pages/Search/SearchPage.tsx index a7f431047902b..9925d953e1997 100644 --- a/src/pages/Search/SearchPage.tsx +++ b/src/pages/Search/SearchPage.tsx @@ -78,7 +78,7 @@ import {shouldRestrictUserBillableActions} from '@libs/SubscriptionUtils'; import {hasTransactionBeenRejected} from '@libs/TransactionUtils'; import type {ReceiptFile} from '@pages/iou/request/step/IOURequestStepScan/types'; import variables from '@styles/variables'; -import {dismissRejectUseExplanation, initMoneyRequest, initSplitExpense, setMoneyRequestParticipantsFromReport, setMoneyRequestReceipt} from '@userActions/IOU'; +import {canIOUBePaid, dismissRejectUseExplanation, initMoneyRequest, initSplitExpense, setMoneyRequestParticipantsFromReport, setMoneyRequestReceipt} from '@userActions/IOU'; import {openOldDotLink} from '@userActions/Link'; import {buildOptimisticTransactionAndCreateDraft} from '@userActions/TransactionEdit'; import CONST from '@src/CONST'; @@ -172,6 +172,15 @@ function SearchPage({route}: SearchPageProps) { const selectedBulkCurrency = selectedReports.at(0)?.currency ?? Object.values(selectedTransactions).at(0)?.currency; const totalFormattedAmount = getTotalFormattedAmount(selectedReports, selectedTransactions, selectedBulkCurrency); + const onlyShowPayElsewhere = useMemo(() => { + const selectedPolicy = currentSearchResults?.data?.[`${ONYXKEYS.COLLECTION.POLICY}${selectedPolicyIDs.at(0)}`]; + return (selectedTransactionReportIDs ?? selectedReportIDs).some((reportID) => { + const report = currentSearchResults?.data?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`]; + const chatReport = currentSearchResults?.data?.[`${ONYXKEYS.COLLECTION.REPORT}${report?.chatReportID}`]; + return report && !canIOUBePaid(report, chatReport, selectedPolicy, undefined, false) && canIOUBePaid(report, chatReport, selectedPolicy, undefined, true); + }) + }, [currentSearchResults?.data, selectedPolicyIDs, selectedReportIDs, selectedTransactionReportIDs]); + const {bulkPayButtonOptions, latestBankItems} = useBulkPayOptions({ selectedPolicyID: selectedPolicyIDs.at(0), selectedReportID: selectedTransactionReportIDs.at(0) ?? selectedReportIDs.at(0), @@ -179,6 +188,7 @@ function SearchPage({route}: SearchPageProps) { isCurrencySupportedWallet: isCurrencySupportedBulkWallet, currency: selectedBulkCurrency, formattedAmount: totalFormattedAmount, + onlyShowPayElsewhere, }); useEffect(() => { From 13bbd16683a320068a2d0bfc9d3a82a4e2092b6a Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Mon, 15 Dec 2025 15:57:43 +0700 Subject: [PATCH 5/5] fix lint --- src/pages/Search/SearchPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/Search/SearchPage.tsx b/src/pages/Search/SearchPage.tsx index 9925d953e1997..0b3e8c0ddf145 100644 --- a/src/pages/Search/SearchPage.tsx +++ b/src/pages/Search/SearchPage.tsx @@ -178,7 +178,7 @@ function SearchPage({route}: SearchPageProps) { const report = currentSearchResults?.data?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`]; const chatReport = currentSearchResults?.data?.[`${ONYXKEYS.COLLECTION.REPORT}${report?.chatReportID}`]; return report && !canIOUBePaid(report, chatReport, selectedPolicy, undefined, false) && canIOUBePaid(report, chatReport, selectedPolicy, undefined, true); - }) + }); }, [currentSearchResults?.data, selectedPolicyIDs, selectedReportIDs, selectedTransactionReportIDs]); const {bulkPayButtonOptions, latestBankItems} = useBulkPayOptions({