From 59ff69523ee62b51f525ad9d2d586215f2d21d8e Mon Sep 17 00:00:00 2001 From: FitseTLT Date: Wed, 13 Aug 2025 23:41:14 +0300 Subject: [PATCH 1/5] fix bulk expense deletion iouReport total update --- src/hooks/useSelectedTransactionsActions.ts | 2 +- src/libs/IOUUtils.ts | 5 +- src/libs/actions/IOU.ts | 54 ++++++++++----- tests/actions/IOUTest.ts | 75 +++++++++++++++++++++ 4 files changed, 117 insertions(+), 19 deletions(-) diff --git a/src/hooks/useSelectedTransactionsActions.ts b/src/hooks/useSelectedTransactionsActions.ts index 1a5a6e613185d..8204a8b9a7907 100644 --- a/src/hooks/useSelectedTransactionsActions.ts +++ b/src/hooks/useSelectedTransactionsActions.ts @@ -98,7 +98,7 @@ function useSelectedTransactionsActions({ return; } - deleteMoneyRequest(transactionID, action, duplicateTransactions, duplicateTransactionViolations, false, deletedTransactionIDs); + deleteMoneyRequest(transactionID, action, duplicateTransactions, duplicateTransactionViolations, false, deletedTransactionIDs, selectedTransactionIDs); deletedTransactionIDs.push(transactionID); }); clearSelectedTransactions(true); diff --git a/src/libs/IOUUtils.ts b/src/libs/IOUUtils.ts index 3fdffbe33c24a..32fe51d980fd4 100644 --- a/src/libs/IOUUtils.ts +++ b/src/libs/IOUUtils.ts @@ -91,6 +91,7 @@ function updateIOUOwnerAndTotal>( isDeleting = false, isUpdating = false, isOnHold = false, + unHeldAmount = amount, ): TReport { // For the update case, we have calculated the diff amount in the calculateDiffAmount function so there is no need to compare currencies here if ((currency !== iouReport?.currency && !isUpdating) || !iouReport) { @@ -107,12 +108,12 @@ function updateIOUOwnerAndTotal>( if (actorAccountID === iouReport.ownerAccountID) { iouReportUpdate.total += isDeleting ? -amount : amount; if (!isOnHold) { - iouReportUpdate.unheldTotal += isDeleting ? -amount : amount; + iouReportUpdate.unheldTotal += isDeleting ? -unHeldAmount : unHeldAmount; } } else { iouReportUpdate.total += isDeleting ? amount : -amount; if (!isOnHold) { - iouReportUpdate.unheldTotal += isDeleting ? amount : -amount; + iouReportUpdate.unheldTotal += isDeleting ? unHeldAmount : -unHeldAmount; } } diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index 3796706f31979..6c405b6e0193e 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -7727,7 +7727,13 @@ function updateMoneyRequestAmountAndCurrency({ * @param reportAction - The reportAction of the transaction in the IOU report * @return the url to navigate back once the money request is deleted */ -function prepareToCleanUpMoneyRequest(transactionID: string, reportAction: OnyxTypes.ReportAction, shouldRemoveIOUTransactionID = true, transactionIDsPendingDeletion?: string[]) { +function prepareToCleanUpMoneyRequest( + transactionID: string, + reportAction: OnyxTypes.ReportAction, + shouldRemoveIOUTransactionID = true, + transactionIDsPendingDeletion?: string[], + selectedTransactionIDs?: string[], +) { // STEP 1: Get all collections we're updating const iouReportID = isMoneyRequestAction(reportAction) ? getOriginalMessage(reportAction)?.IOUReportID : undefined; const iouReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${iouReportID}`] ?? null; @@ -7782,38 +7788,53 @@ function prepareToCleanUpMoneyRequest(transactionID: string, reportAction: OnyxT const currency = getCurrency(transaction); const updatedReportPreviewAction: Partial> = cloneDeep(reportPreviewAction ?? {}); updatedReportPreviewAction.pendingAction = shouldDeleteIOUReport ? CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE : CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE; + + const transactionPendingDelete = transactionIDsPendingDeletion?.map((id) => allTransactions[`${ONYXKEYS.COLLECTION.TRANSACTION}${id}`]); + const selectedTransactions = selectedTransactionIDs?.map((id) => allTransactions[`${ONYXKEYS.COLLECTION.TRANSACTION}${id}`]); + const canEditTotal = !selectedTransactions?.some((trans) => getCurrency(trans) !== iouReport?.currency); + if (iouReport && isExpenseReport(iouReport)) { updatedIOUReport = {...iouReport}; - if (typeof updatedIOUReport.total === 'number' && currency === iouReport?.currency) { + if (typeof updatedIOUReport.total === 'number' && currency === iouReport?.currency && canEditTotal) { // Because of the Expense reports are stored as negative values, we add the total from the amount - const amountDiff = getAmount(transaction, true); + const amountDiff = getAmount(transaction, true) + (transactionPendingDelete?.reduce((prev, curr) => prev + getAmount(curr, true), 0) ?? 0); + const nonReimbursableAmountDiff = + getAmount(transaction, true) + (transactionPendingDelete?.reduce((prev, curr) => prev + (!curr?.reimbursable ? getAmount(curr, true) : 0), 0) ?? 0); + const unheldAmountDiff = getAmount(transaction, true) + (transactionPendingDelete?.reduce((prev, curr) => prev + (!isOnHold(curr) ? getAmount(curr, true) : 0), 0) ?? 0); + const unheldNonReimbursableAmountDiff = + getAmount(transaction, true) + (transactionPendingDelete?.reduce((prev, curr) => prev + (!isOnHold(curr) && !curr?.reimbursable ? getAmount(curr, true) : 0), 0) ?? 0); + updatedIOUReport.total += amountDiff; if (!transaction?.reimbursable && typeof updatedIOUReport.nonReimbursableTotal === 'number') { - updatedIOUReport.nonReimbursableTotal += amountDiff; + updatedIOUReport.nonReimbursableTotal += nonReimbursableAmountDiff; } if (!isTransactionOnHold) { if (typeof updatedIOUReport.unheldTotal === 'number') { - updatedIOUReport.unheldTotal += amountDiff; + updatedIOUReport.unheldTotal += unheldAmountDiff; } if (!transaction?.reimbursable && typeof updatedIOUReport.unheldNonReimbursableTotal === 'number') { - updatedIOUReport.unheldNonReimbursableTotal += amountDiff; + updatedIOUReport.unheldNonReimbursableTotal += unheldNonReimbursableAmountDiff; } } } } else { - updatedIOUReport = updateIOUOwnerAndTotal( - iouReport, - reportAction.actorAccountID ?? CONST.DEFAULT_NUMBER_ID, - getAmount(transaction, false), - currency, - true, - false, - isTransactionOnHold, - ); + updatedIOUReport = + iouReport && !canEditTotal + ? {...iouReport} + : updateIOUOwnerAndTotal( + iouReport, + reportAction.actorAccountID ?? CONST.DEFAULT_NUMBER_ID, + getAmount(transaction, false) + (transactionPendingDelete?.reduce((prev, curr) => prev + getAmount(curr, false), 0) ?? 0), + currency, + true, + false, + isTransactionOnHold, + getAmount(transaction, false) + (transactionPendingDelete?.reduce((prev, curr) => prev + (!isOnHold(curr) ? getAmount(curr, false) : 0), 0) ?? 0), + ); } if (updatedIOUReport) { @@ -8098,6 +8119,7 @@ function deleteMoneyRequest( violations: OnyxCollection, isSingleTransactionView = false, transactionIDsPendingDeletion?: string[], + selectedTransactionIDs?: string[], ) { if (!transactionID) { return; @@ -8117,7 +8139,7 @@ function deleteMoneyRequest( transactionViolations, iouReport, reportPreviewAction, - } = prepareToCleanUpMoneyRequest(transactionID, reportAction, false, transactionIDsPendingDeletion); + } = prepareToCleanUpMoneyRequest(transactionID, reportAction, false, transactionIDsPendingDeletion, selectedTransactionIDs); const urlToNavigateBack = getNavigationUrlOnMoneyRequestDelete(transactionID, reportAction, isSingleTransactionView); diff --git a/tests/actions/IOUTest.ts b/tests/actions/IOUTest.ts index e97e49faf7ef4..bce8601651e70 100644 --- a/tests/actions/IOUTest.ts +++ b/tests/actions/IOUTest.ts @@ -86,6 +86,7 @@ import * as InvoiceData from '../data/Invoice'; import type {InvoiceTestData} from '../data/Invoice'; import createRandomPolicy, {createCategoryTaxExpenseRules} from '../utils/collections/policies'; import createRandomPolicyCategories from '../utils/collections/policyCategory'; +import createRandomReportAction from '../utils/collections/reportActions'; import {createRandomReport} from '../utils/collections/reports'; import createRandomTransaction from '../utils/collections/transaction'; import getOnyxValue from '../utils/getOnyxValue'; @@ -4121,6 +4122,80 @@ describe('actions/IOU', () => { }); }); + describe('bulk deleteMoneyRequest', () => { + it('update IOU report total properly for bulk deletion of expenses', async () => { + const expenseReport: Report = { + ...createRandomReport(11), + type: CONST.REPORT.TYPE.EXPENSE, + total: 30, + currency: CONST.CURRENCY.USD, + unheldTotal: 20, + unheldNonReimbursableTotal: 20, + }; + const transaction1: Transaction = { + ...createRandomTransaction(1), + amount: 10, + comment: {hold: '123'}, + currency: CONST.CURRENCY.USD, + reportID: expenseReport.reportID, + reimbursable: true, + }; + const moneyRequestAction1: ReportAction = { + ...createRandomReportAction(1), + actionName: CONST.REPORT.ACTIONS.TYPE.IOU, + childReportID: '1', + originalMessage: { + IOUReportID: expenseReport.reportID, + amount: transaction1.amount, + currency: transaction1.currency, + type: CONST.IOU.REPORT_ACTION_TYPE.CREATE, + }, + message: undefined, + previousMessage: undefined, + }; + const transaction2: Transaction = {...createRandomTransaction(2), amount: 10, currency: CONST.CURRENCY.USD, reportID: expenseReport.reportID, reimbursable: false}; + const moneyRequestAction2: ReportAction = { + ...createRandomReportAction(2), + actionName: CONST.REPORT.ACTIONS.TYPE.IOU, + childReportID: '2', + originalMessage: { + IOUReportID: expenseReport.reportID, + amount: transaction2.amount, + currency: transaction2.currency, + type: CONST.IOU.REPORT_ACTION_TYPE.CREATE, + }, + message: undefined, + previousMessage: undefined, + }; + const transaction3: Transaction = {...createRandomTransaction(3), amount: 10, currency: CONST.CURRENCY.USD, reportID: expenseReport.reportID, reimbursable: false}; + + await Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION}${transaction1.transactionID}`, transaction1); + await Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION}${transaction2.transactionID}`, transaction2); + await Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION}${transaction3.transactionID}`, transaction3); + await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${expenseReport.reportID}`, expenseReport); + + const selectedTransactionIDs = [transaction1.transactionID, transaction2.transactionID]; + deleteMoneyRequest(transaction1.transactionID, moneyRequestAction1, {}, {}, undefined, [], selectedTransactionIDs); + deleteMoneyRequest(transaction2.transactionID, moneyRequestAction2, {}, {}, undefined, [transaction1.transactionID], selectedTransactionIDs); + + await waitForBatchedUpdates(); + + const report = await new Promise>((resolve) => { + const connection = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.REPORT}${expenseReport.reportID}`, + callback: (val) => { + Onyx.disconnect(connection); + resolve(val); + }, + }); + }); + + expect(report?.total).toBe(10); + expect(report?.unheldTotal).toBe(10); + expect(report?.unheldNonReimbursableTotal).toBe(10); + }); + }); + describe('submitReport', () => { it('correctly submits a report', () => { const amount = 10000; From ef451f563033c99f82884359131bb67e5f290ec6 Mon Sep 17 00:00:00 2001 From: FitseTLT Date: Tue, 26 Aug 2025 18:13:35 +0300 Subject: [PATCH 2/5] grey out total on pending deletion transaction --- .../MoneyRequestReportActionsList.tsx | 5 ++++ .../MoneyRequestReportTransactionList.tsx | 8 +++-- .../MoneyRequestReportView.tsx | 2 ++ src/libs/actions/IOU.ts | 29 +++++++------------ src/pages/home/ReportScreen.tsx | 2 ++ 5 files changed, 26 insertions(+), 20 deletions(-) diff --git a/src/components/MoneyRequestReportView/MoneyRequestReportActionsList.tsx b/src/components/MoneyRequestReportView/MoneyRequestReportActionsList.tsx index 16f3aa3260da4..a2e85873458de 100644 --- a/src/components/MoneyRequestReportView/MoneyRequestReportActionsList.tsx +++ b/src/components/MoneyRequestReportView/MoneyRequestReportActionsList.tsx @@ -88,6 +88,9 @@ type MoneyRequestReportListProps = { /** List of transactions belonging to this report */ transactions?: OnyxTypes.Transaction[]; + /** Whether there is a pending delete transaction */ + hasPendingDeletionTransaction?: boolean; + /** List of transactions that arrived when the report was open */ newTransactions: OnyxTypes.Transaction[]; @@ -116,6 +119,7 @@ function MoneyRequestReportActionsList({ newTransactions, hasNewerActions, hasOlderActions, + hasPendingDeletionTransaction, showReportActionsLoadingState, }: MoneyRequestReportListProps) { const styles = useThemeStyles(); @@ -720,6 +724,7 @@ function MoneyRequestReportActionsList({ report={report} transactions={transactions} newTransactions={newTransactions} + hasPendingDeletionTransaction={hasPendingDeletionTransaction} reportActions={reportActions} hasComments={reportHasComments} isLoadingInitialReportActions={showReportActionsLoadingState} diff --git a/src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx b/src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx index 95182e0950b57..718196f16fdfe 100644 --- a/src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx +++ b/src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx @@ -44,6 +44,9 @@ type MoneyRequestReportTransactionListProps = { /** List of transactions belonging to one report */ transactions: OnyxTypes.Transaction[]; + /** Whether there is a pending delete transaction */ + hasPendingDeletionTransaction?: boolean; + /** List of transactions that arrived when the report was open */ newTransactions: OnyxTypes.Transaction[]; @@ -94,6 +97,7 @@ function MoneyRequestReportTransactionList({ reportActions, hasComments, isLoadingInitialReportActions: isLoadingReportActions, + hasPendingDeletionTransaction = false, scrollToNewTransaction, }: MoneyRequestReportTransactionListProps) { useCopySelectionHelper(); @@ -112,8 +116,8 @@ function MoneyRequestReportTransactionList({ const transactionsWithoutPendingDelete = useMemo(() => transactions.filter((t) => !isTransactionPendingDelete(t)), [transactions]); const hasPendingAction = useMemo(() => { - return transactions.some(getTransactionPendingAction); - }, [transactions]); + return hasPendingDeletionTransaction || transactions.some(getTransactionPendingAction); + }, [hasPendingDeletionTransaction, transactions]); const {selectedTransactionIDs, setSelectedTransactions, clearSelectedTransactions} = useSearchContext(); const isMobileSelectionModeEnabled = useMobileSelectionMode(); diff --git a/src/components/MoneyRequestReportView/MoneyRequestReportView.tsx b/src/components/MoneyRequestReportView/MoneyRequestReportView.tsx index ec5710093bb3a..d35c4f0f0eb92 100644 --- a/src/components/MoneyRequestReportView/MoneyRequestReportView.tsx +++ b/src/components/MoneyRequestReportView/MoneyRequestReportView.tsx @@ -100,6 +100,7 @@ function MoneyRequestReportView({report, policy, reportMetadata, shouldDisplayRe const reportActions = getFilteredReportActionsForReportView(unfilteredReportActions); const {transactions: reportTransactions} = useTransactionsAndViolationsForReport(reportID); + const hasPendingDeletionTransaction = Object.values(reportTransactions ?? {}).some((transaction) => transaction.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE); const transactions = useMemo(() => getAllNonDeletedTransactions(reportTransactions, reportActions), [reportTransactions, reportActions]); const visibleTransactions = transactions?.filter((transaction) => isOffline || transaction.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE); @@ -219,6 +220,7 @@ function MoneyRequestReportView({report, policy, reportMetadata, shouldDisplayRe report={report} policy={policy} transactions={visibleTransactions} + hasPendingDeletionTransaction={hasPendingDeletionTransaction} newTransactions={newTransactions} reportActions={reportActions} hasOlderActions={hasOlderActions} diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index fcd714260f6ee..1adea772b6014 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -7867,22 +7867,21 @@ function prepareToCleanUpMoneyRequest( const transactionPendingDelete = transactionIDsPendingDeletion?.map((id) => allTransactions[`${ONYXKEYS.COLLECTION.TRANSACTION}${id}`]); const selectedTransactions = selectedTransactionIDs?.map((id) => allTransactions[`${ONYXKEYS.COLLECTION.TRANSACTION}${id}`]); const canEditTotal = !selectedTransactions?.some((trans) => getCurrency(trans) !== iouReport?.currency); + const isExpenseReportType = isExpenseReport(iouReport); + const amountDiff = getAmount(transaction, isExpenseReportType) + (transactionPendingDelete?.reduce((prev, curr) => prev + getAmount(curr, isExpenseReportType), 0) ?? 0); + const unheldAmountDiff = + getAmount(transaction, isExpenseReportType) + (transactionPendingDelete?.reduce((prev, curr) => prev + (!isOnHold(curr) ? getAmount(curr, isExpenseReportType) : 0), 0) ?? 0); - if (iouReport && isExpenseReport(iouReport)) { + if (iouReport && isExpenseReportType) { updatedIOUReport = {...iouReport}; if (typeof updatedIOUReport.total === 'number' && currency === iouReport?.currency && canEditTotal) { // Because of the Expense reports are stored as negative values, we add the total from the amount - const amountDiff = getAmount(transaction, true) + (transactionPendingDelete?.reduce((prev, curr) => prev + getAmount(curr, true), 0) ?? 0); - const nonReimbursableAmountDiff = - getAmount(transaction, true) + (transactionPendingDelete?.reduce((prev, curr) => prev + (!curr?.reimbursable ? getAmount(curr, true) : 0), 0) ?? 0); - const unheldAmountDiff = getAmount(transaction, true) + (transactionPendingDelete?.reduce((prev, curr) => prev + (!isOnHold(curr) ? getAmount(curr, true) : 0), 0) ?? 0); - const unheldNonReimbursableAmountDiff = - getAmount(transaction, true) + (transactionPendingDelete?.reduce((prev, curr) => prev + (!isOnHold(curr) && !curr?.reimbursable ? getAmount(curr, true) : 0), 0) ?? 0); - updatedIOUReport.total += amountDiff; if (!transaction?.reimbursable && typeof updatedIOUReport.nonReimbursableTotal === 'number') { + const nonReimbursableAmountDiff = + getAmount(transaction, true) + (transactionPendingDelete?.reduce((prev, curr) => prev + (!curr?.reimbursable ? getAmount(curr, true) : 0), 0) ?? 0); updatedIOUReport.nonReimbursableTotal += nonReimbursableAmountDiff; } @@ -7892,6 +7891,9 @@ function prepareToCleanUpMoneyRequest( } if (!transaction?.reimbursable && typeof updatedIOUReport.unheldNonReimbursableTotal === 'number') { + const unheldNonReimbursableAmountDiff = + getAmount(transaction, true) + + (transactionPendingDelete?.reduce((prev, curr) => prev + (!isOnHold(curr) && !curr?.reimbursable ? getAmount(curr, true) : 0), 0) ?? 0); updatedIOUReport.unheldNonReimbursableTotal += unheldNonReimbursableAmountDiff; } } @@ -7900,16 +7902,7 @@ function prepareToCleanUpMoneyRequest( updatedIOUReport = iouReport && !canEditTotal ? {...iouReport} - : updateIOUOwnerAndTotal( - iouReport, - reportAction.actorAccountID ?? CONST.DEFAULT_NUMBER_ID, - getAmount(transaction, false) + (transactionPendingDelete?.reduce((prev, curr) => prev + getAmount(curr, false), 0) ?? 0), - currency, - true, - false, - isTransactionOnHold, - getAmount(transaction, false) + (transactionPendingDelete?.reduce((prev, curr) => prev + (!isOnHold(curr) ? getAmount(curr, false) : 0), 0) ?? 0), - ); + : updateIOUOwnerAndTotal(iouReport, reportAction.actorAccountID ?? CONST.DEFAULT_NUMBER_ID, amountDiff, currency, true, false, isTransactionOnHold, unheldAmountDiff); } if (updatedIOUReport) { diff --git a/src/pages/home/ReportScreen.tsx b/src/pages/home/ReportScreen.tsx index 53a5f37823761..2eb846949f550 100644 --- a/src/pages/home/ReportScreen.tsx +++ b/src/pages/home/ReportScreen.tsx @@ -302,6 +302,7 @@ function ReportScreen({route, navigation}: ReportScreenProps) { // OpenReport will be called each time the user scrolls up the report a bit, clicks on report preview, and then goes back. const isLinkedMessagePageReady = isLinkedMessageAvailable && (reportActions.length - indexOfLinkedMessage >= CONST.REPORT.MIN_INITIAL_REPORT_ACTION_COUNT || doesCreatedActionExists()); const {transactions: allReportTransactions} = useTransactionsAndViolationsForReport(reportIDFromRoute); + const hasPendingDeletionTransaction = Object.values(allReportTransactions ?? {}).some((transaction) => transaction.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE); const reportTransactions = useMemo(() => getAllNonDeletedTransactions(allReportTransactions, reportActions), [allReportTransactions, reportActions]); // wrapping in useMemo because this is array operation and can cause performance issues @@ -872,6 +873,7 @@ function ReportScreen({route, navigation}: ReportScreenProps) { {!!report && shouldDisplayMoneyRequestActionsList && !shouldWaitForTransactions ? ( Date: Tue, 26 Aug 2025 18:23:48 +0300 Subject: [PATCH 3/5] fix test --- tests/actions/IOUTest.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/actions/IOUTest.ts b/tests/actions/IOUTest.ts index 38c32e2bb5d01..c50d50143db8d 100644 --- a/tests/actions/IOUTest.ts +++ b/tests/actions/IOUTest.ts @@ -6,6 +6,8 @@ import {format} from 'date-fns'; import {deepEqual} from 'fast-equals'; import type {OnyxCollection, OnyxEntry, OnyxInputValue} from 'react-native-onyx'; import Onyx from 'react-native-onyx'; +import createRandomPolicyTags from 'tests/utils/collections/policyTags'; +import createRandomReportAction from 'tests/utils/collections/reportActions'; import OnyxListItemProvider from '@components/OnyxListItemProvider'; import useReportWithTransactionsAndViolations from '@hooks/useReportWithTransactionsAndViolations'; import type {PerDiemExpenseTransactionParams, RequestMoneyParticipantParams} from '@libs/actions/IOU'; From 77bf99054a94794399a16a3d5c3452b105daedc6 Mon Sep 17 00:00:00 2001 From: FitseTLT Date: Tue, 26 Aug 2025 18:38:00 +0300 Subject: [PATCH 4/5] fix import --- tests/actions/IOUTest.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/actions/IOUTest.ts b/tests/actions/IOUTest.ts index c50d50143db8d..393ec00e828d1 100644 --- a/tests/actions/IOUTest.ts +++ b/tests/actions/IOUTest.ts @@ -6,8 +6,6 @@ import {format} from 'date-fns'; import {deepEqual} from 'fast-equals'; import type {OnyxCollection, OnyxEntry, OnyxInputValue} from 'react-native-onyx'; import Onyx from 'react-native-onyx'; -import createRandomPolicyTags from 'tests/utils/collections/policyTags'; -import createRandomReportAction from 'tests/utils/collections/reportActions'; import OnyxListItemProvider from '@components/OnyxListItemProvider'; import useReportWithTransactionsAndViolations from '@hooks/useReportWithTransactionsAndViolations'; import type {PerDiemExpenseTransactionParams, RequestMoneyParticipantParams} from '@libs/actions/IOU'; @@ -94,6 +92,8 @@ import * as InvoiceData from '../data/Invoice'; import type {InvoiceTestData} from '../data/Invoice'; import createRandomPolicy, {createCategoryTaxExpenseRules} from '../utils/collections/policies'; import createRandomPolicyCategories from '../utils/collections/policyCategory'; +import createRandomPolicyTags from '../utils/collections/policyTags'; +import createRandomReportAction from '../utils/collections/reportActions'; import {createRandomReport} from '../utils/collections/reports'; import createRandomTransaction from '../utils/collections/transaction'; import getOnyxValue from '../utils/getOnyxValue'; From 7286dab9f9711b00b3b649efb83994b5b62a04fc Mon Sep 17 00:00:00 2001 From: FitseTLT Date: Wed, 24 Sep 2025 16:02:21 +0300 Subject: [PATCH 5/5] include pending action delete transactions --- src/libs/MoneyRequestReportUtils.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/libs/MoneyRequestReportUtils.ts b/src/libs/MoneyRequestReportUtils.ts index 0d920f2fc3d69..82f771ff8d939 100644 --- a/src/libs/MoneyRequestReportUtils.ts +++ b/src/libs/MoneyRequestReportUtils.ts @@ -76,6 +76,11 @@ function getAllNonDeletedTransactions(transactions: OnyxCollection, if (!transaction) { return false; } + + if (transaction?.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE) { + return true; + } + const action = getIOUActionForTransactionID(reportActions, transaction.transactionID); return !isDeletedParentAction(action) && (reportActions.length === 0 || !isDeletedAction(action)); });