diff --git a/src/components/MoneyReportHeader.tsx b/src/components/MoneyReportHeader.tsx index 32389fca5c77..1d6c3fe4cfba 100644 --- a/src/components/MoneyReportHeader.tsx +++ b/src/components/MoneyReportHeader.tsx @@ -176,7 +176,8 @@ function MoneyReportHeader({policy, report: moneyRequestReport, transactionThrea const isAdmin = policy?.role === CONST.POLICY.ROLE.ADMIN; - const shouldShowSubmitButton = canSubmitReport(moneyRequestReport, policy, transactionIDs); + const filteredTransactions = transactions?.filter((t) => t) ?? []; + const shouldShowSubmitButton = canSubmitReport(moneyRequestReport, policy, filteredTransactions); const shouldShowExportIntegrationButton = !shouldShowPayButton && !shouldShowSubmitButton && connectedIntegration && isAdmin && canBeExported(moneyRequestReport); diff --git a/src/components/ReportActionItem/ReportPreview.tsx b/src/components/ReportActionItem/ReportPreview.tsx index 3a2220515a9c..e975bcb94481 100644 --- a/src/components/ReportActionItem/ReportPreview.tsx +++ b/src/components/ReportActionItem/ReportPreview.tsx @@ -237,8 +237,8 @@ function ReportPreview({ const lastThreeTransactions = transactions?.slice(-3) ?? []; const lastTransaction = transactions?.at(0); const lastThreeReceipts = lastThreeTransactions.map((transaction) => ({...getThumbnailAndImageURIs(transaction), transaction})); + const transactionIDList = transactions?.map((reportTransaction) => reportTransaction.transactionID) ?? []; const showRTERViolationMessage = numberOfRequests === 1 && hasPendingUI(lastTransaction, getTransactionViolations(lastTransaction?.transactionID, transactionViolations)); - const transactionIDList = [lastTransaction?.transactionID].filter((transactionID): transactionID is string => transactionID !== undefined); const shouldShowBrokenConnectionViolation = numberOfRequests === 1 && shouldShowBrokenConnectionViolationTransactionUtils(transactionIDList, iouReport, policy); let formattedMerchant = numberOfRequests === 1 ? getMerchant(lastTransaction) : null; const formattedDescription = numberOfRequests === 1 ? getDescription(lastTransaction) : null; @@ -249,7 +249,8 @@ function ReportPreview({ const isArchived = isArchivedReportWithID(iouReport?.reportID); const isAdmin = policy?.role === CONST.POLICY.ROLE.ADMIN; - const shouldShowSubmitButton = canSubmitReport(iouReport, policy, transactionIDList, transactionViolations); + const filteredTransactions = transactions?.filter((transaction) => transaction) ?? []; + const shouldShowSubmitButton = canSubmitReport(iouReport, policy, filteredTransactions, transactionViolations); const shouldDisableSubmitButton = shouldShowSubmitButton && !isAllowedToSubmitDraftExpenseReport(iouReport); diff --git a/src/libs/SearchUIUtils.ts b/src/libs/SearchUIUtils.ts index 58dcf4932b71..f47a0d56001d 100644 --- a/src/libs/SearchUIUtils.ts +++ b/src/libs/SearchUIUtils.ts @@ -340,8 +340,7 @@ function getAction(data: OnyxTypes.SearchResults['data'], key: string): SearchTr } // We check for isAllowedToApproveExpenseReport because if the policy has preventSelfApprovals enabled, we disable the Submit action and in that case we want to show the View action instead - const transactionIDList = allReportTransactions.map((reportTransaction) => reportTransaction.transactionID); - if (canSubmitReport(report, policy, transactionIDList, allViolations) && isAllowedToApproveExpenseReport) { + if (canSubmitReport(report, policy, allReportTransactions, allViolations) && isAllowedToApproveExpenseReport) { return CONST.SEARCH.ACTION_TYPES.SUBMIT; } diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index b6ce81b0a3d4..8ef4acfa3934 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -145,9 +145,13 @@ import { getTransaction, getUpdatedTransaction, hasReceipt as hasReceiptTransactionUtils, + isAmountMissing, isDistanceRequest as isDistanceRequestTransactionUtils, + isExpensifyCardTransaction, isFetchingWaypointsFromServer, isOnHold, + isPartialMerchant, + isPending, isPerDiemRequest as isPerDiemRequestTransactionUtils, isReceiptBeingScanned as isReceiptBeingScannedTransactionUtils, isScanRequest as isScanRequestTransactionUtils, @@ -7913,21 +7917,25 @@ function canIOUBePaid( function canSubmitReport( report: OnyxEntry | SearchReport, policy: OnyxEntry | SearchPolicy, - transactionIDList: string[], + transactions: OnyxTypes.Transaction[] | SearchTransaction[], allViolations?: OnyxCollection, ) { const currentUserAccountID = getCurrentUserAccountID(); const isOpenExpenseReport = isOpenExpenseReportReportUtils(report); const isArchived = isArchivedReportWithID(report?.reportID); - const {reimbursableSpend} = getMoneyRequestSpendBreakdown(report); const isAdmin = policy?.role === CONST.POLICY.ROLE.ADMIN; + const transactionIDList = transactions.map((transaction) => transaction.transactionID); const hasAllPendingRTERViolations = allHavePendingRTERViolation(transactionIDList, allViolations); const hasBrokenConnectionViolation = shouldShowBrokenConnectionViolation(transactionIDList, report, policy, allViolations); + const hasOnlyPendingCardOrScanFailTransactions = + transactions.length > 0 && + transactions.every((t) => (isExpensifyCardTransaction(t) && isPending(t)) || (isPartialMerchant(getMerchant(t)) && isAmountMissing(t)) || isReceiptBeingScannedTransactionUtils(t)); + return ( isOpenExpenseReport && !isArchived && - reimbursableSpend !== 0 && + !hasOnlyPendingCardOrScanFailTransactions && !hasAllPendingRTERViolations && !hasBrokenConnectionViolation && (report?.ownerAccountID === currentUserAccountID || isAdmin || report?.managerID === currentUserAccountID)