diff --git a/src/components/MoneyReportHeader.tsx b/src/components/MoneyReportHeader.tsx index 47b881dc646c3..bde3950818cb7 100644 --- a/src/components/MoneyReportHeader.tsx +++ b/src/components/MoneyReportHeader.tsx @@ -710,6 +710,12 @@ function MoneyReportHeader({ userBillingGraceEndPeriods, amountOwed, methodID: type === CONST.IOU.PAYMENT_TYPE.VBBA ? methodID : undefined, + onPaid: () => { + if (isFromSelectionMode) { + return; + } + startAnimation(); + }, }); if (currentSearchQueryJSON && !isOffline) { search({ @@ -801,6 +807,12 @@ function MoneyReportHeader({ userBillingGraceEndPeriods, amountOwed, full: true, + onApproved: () => { + if (skipAnimation) { + return; + } + startApprovedAnimation(); + }, }); if (skipAnimation) { clearSelectedTransactions(true); @@ -837,10 +849,23 @@ function MoneyReportHeader({ showDWEModal(); return; } - if (!skipAnimation) { - startSubmittingAnimation(); - } - submitReport(moneyRequestReport, policy, accountID, email ?? '', hasViolations, isASAPSubmitBetaEnabled, nextStep, userBillingGraceEndPeriods, amountOwed); + submitReport({ + expenseReport: moneyRequestReport, + policy, + currentUserAccountIDParam: accountID, + currentUserEmailParam: email ?? '', + hasViolations, + isASAPSubmitBetaEnabled, + expenseReportCurrentNextStepDeprecated: nextStep, + userBillingGraceEndPeriods, + amountOwed, + onSubmitted: () => { + if (skipAnimation) { + return; + } + startSubmittingAnimation(); + }, + }); if (currentSearchQueryJSON && !isOffline) { search({ searchKey: currentSearchKey, @@ -1676,7 +1701,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 a04069449ede6..62b1057ea4698 100644 --- a/src/components/ProcessMoneyReportHoldMenu.tsx +++ b/src/components/ProcessMoneyReportHoldMenu.tsx @@ -100,9 +100,6 @@ function ProcessMoneyReportHoldMenu({ } if (isApprove) { - if (startAnimation) { - startAnimation(); - } approveMoneyRequest({ expenseReport: moneyRequestReport, policy: activePolicy, @@ -115,11 +112,9 @@ function ProcessMoneyReportHoldMenu({ userBillingGraceEndPeriods, amountOwed, full, + onApproved: startAnimation, }); } else if (chatReport && paymentType) { - if (startAnimation) { - startAnimation(); - } payMoneyRequest({ paymentType, chatReport, @@ -135,6 +130,7 @@ function ProcessMoneyReportHoldMenu({ userBillingGraceEndPeriods, amountOwed, methodID, + onPaid: startAnimation, }); } onClose(); diff --git a/src/components/ReportActionItem/MoneyRequestReportPreview/MoneyRequestReportPreviewContent.tsx b/src/components/ReportActionItem/MoneyRequestReportPreview/MoneyRequestReportPreviewContent.tsx index 0a6f33c5630c6..827c41bc68420 100644 --- a/src/components/ReportActionItem/MoneyRequestReportPreview/MoneyRequestReportPreviewContent.tsx +++ b/src/components/ReportActionItem/MoneyRequestReportPreview/MoneyRequestReportPreviewContent.tsx @@ -279,8 +279,8 @@ function MoneyRequestReportPreviewContent({ } else if (hasHeldExpensesReportUtils(iouReport?.reportID)) { setIsHoldMenuVisible(true); } else if (chatReport && iouReport) { - startAnimation(); if (isInvoiceReportUtils(iouReport)) { + startAnimation(); payInvoice({ paymentMethodType: type, chatReport, @@ -311,6 +311,7 @@ function MoneyRequestReportPreviewContent({ isSelfTourViewed, userBillingGraceEndPeriods, amountOwed, + onPaid: startAnimation, }); } } @@ -360,7 +361,6 @@ function MoneyRequestReportPreviewContent({ } else if (hasHeldExpensesReportUtils(iouReport?.reportID)) { setIsHoldMenuVisible(true); } else { - startApprovedAnimation(); approveMoneyRequest({ expenseReport: iouReport, policy: activePolicy, @@ -373,6 +373,7 @@ function MoneyRequestReportPreviewContent({ userBillingGraceEndPeriods, amountOwed, full: true, + onApproved: startApprovedAnimation, }); } }; @@ -753,18 +754,18 @@ function MoneyRequestReportPreviewContent({ showDEWModal(); return; } - startSubmittingAnimation(); - submitReport( - iouReport, + submitReport({ + expenseReport: iouReport, policy, - currentUserAccountID, - currentUserEmail, + currentUserAccountIDParam: currentUserAccountID, + currentUserEmailParam: currentUserEmail, hasViolations, isASAPSubmitBetaEnabled, - iouReportNextStep, + expenseReportCurrentNextStepDeprecated: iouReportNextStep, userBillingGraceEndPeriods, amountOwed, - ); + onSubmitted: startSubmittingAnimation, + }); }} isSubmittingAnimationRunning={isSubmittingAnimationRunning} onAnimationFinish={stopAnimation} diff --git a/src/libs/actions/IOU/index.ts b/src/libs/actions/IOU/index.ts index 99cd0f4e18713..9653eca6411c6 100644 --- a/src/libs/actions/IOU/index.ts +++ b/src/libs/actions/IOU/index.ts @@ -869,6 +869,35 @@ type PayMoneyRequestFunctionParams = { isSelfTourViewed: boolean | undefined; amountOwed: OnyxEntry; methodID?: number; + onPaid?: () => void; +}; + +type ApproveMoneyRequestFunctionParams = { + expenseReport: OnyxEntry; + policy: OnyxEntry; + currentUserAccountIDParam: number; + currentUserEmailParam: string; + hasViolations: boolean; + isASAPSubmitBetaEnabled: boolean; + expenseReportCurrentNextStepDeprecated: OnyxEntry; + betas: OnyxEntry; + 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> = {}; @@ -9833,33 +9862,21 @@ function getReportOriginalCreationTimestamp(expenseReport?: OnyxEntry; - policy: OnyxEntry; - currentUserAccountIDParam: number; - currentUserEmailParam: string; - hasViolations: boolean; - isASAPSubmitBetaEnabled: boolean; - expenseReportCurrentNextStepDeprecated: OnyxEntry; - betas: OnyxEntry; - userBillingGraceEndPeriods: OnyxCollection; - amountOwed: OnyxEntry; - full?: boolean; -}; - -function approveMoneyRequest({ - expenseReport, - policy, - currentUserAccountIDParam, - currentUserEmailParam, - hasViolations, - isASAPSubmitBetaEnabled, - expenseReportCurrentNextStepDeprecated, - betas, - userBillingGraceEndPeriods, - amountOwed, - full, -}: ApproveMoneyRequestParam) { +function approveMoneyRequest(params: ApproveMoneyRequestFunctionParams) { + const { + expenseReport, + policy, + currentUserAccountIDParam, + currentUserEmailParam, + hasViolations, + isASAPSubmitBetaEnabled, + expenseReportCurrentNextStepDeprecated, + betas, + userBillingGraceEndPeriods, + amountOwed, + full, + onApproved, + } = params; if (!expenseReport) { return; } @@ -9969,7 +9986,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, + ), }, }); } @@ -10197,6 +10221,7 @@ function approveMoneyRequest({ optimisticCreatedReportForUnapprovedTransactionsActionID, }; + onApproved?.(); playSound(SOUNDS.SUCCESS); API.write(WRITE_COMMANDS.APPROVE_MONEY_REQUEST, parameters, {optimisticData, successData, failureData}); return optimisticHoldReportID; @@ -10732,17 +10757,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, -) { +function submitReport({ + expenseReport, + policy, + currentUserAccountIDParam, + currentUserEmailParam, + hasViolations, + isASAPSubmitBetaEnabled, + expenseReportCurrentNextStepDeprecated, + userBillingGraceEndPeriods, + amountOwed, + onSubmitted, +}: SubmitReportFunctionParams) { if (!expenseReport) { return; } @@ -11003,6 +11029,7 @@ function submitReport( reportActionID: optimisticSubmittedReportAction.reportActionID, }; + onSubmitted?.(); API.write(WRITE_COMMANDS.SUBMIT_REPORT, parameters, {optimisticData, successData, failureData}); } @@ -11279,6 +11306,7 @@ function payMoneyRequest(params: PayMoneyRequestFunctionParams) { isSelfTourViewed, amountOwed, methodID, + onPaid, } = params; if (chatReport.policyID && shouldRestrictUserBillableActions(chatReport.policyID, userBillingGraceEndPeriods, amountOwed)) { Navigation.navigate(ROUTES.RESTRICTED_ACTION.getRoute(chatReport.policyID)); @@ -11309,6 +11337,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); diff --git a/tests/actions/IOUTest.ts b/tests/actions/IOUTest.ts index b578ad5498138..f773ddc7a4987 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();