From 274bf48b15ad4eb262dcb3668533df923aecdb9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Muzyk?= Date: Wed, 4 Feb 2026 14:19:52 +0100 Subject: [PATCH 1/4] fix: 81349 Mark as paid via bulk --- src/components/SettlementButton/index.tsx | 9 +++------ src/libs/PaymentUtils.ts | 13 +++++++++---- src/libs/actions/Search.ts | 9 ++++----- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/components/SettlementButton/index.tsx b/src/components/SettlementButton/index.tsx index aab82b530e7c..d94b207dbbe0 100644 --- a/src/components/SettlementButton/index.tsx +++ b/src/components/SettlementButton/index.tsx @@ -561,14 +561,11 @@ function SettlementButton({ return; } - const {paymentType, selectedPolicy, shouldSelectPaymentMethod} = getActivePaymentType(selectedOption, activeAdminPolicies, latestBankItem, policyIDKey); - - // Payment type for 'Pay via workspace' option is "Elsewhere" but selected option points to one of workspaces where user is admin - const isPayingViaWorkspace = paymentType === CONST.IOU.PAYMENT_TYPE.ELSEWHERE && activeAdminPolicies.find((activeAdminPolicy) => activeAdminPolicy.id === selectedOption); + const {paymentType, policyFromPaymentMethod, policyFromContext, shouldSelectPaymentMethod} = getActivePaymentType(selectedOption, activeAdminPolicies, latestBankItem, policyIDKey); const isPayingWithMethod = paymentType !== CONST.IOU.PAYMENT_TYPE.ELSEWHERE; - if ((!!selectedPolicy || shouldSelectPaymentMethod) && (isPayingWithMethod || isPayingViaWorkspace)) { - selectPaymentMethod(event, paymentType, triggerKYCFlow, selectedOption as PaymentMethod, selectedPolicy); + if ((!!policyFromContext || !!policyFromPaymentMethod || shouldSelectPaymentMethod) && (isPayingWithMethod || !!policyFromPaymentMethod)) { + selectPaymentMethod(event, paymentType, triggerKYCFlow, selectedOption as PaymentMethod, policyFromPaymentMethod ?? policyFromContext); return; } diff --git a/src/libs/PaymentUtils.ts b/src/libs/PaymentUtils.ts index 3c522efa9686..0899c2ebe459 100644 --- a/src/libs/PaymentUtils.ts +++ b/src/libs/PaymentUtils.ts @@ -218,14 +218,18 @@ const isSecondaryActionAPaymentOption = (item: PopoverMenuItem): item is Payment }; /** - * Get the appropriate payment type, selected policy, and whether a payment method should be selected + * Get the appropriate payment type, policy from context (policy related to payment type), policy from payment method, and whether a payment method should be selected * based on the provided payment method, active admin policies, and latest bank items. */ function getActivePaymentType(paymentMethod: string | undefined, activeAdminPolicies: Policy[], latestBankItems: BankAccountMenuItem[] | undefined, policyID?: string | undefined) { const isPaymentMethod = Object.values(CONST.PAYMENT_METHODS).includes(paymentMethod as ValueOf); const shouldSelectPaymentMethod = isPaymentMethod || !isEmpty(latestBankItems); - // payment method is equal to policyID when user selects "Pay via workspace" option - const selectedPolicy = activeAdminPolicies.find((activePolicy) => activePolicy.id === policyID || activePolicy.id === paymentMethod); + + // Policy related to the context ie: Policy related to opened chat + const policyFromContext = activeAdminPolicies.find((activePolicy) => activePolicy.id === policyID); + + // Policy that is part of payment method ie: Policy when user presses on 'Pay via workspace' option + const policyFromPaymentMethod = activeAdminPolicies.find((activePolicy) => activePolicy.id === paymentMethod); let paymentType; switch (paymentMethod) { @@ -242,7 +246,8 @@ function getActivePaymentType(paymentMethod: string | undefined, activeAdminPoli return { paymentType, - selectedPolicy, + policyFromContext, + policyFromPaymentMethod, shouldSelectPaymentMethod, }; } diff --git a/src/libs/actions/Search.ts b/src/libs/actions/Search.ts index 6ddaf363d871..83a0f58f9c3c 100644 --- a/src/libs/actions/Search.ts +++ b/src/libs/actions/Search.ts @@ -1192,10 +1192,9 @@ function handleBulkPayItemSelected(params: { showDelegateNoAccessModal, confirmPayment, } = params; - const {paymentType, selectedPolicy, shouldSelectPaymentMethod} = getActivePaymentType(item.key, activeAdminPolicies, latestBankItems, policy?.id); - const isPolicyBasedPaymentOption = activeAdminPolicies.some((activePolicy) => activePolicy.id === item.key); + const {paymentType, policyFromPaymentMethod, policyFromContext, shouldSelectPaymentMethod} = getActivePaymentType(item.key, activeAdminPolicies, latestBankItems, policy?.id); // Early return if item is not a valid payment method and not a policy-based payment option - if (!isValidBulkPayOption(item) && !isPolicyBasedPaymentOption) { + if (!isValidBulkPayOption(item) && !policyFromPaymentMethod) { return; } @@ -1219,12 +1218,12 @@ function handleBulkPayItemSelected(params: { return; } - if (!!selectedPolicy || shouldSelectPaymentMethod) { + if (!!policyFromPaymentMethod || shouldSelectPaymentMethod) { triggerKYCFlow({ event: undefined, iouPaymentType: paymentType, paymentMethod: item.key as PaymentMethod, - policy: selectedPolicy, + policy: policyFromPaymentMethod ?? policyFromContext, }); if (paymentType === CONST.IOU.PAYMENT_TYPE.EXPENSIFY || paymentType === CONST.IOU.PAYMENT_TYPE.VBBA) { From af363f5c4416167b97ad6b5b1c2e3f9dfdb1d864 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Muzyk?= Date: Wed, 4 Feb 2026 14:42:55 +0100 Subject: [PATCH 2/4] fix: updated tests --- tests/unit/PaymentUtilsTest.ts | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/tests/unit/PaymentUtilsTest.ts b/tests/unit/PaymentUtilsTest.ts index cf59236bccdc..544b571943a8 100644 --- a/tests/unit/PaymentUtilsTest.ts +++ b/tests/unit/PaymentUtilsTest.ts @@ -76,7 +76,8 @@ describe('PaymentUtils', () => { expect(result.paymentType).toBe(CONST.IOU.PAYMENT_TYPE.EXPENSIFY); expect(result.shouldSelectPaymentMethod).toBe(true); - expect(result.selectedPolicy).toBeUndefined(); + expect(result.policyFromContext).toBeUndefined(); + expect(result.policyFromPaymentMethod).toBeUndefined(); }); it('should return VBBA payment type when paymentMethod is BUSINESS_BANK_ACCOUNT', () => { @@ -84,7 +85,8 @@ describe('PaymentUtils', () => { expect(result.paymentType).toBe(CONST.IOU.PAYMENT_TYPE.VBBA); expect(result.shouldSelectPaymentMethod).toBe(true); - expect(result.selectedPolicy).toBeUndefined(); + expect(result.policyFromContext).toBeUndefined(); + expect(result.policyFromPaymentMethod).toBeUndefined(); }); it('should return ELSEWHERE payment type when paymentMethod is DEBIT_CARD', () => { @@ -92,7 +94,8 @@ describe('PaymentUtils', () => { expect(result.paymentType).toBe(CONST.IOU.PAYMENT_TYPE.ELSEWHERE); expect(result.shouldSelectPaymentMethod).toBe(true); - expect(result.selectedPolicy).toBeUndefined(); + expect(result.policyFromContext).toBeUndefined(); + expect(result.policyFromPaymentMethod).toBeUndefined(); }); it('should return ELSEWHERE payment type when paymentMethod is undefined', () => { @@ -100,7 +103,8 @@ describe('PaymentUtils', () => { expect(result.paymentType).toBe(CONST.IOU.PAYMENT_TYPE.ELSEWHERE); expect(result.shouldSelectPaymentMethod).toBe(false); - expect(result.selectedPolicy).toBeUndefined(); + expect(result.policyFromContext).toBeUndefined(); + expect(result.policyFromPaymentMethod).toBeUndefined(); }); it('should set shouldSelectPaymentMethod to true when latestBankItems is not empty', () => { @@ -110,24 +114,34 @@ describe('PaymentUtils', () => { expect(result.shouldSelectPaymentMethod).toBe(true); }); - it('should find selectedPolicy by policyID', () => { + it('should find policyFromContext by policyID', () => { const result = getActivePaymentType(undefined, [randomPolicyA, randomPolicyB], undefined, randomPolicyA.id); - expect(result.selectedPolicy).toEqual(randomPolicyA); + expect(result.policyFromContext).toEqual(randomPolicyA); + expect(result.policyFromPaymentMethod).toBeUndefined(); }); - it('should find selectedPolicy by paymentMethod when it matches policy id (Pay via workspace scenario)', () => { + it('should find policyFromPaymentMethod when paymentMethod matches policy id (Pay via workspace scenario)', () => { const result = getActivePaymentType(randomPolicyB.id, [randomPolicyA, randomPolicyB], undefined); - expect(result.selectedPolicy).toEqual(randomPolicyB); + expect(result.policyFromPaymentMethod).toEqual(randomPolicyB); + expect(result.policyFromContext).toBeUndefined(); expect(result.paymentType).toBe(CONST.IOU.PAYMENT_TYPE.ELSEWHERE); expect(result.shouldSelectPaymentMethod).toBe(false); }); - it('should return undefined selectedPolicy when no matching policy is found', () => { + it('should return both policyFromContext and policyFromPaymentMethod when both match', () => { + const result = getActivePaymentType(randomPolicyB.id, [randomPolicyA, randomPolicyB], undefined, randomPolicyA.id); + + expect(result.policyFromContext).toEqual(randomPolicyA); + expect(result.policyFromPaymentMethod).toEqual(randomPolicyB); + }); + + it('should return undefined policies when no matching policy is found', () => { const result = getActivePaymentType(undefined, [randomPolicyA], undefined, 'non-existent-policy'); - expect(result.selectedPolicy).toBeUndefined(); + expect(result.policyFromContext).toBeUndefined(); + expect(result.policyFromPaymentMethod).toBeUndefined(); }); }); }); From c11de883e48d2eb99b72e24bd34810ab1734c1d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Muzyk?= Date: Thu, 5 Feb 2026 09:02:57 +0100 Subject: [PATCH 3/4] fix: prettier --- src/libs/PaymentUtils.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libs/PaymentUtils.ts b/src/libs/PaymentUtils.ts index 9b5514b80fea..c0261e6a74b5 100644 --- a/src/libs/PaymentUtils.ts +++ b/src/libs/PaymentUtils.ts @@ -239,7 +239,6 @@ function getActivePaymentType(paymentMethod: string | undefined, activeAdminPoli break; } - // Policy related to the context ie: Policy related to opened chat const policyFromContext = activeAdminPolicies.find((activePolicy) => activePolicy.id === policyID); From da6ca7457af929028219fa3d6c06045e178ea966 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Muzyk?= Date: Fri, 6 Feb 2026 09:46:38 +0100 Subject: [PATCH 4/4] fix: remove redundant variable from condition --- src/components/SettlementButton/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/SettlementButton/index.tsx b/src/components/SettlementButton/index.tsx index 7bae6dd6c03b..d6f2f2baeeaf 100644 --- a/src/components/SettlementButton/index.tsx +++ b/src/components/SettlementButton/index.tsx @@ -565,7 +565,7 @@ function SettlementButton({ const {paymentType, policyFromPaymentMethod, policyFromContext, shouldSelectPaymentMethod} = getActivePaymentType(selectedOption, activeAdminPolicies, latestBankItem, policyIDKey); const isPayingWithMethod = paymentType !== CONST.IOU.PAYMENT_TYPE.ELSEWHERE; - if ((!!policyFromContext || !!policyFromPaymentMethod || shouldSelectPaymentMethod) && (isPayingWithMethod || !!policyFromPaymentMethod)) { + if ((!!policyFromPaymentMethod || shouldSelectPaymentMethod) && (isPayingWithMethod || !!policyFromPaymentMethod)) { selectPaymentMethod(event, paymentType, triggerKYCFlow, selectedOption as PaymentMethod, policyFromPaymentMethod ?? policyFromContext); return; }