@@ -61,6 +61,7 @@ import type {IOUAction, IOUType} from '@src/CONST';
61
61
import CONST from '@src/CONST' ;
62
62
import ONYXKEYS from '@src/ONYXKEYS' ;
63
63
import ROUTES from '@src/ROUTES' ;
64
+ import type { Route } from '@src/ROUTES' ;
64
65
import type * as OnyxTypes from '@src/types/onyx' ;
65
66
import type { Attendee , Participant , Split } from '@src/types/onyx/IOU' ;
66
67
import type { ErrorFields , Errors } from '@src/types/onyx/OnyxCommon' ;
@@ -1795,10 +1796,21 @@ function getDeleteTrackExpenseInformation(
1795
1796
1796
1797
if ( shouldDeleteTransactionThread ) {
1797
1798
optimisticData . push (
1799
+ // Use merge instead of set to avoid deleting the report too quickly, which could cause a brief "not found" page to appear.
1800
+ // The remaining parts of the report object will be removed after the API call is successful.
1798
1801
{
1799
- onyxMethod : Onyx . METHOD . SET ,
1802
+ onyxMethod : Onyx . METHOD . MERGE ,
1800
1803
key : `${ ONYXKEYS . COLLECTION . REPORT } ${ transactionThreadID } ` ,
1801
- value : null ,
1804
+ value : {
1805
+ reportID : null ,
1806
+ stateNum : CONST . REPORT . STATE_NUM . APPROVED ,
1807
+ statusNum : CONST . REPORT . STATUS_NUM . CLOSED ,
1808
+ participants : {
1809
+ [ userAccountID ] : {
1810
+ notificationPreference : CONST . REPORT . NOTIFICATION_PREFERENCE . HIDDEN ,
1811
+ } ,
1812
+ } ,
1813
+ } ,
1802
1814
} ,
1803
1815
{
1804
1816
onyxMethod : Onyx . METHOD . SET ,
@@ -1838,6 +1850,19 @@ function getDeleteTrackExpenseInformation(
1838
1850
} ,
1839
1851
] ;
1840
1852
1853
+ // Ensure that any remaining data is removed upon successful completion, even if the server sends a report removal response.
1854
+ // This is done to prevent the removal update from lingering in the applyHTTPSOnyxUpdates function.
1855
+ if ( shouldDeleteTransactionThread && transactionThread ) {
1856
+ successData . push ( {
1857
+ onyxMethod : Onyx . METHOD . MERGE ,
1858
+ key : `${ ONYXKEYS . COLLECTION . REPORT } ${ transactionThreadID } ` ,
1859
+ value : Object . keys ( transactionThread ) . reduce < Record < string , null > > ( ( acc , key ) => {
1860
+ acc [ key ] = null ;
1861
+ return acc ;
1862
+ } , { } ) ,
1863
+ } ) ;
1864
+ }
1865
+
1841
1866
const failureData : OnyxUpdate [ ] = [ ] ;
1842
1867
1843
1868
if ( shouldDeleteTransactionFromOnyx ) {
@@ -5409,10 +5434,9 @@ function updateMoneyRequestAmountAndCurrency({
5409
5434
*
5410
5435
* @param transactionID - The transactionID of IOU
5411
5436
* @param reportAction - The reportAction of the transaction in the IOU report
5412
- * @param isSingleTransactionView - whether we are in the transaction thread report
5413
5437
* @return the url to navigate back once the money request is deleted
5414
5438
*/
5415
- function prepareToCleanUpMoneyRequest ( transactionID : string , reportAction : OnyxTypes . ReportAction , isSingleTransactionView = false ) {
5439
+ function prepareToCleanUpMoneyRequest ( transactionID : string , reportAction : OnyxTypes . ReportAction ) {
5416
5440
// STEP 1: Get all collections we're updating
5417
5441
const allReports = ReportConnection . getAllReports ( ) ;
5418
5442
const iouReportID = ReportActionsUtils . isMoneyRequestAction ( reportAction ) ? ReportActionsUtils . getOriginalMessage ( reportAction ) ?. IOUReportID : '-1' ;
@@ -5532,19 +5556,6 @@ function prepareToCleanUpMoneyRequest(transactionID: string, reportAction: OnyxT
5532
5556
updatedReportPreviewAction . childMoneyRequestCount = reportPreviewAction . childMoneyRequestCount - 1 ;
5533
5557
}
5534
5558
5535
- // STEP 5: Calculate the url that the user will be navigated back to
5536
- // This depends on which page they are on and which resources were deleted
5537
- let reportIDToNavigateBack : string | undefined ;
5538
- if ( iouReport && isSingleTransactionView && shouldDeleteTransactionThread && ! shouldDeleteIOUReport ) {
5539
- reportIDToNavigateBack = iouReport . reportID ;
5540
- }
5541
-
5542
- if ( iouReport ?. chatReportID && shouldDeleteIOUReport ) {
5543
- reportIDToNavigateBack = iouReport . chatReportID ;
5544
- }
5545
-
5546
- const urlToNavigateBack = reportIDToNavigateBack ? ROUTES . REPORT_WITH_ID . getRoute ( reportIDToNavigateBack ) : undefined ;
5547
-
5548
5559
return {
5549
5560
shouldDeleteTransactionThread,
5550
5561
shouldDeleteIOUReport,
@@ -5558,10 +5569,59 @@ function prepareToCleanUpMoneyRequest(transactionID: string, reportAction: OnyxT
5558
5569
transactionViolations,
5559
5570
reportPreviewAction,
5560
5571
iouReport,
5561
- urlToNavigateBack,
5562
5572
} ;
5563
5573
}
5564
5574
5575
+ /**
5576
+ * Calculate the URL to navigate to after a money request deletion
5577
+ * @param transactionID - The ID of the money request being deleted
5578
+ * @param reportAction - The report action associated with the money request
5579
+ * @param isSingleTransactionView - whether we are in the transaction thread report
5580
+ * @returns The URL to navigate to
5581
+ */
5582
+ function getNavigationUrlOnMoneyRequestDelete ( transactionID : string , reportAction : OnyxTypes . ReportAction , isSingleTransactionView = false ) : Route | undefined {
5583
+ const { shouldDeleteTransactionThread, shouldDeleteIOUReport, iouReport} = prepareToCleanUpMoneyRequest ( transactionID , reportAction ) ;
5584
+
5585
+ // Determine which report to navigate back to
5586
+ if ( iouReport && isSingleTransactionView && shouldDeleteTransactionThread && ! shouldDeleteIOUReport ) {
5587
+ return ROUTES . REPORT_WITH_ID . getRoute ( iouReport . reportID ) ;
5588
+ }
5589
+
5590
+ if ( iouReport ?. chatReportID && shouldDeleteIOUReport ) {
5591
+ return ROUTES . REPORT_WITH_ID . getRoute ( iouReport . chatReportID ) ;
5592
+ }
5593
+
5594
+ return undefined ;
5595
+ }
5596
+
5597
+ /**
5598
+ * Calculate the URL to navigate to after a track expense deletion
5599
+ * @param chatReportID - The ID of the chat report containing the track expense
5600
+ * @param transactionID - The ID of the track expense being deleted
5601
+ * @param reportAction - The report action associated with the track expense
5602
+ * @param isSingleTransactionView - Whether we're in single transaction view
5603
+ * @returns The URL to navigate to
5604
+ */
5605
+ function getNavigationUrlAfterTrackExpenseDelete ( chatReportID : string , transactionID : string , reportAction : OnyxTypes . ReportAction , isSingleTransactionView = false ) : Route | undefined {
5606
+ const chatReport = ReportConnection . getAllReports ( ) ?. [ `${ ONYXKEYS . COLLECTION . REPORT } ${ chatReportID } ` ] ?? null ;
5607
+
5608
+ // If not a self DM, handle it as a regular money request
5609
+ if ( ! ReportUtils . isSelfDM ( chatReport ) ) {
5610
+ return getNavigationUrlOnMoneyRequestDelete ( transactionID , reportAction , isSingleTransactionView ) ;
5611
+ }
5612
+
5613
+ const transactionThreadID = reportAction . childReportID ;
5614
+ const shouldDeleteTransactionThread = transactionThreadID ? ( reportAction ?. childVisibleActionCount ?? 0 ) === 0 : false ;
5615
+
5616
+ // Only navigate if in single transaction view and the thread will be deleted
5617
+ if ( isSingleTransactionView && shouldDeleteTransactionThread && chatReport ?. reportID ) {
5618
+ // Pop the deleted report screen before navigating. This prevents navigating to the Concierge chat due to the missing report.
5619
+ return ROUTES . REPORT_WITH_ID . getRoute ( chatReport . reportID ) ;
5620
+ }
5621
+
5622
+ return undefined ;
5623
+ }
5624
+
5565
5625
/**
5566
5626
*
5567
5627
* @param transactionID - The transactionID of IOU
@@ -5580,9 +5640,9 @@ function cleanUpMoneyRequest(transactionID: string, reportAction: OnyxTypes.Repo
5580
5640
chatReport,
5581
5641
iouReport,
5582
5642
reportPreviewAction,
5583
- urlToNavigateBack,
5584
- } = prepareToCleanUpMoneyRequest ( transactionID , reportAction , isSingleTransactionView ) ;
5643
+ } = prepareToCleanUpMoneyRequest ( transactionID , reportAction ) ;
5585
5644
5645
+ const urlToNavigateBack = getNavigationUrlOnMoneyRequestDelete ( transactionID , reportAction , isSingleTransactionView ) ;
5586
5646
// build Onyx data
5587
5647
5588
5648
// Onyx operations to delete the transaction, update the IOU report action and chat report action
@@ -5726,8 +5786,9 @@ function deleteMoneyRequest(transactionID: string, reportAction: OnyxTypes.Repor
5726
5786
transactionViolations,
5727
5787
iouReport,
5728
5788
reportPreviewAction,
5729
- urlToNavigateBack,
5730
- } = prepareToCleanUpMoneyRequest ( transactionID , reportAction , isSingleTransactionView ) ;
5789
+ } = prepareToCleanUpMoneyRequest ( transactionID , reportAction ) ;
5790
+
5791
+ const urlToNavigateBack = getNavigationUrlOnMoneyRequestDelete ( transactionID , reportAction , isSingleTransactionView ) ;
5731
5792
5732
5793
// STEP 2: Build Onyx data
5733
5794
// The logic mostly resembles the cleanUpMoneyRequest function
@@ -5747,10 +5808,21 @@ function deleteMoneyRequest(transactionID: string, reportAction: OnyxTypes.Repor
5747
5808
5748
5809
if ( shouldDeleteTransactionThread ) {
5749
5810
optimisticData . push (
5811
+ // Use merge instead of set to avoid deleting the report too quickly, which could cause a brief "not found" page to appear.
5812
+ // The remaining parts of the report object will be removed after the API call is successful.
5750
5813
{
5751
- onyxMethod : Onyx . METHOD . SET ,
5814
+ onyxMethod : Onyx . METHOD . MERGE ,
5752
5815
key : `${ ONYXKEYS . COLLECTION . REPORT } ${ transactionThreadID } ` ,
5753
- value : null ,
5816
+ value : {
5817
+ reportID : null ,
5818
+ stateNum : CONST . REPORT . STATE_NUM . APPROVED ,
5819
+ statusNum : CONST . REPORT . STATUS_NUM . CLOSED ,
5820
+ participants : {
5821
+ [ userAccountID ] : {
5822
+ notificationPreference : CONST . REPORT . NOTIFICATION_PREFERENCE . HIDDEN ,
5823
+ } ,
5824
+ } ,
5825
+ } ,
5754
5826
} ,
5755
5827
{
5756
5828
onyxMethod : Onyx . METHOD . SET ,
@@ -5848,6 +5920,19 @@ function deleteMoneyRequest(transactionID: string, reportAction: OnyxTypes.Repor
5848
5920
} ,
5849
5921
] ;
5850
5922
5923
+ // Ensure that any remaining data is removed upon successful completion, even if the server sends a report removal response.
5924
+ // This is done to prevent the removal update from lingering in the applyHTTPSOnyxUpdates function.
5925
+ if ( shouldDeleteTransactionThread && transactionThread ) {
5926
+ successData . push ( {
5927
+ onyxMethod : Onyx . METHOD . MERGE ,
5928
+ key : `${ ONYXKEYS . COLLECTION . REPORT } ${ transactionThreadID } ` ,
5929
+ value : Object . keys ( transactionThread ) . reduce < Record < string , null > > ( ( acc , key ) => {
5930
+ acc [ key ] = null ;
5931
+ return acc ;
5932
+ } , { } ) ,
5933
+ } ) ;
5934
+ }
5935
+
5851
5936
if ( shouldDeleteIOUReport ) {
5852
5937
successData . push ( {
5853
5938
onyxMethod : Onyx . METHOD . SET ,
@@ -5951,15 +6036,18 @@ function deleteMoneyRequest(transactionID: string, reportAction: OnyxTypes.Repor
5951
6036
}
5952
6037
5953
6038
function deleteTrackExpense ( chatReportID : string , transactionID : string , reportAction : OnyxTypes . ReportAction , isSingleTransactionView = false ) {
6039
+ const urlToNavigateBack = getNavigationUrlAfterTrackExpenseDelete ( chatReportID , transactionID , reportAction , isSingleTransactionView ) ;
6040
+
5954
6041
// STEP 1: Get all collections we're updating
5955
6042
const chatReport = ReportConnection . getAllReports ( ) ?. [ `${ ONYXKEYS . COLLECTION . REPORT } ${ chatReportID } ` ] ?? null ;
5956
6043
if ( ! ReportUtils . isSelfDM ( chatReport ) ) {
5957
- return deleteMoneyRequest ( transactionID , reportAction , isSingleTransactionView ) ;
6044
+ deleteMoneyRequest ( transactionID , reportAction , isSingleTransactionView ) ;
6045
+ return urlToNavigateBack ;
5958
6046
}
5959
6047
5960
6048
const whisperAction = ReportActionsUtils . getTrackExpenseActionableWhisper ( transactionID , chatReportID ) ;
5961
6049
const actionableWhisperReportActionID = whisperAction ?. reportActionID ;
5962
- const { parameters, optimisticData, successData, failureData, shouldDeleteTransactionThread } = getDeleteTrackExpenseInformation (
6050
+ const { parameters, optimisticData, successData, failureData} = getDeleteTrackExpenseInformation (
5963
6051
chatReportID ,
5964
6052
transactionID ,
5965
6053
reportAction ,
@@ -5974,10 +6062,7 @@ function deleteTrackExpense(chatReportID: string, transactionID: string, reportA
5974
6062
CachedPDFPaths . clearByKey ( transactionID ) ;
5975
6063
5976
6064
// STEP 7: Navigate the user depending on which page they are on and which resources were deleted
5977
- if ( isSingleTransactionView && shouldDeleteTransactionThread ) {
5978
- // Pop the deleted report screen before navigating. This prevents navigating to the Concierge chat due to the missing report.
5979
- return ROUTES . REPORT_WITH_ID . getRoute ( chatReport ?. reportID ?? '-1' ) ;
5980
- }
6065
+ return urlToNavigateBack ;
5981
6066
}
5982
6067
5983
6068
/**
@@ -8585,5 +8670,7 @@ export {
8585
8670
updateLastLocationPermissionPrompt ,
8586
8671
resolveDuplicates ,
8587
8672
getIOUReportActionToApproveOrPay ,
8673
+ getNavigationUrlOnMoneyRequestDelete ,
8674
+ getNavigationUrlAfterTrackExpenseDelete ,
8588
8675
} ;
8589
8676
export type { GPSPoint as GpsPoint , IOURequestType } ;
0 commit comments