From e4fe1e54da9738c1a7fb92ecdea75efe0189a76b Mon Sep 17 00:00:00 2001 From: truph01 Date: Mon, 27 Apr 2026 11:29:34 +0700 Subject: [PATCH 1/3] fix: refactor payMoneyRequest --- .../MoneyReportHeaderSecondaryActions.tsx | 2 + .../MoneyReportHeaderSelectionDropdown.tsx | 2 + .../PayPrimaryAction.tsx | 2 + .../PayActionButton.tsx | 2 + src/hooks/useHoldMenuSubmit.ts | 2 + src/hooks/useSelectionModeReportActions.ts | 2 + src/libs/actions/IOU/PayMoneyRequest.ts | 9 +- tests/actions/IOUTest/PayMoneyRequestTest.ts | 253 ++++++++++++++---- 8 files changed, 220 insertions(+), 54 deletions(-) diff --git a/src/components/MoneyReportHeaderActions/MoneyReportHeaderSecondaryActions.tsx b/src/components/MoneyReportHeaderActions/MoneyReportHeaderSecondaryActions.tsx index 84eb944cc7b0..5e5d429ece45 100644 --- a/src/components/MoneyReportHeaderActions/MoneyReportHeaderSecondaryActions.tsx +++ b/src/components/MoneyReportHeaderActions/MoneyReportHeaderSecondaryActions.tsx @@ -106,6 +106,7 @@ function MoneyReportHeaderSecondaryActionsInner({reportID, primaryAction, isRepo const {isOffline} = useNetwork(); const activePolicy = usePolicy(activePolicyID); + const chatReportPolicy = usePolicy(chatReport?.policyID); const {isBetaEnabled} = usePermissions(); const isASAPSubmitBetaEnabled = isBetaEnabled(CONST.BETAS.ASAP_SUBMIT); @@ -179,6 +180,7 @@ function MoneyReportHeaderSecondaryActionsInner({reportID, primaryAction, isRepo currentUserAccountID: accountID, activePolicy, policy, + chatReportPolicy, betas, isSelfTourViewed, userBillingGracePeriodEnds, diff --git a/src/components/MoneyReportHeaderActions/MoneyReportHeaderSelectionDropdown.tsx b/src/components/MoneyReportHeaderActions/MoneyReportHeaderSelectionDropdown.tsx index 10994cf45f6c..7e83ea9f39a2 100644 --- a/src/components/MoneyReportHeaderActions/MoneyReportHeaderSelectionDropdown.tsx +++ b/src/components/MoneyReportHeaderActions/MoneyReportHeaderSelectionDropdown.tsx @@ -108,6 +108,7 @@ function MoneyReportHeaderSelectionDropdown({reportID, primaryAction, isReportIn const [activePolicyID] = useOnyx(ONYXKEYS.NVP_ACTIVE_POLICY_ID); const [isSelfTourViewed = false] = useOnyx(ONYXKEYS.NVP_ONBOARDING, {selector: hasSeenTourSelector}); const activePolicy = usePolicy(activePolicyID); + const chatReportPolicy = usePolicy(chatReport?.policyID); const existingB2BInvoiceReport = useParticipantsInvoiceReport(activePolicyID, CONST.REPORT.INVOICE_RECEIVER_TYPE.BUSINESS, chatReport?.policyID); const isInvoiceReport = isInvoiceReportUtil(moneyRequestReport); @@ -262,6 +263,7 @@ function MoneyReportHeaderSelectionDropdown({reportID, primaryAction, isReportIn currentUserAccountID: accountID, activePolicy, policy, + chatReportPolicy, betas, isSelfTourViewed, userBillingGracePeriodEnds, diff --git a/src/components/MoneyReportHeaderPrimaryAction/PayPrimaryAction.tsx b/src/components/MoneyReportHeaderPrimaryAction/PayPrimaryAction.tsx index aaa9ac4ae37c..f1da14154ca7 100644 --- a/src/components/MoneyReportHeaderPrimaryAction/PayPrimaryAction.tsx +++ b/src/components/MoneyReportHeaderPrimaryAction/PayPrimaryAction.tsx @@ -54,6 +54,7 @@ function PayPrimaryAction({reportID, chatReportID}: PayPrimaryActionProps) { const [reportMetadata] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_METADATA}${moneyRequestReport?.reportID}`); const activePolicy = usePolicy(activePolicyID); + const chatReportPolicy = usePolicy(chatReport?.policyID); const invoiceReceiverPolicyID = chatReport?.invoiceReceiver && 'policyID' in chatReport.invoiceReceiver ? chatReport.invoiceReceiver.policyID : undefined; const [invoiceReceiverPolicy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${invoiceReceiverPolicyID}`); const existingB2BInvoiceReport = useParticipantsInvoiceReport(activePolicyID, CONST.REPORT.INVOICE_RECEIVER_TYPE.BUSINESS, chatReport?.policyID); @@ -124,6 +125,7 @@ function PayPrimaryAction({reportID, chatReportID}: PayPrimaryActionProps) { currentUserAccountID: accountID, activePolicy, policy, + chatReportPolicy, betas, isSelfTourViewed, userBillingGracePeriodEnds, diff --git a/src/components/ReportActionItem/MoneyRequestReportPreview/PayActionButton.tsx b/src/components/ReportActionItem/MoneyRequestReportPreview/PayActionButton.tsx index 27fa0b2a630d..b3a809547af6 100644 --- a/src/components/ReportActionItem/MoneyRequestReportPreview/PayActionButton.tsx +++ b/src/components/ReportActionItem/MoneyRequestReportPreview/PayActionButton.tsx @@ -64,6 +64,7 @@ function PayActionButton({ const [iouReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${iouReportID}`); const [chatReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${chatReportID}`); const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${iouReport?.policyID}`); + const chatReportPolicy = usePolicy(chatReport?.policyID); const [invoiceReceiverPolicy] = useOnyx( `${ONYXKEYS.COLLECTION.POLICY}${chatReport?.invoiceReceiver && 'policyID' in chatReport.invoiceReceiver ? chatReport.invoiceReceiver.policyID : undefined}`, ); @@ -160,6 +161,7 @@ function PayActionButton({ currentUserAccountID, activePolicy, policy, + chatReportPolicy, betas, isSelfTourViewed, userBillingGracePeriodEnds, diff --git a/src/hooks/useHoldMenuSubmit.ts b/src/hooks/useHoldMenuSubmit.ts index 00d44abff520..fd26cd41aa40 100644 --- a/src/hooks/useHoldMenuSubmit.ts +++ b/src/hooks/useHoldMenuSubmit.ts @@ -34,6 +34,7 @@ function useHoldMenuSubmit({moneyRequestReport, chatReport, requestType, payment const [ownerBillingGracePeriodEnd] = useOnyx(ONYXKEYS.NVP_PRIVATE_OWNER_BILLING_GRACE_PERIOD_END); const activePolicy = usePolicy(activePolicyID); const policy = usePolicy(moneyRequestReport?.policyID); + const chatReportPolicy = usePolicy(chatReport?.policyID); const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED); const [betas] = useOnyx(ONYXKEYS.BETAS); const [delegateEmail] = useOnyx(ONYXKEYS.ACCOUNT, {selector: delegateEmailSelector}); @@ -87,6 +88,7 @@ function useHoldMenuSubmit({moneyRequestReport, chatReport, requestType, payment full, activePolicy, policy, + chatReportPolicy, betas, isSelfTourViewed, userBillingGracePeriodEnds, diff --git a/src/hooks/useSelectionModeReportActions.ts b/src/hooks/useSelectionModeReportActions.ts index ae0b48f1f792..99382725f596 100644 --- a/src/hooks/useSelectionModeReportActions.ts +++ b/src/hooks/useSelectionModeReportActions.ts @@ -111,6 +111,7 @@ function useSelectionModeReportActions({ const [activePolicyID] = useOnyx(ONYXKEYS.NVP_ACTIVE_POLICY_ID); const activePolicy = usePolicy(activePolicyID); + const chatReportPolicy = usePolicy(chatReport?.policyID); const [invoiceReceiverPolicy] = useOnyx( `${ONYXKEYS.COLLECTION.POLICY}${chatReport?.invoiceReceiver && 'policyID' in chatReport.invoiceReceiver ? chatReport.invoiceReceiver.policyID : undefined}`, ); @@ -380,6 +381,7 @@ function useSelectionModeReportActions({ currentUserAccountID, activePolicy, policy, + chatReportPolicy, betas, isSelfTourViewed, userBillingGracePeriodEnds, diff --git a/src/libs/actions/IOU/PayMoneyRequest.ts b/src/libs/actions/IOU/PayMoneyRequest.ts index f5ecb52fecac..9271ebc60336 100644 --- a/src/libs/actions/IOU/PayMoneyRequest.ts +++ b/src/libs/actions/IOU/PayMoneyRequest.ts @@ -85,6 +85,7 @@ type PayMoneyRequestFunctionParams = { full?: boolean; activePolicy?: OnyxEntry; policy?: OnyxEntry; + chatReportPolicy: OnyxEntry; betas: OnyxEntry; isSelfTourViewed: boolean | undefined; amountOwed: OnyxEntry; @@ -735,6 +736,7 @@ function payMoneyRequest(params: PayMoneyRequestFunctionParams) { full = true, activePolicy, policy, + chatReportPolicy, betas, isSelfTourViewed, amountOwed, @@ -742,7 +744,12 @@ function payMoneyRequest(params: PayMoneyRequestFunctionParams) { methodID, onPaid, } = params; - if (chatReport.policyID && shouldRestrictUserBillableActions(chatReport.policyID, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed)) { + const policyForBillingRestriction = chatReportPolicy ?? (policy?.id === chatReport.policyID ? policy : undefined); + if ( + chatReport.policyID && + policyForBillingRestriction && + shouldRestrictUserBillableActions(policyForBillingRestriction, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed) + ) { Navigation.navigate(ROUTES.RESTRICTED_ACTION.getRoute(chatReport.policyID)); return; } diff --git a/tests/actions/IOUTest/PayMoneyRequestTest.ts b/tests/actions/IOUTest/PayMoneyRequestTest.ts index 6cfe1a5c4d76..0dbbf6cdd346 100644 --- a/tests/actions/IOUTest/PayMoneyRequestTest.ts +++ b/tests/actions/IOUTest/PayMoneyRequestTest.ts @@ -34,6 +34,11 @@ import {getGlobalFetchMock, getOnyxData, translateLocal} from '../../utils/TestH import waitForBatchedUpdates from '../../utils/waitForBatchedUpdates'; const topMostReportID = '23423423'; + +function chatReportPolicyFromChat(chatReport: OnyxEntry): Policy { + return {...createRandomPolicy(0), id: chatReport?.policyID ?? CONST.POLICY.ID_FAKE}; +} + jest.mock('@src/libs/Navigation/Navigation', () => ({ navigate: jest.fn(), dismissModal: jest.fn(), @@ -233,20 +238,22 @@ describe('actions/IOU/PayMoneyRequest', () => { ) .then(() => { mockFetch?.pause?.(); - if (chatReport && iouReport) { - payMoneyRequest({ - paymentType: CONST.IOU.PAYMENT_TYPE.ELSEWHERE, - chatReport, - iouReport, - introSelected: undefined, - iouReportCurrentNextStepDeprecated: undefined, - currentUserAccountID, - betas: [CONST.BETAS.ALL], - isSelfTourViewed: false, - userBillingGracePeriodEnds: undefined, - amountOwed: 0, - }); + if (!chatReport || !iouReport) { + return waitForBatchedUpdates(); } + payMoneyRequest({ + paymentType: CONST.IOU.PAYMENT_TYPE.ELSEWHERE, + chatReport, + iouReport, + introSelected: undefined, + iouReportCurrentNextStepDeprecated: undefined, + currentUserAccountID, + betas: [CONST.BETAS.ALL], + isSelfTourViewed: false, + userBillingGracePeriodEnds: undefined, + amountOwed: 0, + chatReportPolicy: chatReportPolicyFromChat(chatReport), + }); return waitForBatchedUpdates(); }) .then( @@ -441,20 +448,22 @@ describe('actions/IOU/PayMoneyRequest', () => { }), ) .then(() => { - if (chatReport && expenseReport) { - payMoneyRequest({ - paymentType: CONST.IOU.PAYMENT_TYPE.VBBA, - chatReport, - iouReport: expenseReport, - introSelected: undefined, - iouReportCurrentNextStepDeprecated: undefined, - currentUserAccountID: CARLOS_ACCOUNT_ID, - betas: [CONST.BETAS.ALL], - isSelfTourViewed: false, - userBillingGracePeriodEnds: undefined, - amountOwed: 0, - }); + if (!chatReport || !expenseReport) { + return waitForBatchedUpdates(); } + payMoneyRequest({ + paymentType: CONST.IOU.PAYMENT_TYPE.VBBA, + chatReport, + iouReport: expenseReport, + introSelected: undefined, + iouReportCurrentNextStepDeprecated: undefined, + currentUserAccountID: CARLOS_ACCOUNT_ID, + betas: [CONST.BETAS.ALL], + isSelfTourViewed: false, + userBillingGracePeriodEnds: undefined, + amountOwed: 0, + chatReportPolicy: chatReportPolicyFromChat(chatReport), + }); return waitForBatchedUpdates(); }) .then( @@ -603,20 +612,22 @@ describe('actions/IOU/PayMoneyRequest', () => { ) .then(() => { mockFetch?.fail?.(); - if (chatReport && expenseReport) { - payMoneyRequest({ - paymentType: 'ACH', - chatReport, - iouReport: expenseReport, - introSelected: undefined, - iouReportCurrentNextStepDeprecated: undefined, - currentUserAccountID: CARLOS_ACCOUNT_ID, - betas: [CONST.BETAS.ALL], - isSelfTourViewed: false, - userBillingGracePeriodEnds: undefined, - amountOwed: 0, - }); + if (!chatReport || !expenseReport) { + return waitForBatchedUpdates(); } + payMoneyRequest({ + paymentType: 'ACH', + chatReport, + iouReport: expenseReport, + introSelected: undefined, + iouReportCurrentNextStepDeprecated: undefined, + currentUserAccountID: CARLOS_ACCOUNT_ID, + betas: [CONST.BETAS.ALL], + isSelfTourViewed: false, + userBillingGracePeriodEnds: undefined, + amountOwed: 0, + chatReportPolicy: chatReportPolicyFromChat(chatReport), + }); return waitForBatchedUpdates(); }) .then( @@ -656,6 +667,7 @@ describe('actions/IOU/PayMoneyRequest', () => { jest.advanceTimersByTime(10); // When paying the IOU report + const chatReportPolicy = chatReportPolicyFromChat(chatReport); payMoneyRequest({ paymentType: CONST.IOU.PAYMENT_TYPE.ELSEWHERE, chatReport, @@ -667,6 +679,7 @@ describe('actions/IOU/PayMoneyRequest', () => { isSelfTourViewed: false, userBillingGracePeriodEnds: undefined, amountOwed: 0, + chatReportPolicy, }); await waitForBatchedUpdates(); @@ -769,9 +782,10 @@ describe('actions/IOU/PayMoneyRequest', () => { }) .then(() => { // When partially paying an iou report from the chat report via the report preview + const partialPayChatReport = {reportID: topMostReportID, policyID: CONST.POLICY.ID_FAKE}; payMoneyRequest({ paymentType: CONST.IOU.PAYMENT_TYPE.ELSEWHERE, - chatReport: {reportID: topMostReportID}, + chatReport: partialPayChatReport, iouReport, introSelected: undefined, iouReportCurrentNextStepDeprecated: undefined, @@ -781,6 +795,7 @@ describe('actions/IOU/PayMoneyRequest', () => { isSelfTourViewed: false, userBillingGracePeriodEnds: undefined, amountOwed: 0, + chatReportPolicy: chatReportPolicyFromChat(partialPayChatReport), }); return waitForBatchedUpdates(); }) @@ -872,6 +887,7 @@ describe('actions/IOU/PayMoneyRequest', () => { currentUserAccountID: CARLOS_ACCOUNT_ID, full: false, policy, + chatReportPolicy: policy, betas: [CONST.BETAS.ALL], isSelfTourViewed: false, userBillingGracePeriodEnds: undefined, @@ -899,6 +915,7 @@ describe('actions/IOU/PayMoneyRequest', () => { jest.advanceTimersByTime(10); + const chatReportPolicyTrueTour = chatReportPolicyFromChat(chatReport); payMoneyRequest({ paymentType: CONST.IOU.PAYMENT_TYPE.ELSEWHERE, chatReport, @@ -910,6 +927,7 @@ describe('actions/IOU/PayMoneyRequest', () => { isSelfTourViewed: true, userBillingGracePeriodEnds: undefined, amountOwed: 0, + chatReportPolicy: chatReportPolicyTrueTour, }); await waitForBatchedUpdates(); @@ -946,6 +964,7 @@ describe('actions/IOU/PayMoneyRequest', () => { jest.advanceTimersByTime(10); + const chatReportPolicyFalseTour = chatReportPolicyFromChat(chatReport); payMoneyRequest({ paymentType: CONST.IOU.PAYMENT_TYPE.ELSEWHERE, chatReport, @@ -957,6 +976,7 @@ describe('actions/IOU/PayMoneyRequest', () => { isSelfTourViewed: false, userBillingGracePeriodEnds: undefined, amountOwed: 0, + chatReportPolicy: chatReportPolicyFalseTour, }); await waitForBatchedUpdates(); @@ -1025,6 +1045,8 @@ describe('actions/IOU/PayMoneyRequest', () => { userBillingGracePeriodEnds: undefined, amountOwed: 100, ownerBillingGracePeriodEnd: pastDate, + policy, + chatReportPolicy: policy, }); await waitForBatchedUpdates(); @@ -1032,6 +1054,126 @@ describe('actions/IOU/PayMoneyRequest', () => { expect(Navigation.navigate).toHaveBeenCalledWith(ROUTES.RESTRICTED_ACTION.getRoute(policyID)); }); + it('should navigate to restricted using chatReportPolicy when IOU policy id differs from chat workspace policy id', async () => { + const workspacePolicyID = generatePolicyID(); + const expensePolicyID = generatePolicyID(); + + await Onyx.set(ONYXKEYS.SESSION, {email: CARLOS_EMAIL, accountID: CARLOS_ACCOUNT_ID}); + + const workspacePolicy = { + ...createRandomPolicy(9001), + id: workspacePolicyID, + ownerAccountID: CARLOS_ACCOUNT_ID, + role: CONST.POLICY.ROLE.ADMIN, + }; + const expensePolicy = { + ...createRandomPolicy(9002), + id: expensePolicyID, + ownerAccountID: 999, + role: CONST.POLICY.ROLE.ADMIN, + }; + + await Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${workspacePolicyID}`, workspacePolicy); + await Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${expensePolicyID}`, expensePolicy); + + const pastDate = Math.floor(Date.now() / 1000) - 86400 * 30; + await Onyx.set(ONYXKEYS.NVP_PRIVATE_OWNER_BILLING_GRACE_PERIOD_END, pastDate); + await Onyx.set(ONYXKEYS.NVP_PRIVATE_AMOUNT_OWED, 100); + + const chatReport = { + ...createRandomReport(0, undefined), + policyID: workspacePolicyID, + type: CONST.REPORT.TYPE.CHAT, + chatType: CONST.REPORT.CHAT_TYPE.POLICY_EXPENSE_CHAT, + }; + const iouReport = { + ...createRandomReport(1, undefined), + type: CONST.REPORT.TYPE.IOU, + total: 10, + policyID: expensePolicyID, + }; + + await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${chatReport.reportID}`, chatReport); + await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${iouReport.reportID}`, iouReport); + + (Navigation.navigate as jest.Mock).mockClear(); + + payMoneyRequest({ + paymentType: CONST.IOU.PAYMENT_TYPE.ELSEWHERE, + chatReport, + iouReport, + introSelected: undefined, + iouReportCurrentNextStepDeprecated: undefined, + currentUserAccountID: CARLOS_ACCOUNT_ID, + betas: [CONST.BETAS.ALL], + isSelfTourViewed: false, + userBillingGracePeriodEnds: undefined, + amountOwed: 100, + ownerBillingGracePeriodEnd: pastDate, + policy: expensePolicy, + chatReportPolicy: workspacePolicy, + }); + + await waitForBatchedUpdates(); + + expect(Navigation.navigate).toHaveBeenCalledWith(ROUTES.RESTRICTED_ACTION.getRoute(workspacePolicyID)); + }); + + it('should not navigate to restricted when chatReportPolicy passes billing check with future owner grace period', async () => { + const policyID = generatePolicyID(); + + await Onyx.set(ONYXKEYS.SESSION, {email: CARLOS_EMAIL, accountID: CARLOS_ACCOUNT_ID}); + const workspacePolicy = { + ...createRandomPolicy(9003), + id: policyID, + ownerAccountID: CARLOS_ACCOUNT_ID, + role: CONST.POLICY.ROLE.ADMIN, + }; + await Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, workspacePolicy); + + const futureGraceEnd = Math.floor(Date.now() / 1000) + 86400 * 30; + await Onyx.set(ONYXKEYS.NVP_PRIVATE_OWNER_BILLING_GRACE_PERIOD_END, futureGraceEnd); + await Onyx.set(ONYXKEYS.NVP_PRIVATE_AMOUNT_OWED, 100); + + const chatReport = { + ...createRandomReport(0, undefined), + policyID, + type: CONST.REPORT.TYPE.CHAT, + chatType: CONST.REPORT.CHAT_TYPE.POLICY_EXPENSE_CHAT, + }; + const iouReport = { + ...createRandomReport(1, undefined), + type: CONST.REPORT.TYPE.IOU, + total: 10, + policyID, + }; + + await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${chatReport.reportID}`, chatReport); + await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${iouReport.reportID}`, iouReport); + + (Navigation.navigate as jest.Mock).mockClear(); + + payMoneyRequest({ + paymentType: CONST.IOU.PAYMENT_TYPE.ELSEWHERE, + chatReport, + iouReport, + introSelected: undefined, + iouReportCurrentNextStepDeprecated: undefined, + currentUserAccountID: CARLOS_ACCOUNT_ID, + betas: [CONST.BETAS.ALL], + isSelfTourViewed: false, + userBillingGracePeriodEnds: undefined, + amountOwed: 100, + ownerBillingGracePeriodEnd: futureGraceEnd, + chatReportPolicy: workspacePolicy, + policy: workspacePolicy, + }); + + await waitForBatchedUpdates(); + + expect(Navigation.navigate).not.toHaveBeenCalledWith(ROUTES.RESTRICTED_ACTION.getRoute(policyID)); + }); + it('should pay successfully when amountOwed is 0', async () => { const chatReport = { ...createRandomReport(0, undefined), @@ -1047,6 +1189,7 @@ describe('actions/IOU/PayMoneyRequest', () => { mockFetch?.pause?.(); jest.advanceTimersByTime(10); + const chatReportPolicyAmountZero = chatReportPolicyFromChat(chatReport); payMoneyRequest({ paymentType: CONST.IOU.PAYMENT_TYPE.ELSEWHERE, chatReport, @@ -1058,6 +1201,7 @@ describe('actions/IOU/PayMoneyRequest', () => { isSelfTourViewed: false, userBillingGracePeriodEnds: undefined, amountOwed: 0, + chatReportPolicy: chatReportPolicyAmountZero, }); await waitForBatchedUpdates(); @@ -1165,20 +1309,22 @@ describe('actions/IOU/PayMoneyRequest', () => { ) .then(() => { // When the expense report is paid elsewhere (but really, any payment option would work) - if (chatReport && expenseReport) { - payMoneyRequest({ - paymentType: CONST.IOU.PAYMENT_TYPE.ELSEWHERE, - chatReport, - iouReport: expenseReport, - introSelected: undefined, - iouReportCurrentNextStepDeprecated: undefined, - currentUserAccountID: CARLOS_ACCOUNT_ID, - betas: [CONST.BETAS.ALL], - isSelfTourViewed: false, - userBillingGracePeriodEnds: undefined, - amountOwed: 0, - }); + if (!chatReport || !expenseReport) { + return waitForBatchedUpdates(); } + payMoneyRequest({ + paymentType: CONST.IOU.PAYMENT_TYPE.ELSEWHERE, + chatReport, + iouReport: expenseReport, + introSelected: undefined, + iouReportCurrentNextStepDeprecated: undefined, + currentUserAccountID: CARLOS_ACCOUNT_ID, + betas: [CONST.BETAS.ALL], + isSelfTourViewed: false, + userBillingGracePeriodEnds: undefined, + amountOwed: 0, + chatReportPolicy: chatReportPolicyFromChat(chatReport), + }); return waitForBatchedUpdates(); }) .then(() => { @@ -1400,6 +1546,7 @@ describe('actions/IOU/PayMoneyRequest', () => { isSelfTourViewed: false, userBillingGracePeriodEnds: undefined, amountOwed: 0, + chatReportPolicy: chatReportPolicyFromChat(chatReport), }); } await waitForBatchedUpdates(); From cf97312779ac6ecf67278ba72e174392fd6187e7 Mon Sep 17 00:00:00 2001 From: truph01 Date: Wed, 29 Apr 2026 00:15:41 +0700 Subject: [PATCH 2/3] fix: conflicts --- Mobile-Expensify | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mobile-Expensify b/Mobile-Expensify index 7639cf734a06..becf1561d1f2 160000 --- a/Mobile-Expensify +++ b/Mobile-Expensify @@ -1 +1 @@ -Subproject commit 7639cf734a06b7e3f1a0a0fcd3179c851fc34e69 +Subproject commit becf1561d1f25f92bc08456841885116bfa1041f From 18b9b5b7b1b4cbb076b9df91bac103949897aa08 Mon Sep 17 00:00:00 2001 From: truph01 Date: Fri, 1 May 2026 22:46:02 +0700 Subject: [PATCH 3/3] fix: conflicts --- Mobile-Expensify | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mobile-Expensify b/Mobile-Expensify index becf1561d1f2..d62f51382590 160000 --- a/Mobile-Expensify +++ b/Mobile-Expensify @@ -1 +1 @@ -Subproject commit becf1561d1f25f92bc08456841885116bfa1041f +Subproject commit d62f5138259092bd8838fbc8eadff12372768fe4