diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index c60eb8033292..c474a6d5e734 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -6362,6 +6362,14 @@ function hasViolations(reportID: string, transactionViolations: OnyxCollection TransactionUtils.hasViolation(transaction.transactionID, transactionViolations, shouldShowInReview)); } +/** + * Checks to see if a report contains non-hold violations + */ +function hasNonHoldViolation(reportID: string, transactionViolations: OnyxCollection, shouldShowInReview?: boolean): boolean { + const transactions = reportsTransactions[reportID] ?? []; + return transactions.some((transaction) => TransactionUtils.hasNonHoldViolation(transaction.transactionID, transactionViolations, shouldShowInReview)); +} + /** * Checks to see if a report contains a violation of type `warning` */ @@ -8621,6 +8629,7 @@ export { hasSmartscanError, hasUpdatedTotal, hasViolations, + hasNonHoldViolation, hasWarningTypeViolations, hasNoticeTypeViolations, isActionCreator, diff --git a/src/libs/TransactionUtils/index.ts b/src/libs/TransactionUtils/index.ts index d9f7d3a9c712..1760c1671a29 100644 --- a/src/libs/TransactionUtils/index.ts +++ b/src/libs/TransactionUtils/index.ts @@ -15,15 +15,15 @@ import {toLocaleDigit} from '@libs/LocaleDigitUtils'; import * as Localize from '@libs/Localize'; import * as NumberUtils from '@libs/NumberUtils'; import Permissions from '@libs/Permissions'; -import {getCleanedTagName, getDistanceRateCustomUnitRate} from '@libs/PolicyUtils'; import * as PolicyUtils from '@libs/PolicyUtils'; +import {getCleanedTagName, getDistanceRateCustomUnitRate} from '@libs/PolicyUtils'; // eslint-disable-next-line import/no-cycle import * as ReportActionsUtils from '@libs/ReportActionsUtils'; import * as ReportConnection from '@libs/ReportConnection'; import * as ReportUtils from '@libs/ReportUtils'; import type {IOURequestType} from '@userActions/IOU'; -import CONST from '@src/CONST'; import type {IOUType} from '@src/CONST'; +import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type {Beta, OnyxInputOrEntry, Policy, RecentWaypoint, Report, ReviewDuplicates, TaxRate, TaxRates, Transaction, TransactionViolation, TransactionViolations} from '@src/types/onyx'; import type {Attendee} from '@src/types/onyx/IOU'; @@ -872,6 +872,17 @@ function hasViolation(transactionID: string, transactionViolations: OnyxCollecti ); } +/** + * Checks if any non-hold violations for the provided transaction are of type 'violation' + */ +function hasNonHoldViolation(transactionID: string, transactionViolations: OnyxCollection, showInReview?: boolean): boolean { + return !!transactionViolations?.[ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS + transactionID]?.some( + (violation: TransactionViolation) => + violation.type === CONST.VIOLATION_TYPES.VIOLATION && + violation.name !== CONST.VIOLATIONS.HOLD && + (showInReview === undefined || showInReview === (violation.showInReview ?? false)), + ); +} /** * Checks if any violations for the provided transaction are of type 'notice' */ @@ -1292,6 +1303,7 @@ export { getRecentTransactions, hasReservationList, hasViolation, + hasNonHoldViolation, hasBrokenConnectionViolation, shouldShowBrokenConnectionViolation, hasNoticeTypeViolation, diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index 7e014d37c336..3ad3e15cdaa7 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -6836,7 +6836,7 @@ function canApproveIOU( const reportNameValuePairs = chatReportRNVP ?? ReportUtils.getReportNameValuePairs(iouReport?.reportID); const isArchivedReport = ReportUtils.isArchivedRoom(iouReport, reportNameValuePairs); const allViolations = violations ?? allTransactionViolations; - const hasViolations = ReportUtils.hasViolations(iouReport?.reportID ?? '-1', allViolations); + const hasNonHoldViolation = ReportUtils.hasNonHoldViolation(iouReport?.reportID ?? '-1', allViolations); let isTransactionBeingScanned = false; const reportTransactions = TransactionUtils.getAllReportTransactions(iouReport?.reportID); for (const transaction of reportTransactions) { @@ -6849,7 +6849,7 @@ function canApproveIOU( } } - return isCurrentUserManager && !isOpenExpenseReport && !isApproved && !iouSettled && !isArchivedReport && !isTransactionBeingScanned && !hasViolations; + return isCurrentUserManager && !isOpenExpenseReport && !isApproved && !iouSettled && !isArchivedReport && !isTransactionBeingScanned && !hasNonHoldViolation; } function canIOUBePaid( @@ -6906,7 +6906,7 @@ function canIOUBePaid( const isAutoReimbursable = policy?.reimbursementChoice === CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_YES ? false : ReportUtils.canBeAutoReimbursed(iouReport, policy); const allViolations = violations ?? allTransactionViolations; const shouldBeApproved = canApproveIOU(iouReport, policy, allViolations); - const hasViolations = ReportUtils.hasViolations(iouReport?.reportID ?? '-1', allViolations); + const hasNonHoldViolation = ReportUtils.hasNonHoldViolation(iouReport?.reportID ?? '-1', allViolations); const isPayAtEndExpenseReport = ReportUtils.isPayAtEndExpenseReport(iouReport?.reportID, transactions); return ( @@ -6918,7 +6918,7 @@ function canIOUBePaid( !isChatReportArchived && !isAutoReimbursable && !shouldBeApproved && - !hasViolations && + !hasNonHoldViolation && !isPayAtEndExpenseReport ); }