Skip to content

Commit bffc50b

Browse files
authored
Merge pull request Expensify#75445 from situchan/revert-72413
[CP Staging] Revert "Merge pull request Expensify#72413 from Expensify/mollfpr-create-optimistic-ioureport-action-and-transaction-thread"
2 parents d05e6f2 + 4468cb2 commit bffc50b

9 files changed

Lines changed: 72 additions & 299 deletions

File tree

src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -272,8 +272,7 @@ function MoneyRequestReportTransactionList({
272272
} as ReportScreenNavigationProps;
273273

274274
if (!reportIDToNavigate) {
275-
const transaction = sortedTransactions.find((t) => t.transactionID === activeTransactionID);
276-
const transactionThreadReport = createTransactionThreadReport(report, iouAction, transaction);
275+
const transactionThreadReport = createTransactionThreadReport(report, iouAction);
277276
if (transactionThreadReport) {
278277
reportIDToNavigate = transactionThreadReport.reportID;
279278
routeParams.reportID = reportIDToNavigate;

src/components/MoneyRequestReportView/MoneyRequestReportView.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ function MoneyRequestReportView({report, policy, reportMetadata, shouldDisplayRe
9898

9999
const {transactions: reportTransactions, violations: allReportViolations} = useTransactionsAndViolationsForReport(reportID);
100100
const hasPendingDeletionTransaction = Object.values(reportTransactions ?? {}).some((transaction) => transaction.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE);
101-
const transactions = useMemo(() => getAllNonDeletedTransactions(reportTransactions, reportActions, isOffline, true), [reportTransactions, reportActions, isOffline]);
101+
const transactions = useMemo(() => getAllNonDeletedTransactions(reportTransactions, reportActions), [reportTransactions, reportActions]);
102102

103103
const visibleTransactions = transactions?.filter((transaction) => isOffline || transaction.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE);
104104
const reportTransactionIDs = visibleTransactions?.map((transaction) => transaction.transactionID);

src/libs/MoneyRequestReportUtils.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ function getReportIDForTransaction(transactionItem: TransactionListItemType) {
7171
/**
7272
* Filters all available transactions and returns the ones that belong to not removed action and not removed parent action.
7373
*/
74-
function getAllNonDeletedTransactions(transactions: OnyxCollection<Transaction>, reportActions: ReportAction[], isOffline = false, includeOrphanedTransactions = false) {
74+
function getAllNonDeletedTransactions(transactions: OnyxCollection<Transaction>, reportActions: ReportAction[], isOffline = false) {
7575
return Object.values(transactions ?? {}).filter((transaction): transaction is Transaction => {
7676
if (!transaction) {
7777
return false;
@@ -82,9 +82,6 @@ function getAllNonDeletedTransactions(transactions: OnyxCollection<Transaction>,
8282
}
8383

8484
const action = getIOUActionForTransactionID(reportActions, transaction.transactionID);
85-
if (!action && includeOrphanedTransactions) {
86-
return true;
87-
}
8885
if (action?.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE && isOffline) {
8986
return true;
9087
}

src/libs/SearchUIUtils.ts

Lines changed: 6 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1371,69 +1371,14 @@ function getTaskSections(
13711371
);
13721372
}
13731373

1374-
/**
1375-
* @private
1376-
*
1377-
* Extracts the core Transaction fields from a TransactionListItemType
1378-
* This removes UI-specific fields like formattedFrom, hash, violations, etc.
1379-
*/
1380-
function getTransactionFromTransactionListItem(item: TransactionListItemType): OnyxTypes.Transaction {
1381-
// Extract only the core Transaction fields, excluding UI-specific and search-specific fields
1382-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
1383-
const {
1384-
// Remove UI-specific fields
1385-
keyForList,
1386-
action,
1387-
allActions,
1388-
report,
1389-
from,
1390-
to,
1391-
formattedFrom,
1392-
formattedTo,
1393-
formattedTotal,
1394-
formattedMerchant,
1395-
date,
1396-
shouldShowMerchant,
1397-
shouldShowYear: shouldTransactionShowYear,
1398-
isAmountColumnWide,
1399-
isTaxAmountColumnWide,
1400-
violations,
1401-
hash,
1402-
moneyRequestReportActionID,
1403-
canDelete,
1404-
convertedAmount,
1405-
convertedCurrency,
1406-
transactionThreadReportID,
1407-
isFromOneTransactionReport,
1408-
accountID,
1409-
policyID,
1410-
transactionType,
1411-
// Keep all other fields (core Transaction fields)
1412-
...transaction
1413-
} = item;
1414-
1415-
return transaction as OnyxTypes.Transaction;
1416-
}
1417-
14181374
/** Creates transaction thread report and navigates to it from the search page */
14191375
function createAndOpenSearchTransactionThread(item: TransactionListItemType, hash: number, backTo: string, transactionPreviewData?: TransactionPreviewData, shouldNavigate = true) {
1420-
// Treat '0' as empty for reportActionID (0 means no IOU action exists in the backend)
1421-
const reportActionID = item.moneyRequestReportActionID === '0' ? '' : item.moneyRequestReportActionID;
1422-
1423-
// If the IOU action exists in the backend, populate Onyx with data from the search snapshot
1424-
// This shows the transaction thread immediately while waiting for OpenReport to return the real data
1425-
if (reportActionID) {
1426-
const previewData = transactionPreviewData
1427-
? {...transactionPreviewData, hasTransactionThreadReport: true}
1428-
: {hasTransaction: false, hasParentReport: false, hasParentReportAction: false, hasTransactionThreadReport: true};
1429-
setOptimisticDataForTransactionThreadPreview(item, previewData);
1430-
}
1431-
1432-
// For legacy transactions without an IOU action in the backend, pass transaction data
1433-
// This allows OpenReport to create the IOU action and transaction thread on the backend
1434-
const transaction = !reportActionID ? getTransactionFromTransactionListItem(item) : undefined;
1435-
const transactionViolations = !reportActionID ? item.violations : undefined;
1436-
const transactionThreadReport = createTransactionThreadReport(item.report, {reportActionID} as OnyxTypes.ReportAction, transaction, transactionViolations);
1376+
const previewData = transactionPreviewData
1377+
? {...transactionPreviewData, hasTransactionThreadReport: true}
1378+
: {hasTransaction: false, hasParentReport: false, hasParentReportAction: false, hasTransactionThreadReport: true};
1379+
setOptimisticDataForTransactionThreadPreview(item, previewData);
1380+
1381+
const transactionThreadReport = createTransactionThreadReport(item.report, {reportActionID: item.moneyRequestReportActionID} as OnyxTypes.ReportAction);
14371382
if (transactionThreadReport?.reportID) {
14381383
updateSearchResultsWithTransactionThreadReportID(hash, item.transactionID, transactionThreadReport?.reportID);
14391384
}

src/libs/actions/Report.ts

Lines changed: 55 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -974,13 +974,7 @@ function clearAvatarErrors(reportID: string) {
974974
* @param parentReportActionID The parent report action that a thread was created from (only passed for new threads)
975975
* @param isFromDeepLink Whether or not this report is being opened from a deep link
976976
* @param participantAccountIDList The list of accountIDs that are included in a new chat, not including the user creating it
977-
* @param avatar The avatar file to upload for a new group chat
978-
* @param isNewThread Whether this is a new thread being created
979-
* @param transaction The transaction object for legacy transactions that don't have a transaction thread or money request preview yet
980-
* @param transactionViolations The violations for the transaction, if any
981-
* @param parentReportID The parent report ID for the transaction thread (optional, defaults to transaction.reportID)
982977
*/
983-
// eslint-disable-next-line @typescript-eslint/max-params
984978
function openReport(
985979
reportID: string | undefined,
986980
reportActionID?: string,
@@ -990,10 +984,8 @@ function openReport(
990984
isFromDeepLink = false,
991985
participantAccountIDList: number[] = [],
992986
avatar?: File | CustomRNImageManipulatorResult,
987+
transactionID?: string,
993988
isNewThread = false,
994-
transaction?: Transaction,
995-
transactionViolations?: TransactionViolations,
996-
parentReportID?: string,
997989
) {
998990
if (!reportID) {
999991
return;
@@ -1074,92 +1066,59 @@ function openReport(
10741066
emailList: participantLoginList ? participantLoginList.join(',') : '',
10751067
accountIDList: participantAccountIDList ? participantAccountIDList.join(',') : '',
10761068
parentReportActionID,
1077-
transactionID: transaction?.transactionID,
1069+
transactionID,
10781070
};
10791071

1080-
// This is a legacy transaction that doesn't have either a transaction thread or a money request preview
1081-
if (transaction && !parentReportActionID) {
1082-
const transactionParentReportID = parentReportID ?? transaction?.reportID;
1083-
const iouReportActionID = rand64();
1084-
1085-
const optimisticIOUAction = buildOptimisticIOUReportAction({
1086-
type: CONST.IOU.REPORT_ACTION_TYPE.CREATE,
1087-
amount: Math.abs(transaction.amount),
1088-
currency: transaction.currency,
1089-
comment: transaction.comment?.comment ?? '',
1090-
participants: [{accountID: currentUserAccountID, login: currentUserEmail ?? ''}],
1091-
transactionID: transaction.transactionID,
1092-
isOwnPolicyExpenseChat: true,
1093-
reportActionID: iouReportActionID,
1094-
iouReportID: transactionParentReportID,
1095-
});
1096-
1097-
// We have a case where the transaction data is only available from the snapshot
1098-
// So we need to add the transaction data to Onyx so it's available when opening the report
1099-
optimisticData.push({
1100-
onyxMethod: Onyx.METHOD.MERGE,
1101-
key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transaction.transactionID}`,
1102-
value: transaction,
1103-
});
1104-
1105-
// Add violations if they exist. This is needed when opening from search results where
1106-
// violations are in the snapshot but not yet synced to the main collections, so we need
1107-
// to add them to Onyx to ensure they show up in the transaction thread
1108-
if (transactionViolations) {
1109-
optimisticData.push({
1110-
onyxMethod: Onyx.METHOD.MERGE,
1111-
key: `${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${transaction.transactionID}`,
1112-
value: transactionViolations,
1113-
});
1114-
}
1072+
// This is a legacy transactions that doesn't have either a transaction thread or a money request preview
1073+
if (transactionID && !parentReportActionID) {
1074+
const transaction = allTransactions?.[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`];
1075+
1076+
if (transaction) {
1077+
const selfDMReportID = findSelfDMReportID();
1078+
1079+
if (selfDMReportID) {
1080+
const generatedReportActionID = rand64();
1081+
const optimisticParentAction = buildOptimisticIOUReportAction({
1082+
type: CONST.IOU.REPORT_ACTION_TYPE.CREATE,
1083+
amount: Math.abs(transaction.amount),
1084+
currency: transaction.currency,
1085+
comment: transaction.comment?.comment ?? '',
1086+
participants: [{accountID: currentUserAccountID, login: currentUserEmail ?? ''}],
1087+
transactionID,
1088+
isOwnPolicyExpenseChat: true,
1089+
});
11151090

1116-
// Attach the optimistic IOU report action created for the transaction to the transaction thread
1117-
optimisticData.push({
1118-
onyxMethod: Onyx.METHOD.MERGE,
1119-
key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`,
1120-
value: {
1121-
parentReportActionID: iouReportActionID,
1122-
},
1123-
});
1091+
optimisticData.push({
1092+
onyxMethod: Onyx.METHOD.MERGE,
1093+
key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`,
1094+
value: {
1095+
parentReportID: selfDMReportID,
1096+
parentReportActionID: generatedReportActionID,
1097+
},
1098+
});
11241099

1125-
optimisticData.push({
1126-
onyxMethod: Onyx.METHOD.MERGE,
1127-
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionParentReportID}`,
1128-
value: {
1129-
[iouReportActionID]: {
1130-
...optimisticIOUAction,
1131-
childReportID: reportID,
1132-
},
1133-
},
1134-
});
1100+
// Log how often the legacy transaction fallback path is taken
1101+
Log.info('[Report] Legacy transaction fallback: creating money request preview in self DM', false, {
1102+
selfDMReportID,
1103+
transactionID,
1104+
reportID,
1105+
});
11351106

1136-
// Update the snapshot with the new transactionThreadReportID and moneyRequestReportActionID if we're coming from search
1137-
// preventing duplicate reportActionID when moneyRequestReportActionID still empty
1138-
const currentSearchQueryJSON = getCurrentSearchQueryJSON();
1139-
if (currentSearchQueryJSON?.hash) {
1140-
// @ts-expect-error - will be solved in https://github.com/Expensify/App/issues/73830
1141-
optimisticData.push({
1142-
onyxMethod: Onyx.METHOD.MERGE,
1143-
key: `${ONYXKEYS.COLLECTION.SNAPSHOT}${currentSearchQueryJSON.hash}`,
1144-
value: {
1145-
data: {
1146-
[`${ONYXKEYS.COLLECTION.TRANSACTION}${transaction.transactionID}`]: {
1147-
transactionThreadReportID: reportID,
1148-
moneyRequestReportActionID: iouReportActionID,
1107+
optimisticData.push({
1108+
onyxMethod: Onyx.METHOD.MERGE,
1109+
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${selfDMReportID}`,
1110+
value: {
1111+
[generatedReportActionID]: {
1112+
...optimisticParentAction,
1113+
reportActionID: generatedReportActionID,
1114+
childReportID: reportID,
11491115
},
11501116
},
1151-
},
1152-
});
1153-
}
1154-
1155-
parameters.moneyRequestPreviewReportActionID = iouReportActionID;
1117+
});
11561118

1157-
// Log how often the legacy transaction fallback path is taken
1158-
Log.info('[Report] Legacy transaction fallback: creating money request preview', false, {
1159-
transactionParentReportID,
1160-
transactionID: transaction.transactionID,
1161-
reportID,
1162-
});
1119+
parameters.moneyRequestPreviewReportActionID = generatedReportActionID;
1120+
}
1121+
}
11631122
}
11641123

11651124
const isInviteOnboardingComplete = introSelected?.isInviteOnboardingComplete ?? false;
@@ -1396,20 +1355,16 @@ function getOptimisticChatReport(accountID: number): OptimisticChatReport {
13961355
});
13971356
}
13981357

1399-
function createTransactionThreadReport(
1400-
iouReport?: OnyxEntry<Report>,
1401-
iouReportAction?: OnyxEntry<ReportAction>,
1402-
transaction?: Transaction,
1403-
transactionViolations?: TransactionViolations,
1404-
): OptimisticChatReport | undefined {
1405-
// Determine if we need selfDM report (for track expenses or unreported transactions)
1406-
const isTrackExpense = !iouReport && ReportActionsUtils.isTrackExpenseAction(iouReportAction);
1407-
const isUnreportedTransaction = transaction?.reportID === CONST.REPORT.UNREPORTED_REPORT_ID;
1408-
const selfDMReportID = isTrackExpense || isUnreportedTransaction ? findSelfDMReportID() : undefined;
1358+
function createTransactionThreadReport(iouReport: OnyxEntry<Report>, iouReportAction: OnyxEntry<ReportAction>): OptimisticChatReport | undefined {
1359+
if (!iouReportAction) {
1360+
Log.warn('Cannot build transaction thread report without iouReportAction parameter');
1361+
return;
1362+
}
14091363

14101364
let reportToUse = iouReport;
14111365
// For track expenses without iouReport, get the selfDM report
1412-
if (isTrackExpense && selfDMReportID) {
1366+
if (!iouReport && ReportActionsUtils.isTrackExpenseAction(iouReportAction)) {
1367+
const selfDMReportID = findSelfDMReportID();
14131368
reportToUse = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${selfDMReportID}`];
14141369
}
14151370

@@ -1418,29 +1373,9 @@ function createTransactionThreadReport(
14181373
return;
14191374
}
14201375

1421-
// Sync fresh report data from snapshot to allReports. When navigating from search,
1422-
// allReports may be stale and missing parentReportID/parentReportActionID, causing
1423-
// getAllAncestorReportActionIDs() to fail when adding comments optimistically.
1424-
if (iouReport?.reportID && reportToUse.reportID === iouReport.reportID) {
1425-
Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${iouReport.reportID}`, iouReport);
1426-
}
1427-
14281376
const optimisticTransactionThreadReportID = generateReportID();
14291377
const optimisticTransactionThread = buildTransactionThread(iouReportAction, reportToUse, undefined, optimisticTransactionThreadReportID);
1430-
openReport(
1431-
optimisticTransactionThreadReportID,
1432-
undefined,
1433-
currentUserEmail ? [currentUserEmail] : [],
1434-
optimisticTransactionThread,
1435-
iouReportAction?.reportActionID,
1436-
false,
1437-
[],
1438-
undefined,
1439-
false,
1440-
transaction,
1441-
transactionViolations,
1442-
selfDMReportID,
1443-
);
1378+
openReport(optimisticTransactionThreadReportID, undefined, currentUserEmail ? [currentUserEmail] : [], optimisticTransactionThread, iouReportAction?.reportActionID);
14441379
return optimisticTransactionThread;
14451380
}
14461381

@@ -1555,7 +1490,7 @@ function navigateToAndOpenChildReport(childReportID: string | undefined, parentR
15551490

15561491
if (!childReportID) {
15571492
const participantLogins = PersonalDetailsUtils.getLoginsByAccountIDs(Object.keys(newChat.participants ?? {}).map(Number));
1558-
openReport(newChat.reportID, '', participantLogins, newChat, parentReportAction.reportActionID, undefined, undefined, undefined, true);
1493+
openReport(newChat.reportID, '', participantLogins, newChat, parentReportAction.reportActionID, undefined, undefined, undefined, undefined, true);
15591494
} else {
15601495
Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${childReportID}`, newChat);
15611496
}

src/pages/home/ReportScreen.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ function ReportScreen({route, navigation}: ReportScreenProps) {
322322
const {transactions: allReportTransactions, violations: allReportViolations} = useTransactionsAndViolationsForReport(reportIDFromRoute);
323323
const hasPendingDeletionTransaction = Object.values(allReportTransactions ?? {}).some((transaction) => transaction.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE);
324324

325-
const reportTransactions = useMemo(() => getAllNonDeletedTransactions(allReportTransactions, reportActions, isOffline, true), [allReportTransactions, reportActions, isOffline]);
325+
const reportTransactions = useMemo(() => getAllNonDeletedTransactions(allReportTransactions, reportActions, isOffline), [allReportTransactions, reportActions, isOffline]);
326326
// wrapping in useMemo because this is array operation and can cause performance issues
327327
const visibleTransactions = useMemo(
328328
() => reportTransactions?.filter((transaction) => isOffline || transaction.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE),
@@ -507,7 +507,7 @@ function ReportScreen({route, navigation}: ReportScreenProps) {
507507
const currentReportTransaction = getReportTransactions(reportID).filter((transaction) => transaction.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE);
508508
const oneTransactionID = currentReportTransaction.at(0)?.transactionID;
509509
const iouAction = getIOUActionForReportID(reportID, oneTransactionID);
510-
createTransactionThreadReport(report, iouAction, currentReportTransaction.at(0));
510+
createTransactionThreadReport(report, iouAction);
511511
}, [report, reportID]);
512512

513513
const isInviteOnboardingComplete = introSelected?.isInviteOnboardingComplete ?? false;
@@ -523,7 +523,7 @@ function ReportScreen({route, navigation}: ReportScreenProps) {
523523
}
524524

525525
// If there is one transaction thread that has not yet been created, we should create it.
526-
if ((transactionThreadReportID === CONST.FAKE_REPORT_ID && !transactionThreadReport) || (visibleTransactions.length === 1 && !transactionThreadReportID)) {
526+
if (transactionThreadReportID === CONST.FAKE_REPORT_ID && !transactionThreadReport) {
527527
createOneTransactionThreadReport();
528528
return;
529529
}
@@ -549,7 +549,6 @@ function ReportScreen({route, navigation}: ReportScreenProps) {
549549
isOffline,
550550
transactionThreadReportID,
551551
transactionThreadReport,
552-
visibleTransactions.length,
553552
reportIDFromRoute,
554553
reportActionIDFromRoute,
555554
createOneTransactionThreadReport,

0 commit comments

Comments
 (0)