diff --git a/src/components/MoneyReportHeader.tsx b/src/components/MoneyReportHeader.tsx index 714642aa5b2d1..3ecc4bac23a93 100644 --- a/src/components/MoneyReportHeader.tsx +++ b/src/components/MoneyReportHeader.tsx @@ -724,7 +724,19 @@ function MoneyReportHeader({ setIsHoldMenuVisible(true); } else { startApprovedAnimation(); - approveMoneyRequest(moneyRequestReport, policy, accountID, email ?? '', hasViolations, isASAPSubmitBetaEnabled, nextStep, betas, userBillingGraceEndPeriods, true); + approveMoneyRequest({ + expenseReport: moneyRequestReport, + policy, + currentUserAccountIDParam: accountID, + currentUserEmailParam: email ?? '', + hasViolations, + isASAPSubmitBetaEnabled, + expenseReportCurrentNextStepDeprecated: nextStep, + betas, + userBillingGraceEndPeriods, + amountOwed, + full: true, + }); } }; diff --git a/src/components/ProcessMoneyReportHoldMenu.tsx b/src/components/ProcessMoneyReportHoldMenu.tsx index 8c37efcc92739..881c9553f5a8c 100644 --- a/src/components/ProcessMoneyReportHoldMenu.tsx +++ b/src/components/ProcessMoneyReportHoldMenu.tsx @@ -74,6 +74,7 @@ function ProcessMoneyReportHoldMenu({ const {isSmallScreenWidth} = useResponsiveLayout(); const [userBillingGraceEndPeriods] = useOnyx(ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_USER_BILLING_GRACE_PERIOD_END); const [activePolicyID] = useOnyx(ONYXKEYS.NVP_ACTIVE_POLICY_ID); + const [amountOwed] = useOnyx(ONYXKEYS.NVP_PRIVATE_AMOUNT_OWED); const activePolicy = usePolicy(activePolicyID); const policy = usePolicy(moneyRequestReport?.policyID); const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED); @@ -98,18 +99,19 @@ function ProcessMoneyReportHoldMenu({ if (startAnimation) { startAnimation(); } - approveMoneyRequest( - moneyRequestReport, - activePolicy, - currentUserDetails.accountID, - currentUserDetails.email ?? '', + approveMoneyRequest({ + expenseReport: moneyRequestReport, + policy: activePolicy, + currentUserAccountIDParam: currentUserDetails.accountID, + currentUserEmailParam: currentUserDetails.email ?? '', hasViolations, isASAPSubmitBetaEnabled, - moneyRequestReportNextStep, + expenseReportCurrentNextStepDeprecated: moneyRequestReportNextStep, betas, userBillingGraceEndPeriods, + amountOwed, full, - ); + }); } else if (chatReport && paymentType) { if (startAnimation) { startAnimation(); diff --git a/src/components/ReportActionItem/MoneyRequestReportPreview/MoneyRequestReportPreviewContent.tsx b/src/components/ReportActionItem/MoneyRequestReportPreview/MoneyRequestReportPreviewContent.tsx index e8909aea24985..474ade2691a06 100644 --- a/src/components/ReportActionItem/MoneyRequestReportPreview/MoneyRequestReportPreviewContent.tsx +++ b/src/components/ReportActionItem/MoneyRequestReportPreview/MoneyRequestReportPreviewContent.tsx @@ -351,18 +351,19 @@ function MoneyRequestReportPreviewContent({ setIsHoldMenuVisible(true); } else { startApprovedAnimation(); - approveMoneyRequest( - iouReport, - activePolicy, - currentUserAccountID, - currentUserEmail, + approveMoneyRequest({ + expenseReport: iouReport, + policy: activePolicy, + currentUserAccountIDParam: currentUserAccountID, + currentUserEmailParam: currentUserEmail, hasViolations, isASAPSubmitBetaEnabled, - iouReportNextStep, + expenseReportCurrentNextStepDeprecated: iouReportNextStep, betas, userBillingGraceEndPeriods, - true, - ); + amountOwed, + full: true, + }); } }; diff --git a/src/components/SettlementButton/index.tsx b/src/components/SettlementButton/index.tsx index 0c1cefb55061e..0bc982d4be0a0 100644 --- a/src/components/SettlementButton/index.tsx +++ b/src/components/SettlementButton/index.tsx @@ -108,6 +108,7 @@ function SettlementButton({ const [conciergeReportID = ''] = useOnyx(ONYXKEYS.CONCIERGE_REPORT_ID); const [iouReportNextStep] = useOnyx(`${ONYXKEYS.COLLECTION.NEXT_STEP}${iouReport?.reportID}`); const [isUserValidated] = useOnyx(ONYXKEYS.ACCOUNT, {selector: isUserValidatedSelector}); + const [amountOwed] = useOnyx(ONYXKEYS.NVP_PRIVATE_AMOUNT_OWED); const policyEmployeeAccountIDs = getPolicyEmployeeAccountIDs(policy, accountID); const reportBelongsToWorkspace = policyID ? doesReportBelongToWorkspace(chatReport, policyEmployeeAccountIDs, policyID, conciergeReportID) : false; const policyIDKey = reportBelongsToWorkspace ? policyID : (iouReport?.policyID ?? CONST.POLICY.ID_FAKE); @@ -426,7 +427,19 @@ 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, + amountOwed, + full: false, + }); } return; } diff --git a/src/libs/PaymentUtils.ts b/src/libs/PaymentUtils.ts index 5da5ed44e7bb2..abe6d0fd46eb4 100644 --- a/src/libs/PaymentUtils.ts +++ b/src/libs/PaymentUtils.ts @@ -202,7 +202,19 @@ 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, + amountOwed, + full: true, + }); } return; } diff --git a/src/libs/actions/IOU/index.ts b/src/libs/actions/IOU/index.ts index d4885f4ec1691..cb2daeee6dd2d 100644 --- a/src/libs/actions/IOU/index.ts +++ b/src/libs/actions/IOU/index.ts @@ -10602,23 +10602,38 @@ function getReportOriginalCreationTimestamp(expenseReport?: OnyxEntry, - policy: OnyxEntry, - currentUserAccountIDParam: number, - currentUserEmailParam: string, - hasViolations: boolean, - isASAPSubmitBetaEnabled: boolean, - expenseReportCurrentNextStepDeprecated: OnyxEntry, - betas: OnyxEntry, - userBillingGraceEndPeriods: OnyxCollection, - full?: boolean, -) { +type ApproveMoneyRequestParam = { + 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) { if (!expenseReport) { return; } - if (expenseReport.policyID && shouldRestrictUserBillableActions(expenseReport.policyID, userBillingGraceEndPeriods)) { + if (expenseReport.policyID && shouldRestrictUserBillableActions(expenseReport.policyID, userBillingGraceEndPeriods, amountOwed)) { Navigation.navigate(ROUTES.RESTRICTED_ACTION.getRoute(expenseReport.policyID)); return; } diff --git a/tests/actions/IOUTest.ts b/tests/actions/IOUTest.ts index 4b865745ecd25..475e2c783b3c6 100644 --- a/tests/actions/IOUTest.ts +++ b/tests/actions/IOUTest.ts @@ -13864,7 +13864,18 @@ 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, + amountOwed: 0, + }); await waitForBatchedUpdates(); // Should be approved since admin took control and is the last approver @@ -13902,7 +13913,18 @@ 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, + amountOwed: 0, + }); await waitForBatchedUpdates(); // Should be submitted to senior manager (normal flow) since take control was invalidated @@ -13936,7 +13958,18 @@ 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, + amountOwed: 0, + }); await waitForBatchedUpdates(); // Get the optimistic next step @@ -14046,7 +14079,18 @@ 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, + amountOwed: 0, + }); await waitForBatchedUpdates(); // Should be submitted to admin (next in approval chain) since manager is not the final approver @@ -14063,7 +14107,18 @@ 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, + amountOwed: 0, + }); await waitForBatchedUpdates(); // Should be submitted to admin @@ -14078,7 +14133,18 @@ 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, + amountOwed: 0, + }); await waitForBatchedUpdates(); // Should be fully approved @@ -14123,7 +14189,18 @@ 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, + amountOwed: 0, + }); await waitForBatchedUpdates(); // Should be fully approved since manager is the final approver in the chain @@ -14224,7 +14301,19 @@ 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, + amountOwed: 0, + full: false, + }); await waitForBatchedUpdates(); const newExpenseReport = await getOnyxValue(`${ONYXKEYS.COLLECTION.REPORT}${newExpenseReportID}`); diff --git a/tests/unit/PaymentUtilsTest.ts b/tests/unit/PaymentUtilsTest.ts index 51978b8191c09..a2982f543613c 100644 --- a/tests/unit/PaymentUtilsTest.ts +++ b/tests/unit/PaymentUtilsTest.ts @@ -258,12 +258,44 @@ describe('PaymentUtils', () => { expect(approveMoneyRequest).not.toHaveBeenCalled(); }); - it('should call approveMoneyRequest when payment type is APPROVE and no confirmApproval', () => { - const params = {...baseParams, iouPaymentType: CONST.IOU.REPORT_ACTION_TYPE.APPROVE as PaymentMethodType}; + it('should call approveMoneyRequest with amountOwed when payment type is APPROVE and no confirmApproval', () => { + const params = {...baseParams, iouPaymentType: CONST.IOU.REPORT_ACTION_TYPE.APPROVE as PaymentMethodType, amountOwed: 42}; selectPaymentType(params); - expect(approveMoneyRequest).toHaveBeenCalled(); + expect(approveMoneyRequest).toHaveBeenCalledWith({ + expenseReport: params.iouReport, + policy: params.policy, + currentUserAccountIDParam: params.currentAccountID, + currentUserEmailParam: params.currentEmail, + hasViolations: params.hasViolations, + isASAPSubmitBetaEnabled: params.isASAPSubmitBetaEnabled, + expenseReportCurrentNextStepDeprecated: params.iouReportNextStep, + betas: params.betas, + userBillingGraceEndPeriods: params.userBillingGraceEndPeriods, + amountOwed: 42, + full: true, + }); + }); + + it('should pass amountOwed as undefined to approveMoneyRequest when amountOwed is undefined', () => { + const params = {...baseParams, iouPaymentType: CONST.IOU.REPORT_ACTION_TYPE.APPROVE as PaymentMethodType, amountOwed: undefined}; + + selectPaymentType(params); + + expect(approveMoneyRequest).toHaveBeenCalledWith({ + expenseReport: params.iouReport, + policy: params.policy, + currentUserAccountIDParam: params.currentAccountID, + currentUserEmailParam: params.currentEmail, + hasViolations: params.hasViolations, + isASAPSubmitBetaEnabled: params.isASAPSubmitBetaEnabled, + expenseReportCurrentNextStepDeprecated: params.iouReportNextStep, + betas: params.betas, + userBillingGraceEndPeriods: params.userBillingGraceEndPeriods, + amountOwed: undefined, + full: true, + }); }); it('should call onPress with payment type for other payment types', () => { @@ -274,7 +306,7 @@ describe('PaymentUtils', () => { expect(mockOnPress).toHaveBeenCalledWith({paymentType: CONST.IOU.PAYMENT_TYPE.ELSEWHERE}); }); - it('should not restrict when policy is null', () => { + it('should not restrict when policy is undefined', () => { const params = {...baseParams, policy: undefined, amountOwed: 100}; selectPaymentType(params);