From 655a84213266c1155089a91c230e2dbd1ececcab Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Fri, 27 Feb 2026 15:07:37 +0700 Subject: [PATCH 1/4] fix: Submitted/approved/paid animation runs even when actions are restricted --- src/components/MoneyReportHeader.tsx | 32 +++++++------- src/components/ProcessMoneyReportHoldMenu.tsx | 34 +++++++------- .../MoneyRequestReportPreviewContent.tsx | 44 ++++++++++++------- src/libs/actions/IOU/index.ts | 7 ++- 4 files changed, 66 insertions(+), 51 deletions(-) diff --git a/src/components/MoneyReportHeader.tsx b/src/components/MoneyReportHeader.tsx index 8d3e09ee6b699..fff71af9128ed 100644 --- a/src/components/MoneyReportHeader.tsx +++ b/src/components/MoneyReportHeader.tsx @@ -613,18 +613,20 @@ function MoneyReportHeader({ betas, }); } else { - startAnimation(); - payMoneyRequest({ - paymentType: type, - chatReport, - iouReport: moneyRequestReport, - introSelected, - iouReportCurrentNextStepDeprecated: nextStep, - currentUserAccountID: accountID, - activePolicy, - policy, - betas, - }); + payMoneyRequest( + { + paymentType: type, + chatReport, + iouReport: moneyRequestReport, + introSelected, + iouReportCurrentNextStepDeprecated: nextStep, + currentUserAccountID: accountID, + activePolicy, + policy, + betas, + }, + startAnimation, + ); if (currentSearchQueryJSON && !isOffline) { search({ searchKey: currentSearchKey, @@ -685,8 +687,7 @@ function MoneyReportHeader({ } else if (isAnyTransactionOnHold) { setIsHoldMenuVisible(true); } else { - startApprovedAnimation(); - approveMoneyRequest(moneyRequestReport, policy, accountID, email ?? '', hasViolations, isASAPSubmitBetaEnabled, nextStep, betas, true); + approveMoneyRequest(moneyRequestReport, policy, accountID, email ?? '', hasViolations, isASAPSubmitBetaEnabled, nextStep, betas, true, startApprovedAnimation); } }; @@ -1050,8 +1051,7 @@ function MoneyReportHeader({ showDWEModal(); return; } - startSubmittingAnimation(); - submitReport(moneyRequestReport, policy, accountID, email ?? '', hasViolations, isASAPSubmitBetaEnabled, nextStep); + submitReport(moneyRequestReport, policy, accountID, email ?? '', hasViolations, isASAPSubmitBetaEnabled, nextStep, startSubmittingAnimation); if (currentSearchQueryJSON && !isOffline) { search({ searchKey: currentSearchKey, diff --git a/src/components/ProcessMoneyReportHoldMenu.tsx b/src/components/ProcessMoneyReportHoldMenu.tsx index c0f213484fde8..8160dd332bf21 100644 --- a/src/components/ProcessMoneyReportHoldMenu.tsx +++ b/src/components/ProcessMoneyReportHoldMenu.tsx @@ -92,9 +92,6 @@ function ProcessMoneyReportHoldMenu({ } if (isApprove) { - if (startAnimation) { - startAnimation(); - } approveMoneyRequest( moneyRequestReport, activePolicy, @@ -105,23 +102,24 @@ function ProcessMoneyReportHoldMenu({ moneyRequestReportNextStep, betas, full, + startAnimation, ); } else if (chatReport && paymentType) { - if (startAnimation) { - startAnimation(); - } - payMoneyRequest({ - paymentType, - chatReport, - iouReport: moneyRequestReport, - introSelected, - iouReportCurrentNextStepDeprecated: moneyRequestReportNextStep, - currentUserAccountID: currentUserDetails.accountID, - full, - activePolicy, - policy, - betas, - }); + payMoneyRequest( + { + paymentType, + chatReport, + iouReport: moneyRequestReport, + introSelected, + iouReportCurrentNextStepDeprecated: moneyRequestReportNextStep, + currentUserAccountID: currentUserDetails.accountID, + full, + activePolicy, + policy, + betas, + }, + startAnimation, + ); } onClose(); }; diff --git a/src/components/ReportActionItem/MoneyRequestReportPreview/MoneyRequestReportPreviewContent.tsx b/src/components/ReportActionItem/MoneyRequestReportPreview/MoneyRequestReportPreviewContent.tsx index de29513e46706..afa805ef9ac8b 100644 --- a/src/components/ReportActionItem/MoneyRequestReportPreview/MoneyRequestReportPreviewContent.tsx +++ b/src/components/ReportActionItem/MoneyRequestReportPreview/MoneyRequestReportPreviewContent.tsx @@ -259,8 +259,8 @@ function MoneyRequestReportPreviewContent({ } else if (hasHeldExpensesReportUtils(iouReport?.reportID)) { setIsHoldMenuVisible(true); } else if (chatReport && iouReport) { - startAnimation(); if (isInvoiceReportUtils(iouReport)) { + startAnimation(); payInvoice({ paymentMethodType: type, chatReport, @@ -277,17 +277,20 @@ function MoneyRequestReportPreviewContent({ betas, }); } else { - payMoneyRequest({ - paymentType: type, - chatReport, - iouReport, - introSelected, - iouReportCurrentNextStepDeprecated: iouReportNextStep, - currentUserAccountID, - activePolicy, - policy, - betas, - }); + payMoneyRequest( + { + paymentType: type, + chatReport, + iouReport, + introSelected, + iouReportCurrentNextStepDeprecated: iouReportNextStep, + currentUserAccountID, + activePolicy, + policy, + betas, + }, + startAnimation, + ); } } }, @@ -333,8 +336,18 @@ function MoneyRequestReportPreviewContent({ } else if (hasHeldExpensesReportUtils(iouReport?.reportID)) { setIsHoldMenuVisible(true); } else { - startApprovedAnimation(); - approveMoneyRequest(iouReport, activePolicy, currentUserAccountID, currentUserEmail, hasViolations, isASAPSubmitBetaEnabled, iouReportNextStep, betas, true); + approveMoneyRequest( + iouReport, + activePolicy, + currentUserAccountID, + currentUserEmail, + hasViolations, + isASAPSubmitBetaEnabled, + iouReportNextStep, + betas, + true, + startApprovedAnimation, + ); } }; @@ -661,8 +674,7 @@ function MoneyRequestReportPreviewContent({ showDEWModal(); return; } - startSubmittingAnimation(); - submitReport(iouReport, policy, currentUserAccountID, currentUserEmail, hasViolations, isASAPSubmitBetaEnabled, iouReportNextStep); + submitReport(iouReport, policy, currentUserAccountID, currentUserEmail, hasViolations, isASAPSubmitBetaEnabled, iouReportNextStep, startSubmittingAnimation); }} isSubmittingAnimationRunning={isSubmittingAnimationRunning} onAnimationFinish={stopAnimation} diff --git a/src/libs/actions/IOU/index.ts b/src/libs/actions/IOU/index.ts index a0bfbacf8126b..da0f55fc5ae5b 100644 --- a/src/libs/actions/IOU/index.ts +++ b/src/libs/actions/IOU/index.ts @@ -10571,6 +10571,7 @@ function approveMoneyRequest( expenseReportCurrentNextStepDeprecated: OnyxEntry, betas: OnyxEntry, full?: boolean, + onApproved?: () => void, ) { if (!expenseReport) { return; @@ -10909,6 +10910,7 @@ function approveMoneyRequest( optimisticCreatedReportForUnapprovedTransactionsActionID, }; + onApproved?.(); playSound(SOUNDS.SUCCESS); API.write(WRITE_COMMANDS.APPROVE_MONEY_REQUEST, parameters, {optimisticData, successData, failureData}); return optimisticHoldReportID; @@ -11452,6 +11454,7 @@ function submitReport( hasViolations: boolean, isASAPSubmitBetaEnabled: boolean, expenseReportCurrentNextStepDeprecated: OnyxEntry, + onSubmitted?: () => void, ) { if (!expenseReport) { return; @@ -11714,6 +11717,7 @@ function submitReport( }; API.write(WRITE_COMMANDS.SUBMIT_REPORT, parameters, {optimisticData, successData, failureData}); + onSubmitted?.(); } function cancelPayment( @@ -11969,7 +11973,7 @@ function completePaymentOnboarding( }); } -function payMoneyRequest(params: PayMoneyRequestFunctionParams) { +function payMoneyRequest(params: PayMoneyRequestFunctionParams, onPaid?: () => void) { const {paymentType, chatReport, iouReport, introSelected, iouReportCurrentNextStepDeprecated, currentUserAccountID, paymentPolicyID, full = true, activePolicy, policy, betas} = params; if (chatReport.policyID && shouldRestrictUserBillableActions(chatReport.policyID)) { Navigation.navigate(ROUTES.RESTRICTED_ACTION.getRoute(chatReport.policyID)); @@ -11998,6 +12002,7 @@ function payMoneyRequest(params: PayMoneyRequestFunctionParams) { // Expensify Wallets. const apiCommand = paymentType === CONST.IOU.PAYMENT_TYPE.EXPENSIFY ? WRITE_COMMANDS.PAY_MONEY_REQUEST_WITH_WALLET : WRITE_COMMANDS.PAY_MONEY_REQUEST; + onPaid?.(); playSound(SOUNDS.SUCCESS); API.write(apiCommand, payMoneyRequestParams, onyxData); notifyNewAction(!full ? (Navigation.getTopmostReportId() ?? iouReport?.reportID) : iouReport?.reportID, undefined, true); From 44814cd28ff86a4ea26638c5461b686732f111dd Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Thu, 5 Mar 2026 12:35:11 +0700 Subject: [PATCH 2/4] update perf suggestion --- src/libs/actions/IOU/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/actions/IOU/index.ts b/src/libs/actions/IOU/index.ts index fc8e669f85b3d..a03422c0d1bc3 100644 --- a/src/libs/actions/IOU/index.ts +++ b/src/libs/actions/IOU/index.ts @@ -11704,8 +11704,8 @@ function submitReport( reportActionID: optimisticSubmittedReportAction.reportActionID, }; - API.write(WRITE_COMMANDS.SUBMIT_REPORT, parameters, {optimisticData, successData, failureData}); onSubmitted?.(); + API.write(WRITE_COMMANDS.SUBMIT_REPORT, parameters, {optimisticData, successData, failureData}); } function cancelPayment( From a53b4c25cddd6645b345622def30b2297ee75eb4 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Thu, 5 Mar 2026 12:58:46 +0700 Subject: [PATCH 3/4] change approveMoneyRequest to object param --- src/components/MoneyReportHeader.tsx | 22 +++-- src/components/ProcessMoneyReportHoldMenu.tsx | 22 +++-- .../MoneyRequestReportPreviewContent.tsx | 22 +++-- src/components/SettlementButton/index.tsx | 13 ++- src/libs/PaymentUtils.ts | 13 ++- src/libs/actions/IOU/index.ts | 48 ++++++--- tests/actions/IOUTest.ts | 97 +++++++++++++++++-- 7 files changed, 183 insertions(+), 54 deletions(-) diff --git a/src/components/MoneyReportHeader.tsx b/src/components/MoneyReportHeader.tsx index 656a12180e7e6..dd5811d55e225 100644 --- a/src/components/MoneyReportHeader.tsx +++ b/src/components/MoneyReportHeader.tsx @@ -708,16 +708,18 @@ function MoneyReportHeader({ setIsHoldMenuVisible(true); } else { approveMoneyRequest( - moneyRequestReport, - policy, - accountID, - email ?? '', - hasViolations, - isASAPSubmitBetaEnabled, - nextStep, - betas, - userBillingGraceEndPeriods, - true, + { + expenseReport: moneyRequestReport, + policy, + currentUserAccountIDParam: accountID, + currentUserEmailParam: email ?? '', + hasViolations, + isASAPSubmitBetaEnabled, + expenseReportCurrentNextStepDeprecated: nextStep, + betas, + userBillingGraceEndPeriods, + full: true, + }, startApprovedAnimation, ); } diff --git a/src/components/ProcessMoneyReportHoldMenu.tsx b/src/components/ProcessMoneyReportHoldMenu.tsx index 562672821c2bf..39ae3cfd96b4c 100644 --- a/src/components/ProcessMoneyReportHoldMenu.tsx +++ b/src/components/ProcessMoneyReportHoldMenu.tsx @@ -94,16 +94,18 @@ function ProcessMoneyReportHoldMenu({ if (isApprove) { approveMoneyRequest( - moneyRequestReport, - activePolicy, - currentUserDetails.accountID, - currentUserDetails.email ?? '', - hasViolations, - isASAPSubmitBetaEnabled, - moneyRequestReportNextStep, - betas, - userBillingGraceEndPeriods, - full, + { + expenseReport: moneyRequestReport, + policy: activePolicy, + currentUserAccountIDParam: currentUserDetails.accountID, + currentUserEmailParam: currentUserDetails.email ?? '', + hasViolations, + isASAPSubmitBetaEnabled, + expenseReportCurrentNextStepDeprecated: moneyRequestReportNextStep, + betas, + userBillingGraceEndPeriods, + full, + }, startAnimation, ); } else if (chatReport && paymentType) { diff --git a/src/components/ReportActionItem/MoneyRequestReportPreview/MoneyRequestReportPreviewContent.tsx b/src/components/ReportActionItem/MoneyRequestReportPreview/MoneyRequestReportPreviewContent.tsx index 82f639200c2ff..9d56e39b89e44 100644 --- a/src/components/ReportActionItem/MoneyRequestReportPreview/MoneyRequestReportPreviewContent.tsx +++ b/src/components/ReportActionItem/MoneyRequestReportPreview/MoneyRequestReportPreviewContent.tsx @@ -353,16 +353,18 @@ function MoneyRequestReportPreviewContent({ setIsHoldMenuVisible(true); } else { approveMoneyRequest( - iouReport, - activePolicy, - currentUserAccountID, - currentUserEmail, - hasViolations, - isASAPSubmitBetaEnabled, - iouReportNextStep, - betas, - userBillingGraceEndPeriods, - true, + { + expenseReport: iouReport, + policy: activePolicy, + currentUserAccountIDParam: currentUserAccountID, + currentUserEmailParam: currentUserEmail, + hasViolations, + isASAPSubmitBetaEnabled, + expenseReportCurrentNextStepDeprecated: iouReportNextStep, + betas, + userBillingGraceEndPeriods, + full: true, + }, startApprovedAnimation, ); } diff --git a/src/components/SettlementButton/index.tsx b/src/components/SettlementButton/index.tsx index 0c1cefb55061e..5ffb98b0759c1 100644 --- a/src/components/SettlementButton/index.tsx +++ b/src/components/SettlementButton/index.tsx @@ -426,7 +426,18 @@ function SettlementButton({ if (confirmApproval) { confirmApproval(); } else { - approveMoneyRequest(iouReport, policy, accountID, email ?? '', hasViolations, isASAPSubmitBetaEnabled, iouReportNextStep, betas, userBillingGraceEndPeriods, false); + approveMoneyRequest({ + expenseReport: iouReport, + policy, + currentUserAccountIDParam: accountID, + currentUserEmailParam: email ?? '', + hasViolations, + isASAPSubmitBetaEnabled, + expenseReportCurrentNextStepDeprecated: iouReportNextStep, + betas, + userBillingGraceEndPeriods, + full: false, + }); } return; } diff --git a/src/libs/PaymentUtils.ts b/src/libs/PaymentUtils.ts index f5c747060373e..45d03c1446f24 100644 --- a/src/libs/PaymentUtils.ts +++ b/src/libs/PaymentUtils.ts @@ -200,7 +200,18 @@ const selectPaymentType = (params: SelectPaymentTypeParams) => { if (confirmApproval) { confirmApproval(); } else { - approveMoneyRequest(iouReport, policy, currentAccountID, currentEmail, hasViolations, isASAPSubmitBetaEnabled, iouReportNextStep, betas, userBillingGraceEndPeriods, true); + approveMoneyRequest({ + expenseReport: iouReport, + policy, + currentUserAccountIDParam: currentAccountID, + currentUserEmailParam: currentEmail, + hasViolations, + isASAPSubmitBetaEnabled, + expenseReportCurrentNextStepDeprecated: iouReportNextStep, + betas, + userBillingGraceEndPeriods, + full: true, + }); } return; } diff --git a/src/libs/actions/IOU/index.ts b/src/libs/actions/IOU/index.ts index a03422c0d1bc3..b790f2b4516b2 100644 --- a/src/libs/actions/IOU/index.ts +++ b/src/libs/actions/IOU/index.ts @@ -906,6 +906,19 @@ type PayMoneyRequestFunctionParams = { betas: OnyxEntry; }; +type ApproveMoneyRequestFunctionParams = { + expenseReport: OnyxEntry; + policy: OnyxEntry; + currentUserAccountIDParam: number; + currentUserEmailParam: string; + hasViolations: boolean; + isASAPSubmitBetaEnabled: boolean; + expenseReportCurrentNextStepDeprecated: OnyxEntry; + betas: OnyxEntry; + userBillingGraceEndPeriods: OnyxCollection; + full?: boolean; +}; + let allTransactions: NonNullable> = {}; Onyx.connect({ key: ONYXKEYS.COLLECTION.TRANSACTION, @@ -10551,19 +10564,19 @@ function getReportOriginalCreationTimestamp(expenseReport?: OnyxEntry, - policy: OnyxEntry, - currentUserAccountIDParam: number, - currentUserEmailParam: string, - hasViolations: boolean, - isASAPSubmitBetaEnabled: boolean, - expenseReportCurrentNextStepDeprecated: OnyxEntry, - betas: OnyxEntry, - userBillingGraceEndPeriods: OnyxCollection, - full?: boolean, - onApproved?: () => void, -) { +function approveMoneyRequest(params: ApproveMoneyRequestFunctionParams, onApproved?: () => void) { + const { + expenseReport, + policy, + currentUserAccountIDParam, + currentUserEmailParam, + hasViolations, + isASAPSubmitBetaEnabled, + expenseReportCurrentNextStepDeprecated, + betas, + userBillingGraceEndPeriods, + full, + } = params; if (!expenseReport) { return; } @@ -10673,7 +10686,14 @@ function approveMoneyRequest( onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT}${expenseReport.chatReportID}`, value: { - hasOutstandingChildRequest: hasOutstandingChildRequest(chatReport, updatedExpenseReport, currentUserEmail, currentUserAccountIDParam, allTransactionViolations, undefined), + hasOutstandingChildRequest: hasOutstandingChildRequest( + chatReport, + updatedExpenseReport, + currentUserEmailParam, + currentUserAccountIDParam, + allTransactionViolations, + undefined, + ), }, }); } diff --git a/tests/actions/IOUTest.ts b/tests/actions/IOUTest.ts index 8a2f5c8a29a43..505d0eccc3aa6 100644 --- a/tests/actions/IOUTest.ts +++ b/tests/actions/IOUTest.ts @@ -13474,7 +13474,17 @@ describe('actions/IOU', () => { }); // Admin approves the report - approveMoneyRequest(expenseReport, policy, adminAccountID, adminEmail, false, false, undefined, [CONST.BETAS.ALL], undefined); + approveMoneyRequest({ + expenseReport, + policy, + currentUserAccountIDParam: adminAccountID, + currentUserEmailParam: adminEmail, + hasViolations: false, + isASAPSubmitBetaEnabled: false, + expenseReportCurrentNextStepDeprecated: undefined, + betas: [CONST.BETAS.ALL], + userBillingGraceEndPeriods: undefined, + }); await waitForBatchedUpdates(); // Should be approved since admin took control and is the last approver @@ -13512,7 +13522,17 @@ describe('actions/IOU', () => { }); // Manager approves the report - approveMoneyRequest(expenseReport, policy, managerAccountID, managerEmail, false, false, undefined, [CONST.BETAS.ALL], undefined); + approveMoneyRequest({ + expenseReport, + policy, + currentUserAccountIDParam: managerAccountID, + currentUserEmailParam: managerEmail, + hasViolations: false, + isASAPSubmitBetaEnabled: false, + expenseReportCurrentNextStepDeprecated: undefined, + betas: [CONST.BETAS.ALL], + userBillingGraceEndPeriods: undefined, + }); await waitForBatchedUpdates(); // Should be submitted to senior manager (normal flow) since take control was invalidated @@ -13546,7 +13566,17 @@ describe('actions/IOU', () => { }); // Admin approves the report - approveMoneyRequest(expenseReport, policy, adminAccountID, adminEmail, false, false, undefined, [CONST.BETAS.ALL], undefined); + approveMoneyRequest({ + expenseReport, + policy, + currentUserAccountIDParam: adminAccountID, + currentUserEmailParam: adminEmail, + hasViolations: false, + isASAPSubmitBetaEnabled: false, + expenseReportCurrentNextStepDeprecated: undefined, + betas: [CONST.BETAS.ALL], + userBillingGraceEndPeriods: undefined, + }); await waitForBatchedUpdates(); // Get the optimistic next step @@ -13656,7 +13686,17 @@ describe('actions/IOU', () => { }); // Manager approves the report (no take control actions) - approveMoneyRequest(expenseReport, policy, managerAccountID, managerEmail, false, false, undefined, [CONST.BETAS.ALL], undefined); + approveMoneyRequest({ + expenseReport, + policy, + currentUserAccountIDParam: managerAccountID, + currentUserEmailParam: managerEmail, + hasViolations: false, + isASAPSubmitBetaEnabled: false, + expenseReportCurrentNextStepDeprecated: undefined, + betas: [CONST.BETAS.ALL], + userBillingGraceEndPeriods: undefined, + }); await waitForBatchedUpdates(); // Should be submitted to admin (next in approval chain) since manager is not the final approver @@ -13673,7 +13713,17 @@ describe('actions/IOU', () => { accountID: managerAccountID, }); - approveMoneyRequest(expenseReport, policy, managerAccountID, managerEmail, false, false, undefined, [CONST.BETAS.ALL], undefined); + approveMoneyRequest({ + expenseReport, + policy, + currentUserAccountIDParam: managerAccountID, + currentUserEmailParam: managerEmail, + hasViolations: false, + isASAPSubmitBetaEnabled: false, + expenseReportCurrentNextStepDeprecated: undefined, + betas: [CONST.BETAS.ALL], + userBillingGraceEndPeriods: undefined, + }); await waitForBatchedUpdates(); // Should be submitted to admin @@ -13688,7 +13738,17 @@ describe('actions/IOU', () => { accountID: adminAccountID, }); - approveMoneyRequest(updatedReport, policy, adminAccountID, adminEmail, false, false, undefined, [CONST.BETAS.ALL], undefined); + approveMoneyRequest({ + expenseReport: updatedReport, + policy, + currentUserAccountIDParam: adminAccountID, + currentUserEmailParam: adminEmail, + hasViolations: false, + isASAPSubmitBetaEnabled: false, + expenseReportCurrentNextStepDeprecated: undefined, + betas: [CONST.BETAS.ALL], + userBillingGraceEndPeriods: undefined, + }); await waitForBatchedUpdates(); // Should be fully approved @@ -13733,7 +13793,17 @@ describe('actions/IOU', () => { }); // Manager approves the report - approveMoneyRequest(singleApproverReport, singleApproverPolicy, managerAccountID, managerEmail, false, false, undefined, [CONST.BETAS.ALL], undefined); + approveMoneyRequest({ + expenseReport: singleApproverReport, + policy: singleApproverPolicy, + currentUserAccountIDParam: managerAccountID, + currentUserEmailParam: managerEmail, + hasViolations: false, + isASAPSubmitBetaEnabled: false, + expenseReportCurrentNextStepDeprecated: undefined, + betas: [CONST.BETAS.ALL], + userBillingGraceEndPeriods: undefined, + }); await waitForBatchedUpdates(); // Should be fully approved since manager is the final approver in the chain @@ -13834,7 +13904,18 @@ describe('actions/IOU', () => { accountID: adminAccountID, }); - const newExpenseReportID = approveMoneyRequest(expenseReport, policy, adminAccountID, adminEmail, false, false, undefined, [CONST.BETAS.ALL], undefined, false); + const newExpenseReportID = approveMoneyRequest({ + expenseReport, + policy, + currentUserAccountIDParam: adminAccountID, + currentUserEmailParam: adminEmail, + hasViolations: false, + isASAPSubmitBetaEnabled: false, + expenseReportCurrentNextStepDeprecated: undefined, + betas: [CONST.BETAS.ALL], + userBillingGraceEndPeriods: undefined, + full: false, + }); await waitForBatchedUpdates(); const newExpenseReport = await getOnyxValue(`${ONYXKEYS.COLLECTION.REPORT}${newExpenseReportID}`); From a95b8d2e747c83c56e7c2d7d7e9b5f1048624404 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Fri, 13 Mar 2026 13:47:07 +0700 Subject: [PATCH 4/4] update submitReport function to object parameter --- src/components/MoneyReportHeader.tsx | 88 ++++++++++--------- src/components/ProcessMoneyReportHoldMenu.tsx | 64 +++++++------- .../MoneyRequestReportPreviewContent.tsx | 76 ++++++++-------- src/libs/actions/IOU/index.ts | 45 +++++++--- tests/actions/IOUTest.ts | 72 +++++++++++++-- 5 files changed, 210 insertions(+), 135 deletions(-) diff --git a/src/components/MoneyReportHeader.tsx b/src/components/MoneyReportHeader.tsx index ea9f4baa964af..455aa64a0d5be 100644 --- a/src/components/MoneyReportHeader.tsx +++ b/src/components/MoneyReportHeader.tsx @@ -665,23 +665,21 @@ function MoneyReportHeader({ isSelfTourViewed, }); } else { - payMoneyRequest( - { - paymentType: type, - chatReport, - iouReport: moneyRequestReport, - introSelected, - iouReportCurrentNextStepDeprecated: nextStep, - currentUserAccountID: accountID, - activePolicy, - policy, - betas, - isSelfTourViewed, - userBillingGraceEndPeriods, - amountOwed, - }, - startAnimation, - ); + payMoneyRequest({ + paymentType: type, + chatReport, + iouReport: moneyRequestReport, + introSelected, + iouReportCurrentNextStepDeprecated: nextStep, + currentUserAccountID: accountID, + activePolicy, + policy, + betas, + isSelfTourViewed, + userBillingGraceEndPeriods, + amountOwed, + onPaid: startAnimation, + }); if (currentSearchQueryJSON && !isOffline) { search({ searchKey: currentSearchKey, @@ -745,22 +743,20 @@ function MoneyReportHeader({ } else if (isAnyTransactionOnHold) { setIsHoldMenuVisible(true); } else { - approveMoneyRequest( - { - expenseReport: moneyRequestReport, - policy, - currentUserAccountIDParam: accountID, - currentUserEmailParam: email ?? '', - hasViolations, - isASAPSubmitBetaEnabled, - expenseReportCurrentNextStepDeprecated: nextStep, - betas, - userBillingGraceEndPeriods, - amountOwed, - full: true, - }, - startApprovedAnimation, - ); + approveMoneyRequest({ + expenseReport: moneyRequestReport, + policy, + currentUserAccountIDParam: accountID, + currentUserEmailParam: email ?? '', + hasViolations, + isASAPSubmitBetaEnabled, + expenseReportCurrentNextStepDeprecated: nextStep, + betas, + userBillingGraceEndPeriods, + amountOwed, + full: true, + onApproved: startApprovedAnimation, + }); } }; @@ -1172,18 +1168,18 @@ function MoneyReportHeader({ showDWEModal(); return; } - submitReport( - moneyRequestReport, + submitReport({ + expenseReport: moneyRequestReport, policy, - accountID, - email ?? '', + currentUserAccountIDParam: accountID, + currentUserEmailParam: email ?? '', hasViolations, isASAPSubmitBetaEnabled, - nextStep, + expenseReportCurrentNextStepDeprecated: nextStep, userBillingGraceEndPeriods, amountOwed, - startSubmittingAnimation, - ); + onSubmitted: startSubmittingAnimation, + }); if (currentSearchQueryJSON && !isOffline) { search({ searchKey: currentSearchKey, @@ -1459,7 +1455,17 @@ function MoneyReportHeader({ showDWEModal(); return; } - submitReport(moneyRequestReport, policy, accountID, email ?? '', hasViolations, isASAPSubmitBetaEnabled, nextStep, userBillingGraceEndPeriods, amountOwed); + submitReport({ + expenseReport: moneyRequestReport, + policy, + currentUserAccountIDParam: accountID, + currentUserEmailParam: email ?? '', + hasViolations, + isASAPSubmitBetaEnabled, + expenseReportCurrentNextStepDeprecated: nextStep, + userBillingGraceEndPeriods, + amountOwed, + }); }, }, [CONST.REPORT.SECONDARY_ACTIONS.APPROVE]: { diff --git a/src/components/ProcessMoneyReportHoldMenu.tsx b/src/components/ProcessMoneyReportHoldMenu.tsx index e76c0aae26efd..e191b59d4c8e8 100644 --- a/src/components/ProcessMoneyReportHoldMenu.tsx +++ b/src/components/ProcessMoneyReportHoldMenu.tsx @@ -96,41 +96,37 @@ function ProcessMoneyReportHoldMenu({ } if (isApprove) { - approveMoneyRequest( - { - expenseReport: moneyRequestReport, - policy: activePolicy, - currentUserAccountIDParam: currentUserDetails.accountID, - currentUserEmailParam: currentUserDetails.email ?? '', - hasViolations, - isASAPSubmitBetaEnabled, - expenseReportCurrentNextStepDeprecated: moneyRequestReportNextStep, - betas, - userBillingGraceEndPeriods, - amountOwed, - full, - }, - startAnimation, - ); + approveMoneyRequest({ + expenseReport: moneyRequestReport, + policy: activePolicy, + currentUserAccountIDParam: currentUserDetails.accountID, + currentUserEmailParam: currentUserDetails.email ?? '', + hasViolations, + isASAPSubmitBetaEnabled, + expenseReportCurrentNextStepDeprecated: moneyRequestReportNextStep, + betas, + userBillingGraceEndPeriods, + amountOwed, + full, + onApproved: startAnimation, + }); } else if (chatReport && paymentType) { - payMoneyRequest( - { - paymentType, - chatReport, - iouReport: moneyRequestReport, - introSelected, - iouReportCurrentNextStepDeprecated: moneyRequestReportNextStep, - currentUserAccountID: currentUserDetails.accountID, - full, - activePolicy, - policy, - betas, - isSelfTourViewed, - userBillingGraceEndPeriods, - amountOwed, - }, - startAnimation, - ); + payMoneyRequest({ + paymentType, + chatReport, + iouReport: moneyRequestReport, + introSelected, + iouReportCurrentNextStepDeprecated: moneyRequestReportNextStep, + currentUserAccountID: currentUserDetails.accountID, + full, + activePolicy, + policy, + betas, + isSelfTourViewed, + userBillingGraceEndPeriods, + amountOwed, + onPaid: startAnimation, + }); } onClose(); }; diff --git a/src/components/ReportActionItem/MoneyRequestReportPreview/MoneyRequestReportPreviewContent.tsx b/src/components/ReportActionItem/MoneyRequestReportPreview/MoneyRequestReportPreviewContent.tsx index 70b93cac27d21..827c41bc68420 100644 --- a/src/components/ReportActionItem/MoneyRequestReportPreview/MoneyRequestReportPreviewContent.tsx +++ b/src/components/ReportActionItem/MoneyRequestReportPreview/MoneyRequestReportPreviewContent.tsx @@ -298,23 +298,21 @@ function MoneyRequestReportPreviewContent({ isSelfTourViewed, }); } else { - payMoneyRequest( - { - paymentType: type, - chatReport, - iouReport, - introSelected, - iouReportCurrentNextStepDeprecated: iouReportNextStep, - currentUserAccountID, - activePolicy, - policy, - betas, - isSelfTourViewed, - userBillingGraceEndPeriods, - amountOwed, - }, - startAnimation, - ); + payMoneyRequest({ + paymentType: type, + chatReport, + iouReport, + introSelected, + iouReportCurrentNextStepDeprecated: iouReportNextStep, + currentUserAccountID, + activePolicy, + policy, + betas, + isSelfTourViewed, + userBillingGraceEndPeriods, + amountOwed, + onPaid: startAnimation, + }); } } }, @@ -363,22 +361,20 @@ function MoneyRequestReportPreviewContent({ } else if (hasHeldExpensesReportUtils(iouReport?.reportID)) { setIsHoldMenuVisible(true); } else { - approveMoneyRequest( - { - expenseReport: iouReport, - policy: activePolicy, - currentUserAccountIDParam: currentUserAccountID, - currentUserEmailParam: currentUserEmail, - hasViolations, - isASAPSubmitBetaEnabled, - expenseReportCurrentNextStepDeprecated: iouReportNextStep, - betas, - userBillingGraceEndPeriods, - amountOwed, - full: true, - }, - startApprovedAnimation, - ); + approveMoneyRequest({ + expenseReport: iouReport, + policy: activePolicy, + currentUserAccountIDParam: currentUserAccountID, + currentUserEmailParam: currentUserEmail, + hasViolations, + isASAPSubmitBetaEnabled, + expenseReportCurrentNextStepDeprecated: iouReportNextStep, + betas, + userBillingGraceEndPeriods, + amountOwed, + full: true, + onApproved: startApprovedAnimation, + }); } }; @@ -758,18 +754,18 @@ function MoneyRequestReportPreviewContent({ showDEWModal(); return; } - submitReport( - iouReport, + submitReport({ + expenseReport: iouReport, policy, - currentUserAccountID, - currentUserEmail, + currentUserAccountIDParam: currentUserAccountID, + currentUserEmailParam: currentUserEmail, hasViolations, isASAPSubmitBetaEnabled, - iouReportNextStep, + expenseReportCurrentNextStepDeprecated: iouReportNextStep, userBillingGraceEndPeriods, amountOwed, - startSubmittingAnimation, - ); + onSubmitted: startSubmittingAnimation, + }); }} isSubmittingAnimationRunning={isSubmittingAnimationRunning} onAnimationFinish={stopAnimation} diff --git a/src/libs/actions/IOU/index.ts b/src/libs/actions/IOU/index.ts index 43161b109623f..5aa4a838b7c80 100644 --- a/src/libs/actions/IOU/index.ts +++ b/src/libs/actions/IOU/index.ts @@ -867,6 +867,7 @@ type PayMoneyRequestFunctionParams = { betas: OnyxEntry; isSelfTourViewed: boolean | undefined; amountOwed: OnyxEntry; + onPaid?: () => void; }; type ApproveMoneyRequestFunctionParams = { @@ -881,6 +882,20 @@ type ApproveMoneyRequestFunctionParams = { userBillingGraceEndPeriods: OnyxCollection; amountOwed: OnyxEntry; full?: boolean; + onApproved?: () => void; +}; + +type SubmitReportFunctionParams = { + expenseReport: OnyxEntry; + policy: OnyxEntry; + currentUserAccountIDParam: number; + currentUserEmailParam: string; + hasViolations: boolean; + isASAPSubmitBetaEnabled: boolean; + expenseReportCurrentNextStepDeprecated: OnyxEntry; + userBillingGraceEndPeriods: OnyxCollection; + amountOwed: OnyxEntry; + onSubmitted?: () => void; }; let allTransactions: NonNullable> = {}; @@ -9836,7 +9851,7 @@ function getReportOriginalCreationTimestamp(expenseReport?: OnyxEntry void) { +function approveMoneyRequest(params: ApproveMoneyRequestFunctionParams) { const { expenseReport, policy, @@ -9849,6 +9864,7 @@ function approveMoneyRequest(params: ApproveMoneyRequestFunctionParams, onApprov userBillingGraceEndPeriods, amountOwed, full, + onApproved, } = params; if (!expenseReport) { return; @@ -10730,18 +10746,18 @@ function unapproveExpenseReport( API.write(WRITE_COMMANDS.UNAPPROVE_EXPENSE_REPORT, parameters, {optimisticData, successData, failureData}); } -function submitReport( - expenseReport: OnyxEntry, - policy: OnyxEntry, - currentUserAccountIDParam: number, - currentUserEmailParam: string, - hasViolations: boolean, - isASAPSubmitBetaEnabled: boolean, - expenseReportCurrentNextStepDeprecated: OnyxEntry, - userBillingGraceEndPeriods: OnyxCollection, - amountOwed: OnyxEntry, - onSubmitted?: () => void, -) { +function submitReport({ + expenseReport, + policy, + currentUserAccountIDParam, + currentUserEmailParam, + hasViolations, + isASAPSubmitBetaEnabled, + expenseReportCurrentNextStepDeprecated, + userBillingGraceEndPeriods, + amountOwed, + onSubmitted, +}: SubmitReportFunctionParams) { if (!expenseReport) { return; } @@ -11263,7 +11279,7 @@ function completePaymentOnboarding( }); } -function payMoneyRequest(params: PayMoneyRequestFunctionParams, onPaid?: () => void) { +function payMoneyRequest(params: PayMoneyRequestFunctionParams) { const { paymentType, chatReport, @@ -11279,6 +11295,7 @@ function payMoneyRequest(params: PayMoneyRequestFunctionParams, onPaid?: () => v betas, isSelfTourViewed, amountOwed, + onPaid, } = params; if (chatReport.policyID && shouldRestrictUserBillableActions(chatReport.policyID, userBillingGraceEndPeriods, amountOwed)) { Navigation.navigate(ROUTES.RESTRICTED_ACTION.getRoute(chatReport.policyID)); diff --git a/tests/actions/IOUTest.ts b/tests/actions/IOUTest.ts index 21805f5853915..1138f78d74aaa 100644 --- a/tests/actions/IOUTest.ts +++ b/tests/actions/IOUTest.ts @@ -9555,7 +9555,17 @@ describe('actions/IOU', () => { .then(async () => { if (expenseReport) { const nextStep = await getOnyxValue(`${ONYXKEYS.COLLECTION.NEXT_STEP}${expenseReport.reportID}`); - submitReport(expenseReport, {} as Policy, CARLOS_ACCOUNT_ID, CARLOS_EMAIL, true, true, nextStep, undefined, 0); + submitReport({ + expenseReport, + policy: {} as Policy, + currentUserAccountIDParam: CARLOS_ACCOUNT_ID, + currentUserEmailParam: CARLOS_EMAIL, + hasViolations: true, + isASAPSubmitBetaEnabled: true, + expenseReportCurrentNextStepDeprecated: nextStep, + userBillingGraceEndPeriods: undefined, + amountOwed: 0, + }); } return waitForBatchedUpdates(); }) @@ -9839,7 +9849,17 @@ describe('actions/IOU', () => { .then(async () => { if (expenseReport) { const nextStep = await getOnyxValue(`${ONYXKEYS.COLLECTION.NEXT_STEP}${expenseReport.reportID}`); - submitReport(expenseReport, policy, CARLOS_ACCOUNT_ID, CARLOS_EMAIL, true, true, nextStep, undefined, 0); + submitReport({ + expenseReport, + policy, + currentUserAccountIDParam: CARLOS_ACCOUNT_ID, + currentUserEmailParam: CARLOS_EMAIL, + hasViolations: true, + isASAPSubmitBetaEnabled: true, + expenseReportCurrentNextStepDeprecated: nextStep, + userBillingGraceEndPeriods: undefined, + amountOwed: 0, + }); } return waitForBatchedUpdates(); }) @@ -10093,7 +10113,17 @@ describe('actions/IOU', () => { mockFetch?.fail?.(); if (expenseReport) { const nextStep = await getOnyxValue(`${ONYXKEYS.COLLECTION.NEXT_STEP}${expenseReport.reportID}`); - submitReport(expenseReport, {} as Policy, CARLOS_ACCOUNT_ID, CARLOS_EMAIL, true, true, nextStep, undefined, 0); + submitReport({ + expenseReport, + policy: {} as Policy, + currentUserAccountIDParam: CARLOS_ACCOUNT_ID, + currentUserEmailParam: CARLOS_EMAIL, + hasViolations: true, + isASAPSubmitBetaEnabled: true, + expenseReportCurrentNextStepDeprecated: nextStep, + userBillingGraceEndPeriods: undefined, + amountOwed: 0, + }); } return waitForBatchedUpdates(); }) @@ -10248,7 +10278,17 @@ describe('actions/IOU', () => { ) .then(() => { if (expenseReport) { - submitReport(expenseReport, policy, CARLOS_ACCOUNT_ID, CARLOS_EMAIL, true, true, undefined, undefined, 0); + submitReport({ + expenseReport, + policy, + currentUserAccountIDParam: CARLOS_ACCOUNT_ID, + currentUserEmailParam: CARLOS_EMAIL, + hasViolations: true, + isASAPSubmitBetaEnabled: true, + expenseReportCurrentNextStepDeprecated: undefined, + userBillingGraceEndPeriods: undefined, + amountOwed: 0, + }); } return waitForBatchedUpdates(); }) @@ -10308,7 +10348,17 @@ describe('actions/IOU', () => { (Navigation.navigate as jest.Mock).mockClear(); // Submit with amountOwed > 0 should trigger restriction - submitReport(expenseReport, policy, CARLOS_ACCOUNT_ID, CARLOS_EMAIL, false, true, undefined, undefined, 100); + submitReport({ + expenseReport, + policy, + currentUserAccountIDParam: CARLOS_ACCOUNT_ID, + currentUserEmailParam: CARLOS_EMAIL, + hasViolations: false, + isASAPSubmitBetaEnabled: true, + expenseReportCurrentNextStepDeprecated: undefined, + userBillingGraceEndPeriods: undefined, + amountOwed: 100, + }); await waitForBatchedUpdates(); @@ -10404,7 +10454,17 @@ describe('actions/IOU', () => { (Navigation.navigate as jest.Mock).mockClear(); const nextStep = await getOnyxValue(`${ONYXKEYS.COLLECTION.NEXT_STEP}${expenseReport.reportID}`); - submitReport(expenseReport, policy, CARLOS_ACCOUNT_ID, CARLOS_EMAIL, false, true, nextStep, undefined, 0); + submitReport({ + expenseReport, + policy, + currentUserAccountIDParam: CARLOS_ACCOUNT_ID, + currentUserEmailParam: CARLOS_EMAIL, + hasViolations: false, + isASAPSubmitBetaEnabled: true, + expenseReportCurrentNextStepDeprecated: nextStep, + userBillingGraceEndPeriods: undefined, + amountOwed: 0, + }); await waitForBatchedUpdates();