From 7adf36963c5d73d2e575c104fa48610b30d470ef Mon Sep 17 00:00:00 2001 From: Rajat Parashar Date: Sat, 16 May 2026 20:24:21 +0530 Subject: [PATCH 1/3] Refactor `deleteMoneyRequest` to pass transactionThreadReport --- src/hooks/useDeleteTransactions.ts | 2 ++ src/libs/actions/IOU/DeleteMoneyRequest.ts | 37 +++++++++++++++------- src/libs/actions/IOU/TrackExpense.ts | 4 +++ src/libs/actions/Search.ts | 2 ++ 4 files changed, 34 insertions(+), 11 deletions(-) diff --git a/src/hooks/useDeleteTransactions.ts b/src/hooks/useDeleteTransactions.ts index 87fbde952383..69c96656c870 100644 --- a/src/hooks/useDeleteTransactions.ts +++ b/src/hooks/useDeleteTransactions.ts @@ -193,11 +193,13 @@ function useDeleteTransactions({report, reportActions, policy}: UseDeleteTransac const iouReportID = isMoneyRequestAction(action) ? getOriginalMessage(action)?.IOUReportID : undefined; const iouReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${iouReportID}`]; const chatReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${iouReport?.chatReportID}`]; + const transactionThreadReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${action?.childReportID}`]; const chatIOUReportID = chatReport?.reportID; const isChatIOUReportArchived = archivedReportsIdSet.has(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${chatIOUReportID}`); deleteMoneyRequest({ transactionID, reportAction: action, + transactionThreadReport, transactions: duplicateTransactions, violations: duplicateTransactionViolations, iouReport, diff --git a/src/libs/actions/IOU/DeleteMoneyRequest.ts b/src/libs/actions/IOU/DeleteMoneyRequest.ts index 779559463b05..af92328edfbc 100644 --- a/src/libs/actions/IOU/DeleteMoneyRequest.ts +++ b/src/libs/actions/IOU/DeleteMoneyRequest.ts @@ -51,6 +51,7 @@ type DeleteMoneyRequestFunctionParams = { allTransactionViolationsParam: OnyxCollection; currentUserAccountID: number; currentUserEmail: string; + transactionThreadReport: OnyxEntry; }; /** @@ -62,6 +63,7 @@ type DeleteMoneyRequestFunctionParams = { function prepareToCleanUpMoneyRequest( transactionID: string, reportAction: OnyxTypes.ReportAction, + transactionThreadReport: OnyxEntry, iouReport: OnyxEntry, chatReport: OnyxEntry, isChatReportArchived: boolean | undefined, @@ -71,7 +73,6 @@ function prepareToCleanUpMoneyRequest( ) { const allTransactions = getAllTransactions(); const allTransactionViolations = getAllTransactionViolations(); - const allReports = getAllReports(); const allReportActions = getAllReportActionsFromIOU(); // STEP 1: Get all collections we're updating @@ -80,18 +81,13 @@ function prepareToCleanUpMoneyRequest( const transaction = allTransactions[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`]; const isTransactionOnHold = isOnHold(transaction); const transactionViolations = allTransactionViolations[`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${transactionID}`]; - const transactionThreadID = reportAction.childReportID; - let transactionThread = null; - if (transactionThreadID) { - transactionThread = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${transactionThreadID}`] ?? null; - } // STEP 2: Decide if we need to: // 1. Delete the transactionThread - delete if there are no visible comments in the thread // 2. Update the moneyRequestPreview to show [Deleted expense] - update if the transactionThread exists AND it isn't being deleted // The current state is that we want to get rid of the [Deleted expense] breadcrumb, // so we never want to display it if transactionThreadID is present. - const shouldDeleteTransactionThread = !!transactionThreadID; + const shouldDeleteTransactionThread = !!transactionThreadReport?.reportID; // STEP 3: Update the IOU reportAction and decide if the iouReport should be deleted. We delete the iouReport if there are no visible comments left in the report. const updatedReportAction = { @@ -234,8 +230,8 @@ function prepareToCleanUpMoneyRequest( updatedReportAction, updatedIOUReport, updatedReportPreviewAction, - transactionThreadID, - transactionThread, + transactionThreadID: transactionThreadReport?.reportID, + transactionThreadReport, transaction, transactionViolations, reportPreviewAction, @@ -261,8 +257,16 @@ function getNavigationUrlOnMoneyRequestDelete( if (!transactionID) { return undefined; } + const allReports = getAllReports(); + const transactionThreadID = reportAction.childReportID; + let transactionThread = null; + if (transactionThreadID) { + transactionThread = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${transactionThreadID}`] ?? null; + } + + transactionThread = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${transactionThreadID}`]; - const {shouldDeleteTransactionThread, shouldDeleteIOUReport} = prepareToCleanUpMoneyRequest(transactionID, reportAction, iouReport, chatReport, isChatReportArchived); + const {shouldDeleteTransactionThread, shouldDeleteIOUReport} = prepareToCleanUpMoneyRequest(transactionID, reportAction, transactionThread, iouReport, chatReport, isChatReportArchived); // Determine which report to navigate back to if (iouReport && isSingleTransactionView && shouldDeleteTransactionThread && !shouldDeleteIOUReport) { @@ -637,6 +641,7 @@ function deleteMoneyRequest({ transactionID, reportAction, transactions, + transactionThreadReport, violations, iouReport, chatReport, @@ -664,7 +669,17 @@ function deleteMoneyRequest({ transactionViolations, reportPreviewAction, iouReportActions, - } = prepareToCleanUpMoneyRequest(transactionID, reportAction, iouReport, chatReport, isChatIOUReportArchived, false, transactionIDsPendingDeletion, selectedTransactionIDs); + } = prepareToCleanUpMoneyRequest( + transactionID, + reportAction, + transactionThreadReport, + iouReport, + chatReport, + isChatIOUReportArchived, + false, + transactionIDsPendingDeletion, + selectedTransactionIDs, + ); const urlToNavigateBack = getNavigationUrlOnMoneyRequestDelete(transactionID, reportAction, iouReport, chatReport, isChatIOUReportArchived, isSingleTransactionView); diff --git a/src/libs/actions/IOU/TrackExpense.ts b/src/libs/actions/IOU/TrackExpense.ts index 4e77fae10fa1..26f1e63cf4b4 100644 --- a/src/libs/actions/IOU/TrackExpense.ts +++ b/src/libs/actions/IOU/TrackExpense.ts @@ -2762,10 +2762,14 @@ function deleteTrackExpense({ // STEP 1: Get all collections we're updating if (!isSelfDM(chatReport)) { + const allReports = getAllReports(); + const transactionThreadReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportAction.childReportID}`]; + deleteMoneyRequest({ transactionID, reportAction, transactions, + transactionThreadReport, violations, iouReport, chatReport: chatIOUReport, diff --git a/src/libs/actions/Search.ts b/src/libs/actions/Search.ts index 20059d76789c..753fa63eea77 100644 --- a/src/libs/actions/Search.ts +++ b/src/libs/actions/Search.ts @@ -959,11 +959,13 @@ function bulkDeleteReports({ const reportID = selectedTransactions[transactionID].report?.reportID; const batchTransactionIDsForReport = reportID ? (transactionsByReport[reportID] ?? []) : []; const chatReport = reports?.[`${ONYXKEYS.COLLECTION.REPORT}${selectedTransactions[transactionID].report?.chatReportID}`]; + const transactionThreadReport = reports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportAction?.childReportID}`]; const reportNameValuePair = allReportNameValuePairs?.[`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${chatReport?.reportID}`]; deleteMoneyRequest({ transactionID, reportAction, + transactionThreadReport, transactions, violations: transactionsViolations, iouReport: selectedTransactions[transactionID].report, From 6a97861b1dd8488b7437f1d6f9dc51f78b347e59 Mon Sep 17 00:00:00 2001 From: Rajat Parashar Date: Sat, 16 May 2026 20:30:58 +0530 Subject: [PATCH 2/3] cleanup --- src/libs/actions/IOU/DeleteMoneyRequest.ts | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/libs/actions/IOU/DeleteMoneyRequest.ts b/src/libs/actions/IOU/DeleteMoneyRequest.ts index af92328edfbc..8c8ec568fa64 100644 --- a/src/libs/actions/IOU/DeleteMoneyRequest.ts +++ b/src/libs/actions/IOU/DeleteMoneyRequest.ts @@ -258,15 +258,16 @@ function getNavigationUrlOnMoneyRequestDelete( return undefined; } const allReports = getAllReports(); - const transactionThreadID = reportAction.childReportID; - let transactionThread = null; - if (transactionThreadID) { - transactionThread = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${transactionThreadID}`] ?? null; - } - - transactionThread = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${transactionThreadID}`]; + const transactionThreadReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportAction.childReportID}`]; - const {shouldDeleteTransactionThread, shouldDeleteIOUReport} = prepareToCleanUpMoneyRequest(transactionID, reportAction, transactionThread, iouReport, chatReport, isChatReportArchived); + const {shouldDeleteTransactionThread, shouldDeleteIOUReport} = prepareToCleanUpMoneyRequest( + transactionID, + reportAction, + transactionThreadReport, + iouReport, + chatReport, + isChatReportArchived, + ); // Determine which report to navigate back to if (iouReport && isSingleTransactionView && shouldDeleteTransactionThread && !shouldDeleteIOUReport) { @@ -297,8 +298,11 @@ function cleanUpMoneyRequest( originalReportID: string | undefined, isSingleTransactionView = false, ) { + const allReports = getAllReports(); + const transactionThreadReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportAction.childReportID}`]; + const {shouldDeleteTransactionThread, shouldDeleteIOUReport, updatedReportAction, updatedIOUReport, updatedReportPreviewAction, transactionThreadID, reportPreviewAction} = - prepareToCleanUpMoneyRequest(transactionID, reportAction, iouReport, chatReport, isChatIOUReportArchived, false); + prepareToCleanUpMoneyRequest(transactionID, reportAction, transactionThreadReport, iouReport, chatReport, isChatIOUReportArchived, false); const urlToNavigateBack = getNavigationUrlOnMoneyRequestDelete(transactionID, reportAction, iouReport, chatReport, isChatIOUReportArchived, isSingleTransactionView); // build Onyx data From 25646bca462927843f87d8896751066519e7085e Mon Sep 17 00:00:00 2001 From: Rajat Parashar Date: Sat, 16 May 2026 20:50:47 +0530 Subject: [PATCH 3/3] Fix tests --- .../actions/IOUTest/DeleteMoneyRequestTest.ts | 29 +++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/tests/actions/IOUTest/DeleteMoneyRequestTest.ts b/tests/actions/IOUTest/DeleteMoneyRequestTest.ts index 5efa40a11da5..3a5fe2ad132c 100644 --- a/tests/actions/IOUTest/DeleteMoneyRequestTest.ts +++ b/tests/actions/IOUTest/DeleteMoneyRequestTest.ts @@ -124,6 +124,9 @@ describe('actions/IOU/DeleteMoneyRequest', () => { let thread: OptimisticChatReport; const TEST_USER_ACCOUNT_ID = 1; const TEST_USER_LOGIN = 'test@test.com'; + const expectedTransactionThreadParticipants = { + [TEST_USER_ACCOUNT_ID]: {notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN, role: CONST.REPORT.ROLE.ADMIN}, + }; let IOU_REPORT_ID: string | undefined; let IOU_REPORT: OnyxEntry; let reportActionID; @@ -243,6 +246,7 @@ describe('actions/IOU/DeleteMoneyRequest', () => { ); expect(createIOUAction).toBeTruthy(); expect(createIOUAction && getOriginalMessage(createIOUAction)?.IOUReportID).toBe(iouReport?.reportID); + thread = (await getOnyxValue(`${ONYXKEYS.COLLECTION.REPORT}${createIOUAction?.childReportID}`)) as OptimisticChatReport; // When fetching all transactions from Onyx let allTransactions: OnyxCollection; @@ -277,6 +281,7 @@ describe('actions/IOU/DeleteMoneyRequest', () => { violations: {}, iouReport, chatReport, + transactionThreadReport: thread, isChatIOUReportArchived: true, allTransactionViolationsParam: {}, currentUserAccountID: TEST_USER_ACCOUNT_ID, @@ -367,6 +372,7 @@ describe('actions/IOU/DeleteMoneyRequest', () => { violations: {}, iouReport, chatReport, + transactionThreadReport: thread, isChatIOUReportArchived: true, allTransactionViolationsParam: {}, currentUserAccountID: TEST_USER_ACCOUNT_ID, @@ -451,6 +457,7 @@ describe('actions/IOU/DeleteMoneyRequest', () => { violations: {}, iouReport, chatReport, + transactionThreadReport: thread, allTransactionViolationsParam: {}, currentUserAccountID: TEST_USER_ACCOUNT_ID, currentUserEmail: TEST_USER_LOGIN, @@ -505,7 +512,7 @@ describe('actions/IOU/DeleteMoneyRequest', () => { // Given a transaction thread thread = buildTransactionThread(createIOUAction, iouReport, TEST_USER_ACCOUNT_ID); - expect(thread.participants).toStrictEqual({[CARLOS_ACCOUNT_ID]: {notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN, role: CONST.REPORT.ROLE.ADMIN}}); + expect(thread.participants).toStrictEqual(expectedTransactionThreadParticipants); Onyx.connect({ key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${thread.reportID}`, @@ -568,6 +575,7 @@ describe('actions/IOU/DeleteMoneyRequest', () => { violations: {}, iouReport, chatReport, + transactionThreadReport: thread, allTransactionViolationsParam: {}, currentUserAccountID: TEST_USER_ACCOUNT_ID, currentUserEmail: TEST_USER_LOGIN, @@ -723,6 +731,7 @@ describe('actions/IOU/DeleteMoneyRequest', () => { violations: {}, iouReport, chatReport, + transactionThreadReport: thread, allTransactionViolationsParam: {}, currentUserAccountID: TEST_USER_ACCOUNT_ID, currentUserEmail: TEST_USER_LOGIN, @@ -752,7 +761,7 @@ describe('actions/IOU/DeleteMoneyRequest', () => { // Given a transaction thread thread = buildTransactionThread(createIOUAction, iouReport, TEST_USER_ACCOUNT_ID); - expect(thread.participants).toEqual({[CARLOS_ACCOUNT_ID]: {notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN, role: CONST.REPORT.ROLE.ADMIN}}); + expect(thread.participants).toEqual(expectedTransactionThreadParticipants); const participantAccountIDs = Object.keys(thread.participants ?? {}).map(Number); const userLogins = getLoginsByAccountIDs(participantAccountIDs); @@ -844,6 +853,7 @@ describe('actions/IOU/DeleteMoneyRequest', () => { violations: {}, iouReport, chatReport, + transactionThreadReport: thread, allTransactionViolationsParam: {}, currentUserAccountID: TEST_USER_ACCOUNT_ID, currentUserEmail: TEST_USER_LOGIN, @@ -891,7 +901,7 @@ describe('actions/IOU/DeleteMoneyRequest', () => { jest.advanceTimersByTime(10); thread = buildTransactionThread(createIOUAction, iouReport, TEST_USER_ACCOUNT_ID); - expect(thread.participants).toStrictEqual({[CARLOS_ACCOUNT_ID]: {notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN, role: CONST.REPORT.ROLE.ADMIN}}); + expect(thread.participants).toStrictEqual(expectedTransactionThreadParticipants); Onyx.connect({ key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${thread.reportID}`, @@ -1038,6 +1048,7 @@ describe('actions/IOU/DeleteMoneyRequest', () => { violations: {}, iouReport, chatReport, + transactionThreadReport: thread, isChatIOUReportArchived: undefined, allTransactionViolationsParam: {}, currentUserAccountID: TEST_USER_ACCOUNT_ID, @@ -1152,6 +1163,7 @@ describe('actions/IOU/DeleteMoneyRequest', () => { violations: {}, iouReport, chatReport, + transactionThreadReport: thread, isChatIOUReportArchived: undefined, allTransactionViolationsParam: {}, currentUserAccountID: TEST_USER_ACCOUNT_ID, @@ -1213,7 +1225,7 @@ describe('actions/IOU/DeleteMoneyRequest', () => { jest.advanceTimersByTime(10); thread = buildTransactionThread(createIOUAction, iouReport, TEST_USER_ACCOUNT_ID); - expect(thread.participants).toStrictEqual({[CARLOS_ACCOUNT_ID]: {notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN, role: CONST.REPORT.ROLE.ADMIN}}); + expect(thread.participants).toStrictEqual(expectedTransactionThreadParticipants); jest.advanceTimersByTime(10); const participantAccountIDs = Object.keys(thread.participants ?? {}).map(Number); @@ -1263,6 +1275,7 @@ describe('actions/IOU/DeleteMoneyRequest', () => { violations: {}, iouReport, chatReport, + transactionThreadReport: thread, isSingleTransactionView: true, allTransactionViolationsParam: {}, currentUserAccountID: TEST_USER_ACCOUNT_ID, @@ -1322,6 +1335,7 @@ describe('actions/IOU/DeleteMoneyRequest', () => { violations: {}, iouReport, chatReport, + transactionThreadReport: thread, allTransactionViolationsParam: {}, currentUserAccountID: TEST_USER_ACCOUNT_ID, currentUserEmail: TEST_USER_LOGIN, @@ -1393,7 +1407,7 @@ describe('actions/IOU/DeleteMoneyRequest', () => { // Given a transaction thread thread = buildTransactionThread(createIOUAction, iouReport, TEST_USER_ACCOUNT_ID); - expect(thread.participants).toEqual({[CARLOS_ACCOUNT_ID]: {notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN, role: CONST.REPORT.ROLE.ADMIN}}); + expect(thread.participants).toEqual(expectedTransactionThreadParticipants); const participantAccountIDs = Object.keys(thread.participants ?? {}).map(Number); const userLogins = getLoginsByAccountIDs(participantAccountIDs); @@ -1494,6 +1508,7 @@ describe('actions/IOU/DeleteMoneyRequest', () => { violations: {}, iouReport, chatReport, + transactionThreadReport: thread, allTransactionViolationsParam: {}, currentUserAccountID: TEST_USER_ACCOUNT_ID, currentUserEmail: TEST_USER_LOGIN, @@ -1584,6 +1599,7 @@ describe('actions/IOU/DeleteMoneyRequest', () => { violations: {}, iouReport: expenseReport, chatReport: expenseReport, + transactionThreadReport: undefined, transactionIDsPendingDeletion: [], selectedTransactionIDs, allTransactionViolationsParam: {}, @@ -1597,6 +1613,7 @@ describe('actions/IOU/DeleteMoneyRequest', () => { violations: {}, iouReport: expenseReport, chatReport: expenseReport, + transactionThreadReport: undefined, transactionIDsPendingDeletion: [transaction1.transactionID], selectedTransactionIDs, allTransactionViolationsParam: {}, @@ -1676,6 +1693,7 @@ describe('actions/IOU/DeleteMoneyRequest', () => { violations: {}, iouReport: expenseReport, chatReport: expenseReport, + transactionThreadReport: undefined, allTransactionViolationsParam: transactionViolations, currentUserAccountID: TEST_USER_ACCOUNT_ID, currentUserEmail: TEST_USER_LOGIN, @@ -1740,6 +1758,7 @@ describe('actions/IOU/DeleteMoneyRequest', () => { violations: {}, iouReport: expenseReport, chatReport: expenseReport, + transactionThreadReport: undefined, allTransactionViolationsParam: {}, currentUserAccountID: TEST_USER_ACCOUNT_ID, currentUserEmail: TEST_USER_LOGIN,