Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import type {PopoverMenuItem} from '@components/PopoverMenu';
import {useSearchStateContext} from '@components/Search/SearchContext';
import type {PaymentActionParams} from '@components/SettlementButton/types';
import useActiveAdminPolicies from '@hooks/useActiveAdminPolicies';
import {useCurrencyListActions} from '@hooks/useCurrencyList';
import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
import useExpenseActions from '@hooks/useExpenseActions';
import useExportActions from '@hooks/useExportActions';
Expand Down Expand Up @@ -111,6 +112,8 @@ function MoneyReportHeaderSecondaryActionsInner({reportID, primaryAction, isRepo
const activePolicy = usePolicy(activePolicyID);
const lastWorkspaceNumber = useLastWorkspaceNumber();

const {convertToDisplayString} = useCurrencyListActions();

const {isBetaEnabled} = usePermissions();
const isASAPSubmitBetaEnabled = isBetaEnabled(CONST.BETAS.ASAP_SUBMIT);

Expand Down Expand Up @@ -216,7 +219,7 @@ function MoneyReportHeaderSecondaryActionsInner({reportID, primaryAction, isRepo
const shouldShowApproveButton = (canApproveIOU(moneyRequestReport, policy, reportMetadata, allTransactions) && !hasOnlyPendingTransactions) || isApprovedAnimationRunning;
const isApproveDisabled = shouldShowApproveButton && !isAllowedToApproveExpenseReport(moneyRequestReport);

const totalAmount = getTotalAmountForIOUReportPreviewButton(moneyRequestReport, policy, CONST.REPORT.PRIMARY_ACTIONS.PAY, nonPendingDeleteTransactions);
const totalAmount = getTotalAmountForIOUReportPreviewButton(moneyRequestReport, policy, CONST.REPORT.PRIMARY_ACTIONS.PAY, nonPendingDeleteTransactions, convertToDisplayString);

const paymentButtonOptions = usePaymentOptions({
currency: moneyRequestReport?.currency,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {useSearchActionsContext, useSearchStateContext} from '@components/Search
import type {PaymentActionParams} from '@components/SettlementButton/types';
import useActiveAdminPolicies from '@hooks/useActiveAdminPolicies';
import useConfirmModal from '@hooks/useConfirmModal';
import {useCurrencyListActions} from '@hooks/useCurrencyList';
import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
import useExportActions from '@hooks/useExportActions';
import useLastWorkspaceNumber from '@hooks/useLastWorkspaceNumber';
Expand Down Expand Up @@ -86,6 +87,7 @@ function MoneyReportHeaderSelectionDropdown({reportID, primaryAction, isReportIn
const isBulkSubmitApprovePayBetaEnabled = isBetaEnabled(CONST.BETAS.BULK_SUBMIT_APPROVE_PAY);
const activeAdminPolicies = useActiveAdminPolicies();
const lastWorkspaceNumber = useLastWorkspaceNumber();
const {convertToDisplayString} = useCurrencyListActions();

const {selectedTransactionIDs, currentSearchQueryJSON, currentSearchKey, currentSearchResults} = useSearchStateContext();
const {clearSelectedTransactions} = useSearchActionsContext();
Expand Down Expand Up @@ -219,7 +221,7 @@ function MoneyReportHeaderSelectionDropdown({reportID, primaryAction, isReportIn
};

const canAllowSettlement = hasUpdatedTotal(moneyRequestReport, policy);
const totalAmount = getTotalAmountForIOUReportPreviewButton(moneyRequestReport, policy, CONST.REPORT.PRIMARY_ACTIONS.PAY, nonPendingDeleteTransactions);
const totalAmount = getTotalAmountForIOUReportPreviewButton(moneyRequestReport, policy, CONST.REPORT.PRIMARY_ACTIONS.PAY, nonPendingDeleteTransactions, convertToDisplayString);
const canIOUBePaid = canIOUBePaidAction(moneyRequestReport, chatReport, policy, bankAccountList, undefined, false, undefined, invoiceReceiverPolicy);
const onlyShowPayElsewhere = !canIOUBePaid && canIOUBePaidAction(moneyRequestReport, chatReport, policy, bankAccountList, undefined, true, undefined, invoiceReceiverPolicy);
const isPayable = hasPayAction && canIOUBePaid;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {usePaymentAnimationsContext} from '@components/PaymentAnimationsContext'
import {useSearchStateContext} from '@components/Search/SearchContext';
import AnimatedSettlementButton from '@components/SettlementButton/AnimatedSettlementButton';
import type {PaymentActionParams} from '@components/SettlementButton/types';
import {useCurrencyListActions} from '@hooks/useCurrencyList';
import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
import useLastWorkspaceNumber from '@hooks/useLastWorkspaceNumber';
import useLocalize from '@hooks/useLocalize';
Expand Down Expand Up @@ -62,6 +63,7 @@ function PayPrimaryAction({reportID, chatReportID}: PayPrimaryActionProps) {
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);
const {convertToDisplayString} = useCurrencyListActions();

const isInvoiceReport = isInvoiceReportUtil(moneyRequestReport);

Expand All @@ -77,7 +79,7 @@ function PayPrimaryAction({reportID, chatReportID}: PayPrimaryActionProps) {
const shouldShowApproveButton = (canApproveIOU(moneyRequestReport, policy, reportMetadata, transactions) && !hasOnlyPendingTransactions) || isApprovedAnimationRunning;
const shouldDisableApproveButton = shouldShowApproveButton && !isAllowedToApproveExpenseReport(moneyRequestReport);
const canAllowSettlement = hasUpdatedTotal(moneyRequestReport, policy);
const totalAmount = getTotalAmountForIOUReportPreviewButton(moneyRequestReport, policy, CONST.REPORT.PRIMARY_ACTIONS.PAY, nonPendingDeleteTransactions);
const totalAmount = getTotalAmountForIOUReportPreviewButton(moneyRequestReport, policy, CONST.REPORT.PRIMARY_ACTIONS.PAY, nonPendingDeleteTransactions, convertToDisplayString);
const isAnyTransactionOnHold = hasHeldExpensesReportUtils(transactions);

const {currentSearchQueryJSON, currentSearchKey, currentSearchResults} = useSearchStateContext();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type {ValueOf} from 'type-fest';
import {useDelegateNoAccessActions, useDelegateNoAccessState} from '@components/DelegateNoAccessModalProvider';
import AnimatedSettlementButton from '@components/SettlementButton/AnimatedSettlementButton';
import type {PaymentActionParams} from '@components/SettlementButton/types';
import {useCurrencyListActions} from '@hooks/useCurrencyList';
import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
import useLastWorkspaceNumber from '@hooks/useLastWorkspaceNumber';
import useLocalize from '@hooks/useLocalize';
Expand Down Expand Up @@ -68,6 +69,7 @@ function PayActionButton({
const {isDelegateAccessRestricted} = useDelegateNoAccessState();
const {showDelegateNoAccessModal} = useDelegateNoAccessActions();
const lastWorkspaceNumber = useLastWorkspaceNumber();
const {convertToDisplayString} = useCurrencyListActions();

const [activePolicyID] = useOnyx(ONYXKEYS.NVP_ACTIVE_POLICY_ID);
const activePolicy = usePolicy(activePolicyID);
Expand Down Expand Up @@ -105,7 +107,7 @@ function PayActionButton({
const shouldShowOnlyPayElsewhere = !canIOUBePaid && onlyShowPayElsewhere;
const canIOUBePaidAndApproved = canIOUBePaid;

const formattedAmount = getTotalAmountForIOUReportPreviewButton(iouReport, policy, reportPreviewAction, transactions);
const formattedAmount = getTotalAmountForIOUReportPreviewButton(iouReport, policy, reportPreviewAction, transactions, convertToDisplayString);

const confirmApproval = () => {
if (isDelegateAccessRestricted) {
Expand Down
4 changes: 3 additions & 1 deletion src/hooks/useSelectionModeReportActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import type * as OnyxTypes from '@src/types/onyx';
import type {PaymentMethodType} from '@src/types/onyx/OriginalMessage';
import useActiveAdminPolicies from './useActiveAdminPolicies';
import useConfirmPendingRTERAndProceed from './useConfirmPendingRTERAndProceed';
import {useCurrencyListActions} from './useCurrencyList';
import useCurrentUserPersonalDetails from './useCurrentUserPersonalDetails';
import useLastWorkspaceNumber from './useLastWorkspaceNumber';
import {useMemoizedLazyExpensifyIcons} from './useLazyAsset';
Expand Down Expand Up @@ -120,6 +121,7 @@ function useSelectionModeReportActions({
const existingB2BInvoiceReport = useParticipantsInvoiceReport(activePolicyID, CONST.REPORT.INVOICE_RECEIVER_TYPE.BUSINESS, chatReport?.policyID);
const activeAdminPolicies = useActiveAdminPolicies();
const lastWorkspaceNumber = useLastWorkspaceNumber();
const {convertToDisplayString} = useCurrencyListActions();

const isChatReportArchived = useReportIsArchived(chatReport?.reportID);

Expand Down Expand Up @@ -173,7 +175,7 @@ function useSelectionModeReportActions({

const shouldDisableApproveButton = shouldShowApproveButton && !isAllowedToApproveExpenseReport(report);

const totalAmount = getTotalAmountForIOUReportPreviewButton(report, policy, CONST.REPORT.PRIMARY_ACTIONS.PAY, nonPendingDeleteTransactions);
const totalAmount = getTotalAmountForIOUReportPreviewButton(report, policy, CONST.REPORT.PRIMARY_ACTIONS.PAY, nonPendingDeleteTransactions, convertToDisplayString);

// confirmPayment is declared below but used by usePaymentOptions; we use a ref to avoid a circular dependency.
const confirmPaymentRef = useRef<(params: PaymentActionParams) => void>(() => {});
Expand Down
3 changes: 2 additions & 1 deletion src/libs/MoneyRequestReportUtils.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
import type {ValueOf} from 'type-fest';
import type {TransactionListItemType} from '@components/Search/SearchList/ListItem/types';
import type {CurrencyListActionsContextType} from '@hooks/useCurrencyList';
import CONST from '@src/CONST';
import type {OriginalMessageIOU, Policy, Report, ReportAction, ReportLoadingState, Transaction} from '@src/types/onyx';
import {convertToDisplayString} from './CurrencyUtils';
import {isPaidGroupPolicy} from './PolicyUtils';
import {getIOUActionForTransactionID, getOriginalMessage, isDeletedAction, isDeletedParentAction, isMoneyRequestAction} from './ReportActionsUtils';
import {
Expand Down Expand Up @@ -159,6 +159,7 @@ const getTotalAmountForIOUReportPreviewButton = (
policy: OnyxEntry<Policy>,
reportPreviewAction: ValueOf<typeof CONST.REPORT.REPORT_PREVIEW_ACTIONS>,
transactions: Transaction[],
convertToDisplayString: CurrencyListActionsContextType['convertToDisplayString'],
) => {
// Determine whether the non-held amount is appropriate to display for the PAY button.
const {nonHeldAmount, hasValidNonHeldAmount} = getNonHeldAndFullAmount(report, reportPreviewAction === CONST.REPORT.REPORT_PREVIEW_ACTIONS.PAY);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import RenderHTML from '@components/RenderHTML';
import ScreenWrapper from '@components/ScreenWrapper';
import ScrollView from '@components/ScrollView';
import Text from '@components/Text';
import {useCurrencyListActions} from '@hooks/useCurrencyList';
import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
import useEnvironment from '@hooks/useEnvironment';
import useHasTeam2025Pricing from '@hooks/useHasTeam2025Pricing';
Expand All @@ -30,7 +31,7 @@ import useTheme from '@hooks/useTheme';
import useThemeIllustrations from '@hooks/useThemeIllustrations';
import useThemeStyles from '@hooks/useThemeStyles';
import {openLink} from '@libs/actions/Link';
import {convertToDisplayString, convertToShortDisplayString} from '@libs/CurrencyUtils';
import {convertToShortDisplayString} from '@libs/CurrencyUtils';
import {isPolicyAdmin} from '@libs/PolicyUtils';
import {getSubscriptionPrice, isSubscriptionTypeOfInvoicing, shouldUseSimplifiedCollectSubscriptionUI} from '@libs/SubscriptionUtils';
import type {SkeletonSpanReasonAttributes} from '@libs/telemetry/useSkeletonSpan';
Expand All @@ -48,6 +49,7 @@ import ROUTES from '@src/ROUTES';

function SubscriptionSettings() {
const {translate} = useLocalize();
const {convertToDisplayString} = useCurrencyListActions();
const icons = useMemoizedLazyExpensifyIcons(['Coins']);
const styles = useThemeStyles();
const theme = useTheme();
Expand Down
9 changes: 5 additions & 4 deletions tests/unit/MoneyRequestReportButtonUtils.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Onyx from 'react-native-onyx';
import {convertToDisplayString} from '@libs/CurrencyUtils';
import {getTotalAmountForIOUReportPreviewButton} from '@libs/MoneyRequestReportUtils';
import {hasOnlyNonReimbursableTransactions} from '@libs/ReportUtils';
import CONST from '@src/CONST';
Expand Down Expand Up @@ -45,15 +46,15 @@ describe('ReportButtonUtils', () => {
});

it('returns total reimbursable spend for PAY & total value for other buttons', () => {
expect(getTotalAmountForIOUReportPreviewButton(mockReport, mockPolicy, CONST.REPORT.REPORT_PREVIEW_ACTIONS.PAY, [])).toBe(`$50.00`);
expect(getTotalAmountForIOUReportPreviewButton(mockReport, mockPolicy, CONST.REPORT.REPORT_PREVIEW_ACTIONS.APPROVE, [])).toBe(`$100.00`);
expect(getTotalAmountForIOUReportPreviewButton(mockReport, mockPolicy, CONST.REPORT.REPORT_PREVIEW_ACTIONS.SUBMIT, [])).toBe(`$100.00`);
expect(getTotalAmountForIOUReportPreviewButton(mockReport, mockPolicy, CONST.REPORT.REPORT_PREVIEW_ACTIONS.PAY, [], convertToDisplayString)).toBe(`$50.00`);
expect(getTotalAmountForIOUReportPreviewButton(mockReport, mockPolicy, CONST.REPORT.REPORT_PREVIEW_ACTIONS.APPROVE, [], convertToDisplayString)).toBe(`$100.00`);
expect(getTotalAmountForIOUReportPreviewButton(mockReport, mockPolicy, CONST.REPORT.REPORT_PREVIEW_ACTIONS.SUBMIT, [], convertToDisplayString)).toBe(`$100.00`);
});

it('returns total display spend for PAY when report has only non-reimbursable transactions', () => {
jest.mocked(hasOnlyNonReimbursableTransactions).mockReturnValueOnce(true);

expect(getTotalAmountForIOUReportPreviewButton(mockReport, mockPolicy, CONST.REPORT.REPORT_PREVIEW_ACTIONS.PAY, [])).toBe(`$100.00`);
expect(getTotalAmountForIOUReportPreviewButton(mockReport, mockPolicy, CONST.REPORT.REPORT_PREVIEW_ACTIONS.PAY, [], convertToDisplayString)).toBe(`$100.00`);
});
});
});
Loading