diff --git a/src/components/Modal/Global/HoldMenuModalWrapper.tsx b/src/components/Modal/Global/HoldMenuModalWrapper.tsx index 96738afeb862f..4cafe0ce58228 100644 --- a/src/components/Modal/Global/HoldMenuModalWrapper.tsx +++ b/src/components/Modal/Global/HoldMenuModalWrapper.tsx @@ -5,7 +5,6 @@ import type {ActionHandledType} from '@hooks/useHoldMenuSubmit'; import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; -import useTransactionsAndViolationsForReport from '@hooks/useTransactionsAndViolationsForReport'; import ONYXKEYS from '@src/ONYXKEYS'; import type {PaymentMethodType} from '@src/types/onyx/OriginalMessage'; import type {ModalProps} from './ModalContext'; @@ -45,9 +44,6 @@ function HoldMenuModalWrapper({ const [moneyRequestReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`); const [chatReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${chatReportID}`); - const {transactions: reportTransactions} = useTransactionsAndViolationsForReport(moneyRequestReport?.reportID); - const transactions = Object.values(reportTransactions); - const {onSubmit, isApprove} = useHoldMenuSubmit({ moneyRequestReport, chatReport, @@ -56,7 +52,6 @@ function HoldMenuModalWrapper({ methodID, onClose: () => setIsVisible(false), onConfirm, - transactions, }); return ( diff --git a/src/components/MoneyReportHeader.tsx b/src/components/MoneyReportHeader.tsx index 17849830b8dd2..60f3add542f4f 100644 --- a/src/components/MoneyReportHeader.tsx +++ b/src/components/MoneyReportHeader.tsx @@ -22,7 +22,6 @@ import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset'; import useLocalize from '@hooks/useLocalize'; import useMobileSelectionMode from '@hooks/useMobileSelectionMode'; import useNetwork from '@hooks/useNetwork'; -import useNonReimbursablePaymentModal from '@hooks/useNonReimbursablePaymentModal'; import useOnyx from '@hooks/useOnyx'; import usePaginatedReportActions from '@hooks/usePaginatedReportActions'; import useParticipantsInvoiceReport from '@hooks/useParticipantsInvoiceReport'; @@ -80,7 +79,6 @@ import { getNextApproverAccountID, getPolicyExpenseChat, hasHeldExpenses as hasHeldExpensesReportUtils, - hasOnlyNonReimbursableTransactions, hasUpdatedTotal, hasViolations as hasViolationsReportUtils, isAllowedToApproveExpenseReport, @@ -466,7 +464,6 @@ function MoneyReportHeaderContent({reportID: reportIDProp, shouldDisplayBackButt const shouldDisplayNarrowMoreButton = !shouldDisplayNarrowVersion || isWideRHPDisplayedOnWideLayout || isSuperWideRHPDisplayedOnWideLayout; - const {showNonReimbursablePaymentErrorModal, shouldBlockDirectPayment} = useNonReimbursablePaymentModal(moneyRequestReport, transactions); const {openHoldMenu, openPDFDownload, openHoldEducational, openRejectModal} = useMoneyReportHeaderModals(); const showExportProgressModal = useCallback(() => { @@ -529,15 +526,11 @@ function MoneyReportHeaderContent({reportID: reportIDProp, shouldDisplayBackButt }); const canIOUBePaid = useMemo(() => getCanIOUBePaid(), [getCanIOUBePaid]); - const reportHasOnlyNonReimbursableTransactions = hasOnlyNonReimbursableTransactions(moneyRequestReport?.reportID, transactions); const onlyShowPayElsewhere = useMemo(() => { - if (reportHasOnlyNonReimbursableTransactions) { - return false; - } return !canIOUBePaid && getCanIOUBePaid(true); - }, [canIOUBePaid, getCanIOUBePaid, reportHasOnlyNonReimbursableTransactions]); + }, [canIOUBePaid, getCanIOUBePaid]); - const shouldShowPayButton = isPaidAnimationRunning || canIOUBePaid || onlyShowPayElsewhere || (reportHasOnlyNonReimbursableTransactions && (moneyRequestReport?.total ?? 0) !== 0); + const shouldShowPayButton = isPaidAnimationRunning || canIOUBePaid || onlyShowPayElsewhere; const shouldShowApproveButton = useMemo( () => (canApproveIOU(moneyRequestReport, policy, reportMetadata, transactions) && !hasOnlyPendingTransactions) || isApprovedAnimationRunning, @@ -567,10 +560,6 @@ function MoneyReportHeaderContent({reportID: reportIDProp, shouldDisplayBackButt if (!type || !chatReport) { return; } - if (shouldBlockDirectPayment(type)) { - showNonReimbursablePaymentErrorModal(); - return; - } const isFromSelectionMode = isSelectionModePaymentRef.current; if (isDelegateAccessRestricted) { showDelegateNoAccessModal(); @@ -659,8 +648,6 @@ function MoneyReportHeaderContent({reportID: reportIDProp, shouldDisplayBackButt isAnyTransactionOnHold, isInvoiceReport, showDelegateNoAccessModal, - showNonReimbursablePaymentErrorModal, - shouldBlockDirectPayment, openHoldMenu, startAnimation, moneyRequestReport, diff --git a/src/components/MoneyReportHeaderModals.tsx b/src/components/MoneyReportHeaderModals.tsx index c36d82f182b43..fb9df9fa44f56 100644 --- a/src/components/MoneyReportHeaderModals.tsx +++ b/src/components/MoneyReportHeaderModals.tsx @@ -8,7 +8,7 @@ import useOnyx from '@hooks/useOnyx'; import useTransactionsAndViolationsForReport from '@hooks/useTransactionsAndViolationsForReport'; import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID'; import getPlatform from '@libs/getPlatform'; -import {getNonHeldAndFullAmount, hasOnlyHeldExpenses as hasOnlyHeldExpensesReportUtils, hasOnlyNonReimbursableTransactions} from '@libs/ReportUtils'; +import {getNonHeldAndFullAmount, hasOnlyHeldExpenses as hasOnlyHeldExpensesReportUtils} from '@libs/ReportUtils'; import {canIOUBePaid as canIOUBePaidAction} from '@userActions/IOU'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; @@ -42,8 +42,7 @@ function MoneyReportHeaderModals({reportID, children}: MoneyReportHeaderModalsPr // Derive data for hold menu const canIOUBePaid = canIOUBePaidAction(moneyRequestReport, chatReport, policy, bankAccountList); const onlyShowPayElsewhere = !canIOUBePaid && canIOUBePaidAction(moneyRequestReport, chatReport, policy, bankAccountList, undefined, true); - const reportHasOnlyNonReimbursableTransactions = hasOnlyNonReimbursableTransactions(moneyRequestReport?.reportID, transactions); - const shouldShowPayButton = canIOUBePaid || onlyShowPayElsewhere || reportHasOnlyNonReimbursableTransactions; + const shouldShowPayButton = canIOUBePaid || onlyShowPayElsewhere; const {nonHeldAmount, fullAmount, hasValidNonHeldAmount} = getNonHeldAndFullAmount(moneyRequestReport, shouldShowPayButton); const hasOnlyHeldExpenses = hasOnlyHeldExpensesReportUtils(moneyRequestReport?.reportID); const transactionIDs = transactions.map((t) => t.transactionID); diff --git a/src/components/MoneyReportHeaderPrimaryAction/PayPrimaryAction.tsx b/src/components/MoneyReportHeaderPrimaryAction/PayPrimaryAction.tsx index 0bba9ba3b42bf..a46dbd6cb5e9e 100644 --- a/src/components/MoneyReportHeaderPrimaryAction/PayPrimaryAction.tsx +++ b/src/components/MoneyReportHeaderPrimaryAction/PayPrimaryAction.tsx @@ -7,7 +7,6 @@ import AnimatedSettlementButton from '@components/SettlementButton/AnimatedSettl import type {PaymentActionParams} from '@components/SettlementButton/types'; import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import useNetwork from '@hooks/useNetwork'; -import useNonReimbursablePaymentModal from '@hooks/useNonReimbursablePaymentModal'; import useOnyx from '@hooks/useOnyx'; import useParticipantsInvoiceReport from '@hooks/useParticipantsInvoiceReport'; import usePolicy from '@hooks/usePolicy'; @@ -16,18 +15,13 @@ import useTransactionsAndViolationsForReport from '@hooks/useTransactionsAndViol import {search} from '@libs/actions/Search'; import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID'; import {getTotalAmountForIOUReportPreviewButton} from '@libs/MoneyRequestReportUtils'; -import { - hasHeldExpenses as hasHeldExpensesReportUtils, - hasOnlyNonReimbursableTransactions, - hasUpdatedTotal, - isAllowedToApproveExpenseReport, - isInvoiceReport as isInvoiceReportUtil, -} from '@libs/ReportUtils'; +import {hasHeldExpenses as hasHeldExpensesReportUtils, hasUpdatedTotal, isAllowedToApproveExpenseReport, isInvoiceReport as isInvoiceReportUtil} from '@libs/ReportUtils'; import {isExpensifyCardTransaction, isPending} from '@libs/TransactionUtils'; import {canApproveIOU, canIOUBePaid as canIOUBePaidAction, payInvoice, payMoneyRequest} from '@userActions/IOU'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; +import type {Transaction} from '@src/types/onyx'; import useConfirmApproval from './useConfirmApproval'; import useTransactionThreadData from './useTransactionThreadData'; @@ -71,18 +65,16 @@ function PayPrimaryAction({reportID, chatReportID, isPaidAnimationRunning, isApp const {transactions: reportTransactionsMap} = useTransactionsAndViolationsForReport(moneyRequestReport?.reportID); const transactions = Object.values(reportTransactionsMap); const hasOnlyPendingTransactions = transactions.length > 0 && transactions.every((t) => isExpensifyCardTransaction(t) && isPending(t)); + const nonPendingDeleteTransactions = transactions.filter((t): t is Transaction => !!t && (isOffline || t.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE)); const canIOUBePaid = canIOUBePaidAction(moneyRequestReport, chatReport, policy, bankAccountList, transaction ? [transaction] : undefined, false, undefined, invoiceReceiverPolicy); - const reportHasOnlyNonReimbursableTransactions = hasOnlyNonReimbursableTransactions(moneyRequestReport?.reportID, transactions); - const {showNonReimbursablePaymentErrorModal, shouldBlockDirectPayment} = useNonReimbursablePaymentModal(moneyRequestReport, transactions); - const onlyShowPayElsewhere = reportHasOnlyNonReimbursableTransactions - ? false - : !canIOUBePaid && canIOUBePaidAction(moneyRequestReport, chatReport, policy, bankAccountList, transaction ? [transaction] : undefined, true, undefined, invoiceReceiverPolicy); - const shouldShowPayButton = isPaidAnimationRunning || canIOUBePaid || onlyShowPayElsewhere || (reportHasOnlyNonReimbursableTransactions && (moneyRequestReport?.total ?? 0) !== 0); + const onlyShowPayElsewhere = + !canIOUBePaid && canIOUBePaidAction(moneyRequestReport, chatReport, policy, bankAccountList, transaction ? [transaction] : undefined, true, undefined, invoiceReceiverPolicy); + const shouldShowPayButton = isPaidAnimationRunning || canIOUBePaid || onlyShowPayElsewhere; 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); + const totalAmount = getTotalAmountForIOUReportPreviewButton(moneyRequestReport, policy, CONST.REPORT.PRIMARY_ACTIONS.PAY, nonPendingDeleteTransactions); const isAnyTransactionOnHold = hasHeldExpensesReportUtils(moneyRequestReport?.reportID); const {currentSearchQueryJSON, currentSearchKey, currentSearchResults} = useSearchStateContext(); @@ -96,10 +88,6 @@ function PayPrimaryAction({reportID, chatReportID, isPaidAnimationRunning, isApp if (!type || !chatReport) { return; } - if (shouldBlockDirectPayment(type)) { - showNonReimbursablePaymentErrorModal(); - return; - } if (isDelegateAccessRestricted) { showDelegateNoAccessModal(); } else if (isAnyTransactionOnHold) { diff --git a/src/components/MoneyRequestReportView/MoneyRequestReportActionsList.tsx b/src/components/MoneyRequestReportView/MoneyRequestReportActionsList.tsx index d477a372e2e2f..1ed9d6926ad7d 100644 --- a/src/components/MoneyRequestReportView/MoneyRequestReportActionsList.tsx +++ b/src/components/MoneyRequestReportView/MoneyRequestReportActionsList.tsx @@ -1064,7 +1064,6 @@ function MoneyRequestReportActionsList({reportID: reportIDProp, onLayout}: Money hasNonHeldExpenses={!hasOnlyHeldExpenses} onConfirm={handleHoldMenuConfirm} transactionCount={transactions.length} - transactions={transactionsWithoutPendingDelete} /> )} diff --git a/src/components/ProcessMoneyReportHoldMenu.tsx b/src/components/ProcessMoneyReportHoldMenu.tsx index 3ce0875f1f43b..ec2b1d031c66f 100644 --- a/src/components/ProcessMoneyReportHoldMenu.tsx +++ b/src/components/ProcessMoneyReportHoldMenu.tsx @@ -44,9 +44,6 @@ type ProcessMoneyReportHoldMenuProps = { /** Whether the report has non held expenses */ hasNonHeldExpenses?: boolean; - - /** Transactions associated with report */ - transactions?: OnyxTypes.Transaction[]; }; function ProcessMoneyReportHoldMenu({ @@ -62,7 +59,6 @@ function ProcessMoneyReportHoldMenu({ transactionCount, onConfirm, hasNonHeldExpenses, - transactions, }: ProcessMoneyReportHoldMenuProps) { const {translate} = useLocalize(); // We need to use isSmallScreenWidth instead of shouldUseNarrowLayout to apply the correct modal type @@ -77,7 +73,6 @@ function ProcessMoneyReportHoldMenu({ methodID, onClose, onConfirm, - transactions, }); return ( diff --git a/src/components/ReportActionItem/MoneyRequestReportPreview/MoneyRequestReportPreviewContent.tsx b/src/components/ReportActionItem/MoneyRequestReportPreview/MoneyRequestReportPreviewContent.tsx index 6fadc556a2a3a..71eacada5a90e 100644 --- a/src/components/ReportActionItem/MoneyRequestReportPreview/MoneyRequestReportPreviewContent.tsx +++ b/src/components/ReportActionItem/MoneyRequestReportPreview/MoneyRequestReportPreviewContent.tsx @@ -20,7 +20,6 @@ import StatusBadge from '@components/StatusBadge'; import Text from '@components/Text'; import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset'; import useLocalize from '@hooks/useLocalize'; -import useNonReimbursablePaymentModal from '@hooks/useNonReimbursablePaymentModal'; import useOnyx from '@hooks/useOnyx'; import usePaymentAnimations from '@hooks/usePaymentAnimations'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; @@ -157,7 +156,6 @@ function MoneyRequestReportPreviewContent({ const [isHoldMenuVisible, setIsHoldMenuVisible] = useState(false); const [requestType, setRequestType] = useState(); - const {showNonReimbursablePaymentErrorModal} = useNonReimbursablePaymentModal(iouReport, transactions); const [paymentType, setPaymentType] = useState(); const [shouldShowPayButton, setShouldShowPayButton] = useState(false); const hasOnlyHeldExpenses = hasOnlyHeldExpensesReportUtils(iouReport?.reportID); @@ -710,7 +708,6 @@ function MoneyRequestReportPreviewContent({ onPaymentOptionsHide={onPaymentOptionsHide} openReportFromPreview={openReportFromPreview} onHoldMenuOpen={handleHoldMenuOpen} - onNonReimbursablePaymentError={showNonReimbursablePaymentErrorModal} transactionPreviewCarouselWidth={reportPreviewStyles.transactionPreviewCarouselStyle.width} /> {transactions.length > 1 && !shouldShowAccessPlaceHolder && ( @@ -747,7 +744,6 @@ function MoneyRequestReportPreviewContent({ chatReport={chatReport} moneyRequestReport={iouReport} transactionCount={numberOfRequests} - transactions={transactions} hasNonHeldExpenses={!hasOnlyHeldExpenses} onConfirm={() => { if (requestType === CONST.IOU.REPORT_ACTION_TYPE.APPROVE) { diff --git a/src/components/ReportActionItem/MoneyRequestReportPreview/PayActionButton.tsx b/src/components/ReportActionItem/MoneyRequestReportPreview/PayActionButton.tsx index c595a54ff7af8..823bbdbe869b1 100644 --- a/src/components/ReportActionItem/MoneyRequestReportPreview/PayActionButton.tsx +++ b/src/components/ReportActionItem/MoneyRequestReportPreview/PayActionButton.tsx @@ -13,13 +13,7 @@ import usePermissions from '@hooks/usePermissions'; import usePolicy from '@hooks/usePolicy'; import useReportTransactionsCollection from '@hooks/useReportTransactionsCollection'; import {getTotalAmountForIOUReportPreviewButton} from '@libs/MoneyRequestReportUtils'; -import { - hasHeldExpenses as hasHeldExpensesReportUtils, - hasOnlyNonReimbursableTransactions, - hasUpdatedTotal, - hasViolations as hasViolationsReportUtils, - isInvoiceReport as isInvoiceReportUtils, -} from '@libs/ReportUtils'; +import {hasHeldExpenses as hasHeldExpensesReportUtils, hasUpdatedTotal, hasViolations as hasViolationsReportUtils, isInvoiceReport as isInvoiceReportUtils} from '@libs/ReportUtils'; import {approveMoneyRequest, canIOUBePaid as canIOUBePaidIOUActions, payInvoice, payMoneyRequest} from '@userActions/IOU'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; @@ -38,7 +32,6 @@ type PayActionButtonProps = { onPaymentOptionsShow?: () => void; onPaymentOptionsHide?: () => void; onHoldMenuOpen: (requestType: string, paymentType?: PaymentMethodType, canPay?: boolean) => void; - onNonReimbursablePaymentError?: () => void; buttonMaxWidth: {maxWidth?: number}; reportPreviewAction: ValueOf; }; @@ -54,7 +47,6 @@ function PayActionButton({ onPaymentOptionsShow, onPaymentOptionsHide, onHoldMenuOpen, - onNonReimbursablePaymentError, buttonMaxWidth, reportPreviewAction, }: PayActionButtonProps) { @@ -97,11 +89,8 @@ function PayActionButton({ const hasViolations = hasViolationsReportUtils(iouReport?.reportID, transactionViolations, currentUserAccountID, currentUserEmail); const canIOUBePaid = canIOUBePaidIOUActions(iouReport, chatReport, policy, bankAccountList, transactions, false, undefined, invoiceReceiverPolicy); - const reportHasOnlyNonReimbursableTransactions = hasOnlyNonReimbursableTransactions(iouReport?.reportID, transactions); - const onlyShowPayElsewhere = reportHasOnlyNonReimbursableTransactions - ? false - : !canIOUBePaid && canIOUBePaidIOUActions(iouReport, chatReport, policy, bankAccountList, transactions, true, undefined, invoiceReceiverPolicy); - const shouldShowPayButton = isPaidAnimationRunning || canIOUBePaid || onlyShowPayElsewhere || (reportHasOnlyNonReimbursableTransactions && (iouReport?.total ?? 0) !== 0); + const onlyShowPayElsewhere = !canIOUBePaid && canIOUBePaidIOUActions(iouReport, chatReport, policy, bankAccountList, transactions, true, undefined, invoiceReceiverPolicy); + const shouldShowPayButton = isPaidAnimationRunning || canIOUBePaid || onlyShowPayElsewhere; const shouldShowOnlyPayElsewhere = !canIOUBePaid && onlyShowPayElsewhere; const canIOUBePaidAndApproved = canIOUBePaid; @@ -136,10 +125,6 @@ function PayActionButton({ if (!type) { return; } - if (!isInvoiceReportUtils(iouReport) && reportHasOnlyNonReimbursableTransactions && type !== CONST.IOU.PAYMENT_TYPE.ELSEWHERE) { - onNonReimbursablePaymentError?.(); - return; - } if (isDelegateAccessRestricted) { showDelegateNoAccessModal(); } else if (hasHeldExpensesReportUtils(iouReport?.reportID)) { diff --git a/src/components/ReportActionItem/MoneyRequestReportPreview/ReportPreviewActionButton.tsx b/src/components/ReportActionItem/MoneyRequestReportPreview/ReportPreviewActionButton.tsx index 838faee3c16b5..2376bedc3500b 100644 --- a/src/components/ReportActionItem/MoneyRequestReportPreview/ReportPreviewActionButton.tsx +++ b/src/components/ReportActionItem/MoneyRequestReportPreview/ReportPreviewActionButton.tsx @@ -39,7 +39,6 @@ type ReportPreviewActionButtonProps = { startSubmittingAnimation: () => void; onPaymentOptionsShow?: () => void; onPaymentOptionsHide?: () => void; - onNonReimbursablePaymentError?: () => void; openReportFromPreview: () => void; onHoldMenuOpen: (requestType: string, paymentType?: PaymentMethodType, canPay?: boolean) => void; transactionPreviewCarouselWidth: number; @@ -57,7 +56,6 @@ function ReportPreviewActionButton({ startSubmittingAnimation, onPaymentOptionsShow, onPaymentOptionsHide, - onNonReimbursablePaymentError, openReportFromPreview, onHoldMenuOpen, transactionPreviewCarouselWidth, @@ -156,7 +154,6 @@ function ReportPreviewActionButton({ onPaymentOptionsShow={onPaymentOptionsShow} onPaymentOptionsHide={onPaymentOptionsHide} onHoldMenuOpen={onHoldMenuOpen} - onNonReimbursablePaymentError={onNonReimbursablePaymentError} buttonMaxWidth={buttonMaxWidth} reportPreviewAction={reportPreviewAction} /> diff --git a/src/components/Search/SearchBulkActionsButton.tsx b/src/components/Search/SearchBulkActionsButton.tsx index d0184c76a33c3..099cb9f498af2 100644 --- a/src/components/Search/SearchBulkActionsButton.tsx +++ b/src/components/Search/SearchBulkActionsButton.tsx @@ -60,13 +60,11 @@ function SearchBulkActionsButton({queryJSON}: SearchBulkActionsButtonProps) { confirmPayment, isOfflineModalVisible, isDownloadErrorModalVisible, - isNonReimbursablePaymentErrorModalVisible, isHoldEducationalModalVisible, rejectModalAction, emptyReportsCount, handleOfflineModalClose, handleDownloadErrorModalClose, - handleNonReimbursablePaymentErrorModalClose, dismissModalAndUpdateUseHold, dismissRejectModalBasedOnAction, isDuplicateOptionVisible, @@ -243,15 +241,6 @@ function SearchBulkActionsButton({queryJSON}: SearchBulkActionsButtonProps) { isVisible={isDownloadErrorModalVisible} onClose={handleDownloadErrorModalClose} /> - 1)} - isSmallScreenWidth={isSmallScreenWidth} - onSecondOptionSubmit={handleNonReimbursablePaymentErrorModalClose} - secondOptionText={translate('common.buttonConfirm')} - isVisible={isNonReimbursablePaymentErrorModalVisible} - onClose={handleNonReimbursablePaymentErrorModalClose} - /> {!!rejectModalAction && ( void; onConfirm?: (full: boolean) => void; - transactions?: OnyxTypes.Transaction[]; }; -function useHoldMenuSubmit({moneyRequestReport, chatReport, requestType, paymentType, methodID, onClose, onConfirm, transactions}: UseHoldMenuSubmitParams) { +function useHoldMenuSubmit({moneyRequestReport, chatReport, requestType, paymentType, methodID, onClose, onConfirm}: UseHoldMenuSubmitParams) { const [userBillingGracePeriodEnds] = 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); @@ -48,7 +46,6 @@ function useHoldMenuSubmit({moneyRequestReport, chatReport, requestType, payment const {isDelegateAccessRestricted} = useDelegateNoAccessState(); const {showDelegateNoAccessModal} = useDelegateNoAccessActions(); - const {showNonReimbursablePaymentErrorModal} = useNonReimbursablePaymentModal(moneyRequestReport, transactions); const isApprove = requestType === CONST.IOU.REPORT_ACTION_TYPE.APPROVE; @@ -58,12 +55,6 @@ function useHoldMenuSubmit({moneyRequestReport, chatReport, requestType, payment return; } - if (!isApprove && chatReport && hasOnlyNonReimbursableTransactions(moneyRequestReport?.reportID, transactions) && paymentType && paymentType !== CONST.IOU.PAYMENT_TYPE.ELSEWHERE) { - onClose(); - showNonReimbursablePaymentErrorModal(); - return; - } - const animationCallback = () => onConfirm?.(full); if (isApprove) { diff --git a/src/hooks/useNonReimbursablePaymentModal.ts b/src/hooks/useNonReimbursablePaymentModal.ts deleted file mode 100644 index d37e7bccbbb21..0000000000000 --- a/src/hooks/useNonReimbursablePaymentModal.ts +++ /dev/null @@ -1,36 +0,0 @@ -import type {OnyxEntry} from 'react-native-onyx'; -import {hasOnlyNonReimbursableTransactions, isInvoiceReport} from '@libs/ReportUtils'; -import CONST from '@src/CONST'; -import type {Report, Transaction} from '@src/types/onyx'; -import type {PaymentMethodType} from '@src/types/onyx/OriginalMessage'; -import useDecisionModal from './useDecisionModal'; -import useLocalize from './useLocalize'; - -type UseNonReimbursablePaymentModalReturn = { - showNonReimbursablePaymentErrorModal: () => void; - shouldBlockDirectPayment: (paymentType: PaymentMethodType) => boolean; -}; - -/** Blocks direct payment and shows the error modal when the report contains only non-reimbursable expenses. */ -function useNonReimbursablePaymentModal(iouReport: OnyxEntry, transactions?: Transaction[]): UseNonReimbursablePaymentModalReturn { - const {translate} = useLocalize(); - const {showDecisionModal} = useDecisionModal(); - - const showNonReimbursablePaymentErrorModal = () => { - showDecisionModal({ - title: translate('iou.error.nonReimbursablePayment'), - prompt: translate('iou.error.nonReimbursablePaymentDescription', false), - secondOptionText: translate('common.buttonConfirm'), - }); - }; - - const shouldBlockDirectPayment = (paymentType: PaymentMethodType): boolean => - !isInvoiceReport(iouReport) && hasOnlyNonReimbursableTransactions(iouReport?.reportID, transactions) && paymentType !== CONST.IOU.PAYMENT_TYPE.ELSEWHERE; - - return { - showNonReimbursablePaymentErrorModal, - shouldBlockDirectPayment, - }; -} - -export default useNonReimbursablePaymentModal; diff --git a/src/hooks/useSearchBulkActions.ts b/src/hooks/useSearchBulkActions.ts index 7481b7d6a8a3f..23e1e3d9cbe1f 100644 --- a/src/hooks/useSearchBulkActions.ts +++ b/src/hooks/useSearchBulkActions.ts @@ -41,7 +41,6 @@ import { getIntegrationIcon, getPolicyExpenseChat, getReportOrDraftReport, - hasOnlyNonReimbursableTransactions, isArchivedReport, isBusinessInvoiceRoom, isCurrentUserSubmitter, @@ -231,7 +230,6 @@ function useSearchBulkActions({queryJSON}: UseSearchBulkActionsParams) { const [isOfflineModalVisible, setIsOfflineModalVisible] = useState(false); const [isDownloadErrorModalVisible, setIsDownloadErrorModalVisible] = useState(false); - const [isNonReimbursablePaymentErrorModalVisible, setIsNonReimbursablePaymentErrorModalVisible] = useState(false); const {showConfirmModal} = useConfirmModal(); const [isHoldEducationalModalVisible, setIsHoldEducationalModalVisible] = useState(false); const [rejectModalAction, setRejectModalAction] = useState => !!transaction && transaction.reportID === itemReportID, ); - if ( - isExpenseReport && - !isInvoiceReport(itemReportID) && - hasOnlyNonReimbursableTransactions(itemReportID, reportTransactions.length > 0 ? reportTransactions : undefined) && - lastPolicyPaymentMethod !== CONST.IOU.PAYMENT_TYPE.ELSEWHERE - ) { - setIsNonReimbursablePaymentErrorModalVisible(true); - return; - } - const hasPolicyVBBA = itemPolicyID ? policyIDsWithVBBA.includes(itemPolicyID) : false; // Allow bulk pay when user selected a business bank account, even if that account is not linked to the report's policy const hasSelectedBusinessBankAccount = expenseReportBankAccountID != null; @@ -1373,21 +1361,6 @@ function useSearchBulkActions({queryJSON}: UseSearchBulkActionsParams) { selectedTransactions, queryJSON?.type, expensifyIcons, - expensifyIcons.Export, - expensifyIcons.ArrowRight, - expensifyIcons.Table, - expensifyIcons.ThumbsUp, - expensifyIcons.ThumbsDown, - expensifyIcons.Send, - expensifyIcons.MoneyBag, - expensifyIcons.Stopwatch, - expensifyIcons.ArrowCollapse, - expensifyIcons.DocumentMerge, - expensifyIcons.ArrowSplit, - expensifyIcons.Pencil, - expensifyIcons.Trashcan, - expensifyIcons.Exclamation, - expensifyIcons.Workflows, translate, areAllMatchingItemsSelected, isOffline, @@ -1453,10 +1426,6 @@ function useSearchBulkActions({queryJSON}: UseSearchBulkActionsParams) { setIsDownloadErrorModalVisible(false); }, [setIsDownloadErrorModalVisible]); - const handleNonReimbursablePaymentErrorModalClose = useCallback(() => { - setIsNonReimbursablePaymentErrorModalVisible(false); - }, [setIsNonReimbursablePaymentErrorModalVisible]); - const dismissModalAndUpdateUseHold = useCallback(() => { setIsHoldEducationalModalVisible(false); setNameValuePair(ONYXKEYS.NVP_DISMISSED_HOLD_USE_EXPLANATION, true, false, !isOffline); @@ -1487,13 +1456,11 @@ function useSearchBulkActions({queryJSON}: UseSearchBulkActionsParams) { confirmPayment: stableOnBulkPaySelected, isOfflineModalVisible, isDownloadErrorModalVisible, - isNonReimbursablePaymentErrorModalVisible, isHoldEducationalModalVisible, rejectModalAction, emptyReportsCount, handleOfflineModalClose, handleDownloadErrorModalClose, - handleNonReimbursablePaymentErrorModalClose, dismissModalAndUpdateUseHold, dismissRejectModalBasedOnAction, isDuplicateOptionVisible, diff --git a/src/hooks/useSelectionModeReportActions.ts b/src/hooks/useSelectionModeReportActions.ts index b24de6afef1d5..d6ccdd2b06f2a 100644 --- a/src/hooks/useSelectionModeReportActions.ts +++ b/src/hooks/useSelectionModeReportActions.ts @@ -28,7 +28,6 @@ import { getNonHeldAndFullAmount, hasHeldExpenses as hasHeldExpensesReportUtils, hasOnlyHeldExpenses as hasOnlyHeldExpensesReportUtils, - hasOnlyNonReimbursableTransactions, hasUpdatedTotal, hasViolations as hasViolationsReportUtils, isAllowedToApproveExpenseReport, @@ -48,7 +47,6 @@ import useConfirmPendingRTERAndProceed from './useConfirmPendingRTERAndProceed'; import useCurrentUserPersonalDetails from './useCurrentUserPersonalDetails'; import {useMemoizedLazyExpensifyIcons} from './useLazyAsset'; import useLocalize from './useLocalize'; -import useNonReimbursablePaymentModal from './useNonReimbursablePaymentModal'; import useOnyx from './useOnyx'; import useParticipantsInvoiceReport from './useParticipantsInvoiceReport'; import usePaymentOptions from './usePaymentOptions'; @@ -119,7 +117,6 @@ function useSelectionModeReportActions({ const activeAdminPolicies = useActiveAdminPolicies(); const isChatReportArchived = useReportIsArchived(chatReport?.reportID); - const {showNonReimbursablePaymentErrorModal, shouldBlockDirectPayment} = useNonReimbursablePaymentModal(report, transactions); const expensifyIcons = useMemoizedLazyExpensifyIcons(['Send', 'ThumbsUp', 'Cash', 'ArrowRight', 'Building'] as const); @@ -154,15 +151,15 @@ function useSelectionModeReportActions({ const isInvoiceReport = isInvoiceReportUtil(report); const hasOnlyPendingTransactions = !!transactions && transactions.length > 0 && transactions.every((t) => isExpensifyCardTransaction(t) && isPending(t)); + const nonPendingDeleteTransactions = transactions.filter((t): t is OnyxTypes.Transaction => !!t && (isOffline || t.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE)); const getCanIOUBePaid = (onlyShowPayElsewhere = false) => canIOUBePaidAction(report, chatReport, policy, bankAccountList, transactions, onlyShowPayElsewhere, undefined, invoiceReceiverPolicy); const canIOUBePaid = getCanIOUBePaid(); - const reportHasOnlyNonReimbursableTransactions = hasOnlyNonReimbursableTransactions(report?.reportID, transactions); - const onlyShowPayElsewhere = reportHasOnlyNonReimbursableTransactions ? false : !canIOUBePaid && getCanIOUBePaid(true); + const onlyShowPayElsewhere = !canIOUBePaid && getCanIOUBePaid(true); - const shouldShowPayButton = canIOUBePaid || onlyShowPayElsewhere || (reportHasOnlyNonReimbursableTransactions && (report?.total ?? 0) !== 0); + const shouldShowPayButton = canIOUBePaid || onlyShowPayElsewhere; const {nonHeldAmount, fullAmount, hasValidNonHeldAmount} = getNonHeldAndFullAmount(report, shouldShowPayButton); @@ -170,7 +167,7 @@ function useSelectionModeReportActions({ const shouldDisableApproveButton = shouldShowApproveButton && !isAllowedToApproveExpenseReport(report); - const totalAmount = getTotalAmountForIOUReportPreviewButton(report, policy, CONST.REPORT.PRIMARY_ACTIONS.PAY); + const totalAmount = getTotalAmountForIOUReportPreviewButton(report, policy, CONST.REPORT.PRIMARY_ACTIONS.PAY, nonPendingDeleteTransactions); // confirmPayment is declared below but used by usePaymentOptions; we use a ref to avoid a circular dependency. const confirmPaymentRef = useRef<(params: PaymentActionParams) => void>(() => {}); @@ -338,10 +335,6 @@ function useSelectionModeReportActions({ if (!type || !chatReport) { return; } - if (shouldBlockDirectPayment(type)) { - showNonReimbursablePaymentErrorModal(); - return; - } setPaymentType(type); setRequestType(CONST.IOU.REPORT_ACTION_TYPE.PAY); if (isDelegateAccessRestricted) { diff --git a/src/languages/de.ts b/src/languages/de.ts index 752e1256bb7a8..5ef1869761861 100644 --- a/src/languages/de.ts +++ b/src/languages/de.ts @@ -1425,11 +1425,6 @@ const translations: TranslationDeepObject = { manySplitsProvided: `Die maximale Anzahl zulässiger Aufteilungen beträgt ${CONST.IOU.SPLITS_LIMIT}.`, dateRangeExceedsMaxDays: `Der Datumsbereich darf ${CONST.IOU.SPLITS_LIMIT} Tage nicht überschreiten.`, stitchOdometerImagesFailed: 'Kilometerzählerbilder konnten nicht zusammengeführt werden. Bitte versuchen Sie es später noch einmal.', - nonReimbursablePayment: 'Kann nicht über Expensify bezahlt werden', - nonReimbursablePaymentDescription: (isMultiple?: boolean) => - isMultiple - ? 'Einer oder mehrere ausgewählte Berichte enthalten keine erstattungsfähigen Ausgaben. Überprüfe die Ausgaben erneut oder markiere sie manuell als bezahlt.' - : 'Der Bericht enthält keine erstattungsfähigen Ausgaben. Überprüfe die Ausgaben erneut oder markiere ihn manuell als bezahlt.', }, dismissReceiptError: 'Fehler ausblenden', dismissReceiptErrorConfirmation: 'Achtung! Wenn du diesen Fehler schließt, wird deine hochgeladene Quittung vollständig entfernt. Bist du sicher?', diff --git a/src/languages/en.ts b/src/languages/en.ts index 478d73a43ac74..1c73b8e8a48df 100644 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -1477,11 +1477,6 @@ const translations = { endDateSameAsStartDate: "The end date can't be the same as the start date", manySplitsProvided: `The maximum splits allowed is ${CONST.IOU.SPLITS_LIMIT}.`, dateRangeExceedsMaxDays: `The date range can't exceed ${CONST.IOU.SPLITS_LIMIT} days.`, - nonReimbursablePayment: 'Cannot pay via Expensify', - nonReimbursablePaymentDescription: (isMultiple?: boolean) => - isMultiple - ? "One or more selected reports don't have reimbursable expenses. Double check the expenses, or manually mark as paid." - : "The report doesn't have reimbursable expenses. Double check the expenses, or manually mark as paid.", }, dismissReceiptError: 'Dismiss error', dismissReceiptErrorConfirmation: 'Heads up! Dismissing this error will remove your uploaded receipt entirely. Are you sure?', diff --git a/src/languages/es.ts b/src/languages/es.ts index 1d106155ca772..aa8e424075b7d 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -1363,11 +1363,6 @@ const translations: TranslationDeepObject = { endDateSameAsStartDate: 'La fecha de finalización no puede ser la misma que la fecha de inicio', manySplitsProvided: `La cantidad máxima de divisiones permitidas es ${CONST.IOU.SPLITS_LIMIT}.`, dateRangeExceedsMaxDays: `El rango de fechas no puede exceder los ${CONST.IOU.SPLITS_LIMIT} días.`, - nonReimbursablePayment: 'No se puede pagar a través de Expensify', - nonReimbursablePaymentDescription: (isMultiple?: boolean) => - isMultiple - ? 'Uno o más informes seleccionados no tienen gastos reembolsables. Vuelve a revisar los gastos o márcalos manualmente como pagados.' - : 'El informe no tiene gastos reembolsables. Vuelve a revisar los gastos o márcalo manualmente como pagado.', }, dismissReceiptError: 'Descartar error', dismissReceiptErrorConfirmation: '¡Atención! Descartar este error eliminará completamente tu recibo cargado. ¿Estás seguro?', diff --git a/src/languages/fr.ts b/src/languages/fr.ts index 7a64d56cf77f0..975aa98dc73c8 100644 --- a/src/languages/fr.ts +++ b/src/languages/fr.ts @@ -1429,11 +1429,6 @@ const translations: TranslationDeepObject = { manySplitsProvided: `Le nombre maximal de répartitions autorisées est de ${CONST.IOU.SPLITS_LIMIT}.`, dateRangeExceedsMaxDays: `La plage de dates ne peut pas dépasser ${CONST.IOU.SPLITS_LIMIT} jours.`, stitchOdometerImagesFailed: 'Échec de la combinaison des images de l’odomètre. Veuillez réessayer plus tard.', - nonReimbursablePayment: 'Impossible de payer via Expensify', - nonReimbursablePaymentDescription: (isMultiple?: boolean) => - isMultiple - ? 'Un ou plusieurs rapports sélectionnés ne contiennent pas de dépenses remboursables. Vérifiez les dépenses ou marquez-les manuellement comme payés.' - : 'Le rapport ne contient pas de dépenses remboursables. Vérifiez les dépenses ou marquez-le manuellement comme payé.', }, dismissReceiptError: 'Ignorer l’erreur', dismissReceiptErrorConfirmation: 'Attention ! Ignorer cette erreur supprimera complètement votre reçu téléversé. Êtes-vous sûr ?', diff --git a/src/languages/it.ts b/src/languages/it.ts index e644ec155a928..a0e1628081c4b 100644 --- a/src/languages/it.ts +++ b/src/languages/it.ts @@ -1423,11 +1423,6 @@ const translations: TranslationDeepObject = { manySplitsProvided: `Il numero massimo di suddivisioni consentite è ${CONST.IOU.SPLITS_LIMIT}.`, dateRangeExceedsMaxDays: `L’intervallo di date non può superare ${CONST.IOU.SPLITS_LIMIT} giorni.`, stitchOdometerImagesFailed: 'Impossibile combinare le immagini del contachilometri. Riprova più tardi.', - nonReimbursablePayment: 'Impossibile pagare tramite Expensify', - nonReimbursablePaymentDescription: (isMultiple?: boolean) => - isMultiple - ? 'Uno o più report selezionati non contengono spese rimborsabili. Ricontrolla le spese oppure contrassegnali manualmente come pagati.' - : 'Il report non contiene spese rimborsabili. Ricontrolla le spese oppure contrassegnalo manualmente come pagato.', }, dismissReceiptError: 'Ignora errore', dismissReceiptErrorConfirmation: 'Attenzione! Chiudere questo errore rimuoverà completamente la ricevuta che hai caricato. Sei sicuro?', diff --git a/src/languages/ja.ts b/src/languages/ja.ts index efa46fcc3fe32..1fc42b96614c4 100644 --- a/src/languages/ja.ts +++ b/src/languages/ja.ts @@ -1405,11 +1405,6 @@ const translations: TranslationDeepObject = { manySplitsProvided: `分割できる最大数は${CONST.IOU.SPLITS_LIMIT}件です。`, dateRangeExceedsMaxDays: `日付範囲は${CONST.IOU.SPLITS_LIMIT}日を超えることはできません。`, stitchOdometerImagesFailed: '走行距離計の画像を結合できませんでした。後でもう一度お試しください。', - nonReimbursablePayment: 'Expensify経由では支払えません', - nonReimbursablePaymentDescription: (isMultiple?: boolean) => - isMultiple - ? '1つ以上の選択したレポートには精算可能な経費がありません。経費を再確認するか、手動で支払い済みにしてください。' - : 'このレポートには精算可能な経費がありません。経費を再確認するか、手動で支払い済みにしてください。', }, dismissReceiptError: 'エラーを閉じる', dismissReceiptErrorConfirmation: 'ご注意ください!このエラーを閉じると、アップロード済みのレシートが完全に削除されます。本当に続行しますか?', diff --git a/src/languages/nl.ts b/src/languages/nl.ts index ccdb7aa0a256c..da68ff543f214 100644 --- a/src/languages/nl.ts +++ b/src/languages/nl.ts @@ -1421,11 +1421,6 @@ const translations: TranslationDeepObject = { manySplitsProvided: `Het maximale aantal toegestane splitsingen is ${CONST.IOU.SPLITS_LIMIT}.`, dateRangeExceedsMaxDays: `Het datumbereik mag niet meer dan ${CONST.IOU.SPLITS_LIMIT} dagen zijn.`, stitchOdometerImagesFailed: 'Odometerafbeeldingen combineren mislukt. Probeer het later opnieuw.', - nonReimbursablePayment: 'Kan niet via Expensify worden betaald', - nonReimbursablePaymentDescription: (isMultiple?: boolean) => - isMultiple - ? 'Een of meer geselecteerde rapporten bevatten geen declareerbare kosten. Controleer de kosten opnieuw of markeer ze handmatig als betaald.' - : 'Het rapport bevat geen declareerbare kosten. Controleer de kosten opnieuw of markeer het handmatig als betaald.', }, dismissReceiptError: 'Foutmelding sluiten', dismissReceiptErrorConfirmation: 'Let op! Dit foutbericht negeren verwijdert je geüploade bon volledig. Weet je het zeker?', diff --git a/src/languages/pl.ts b/src/languages/pl.ts index e4e3acf3e9014..73e8470291d22 100644 --- a/src/languages/pl.ts +++ b/src/languages/pl.ts @@ -1419,11 +1419,6 @@ const translations: TranslationDeepObject = { manySplitsProvided: `Maksymalna dozwolona liczba podziałów to ${CONST.IOU.SPLITS_LIMIT}.`, dateRangeExceedsMaxDays: `Zakres dat nie może przekraczać ${CONST.IOU.SPLITS_LIMIT} dni.`, stitchOdometerImagesFailed: 'Nie udało się połączyć zdjęć licznika kilometrów. Spróbuj ponownie później.', - nonReimbursablePayment: 'Nie można zapłacić przez Expensify', - nonReimbursablePaymentDescription: (isMultiple?: boolean) => - isMultiple - ? 'Co najmniej jeden z wybranych raportów nie zawiera wydatków podlegających zwrotowi. Sprawdź wydatki ponownie lub oznacz je ręcznie jako opłacone.' - : 'Raport nie zawiera wydatków podlegających zwrotowi. Sprawdź wydatki ponownie lub oznacz go ręcznie jako opłacony.', }, dismissReceiptError: 'Odrzuć błąd', dismissReceiptErrorConfirmation: 'Uwaga! Zamknięcie tego błędu spowoduje całkowite usunięcie przesłanego paragonu. Czy na pewno chcesz kontynuować?', diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts index 6ca934340b49c..d9c226dcc2ce4 100644 --- a/src/languages/pt-BR.ts +++ b/src/languages/pt-BR.ts @@ -1418,11 +1418,6 @@ const translations: TranslationDeepObject = { manySplitsProvided: `O número máximo de divisões permitido é ${CONST.IOU.SPLITS_LIMIT}.`, dateRangeExceedsMaxDays: `O intervalo de datas não pode exceder ${CONST.IOU.SPLITS_LIMIT} dias.`, stitchOdometerImagesFailed: 'Falha ao combinar imagens do hodômetro. Tente novamente mais tarde.', - nonReimbursablePayment: 'Não é possível pagar via Expensify', - nonReimbursablePaymentDescription: (isMultiple?: boolean) => - isMultiple - ? 'Um ou mais relatórios selecionados não possuem despesas reembolsáveis. Verifique as despesas novamente ou marque-os manualmente como pagos.' - : 'O relatório não possui despesas reembolsáveis. Verifique as despesas novamente ou marque-o manualmente como pago.', }, dismissReceiptError: 'Dispensar erro', dismissReceiptErrorConfirmation: 'Atenção! Ignorar este erro removerá completamente o comprovante que você enviou. Tem certeza?', diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts index c2cf6cccab2b8..703eaf3425c40 100644 --- a/src/languages/zh-hans.ts +++ b/src/languages/zh-hans.ts @@ -1378,9 +1378,6 @@ const translations: TranslationDeepObject = { manySplitsProvided: `允许的最大拆分数为 ${CONST.IOU.SPLITS_LIMIT}。`, dateRangeExceedsMaxDays: `日期范围不能超过 ${CONST.IOU.SPLITS_LIMIT} 天。`, stitchOdometerImagesFailed: '合并里程表图片失败。请稍后重试。', - nonReimbursablePayment: '无法通过 Expensify 付款', - nonReimbursablePaymentDescription: (isMultiple?: boolean) => - isMultiple ? '一个或多个所选报告没有可报销的费用。请再次检查费用,或手动将其标记为已支付。' : '该报告没有可报销的费用。请再次检查费用,或手动将其标记为已支付。', }, dismissReceiptError: '忽略错误', dismissReceiptErrorConfirmation: '提醒:关闭此错误将彻底删除你上传的收据。确定要继续吗?', diff --git a/src/libs/MoneyRequestReportUtils.ts b/src/libs/MoneyRequestReportUtils.ts index f5c542e3bbc6d..957b9196bed6f 100644 --- a/src/libs/MoneyRequestReportUtils.ts +++ b/src/libs/MoneyRequestReportUtils.ts @@ -151,13 +151,14 @@ function shouldWaitForTransactions(report: OnyxEntry, transactions: Tran * @param report - Onyx report object * @param policy - Onyx policy object * @param reportPreviewAction - The action that will take place when button is clicked which determines how amounts are calculated and displayed. + * @param transactions * @returns - The total amount to be formatted as a string. Returns an empty string if no amount is applicable. */ const getTotalAmountForIOUReportPreviewButton = ( report: OnyxEntry, policy: OnyxEntry, reportPreviewAction: ValueOf, - transactions?: Transaction[], + transactions: Transaction[], ) => { // 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); diff --git a/src/libs/SearchUIUtils.ts b/src/libs/SearchUIUtils.ts index 88a116a7b3ca8..cb37da2b26055 100644 --- a/src/libs/SearchUIUtils.ts +++ b/src/libs/SearchUIUtils.ts @@ -143,7 +143,6 @@ import { hasAnyViolations, hasHeldExpenses, hasInvoiceReports, - hasOnlyNonReimbursableTransactions, isAllowedToApproveExpenseReport as isAllowedToApproveExpenseReportUtils, isArchivedReport, isClosedReport, @@ -2040,11 +2039,10 @@ function getActions( const chatReport = getChatReport(data, report); const canBePaid = canIOUBePaid(report, chatReport, policy, bankAccountList, allReportTransactions, false, chatReportRNVP, invoiceReceiverPolicy); const canOnlyBePaidElsewhere = canIOUBePaid(report, chatReport, policy, bankAccountList, allReportTransactions, true, chatReportRNVP, invoiceReceiverPolicy); - const reportHasOnlyNonReimbursableTransactions = hasOnlyNonReimbursableTransactions(report?.reportID, allReportTransactions?.length ? allReportTransactions : undefined); - const shouldOnlyShowElsewhere = !canBePaid && canOnlyBePaidElsewhere && !reportHasOnlyNonReimbursableTransactions; + const shouldOnlyShowElsewhere = !canBePaid && canOnlyBePaidElsewhere; // We're not supporting pay partial amount on search page now. - if ((canBePaid || shouldOnlyShowElsewhere || (reportHasOnlyNonReimbursableTransactions && canOnlyBePaidElsewhere)) && !hasHeldExpenses(report.reportID, allReportTransactions)) { + if ((canBePaid || shouldOnlyShowElsewhere) && !hasHeldExpenses(report.reportID, allReportTransactions)) { allActions.push(CONST.SEARCH.ACTION_TYPES.PAY); } @@ -2052,7 +2050,7 @@ function getActions( allActions.push(CONST.SEARCH.ACTION_TYPES.EXPORT_TO_ACCOUNTING); } - if (isClosedReport(report) && !(canBePaid || shouldOnlyShowElsewhere || (reportHasOnlyNonReimbursableTransactions && canOnlyBePaidElsewhere))) { + if (isClosedReport(report) && !(canBePaid || shouldOnlyShowElsewhere)) { return allActions.length > 0 ? allActions : [CONST.SEARCH.ACTION_TYPES.DONE]; } diff --git a/tests/unit/MoneyRequestReportButtonUtils.test.ts b/tests/unit/MoneyRequestReportButtonUtils.test.ts index f83ac7b300122..743421f63c71e 100644 --- a/tests/unit/MoneyRequestReportButtonUtils.test.ts +++ b/tests/unit/MoneyRequestReportButtonUtils.test.ts @@ -45,15 +45,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, [])).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`); }); 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, [])).toBe(`$100.00`); }); }); }); diff --git a/tests/unit/hooks/useSelectionModeReportActions.test.ts b/tests/unit/hooks/useSelectionModeReportActions.test.ts index 6d01eccb3d9e0..f84165b698ba1 100644 --- a/tests/unit/hooks/useSelectionModeReportActions.test.ts +++ b/tests/unit/hooks/useSelectionModeReportActions.test.ts @@ -104,15 +104,6 @@ jest.mock('@hooks/usePaymentOptions', () => ({ default: jest.fn(() => []), })); -jest.mock('@hooks/useNonReimbursablePaymentModal', () => ({ - __esModule: true, - default: jest.fn(() => ({ - showNonReimbursablePaymentErrorModal: jest.fn(), - shouldBlockDirectPayment: jest.fn(() => false), - nonReimbursablePaymentErrorDecisionModal: null, - })), -})); - jest.mock('@hooks/useLazyAsset', () => ({ __esModule: true, useMemoizedLazyExpensifyIcons: jest.fn(() => ({