diff --git a/Mobile-Expensify b/Mobile-Expensify
index 984335621e0c4..4c7a93ee82200 160000
--- a/Mobile-Expensify
+++ b/Mobile-Expensify
@@ -1 +1 @@
-Subproject commit 984335621e0c4713ab1338f3064c51f513b4256b
+Subproject commit 4c7a93ee8220007ef4ba6a8bbbec960e840ec07f
diff --git a/android/app/build.gradle b/android/app/build.gradle
index e917ec1648cc1..b3a0376889614 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -114,8 +114,8 @@ android {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
multiDexEnabled rootProject.ext.multiDexEnabled
- versionCode 1009015904
- versionName "9.1.59-4"
+ versionCode 1009015906
+ versionName "9.1.59-6"
// Supported language variants must be declared here to avoid from being removed during the compilation.
// This also helps us to not include unnecessary language variants in the APK.
resConfigs "en", "es"
diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist
index 08c0bd194e515..e124328df974e 100644
--- a/ios/NewExpensify/Info.plist
+++ b/ios/NewExpensify/Info.plist
@@ -44,7 +44,7 @@
CFBundleVersion
- 9.1.59.4
+ 9.1.59.6
FullStory
OrgId
diff --git a/ios/NotificationServiceExtension/Info.plist b/ios/NotificationServiceExtension/Info.plist
index 7ef6594d98ef8..aab6d712fc26a 100644
--- a/ios/NotificationServiceExtension/Info.plist
+++ b/ios/NotificationServiceExtension/Info.plist
@@ -13,7 +13,7 @@
CFBundleShortVersionString
9.1.59
CFBundleVersion
- 9.1.59.4
+ 9.1.59.6
NSExtension
NSExtensionPointIdentifier
diff --git a/ios/ShareViewController/Info.plist b/ios/ShareViewController/Info.plist
index cb01562952fa6..4c16fe60a781f 100644
--- a/ios/ShareViewController/Info.plist
+++ b/ios/ShareViewController/Info.plist
@@ -13,7 +13,7 @@
CFBundleShortVersionString
9.1.59
CFBundleVersion
- 9.1.59.4
+ 9.1.59.6
NSExtension
NSExtensionAttributes
diff --git a/package-lock.json b/package-lock.json
index 215cd96d6a517..8c93a616970fa 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "new.expensify",
- "version": "9.1.59-4",
+ "version": "9.1.59-6",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "new.expensify",
- "version": "9.1.59-4",
+ "version": "9.1.59-6",
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
diff --git a/package.json b/package.json
index c00b3081daa70..0c82c5cebc804 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "new.expensify",
- "version": "9.1.59-4",
+ "version": "9.1.59-6",
"author": "Expensify, Inc.",
"homepage": "https://new.expensify.com",
"description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.",
diff --git a/src/CONST.ts b/src/CONST.ts
index 8ae664811cb73..910fffd5583c9 100755
--- a/src/CONST.ts
+++ b/src/CONST.ts
@@ -1063,7 +1063,6 @@ const CONST = {
EMPTY_ARRAY,
EMPTY_OBJECT,
DEFAULT_NUMBER_ID,
- FAKE_REPORT_ID: 'FAKE_REPORT_ID',
USE_EXPENSIFY_URL,
EXPENSIFY_URL,
EXPENSIFY_MOBILE_URL,
diff --git a/src/ROUTES.ts b/src/ROUTES.ts
index 39cb1bb389d9a..9485b758d8c33 100644
--- a/src/ROUTES.ts
+++ b/src/ROUTES.ts
@@ -84,14 +84,12 @@ const ROUTES = {
backTo,
moneyRequestReportActionID,
transactionID,
- iouReportID,
}: {
reportID: string | undefined;
reportActionID?: string;
backTo?: string;
moneyRequestReportActionID?: string;
transactionID?: string;
- iouReportID?: string;
}) => {
if (!reportID) {
Log.warn('Invalid reportID is used to build the SEARCH_REPORT route');
@@ -108,10 +106,6 @@ const ROUTES = {
queryParams.push(`moneyRequestReportActionID=${moneyRequestReportActionID}`);
}
- if (iouReportID) {
- queryParams.push(`iouReportID=${iouReportID}`);
- }
-
const queryString = queryParams.length > 0 ? (`${baseRoute}?${queryParams.join('&')}` as const) : baseRoute;
return getUrlWithBackToParam(queryString, backTo);
},
@@ -382,19 +376,10 @@ const ROUTES = {
REPORT: 'r',
REPORT_WITH_ID: {
route: 'r/:reportID?/:reportActionID?',
- getRoute: (
- reportID: string | undefined,
- reportActionID?: string,
- referrer?: string,
- moneyRequestReportActionID?: string,
- transactionID?: string,
- backTo?: string,
- iouReportID?: string,
- ) => {
+ getRoute: (reportID: string | undefined, reportActionID?: string, referrer?: string, moneyRequestReportActionID?: string, transactionID?: string, backTo?: string) => {
if (!reportID) {
Log.warn('Invalid reportID is used to build the REPORT_WITH_ID route');
}
-
const baseRoute = reportActionID ? (`r/${reportID}/${reportActionID}` as const) : (`r/${reportID}` as const);
const queryParams: string[] = [];
@@ -408,10 +393,6 @@ const ROUTES = {
queryParams.push(`transactionID=${transactionID}`);
}
- if (iouReportID) {
- queryParams.push(`iouReportID=${iouReportID}`);
- }
-
const queryString = queryParams.length > 0 ? `?${queryParams.join('&')}` : '';
return getUrlWithBackToParam(`${baseRoute}${queryString}` as const, backTo);
@@ -611,15 +592,10 @@ const ROUTES = {
},
MONEY_REQUEST_HOLD_REASON: {
route: ':type/edit/reason/:transactionID?/:searchHash?',
- getRoute: (type: ValueOf, transactionID: string, reportID: string | undefined, backTo: string, searchHash?: number) => {
- let route = searchHash
- ? (`${type as string}/edit/reason/${transactionID}/${searchHash}/?backTo=${backTo}` as const)
- : (`${type as string}/edit/reason/${transactionID}/?backTo=${backTo}` as const);
-
- if (reportID) {
- route = `${route}&reportID=${reportID}` as const;
- }
-
+ getRoute: (type: ValueOf, transactionID: string, reportID: string, backTo: string, searchHash?: number) => {
+ const route = searchHash
+ ? (`${type as string}/edit/reason/${transactionID}/${searchHash}/?backTo=${backTo}&reportID=${reportID}` as const)
+ : (`${type as string}/edit/reason/${transactionID}/?backTo=${backTo}&reportID=${reportID}` as const);
return route;
},
},
diff --git a/src/components/MoneyReportHeader.tsx b/src/components/MoneyReportHeader.tsx
index 4ecac1dac0ecd..30e1c9e62ffa6 100644
--- a/src/components/MoneyReportHeader.tsx
+++ b/src/components/MoneyReportHeader.tsx
@@ -17,20 +17,18 @@ import useSelectedTransactionsActions from '@hooks/useSelectedTransactionsAction
import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import {turnOffMobileSelectionMode} from '@libs/actions/MobileSelectionMode';
-import {deleteAppReport, downloadReportPDF, exportReportToCSV, exportReportToPDF, exportToIntegration, markAsManuallyExported, openReport, openUnreportedExpense} from '@libs/actions/Report';
+import {deleteAppReport, downloadReportPDF, exportReportToCSV, exportReportToPDF, exportToIntegration, markAsManuallyExported, openUnreportedExpense} from '@libs/actions/Report';
import {getThreadReportIDsForTransactions, getTotalAmountForIOUReportPreviewButton} from '@libs/MoneyRequestReportUtils';
import Navigation from '@libs/Navigation/Navigation';
import {buildOptimisticNextStepForPreventSelfApprovalsEnabled} from '@libs/NextStepUtils';
import {isSecondaryActionAPaymentOption, selectPaymentType} from '@libs/PaymentUtils';
import type {KYCFlowEvent, TriggerKYCFlow} from '@libs/PaymentUtils';
import {getValidConnectedIntegration} from '@libs/PolicyUtils';
-import {getIOUActionForReportID, getOriginalMessage, getReportAction, isMoneyRequestAction} from '@libs/ReportActionsUtils';
+import {getOriginalMessage, getReportAction, isMoneyRequestAction} from '@libs/ReportActionsUtils';
import {getAllExpensesToHoldIfApplicable, getReportPrimaryAction} from '@libs/ReportPrimaryActionUtils';
import {getSecondaryReportActions} from '@libs/ReportSecondaryActionUtils';
import {
- buildTransactionThread,
changeMoneyRequestHoldStatus,
- generateReportID,
getArchiveReason,
getBankAccountRoute,
getIntegrationIcon,
@@ -605,14 +603,9 @@ function MoneyReportHeader({
success
text={translate('iou.reviewDuplicates')}
onPress={() => {
- let threadID = transactionThreadReportID ?? getFirstDuplicateThreadID(transactions, reportActions);
+ const threadID = transactionThreadReportID ?? getFirstDuplicateThreadID(transactions, reportActions);
if (!threadID) {
- threadID = generateReportID();
- const duplicateTransaction = transactions.find((reportTransaction) => isDuplicate(reportTransaction.transactionID));
- const transactionID = duplicateTransaction?.transactionID;
- const iouAction = getIOUActionForReportID(moneyRequestReport?.reportID, transactionID);
- const optimisticTransactionThread = buildTransactionThread(iouAction, moneyRequestReport, undefined, threadID);
- openReport(threadID, undefined, session?.email ? [session?.email] : [], optimisticTransactionThread, iouAction?.reportActionID);
+ return;
}
Navigation.navigate(ROUTES.TRANSACTION_DUPLICATE_REVIEW_PAGE.getRoute(threadID));
}}
diff --git a/src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx b/src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx
index 7b338fb1d6ca7..8652ffdc7e017 100644
--- a/src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx
+++ b/src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx
@@ -28,16 +28,14 @@ import {canUseTouchScreen} from '@libs/DeviceCapabilities';
import {getThreadReportIDsForTransactions} from '@libs/MoneyRequestReportUtils';
import {navigationRef} from '@libs/Navigation/Navigation';
import {getIOUActionForTransactionID} from '@libs/ReportActionsUtils';
-import {generateReportID, getMoneyRequestSpendBreakdown, isIOUReport} from '@libs/ReportUtils';
+import {getMoneyRequestSpendBreakdown, isIOUReport} from '@libs/ReportUtils';
import {compareValues} from '@libs/SearchUIUtils';
import {getTransactionPendingAction, isTransactionPendingDelete} from '@libs/TransactionUtils';
import shouldShowTransactionYear from '@libs/TransactionUtils/shouldShowTransactionYear';
import Navigation from '@navigation/Navigation';
-import type {ReportsSplitNavigatorParamList} from '@navigation/types';
import variables from '@styles/variables';
import CONST from '@src/CONST';
import NAVIGATORS from '@src/NAVIGATORS';
-import type {Route} from '@src/ROUTES';
import ROUTES from '@src/ROUTES';
import type SCREENS from '@src/SCREENS';
import type * as OnyxTypes from '@src/types/onyx';
@@ -98,8 +96,6 @@ type SortedTransactions = {
sortOrder: SortOrder;
};
-type ReportScreenNavigationProps = ReportsSplitNavigatorParamList[typeof SCREENS.REPORT];
-
const isSortableColumnName = (key: unknown): key is SortableColumnName => !!sortableColumnNames.find((val) => val === key);
const getTransactionKey = (transaction: OnyxTypes.Transaction, key: SortableColumnName) => {
@@ -194,27 +190,19 @@ function MoneyRequestReportTransactionList({
const navigateToTransaction = useCallback(
(activeTransaction: OnyxTypes.Transaction) => {
const iouAction = getIOUActionForTransactionID(reportActions, activeTransaction.transactionID);
- const reportIDToNavigate = iouAction?.childReportID ?? generateReportID();
+ const reportIDToNavigate = iouAction?.childReportID;
+ if (!reportIDToNavigate) {
+ return;
+ }
- const backTo = Navigation.getActiveRoute() as Route;
+ const backTo = Navigation.getActiveRoute();
// Single transaction report will open in RHP, and we need to find every other report ID for the rest of transactions
// to display prev/next arrows in RHP for navigating between transactions
const sortedSiblingTransactionReportIDs = getThreadReportIDsForTransactions(reportActions, sortedTransactions);
setActiveTransactionThreadIDs(sortedSiblingTransactionReportIDs);
- const routeParams = {
- reportID: reportIDToNavigate,
- backTo,
- } as ReportScreenNavigationProps;
-
- if (!iouAction?.childReportID) {
- routeParams.moneyRequestReportActionID = iouAction?.reportActionID;
- routeParams.transactionID = activeTransaction.transactionID;
- routeParams.iouReportID = activeTransaction.reportID;
- }
-
- Navigation.navigate(ROUTES.SEARCH_REPORT.getRoute(routeParams));
+ Navigation.navigate(ROUTES.SEARCH_REPORT.getRoute({reportID: reportIDToNavigate, backTo}));
},
[reportActions, sortedTransactions],
);
diff --git a/src/components/ReportActionItem/MoneyRequestAction.tsx b/src/components/ReportActionItem/MoneyRequestAction.tsx
index 168c640b14b92..d62e6ba3bc095 100644
--- a/src/components/ReportActionItem/MoneyRequestAction.tsx
+++ b/src/components/ReportActionItem/MoneyRequestAction.tsx
@@ -131,7 +131,7 @@ function MoneyRequestAction({
const transactionID = isMoneyRequestAction(action) ? getOriginalMessage(action)?.IOUTransactionID : CONST.DEFAULT_NUMBER_ID;
if (!action?.childReportID && transactionID && action.reportActionID) {
const optimisticReportID = generateReportID();
- Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(optimisticReportID, undefined, undefined, action.reportActionID, transactionID, Navigation.getActiveRoute(), requestReportID));
+ Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(optimisticReportID, undefined, undefined, action.reportActionID, transactionID, Navigation.getActiveRoute()));
return;
}
diff --git a/src/components/Search/index.tsx b/src/components/Search/index.tsx
index 104aabc7efaba..376abbd3932ce 100644
--- a/src/components/Search/index.tsx
+++ b/src/components/Search/index.tsx
@@ -22,7 +22,7 @@ import {canUseTouchScreen} from '@libs/DeviceCapabilities';
import Log from '@libs/Log';
import isSearchTopmostFullScreenRoute from '@libs/Navigation/helpers/isSearchTopmostFullScreenRoute';
import type {PlatformStackNavigationProp} from '@libs/Navigation/PlatformStackNavigation/types';
-import {getIOUActionForTransactionID, getOriginalMessage, getReportAction, isMoneyRequestAction} from '@libs/ReportActionsUtils';
+import {getIOUActionForTransactionID} from '@libs/ReportActionsUtils';
import {canEditFieldOfMoneyRequest, generateReportID} from '@libs/ReportUtils';
import {buildSearchQueryString} from '@libs/SearchQueryUtils';
import {
@@ -400,28 +400,8 @@ function Search({queryJSON, currentSearchResults, lastNonEmptySearchResults, onS
const isFromSelfDM = item.reportID === CONST.REPORT.UNREPORTED_REPORT_ID;
const isTransactionItem = isTransactionListItemType(item);
- const backTo = Navigation.getActiveRoute();
-
- // If we're trying to open a legacy transaction without a transaction thread, let's create the thread and navigate the user
- if (isTransactionItem && item.transactionThreadReportID === CONST.REPORT.UNREPORTED_REPORT_ID) {
- const transactionThreadReportID = generateReportID();
- const reportAction = getReportAction(item.reportID, item.moneyRequestReportActionID);
- const iouReportID = isMoneyRequestAction(reportAction) ? getOriginalMessage(reportAction)?.IOUReportID : undefined;
-
- updateSearchResultsWithTransactionThreadReportID(hash, item.transactionID, transactionThreadReportID);
- Navigation.navigate(
- ROUTES.SEARCH_REPORT.getRoute({
- reportID: transactionThreadReportID,
- backTo,
- moneyRequestReportActionID: item.moneyRequestReportActionID,
- transactionID: item.transactionID,
- iouReportID,
- }),
- );
- return;
- }
- const reportID =
+ let reportID =
isTransactionItem && (!item.isFromOneTransactionReport || isFromSelfDM) && item.transactionThreadReportID !== CONST.REPORT.UNREPORTED_REPORT_ID
? item.transactionThreadReportID
: item.reportID;
@@ -430,6 +410,7 @@ function Search({queryJSON, currentSearchResults, lastNonEmptySearchResults, onS
return;
}
+ const backTo = Navigation.getActiveRoute();
const shouldHandleTransactionAsReport = isReportListItemType(item) || (isTransactionItem && isOpenedAsReport);
if (isBetaEnabled(CONST.BETAS.TABLE_REPORT_VIEW) && shouldHandleTransactionAsReport) {
@@ -437,6 +418,21 @@ function Search({queryJSON, currentSearchResults, lastNonEmptySearchResults, onS
return;
}
+ // If we're trying to open a legacy transaction without a transaction thread, let's create the thread and navigate the user
+ if (isTransactionItem && reportID === CONST.REPORT.UNREPORTED_REPORT_ID) {
+ reportID = generateReportID();
+ updateSearchResultsWithTransactionThreadReportID(hash, item.transactionID, reportID);
+ Navigation.navigate(
+ ROUTES.SEARCH_REPORT.getRoute({
+ reportID,
+ backTo,
+ moneyRequestReportActionID: item.moneyRequestReportActionID,
+ transactionID: item.transactionID,
+ }),
+ );
+ return;
+ }
+
if (isReportActionListItemType(item)) {
const reportActionID = item.reportActionID;
Navigation.navigate(ROUTES.SEARCH_REPORT.getRoute({reportID, reportActionID, backTo}));
diff --git a/src/libs/API/parameters/CreatePerDiemRequestParams.ts b/src/libs/API/parameters/CreatePerDiemRequestParams.ts
index 24f13f203adb3..480acd9ca23db 100644
--- a/src/libs/API/parameters/CreatePerDiemRequestParams.ts
+++ b/src/libs/API/parameters/CreatePerDiemRequestParams.ts
@@ -17,7 +17,7 @@ type CreatePerDiemRequestParams = {
createdChatReportActionID?: string;
createdIOUReportActionID?: string;
reportPreviewReportActionID: string;
- transactionThreadReportID?: string;
+ transactionThreadReportID: string;
createdReportActionIDForThread: string | undefined;
billable?: boolean;
attendees?: string;
diff --git a/src/libs/API/parameters/HoldMoneyRequestParams.ts b/src/libs/API/parameters/HoldMoneyRequestParams.ts
index b22e421898d10..357194d7ae56a 100644
--- a/src/libs/API/parameters/HoldMoneyRequestParams.ts
+++ b/src/libs/API/parameters/HoldMoneyRequestParams.ts
@@ -3,8 +3,6 @@ type HoldMoneyRequestParams = {
comment: string;
reportActionID: string;
commentReportActionID: string;
- transactionThreadReportID?: string;
- createdReportActionIDForThread?: string;
};
export default HoldMoneyRequestParams;
diff --git a/src/libs/API/parameters/MergeDuplicatesParams.ts b/src/libs/API/parameters/MergeDuplicatesParams.ts
index e1cdfd0903c61..b5ef56a52502a 100644
--- a/src/libs/API/parameters/MergeDuplicatesParams.ts
+++ b/src/libs/API/parameters/MergeDuplicatesParams.ts
@@ -13,8 +13,6 @@ type MergeDuplicatesParams = {
receiptID: number;
reportID: string | undefined;
reportActionID?: string | undefined;
- transactionThreadReportID?: string;
- createdReportActionIDForThread?: string;
};
export default MergeDuplicatesParams;
diff --git a/src/libs/API/parameters/RequestMoneyParams.ts b/src/libs/API/parameters/RequestMoneyParams.ts
index f2b6d89aea973..42e0e9aed6dcd 100644
--- a/src/libs/API/parameters/RequestMoneyParams.ts
+++ b/src/libs/API/parameters/RequestMoneyParams.ts
@@ -25,8 +25,8 @@ type RequestMoneyParams = {
taxAmount: number;
billable?: boolean;
receiptGpsPoints?: string;
- transactionThreadReportID?: string;
- createdReportActionIDForThread?: string | undefined;
+ transactionThreadReportID: string;
+ createdReportActionIDForThread: string | undefined;
reimbursible?: boolean;
description?: string;
attendees?: string;
diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts
index c0582583a2e80..1a830a3aa79c7 100644
--- a/src/libs/Navigation/types.ts
+++ b/src/libs/Navigation/types.ts
@@ -1657,7 +1657,6 @@ type ReportsSplitNavigatorParamList = {
backTo?: Routes;
moneyRequestReportActionID?: string;
transactionID?: string;
- iouReportID?: string;
};
};
diff --git a/src/libs/ReportActionsUtils.ts b/src/libs/ReportActionsUtils.ts
index f2a85f3f02693..f491057e5bdf8 100644
--- a/src/libs/ReportActionsUtils.ts
+++ b/src/libs/ReportActionsUtils.ts
@@ -1249,6 +1249,7 @@ function getOneTransactionThreadReportID(
if (
actionType &&
iouRequestTypesSet.has(actionType) &&
+ action.childReportID &&
// Include deleted IOU reportActions if:
// - they have an associated IOU transaction ID or
// - they have visible childActions (like comments) that we'd want to display
@@ -1276,8 +1277,8 @@ function getOneTransactionThreadReportID(
return;
}
- // Since we don't always create transaction thread optimistically, we return CONST.FAKE_REPORT_ID
- return singleAction?.childReportID ?? CONST.FAKE_REPORT_ID;
+ // Ensure we have a childReportID associated with the IOU report action
+ return singleAction?.childReportID;
}
/**
diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts
index 3eb83dc2ab3f5..526f58f5b387b 100644
--- a/src/libs/ReportUtils.ts
+++ b/src/libs/ReportUtils.ts
@@ -619,7 +619,7 @@ type OptimisticModifiedExpenseReportAction = Pick<
| 'delegateAccountID'
> & {reportID?: string};
-type BaseOptimisticMoneyRequestEntities = {
+type OptimisticMoneyRequestEntities = {
iouReport: Report;
type: ValueOf;
amount: number;
@@ -637,10 +637,6 @@ type BaseOptimisticMoneyRequestEntities = {
linkedTrackedExpenseReportAction?: ReportAction;
};
-type OptimisticMoneyRequestEntities = BaseOptimisticMoneyRequestEntities & {shouldGenerateOptimisticTransactionThread?: boolean};
-type OptimisticMoneyRequestEntitiesWithTransactionThreadFlag = BaseOptimisticMoneyRequestEntities & {shouldGenerateOptimisticTransactionThread: boolean};
-type OptimisticMoneyRequestEntitiesWithoutTransactionThreadFlag = BaseOptimisticMoneyRequestEntities;
-
type OptimisticTaskReport = SetRequired<
Pick<
Report,
@@ -4059,8 +4055,8 @@ const changeMoneyRequestHoldStatus = (reportAction: OnyxEntry): vo
const transactionID = getOriginalMessage(reportAction)?.IOUTransactionID;
- if (!transactionID) {
- Log.warn('Missing transactionID during the change of the money request hold status');
+ if (!transactionID || !reportAction.childReportID) {
+ Log.warn('Missing transactionID and reportAction.childReportID during the change of the money request hold status');
return;
}
@@ -4068,7 +4064,7 @@ const changeMoneyRequestHoldStatus = (reportAction: OnyxEntry): vo
const isOnHold = isOnHoldTransactionUtils(transaction);
const policy = allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${moneyRequestReport.policyID}`] ?? null;
- if (isOnHold && reportAction.childReportID) {
+ if (isOnHold) {
unholdRequest(transactionID, reportAction.childReportID);
} else {
const activeRoute = encodeURIComponent(Navigation.getActiveRoute());
@@ -7443,7 +7439,6 @@ function buildTransactionThread(
reportAction: OnyxEntry,
moneyRequestReport: OnyxEntry,
existingTransactionThreadReportID?: string,
- optimisticTransactionThreadReportID?: string,
): OptimisticChatReport {
const participantAccountIDs = [...new Set([currentUserAccountID, Number(reportAction?.actorAccountID)])].filter(Boolean) as number[];
const existingTransactionThreadReport = getReportOrDraftReport(existingTransactionThreadReportID);
@@ -7466,7 +7461,6 @@ function buildTransactionThread(
notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN,
parentReportActionID: reportAction?.reportActionID,
parentReportID: moneyRequestReport?.reportID,
- optimisticReportID: optimisticTransactionThreadReportID,
});
}
@@ -7479,12 +7473,6 @@ function buildTransactionThread(
* 4. Transaction Thread linked to the IOU action via `parentReportActionID`
* 5. CREATED action for the Transaction Thread
*/
-function buildOptimisticMoneyRequestEntities(
- optimisticMoneyRequestEntities: OptimisticMoneyRequestEntitiesWithoutTransactionThreadFlag,
-): [OptimisticCreatedReportAction, OptimisticCreatedReportAction, OptimisticIOUReportAction, OptimisticChatReport, OptimisticCreatedReportAction | null];
-function buildOptimisticMoneyRequestEntities(
- optimisticMoneyRequestEntities: OptimisticMoneyRequestEntitiesWithTransactionThreadFlag,
-): [OptimisticCreatedReportAction, OptimisticCreatedReportAction, OptimisticIOUReportAction, OptimisticChatReport | undefined, OptimisticCreatedReportAction | null];
function buildOptimisticMoneyRequestEntities({
iouReport,
type,
@@ -7498,17 +7486,10 @@ function buildOptimisticMoneyRequestEntities({
isSettlingUp = false,
isSendMoneyFlow = false,
isOwnPolicyExpenseChat = false,
- shouldGenerateOptimisticTransactionThread = true,
isPersonalTrackingExpense,
existingTransactionThreadReportID,
linkedTrackedExpenseReportAction,
-}: OptimisticMoneyRequestEntities): [
- OptimisticCreatedReportAction,
- OptimisticCreatedReportAction,
- OptimisticIOUReportAction,
- OptimisticChatReport | undefined,
- OptimisticCreatedReportAction | null,
-] {
+}: OptimisticMoneyRequestEntities): [OptimisticCreatedReportAction, OptimisticCreatedReportAction, OptimisticIOUReportAction, OptimisticChatReport, OptimisticCreatedReportAction | null] {
const createdActionForChat = buildOptimisticCreatedReportAction(payeeEmail);
// The `CREATED` action must be optimistically generated before the IOU action so that it won't appear after the IOU action in the chat.
@@ -7533,11 +7514,11 @@ function buildOptimisticMoneyRequestEntities({
});
// Create optimistic transactionThread and the `CREATED` action for it, if existingTransactionThreadReportID is undefined
- const transactionThread = shouldGenerateOptimisticTransactionThread ? buildTransactionThread(iouAction, iouReport, existingTransactionThreadReportID) : undefined;
- const createdActionForTransactionThread = !!existingTransactionThreadReportID || !shouldGenerateOptimisticTransactionThread ? null : buildOptimisticCreatedReportAction(payeeEmail);
+ const transactionThread = buildTransactionThread(iouAction, iouReport, existingTransactionThreadReportID);
+ const createdActionForTransactionThread = existingTransactionThreadReportID ? null : buildOptimisticCreatedReportAction(payeeEmail);
// The IOU action and the transactionThread are co-dependent as parent-child, so we need to link them together
- iouAction.childReportID = existingTransactionThreadReportID ?? transactionThread?.reportID;
+ iouAction.childReportID = existingTransactionThreadReportID ?? transactionThread.reportID;
return [createdActionForChat, createdActionForIOUReport, iouAction, transactionThread, createdActionForTransactionThread];
}
@@ -9353,12 +9334,12 @@ function getAllAncestorReportActionIDs(report: Report | null | undefined, includ
/**
* Get optimistic data of parent report action
- * @param reportOrID The reportID of the report that is updated or the optimistic report on its own
+ * @param reportID The reportID of the report that is updated
* @param lastVisibleActionCreated Last visible action created of the child report
* @param type The type of action in the child report
*/
-function getOptimisticDataForParentReportAction(reportOrID: Report | string | undefined, lastVisibleActionCreated: string, type: string): Array {
- const report = typeof reportOrID === 'string' ? getReportOrDraftReport(reportOrID) : reportOrID;
+function getOptimisticDataForParentReportAction(reportID: string | undefined, lastVisibleActionCreated: string, type: string): Array {
+ const report = getReportOrDraftReport(reportID);
if (!report || isEmptyObject(report)) {
return [];
diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts
index 4a9dd36b14216..8902787bb2029 100644
--- a/src/libs/actions/IOU.ts
+++ b/src/libs/actions/IOU.ts
@@ -16,7 +16,6 @@ import type {
CreateWorkspaceParams,
DeleteMoneyRequestParams,
DetachReceiptParams,
- HoldMoneyRequestParams,
MergeDuplicatesParams,
PayInvoiceParams,
PayMoneyRequestParams,
@@ -127,7 +126,6 @@ import {
buildTransactionThread,
canBeAutoReimbursed,
canUserPerformWriteAction as canUserPerformWriteActionReportUtils,
- generateReportID,
getAllHeldTransactions as getAllHeldTransactionsReportUtils,
getAllPolicyReports,
getApprovalChain,
@@ -263,7 +261,7 @@ type MoneyRequestInformation = {
createdChatReportActionID?: string;
createdIOUReportActionID?: string;
reportPreviewAction: OnyxTypes.ReportAction;
- transactionThreadReportID?: string;
+ transactionThreadReportID: string;
createdReportActionIDForThread: string | undefined;
onyxData: OnyxData;
billable?: boolean;
@@ -440,7 +438,6 @@ type MoneyRequestInformationParams = {
existingTransactionID?: string;
existingTransaction?: OnyxEntry;
retryParams?: StartSplitBilActionParams | CreateTrackExpenseParams | RequestMoneyInformation | ReplaceReceipt;
- shouldGenerateOptimisticTransactionThread?: boolean;
isSplitExpense?: boolean;
testDriveCommentReportActionID?: string;
};
@@ -458,8 +455,8 @@ type MoneyRequestOptimisticParams = {
};
transactionParams: {
transaction: OnyxTypes.Transaction;
- transactionThreadReport?: OptimisticChatReport | null;
- transactionThreadCreatedReportAction?: OptimisticCreatedReportAction | null;
+ transactionThreadReport: OptimisticChatReport | null;
+ transactionThreadCreatedReportAction: OptimisticCreatedReportAction | null;
};
policyRecentlyUsed: {
categories?: string[];
@@ -3238,7 +3235,6 @@ function getMoneyRequestInformation(moneyRequestInformation: MoneyRequestInforma
existingTransactionID,
moneyRequestReportID = '',
retryParams,
- shouldGenerateOptimisticTransactionThread = true,
isSplitExpense,
testDriveCommentReportActionID,
} = moneyRequestInformation;
@@ -3381,7 +3377,6 @@ function getMoneyRequestInformation(moneyRequestInformation: MoneyRequestInforma
paymentType: isSelectedManagerMcTest(participant.login) || transactionParams.receipt?.isTestDriveReceipt ? CONST.IOU.PAYMENT_TYPE.ELSEWHERE : undefined,
existingTransactionThreadReportID: linkedTrackedExpenseReportAction?.childReportID,
linkedTrackedExpenseReportAction,
- shouldGenerateOptimisticTransactionThread,
});
let reportPreviewAction = shouldCreateNewMoneyRequestReport ? null : getReportPreviewAction(chatReport.reportID, iouReport.reportID);
@@ -4851,32 +4846,30 @@ const getConvertTrackedExpenseInformation = (
// Build modified expense report action with the transaction changes
const modifiedExpenseReportAction = buildOptimisticMovedTransactionAction(transactionThreadReportID, moneyRequestReportID ?? CONST.REPORT.UNREPORTED_REPORT_ID);
- if (transactionThreadReportID) {
- optimisticData?.push({
- onyxMethod: Onyx.METHOD.MERGE,
- key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThreadReportID}`,
- value: {
- [modifiedExpenseReportAction.reportActionID]: modifiedExpenseReportAction,
- },
- });
- successData?.push({
- onyxMethod: Onyx.METHOD.MERGE,
- key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThreadReportID}`,
- value: {
- [modifiedExpenseReportAction.reportActionID]: {pendingAction: null},
- },
- });
- failureData?.push({
- onyxMethod: Onyx.METHOD.MERGE,
- key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThreadReportID}`,
- value: {
- [modifiedExpenseReportAction.reportActionID]: {
- ...modifiedExpenseReportAction,
- errors: getMicroSecondOnyxErrorWithTranslationKey('iou.error.genericEditFailureMessage'),
- },
+ optimisticData?.push({
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThreadReportID}`,
+ value: {
+ [modifiedExpenseReportAction.reportActionID]: modifiedExpenseReportAction,
+ },
+ });
+ successData?.push({
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThreadReportID}`,
+ value: {
+ [modifiedExpenseReportAction.reportActionID]: {pendingAction: null},
+ },
+ });
+ failureData?.push({
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThreadReportID}`,
+ value: {
+ [modifiedExpenseReportAction.reportActionID]: {
+ ...modifiedExpenseReportAction,
+ errors: getMicroSecondOnyxErrorWithTranslationKey('iou.error.genericEditFailureMessage'),
},
- });
- }
+ },
+ });
return {optimisticData, successData, failureData, modifiedExpenseReportActionID: modifiedExpenseReportAction.reportActionID};
};
@@ -4926,7 +4919,7 @@ type ConvertTrackedExpenseToRequestParams = {
merchant: string;
created: string;
attendees?: Attendee[];
- transactionThreadReportID?: string;
+ transactionThreadReportID: string;
};
chatParams: {
reportID: string;
@@ -5247,19 +5240,30 @@ function requestMoney(requestMoneyInformation: RequestMoneyInformation) {
},
};
- const {payerAccountID, payerEmail, iouReport, chatReport, transaction, iouAction, createdChatReportActionID, createdIOUReportActionID, reportPreviewAction, onyxData} =
- getMoneyRequestInformation({
- parentChatReport: isMovingTransactionFromTrackExpense ? undefined : currentChatReport,
- participantParams,
- policyParams,
- transactionParams,
- moneyRequestReportID,
- existingTransactionID,
- existingTransaction: isDistanceRequestTransactionUtils(existingTransaction) ? existingTransaction : undefined,
- retryParams,
- shouldGenerateOptimisticTransactionThread: false,
- testDriveCommentReportActionID,
- });
+ const {
+ payerAccountID,
+ payerEmail,
+ iouReport,
+ chatReport,
+ transaction,
+ iouAction,
+ createdChatReportActionID,
+ createdIOUReportActionID,
+ reportPreviewAction,
+ transactionThreadReportID,
+ createdReportActionIDForThread,
+ onyxData,
+ } = getMoneyRequestInformation({
+ parentChatReport: isMovingTransactionFromTrackExpense ? undefined : currentChatReport,
+ participantParams,
+ policyParams,
+ transactionParams,
+ moneyRequestReportID,
+ existingTransactionID,
+ existingTransaction: isDistanceRequestTransactionUtils(existingTransaction) ? existingTransaction : undefined,
+ retryParams,
+ testDriveCommentReportActionID,
+ });
const activeReportID = isMoneyRequestReport ? report?.reportID : chatReport.reportID;
if (shouldPlaySound) {
@@ -5302,6 +5306,7 @@ function requestMoney(requestMoneyInformation: RequestMoneyInformation) {
actionableWhisperReportActionID,
linkedTrackedExpenseReportAction,
linkedTrackedExpenseReportID,
+ transactionThreadReportID,
},
chatParams: {
reportID: chatReport.reportID,
@@ -5352,6 +5357,8 @@ function requestMoney(requestMoneyInformation: RequestMoneyInformation) {
billable,
// This needs to be a string of JSON because of limitations with the fetch() API and nested objects
receiptGpsPoints: gpsPoints ? JSON.stringify(gpsPoints) : undefined,
+ transactionThreadReportID,
+ createdReportActionIDForThread,
reimbursible,
description: parsedComment,
attendees: attendees ? JSON.stringify(attendees) : undefined,
@@ -10610,29 +10617,17 @@ function adjustRemainingSplitShares(transaction: NonNullable notifyNewAction(currentReportID, userAccountID));
@@ -11018,9 +10960,7 @@ function getIOUActionForTransactions(transactionIDList: Array value?.email, canBeMissing: false});
-
- const {reportActions: reportActionsWithDeletedExpenses} = usePaginatedReportActions(reportIDFromRoute);
- const reportActions = reportActionsWithDeletedExpenses.filter((value) => !isDeletedParentAction(value));
- const transactionThreadReportID = getOneTransactionThreadReportID(reportIDFromRoute, reportActions ?? [], isOffline);
- const [transactionThreadReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReportID}`, {canBeMissing: true});
const {isEditingDisabled, isCurrentReportLoadedFromOnyx} = useIsReportReadyToDisplay(report, reportIDFromRoute);
@@ -63,29 +52,9 @@ function SearchMoneyRequestReportPage({route}: SearchMoneyRequestPageProps) {
const reportID = report?.reportID;
- const fetchReport = useCallback(() => {
- if (reportMetadata.isOptimisticReport) {
- return;
- }
-
- // If there is one transaction thread that has not yet been created, we should create it.
- if (transactionThreadReportID === CONST.FAKE_REPORT_ID && !transactionThreadReport && currentUserEmail) {
- const optimisticTransactionThreadReportID = generateReportID();
- const transactions = getReportTransactions(reportID).filter((transaction) => transaction.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE);
- const oneTransactionID = transactions.at(0)?.transactionID;
- const iouAction = getIOUActionForReportID(reportID, oneTransactionID);
- const optimisticTransactionThread = buildTransactionThread(iouAction, report, undefined, optimisticTransactionThreadReportID);
- openReport(optimisticTransactionThreadReportID, undefined, [currentUserEmail], optimisticTransactionThread, iouAction?.reportActionID, false, [], undefined, true);
- }
-
- openReport(reportID, undefined, [], undefined, undefined, false, [], undefined, true);
- // We don't want to call openReport when report is changed
- // eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps
- }, [reportMetadata.isOptimisticReport, currentUserEmail, reportID, transactionThreadReport, transactionThreadReportID]);
-
useEffect(() => {
- fetchReport();
- }, [fetchReport]);
+ openReport(reportIDFromRoute, '', [], undefined, undefined, false, [], undefined, true);
+ }, [reportIDFromRoute]);
// eslint-disable-next-line rulesdir/no-negated-variables
const shouldShowNotFoundPage = useMemo(
diff --git a/src/pages/TransactionDuplicate/Confirmation.tsx b/src/pages/TransactionDuplicate/Confirmation.tsx
index fd1b35ffc9a96..6078b38d5e1ef 100644
--- a/src/pages/TransactionDuplicate/Confirmation.tsx
+++ b/src/pages/TransactionDuplicate/Confirmation.tsx
@@ -26,7 +26,6 @@ import CONST from '@src/CONST';
import * as IOU from '@src/libs/actions/IOU';
import * as ReportActionsUtils from '@src/libs/ReportActionsUtils';
import * as ReportUtils from '@src/libs/ReportUtils';
-import {generateReportID} from '@src/libs/ReportUtils';
import * as TransactionUtils from '@src/libs/TransactionUtils';
import {getTransactionID} from '@src/libs/TransactionUtils';
import ONYXKEYS from '@src/ONYXKEYS';
@@ -58,18 +57,15 @@ function Confirmation() {
const isReportOwner = iouReport?.ownerAccountID === currentUserPersonalDetails?.accountID;
const mergeDuplicates = useCallback(() => {
- const transactionThreadReportID = reportAction?.childReportID ?? generateReportID();
-
if (!reportAction?.childReportID) {
- transactionsMergeParams.transactionThreadReportID = transactionThreadReportID;
+ return;
}
-
IOU.mergeDuplicates(transactionsMergeParams);
if (isBetaEnabled(CONST.BETAS.TABLE_REPORT_VIEW)) {
Navigation.dismissModal();
return;
}
- Navigation.goBack(ROUTES.REPORT_WITH_ID.getRoute(transactionThreadReportID), {compareParams: false});
+ Navigation.goBack(ROUTES.REPORT_WITH_ID.getRoute(reportAction.childReportID), {compareParams: false});
}, [reportAction?.childReportID, transactionsMergeParams, isBetaEnabled]);
const resolveDuplicates = useCallback(() => {
diff --git a/src/pages/home/ReportScreen.tsx b/src/pages/home/ReportScreen.tsx
index e28add3bb9b5a..09c0f2a4df35d 100644
--- a/src/pages/home/ReportScreen.tsx
+++ b/src/pages/home/ReportScreen.tsx
@@ -40,9 +40,7 @@ import {getDisplayNameOrDefault} from '@libs/PersonalDetailsUtils';
import {
getCombinedReportActions,
getFilteredReportActionsForReportView,
- getIOUActionForReportID,
getOneTransactionThreadReportID,
- getReportAction,
isCreatedAction,
isDeletedParentAction,
isMoneyRequestAction,
@@ -50,15 +48,11 @@ import {
shouldReportActionBeVisible,
} from '@libs/ReportActionsUtils';
import {
- buildTransactionThread,
canEditReportAction,
canUserPerformWriteAction,
findLastAccessedReport,
- generateReportID,
getParticipantsAccountIDsForDisplay,
getReportOfflinePendingActionAndErrors,
- getReportOrDraftReport,
- getReportTransactions,
isChatThread,
isConciergeChatReport,
isGroupChat,
@@ -305,7 +299,6 @@ function ReportScreen({route, navigation}: ReportScreenProps) {
});
const reportTransactionIDs = reportTransactions?.map((transaction) => transaction.transactionID);
const transactionThreadReportID = getOneTransactionThreadReportID(reportID, reportActions ?? [], isOffline, reportTransactionIDs);
- const [transactionThreadReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReportID}`, {canBeMissing: true});
const [transactionThreadReportActions = {}] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThreadReportID}`, {canBeMissing: true});
const combinedReportActions = getCombinedReportActions(reportActions, transactionThreadReportID ?? null, Object.values(transactionThreadReportActions));
const lastReportAction = [...combinedReportActions, parentReportAction].find((action) => canEditReportAction(action) && !isMoneyRequestAction(action));
@@ -472,7 +465,7 @@ function ReportScreen({route, navigation}: ReportScreenProps) {
);
const fetchReport = useCallback(() => {
- if (reportMetadata.isOptimisticReport && report?.type === CONST.REPORT.TYPE.CHAT && transactionThreadReportID !== CONST.FAKE_REPORT_ID) {
+ if (reportMetadata.isOptimisticReport && report?.type === CONST.REPORT.TYPE.CHAT) {
return;
}
@@ -480,41 +473,26 @@ function ReportScreen({route, navigation}: ReportScreenProps) {
return;
}
- const {moneyRequestReportActionID, transactionID, iouReportID} = route.params;
+ const moneyRequestReportActionID: string | undefined = route.params?.moneyRequestReportActionID;
+ const transactionID: string | undefined = route.params?.transactionID;
// When we get here with a moneyRequestReportActionID and a transactionID from the route it means we don't have the transaction thread created yet
// so we have to call OpenReport in a way that the transaction thread will be created and attached to the parentReportAction
- if (transactionID && currentUserEmail && !report) {
- const iouReport = getReportOrDraftReport(iouReportID);
- const iouAction = getReportAction(iouReportID, moneyRequestReportActionID);
- const optimisticTransactionThread = buildTransactionThread(iouAction, iouReport, undefined, reportIDFromRoute);
- openReport(reportIDFromRoute, undefined, [currentUserEmail], optimisticTransactionThread, moneyRequestReportActionID, false, [], undefined, undefined, transactionID);
+ if (transactionID && currentUserEmail) {
+ openReport(reportIDFromRoute, '', [currentUserEmail], undefined, moneyRequestReportActionID, false, [], undefined, undefined, transactionID);
return;
}
-
- // If there is one transaction thread that has not yet been created, we should create it.
- if (transactionThreadReportID === CONST.FAKE_REPORT_ID && !transactionThreadReport && parentReportAction?.childMoneyRequestCount === 1 && currentUserEmail) {
- const optimisticTransactionThreadReportID = generateReportID();
- const transactions = getReportTransactions(reportID).filter((transaction) => transaction.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE);
- const oneTransactionID = transactions.at(0)?.transactionID;
- const iouAction = getIOUActionForReportID(reportID, oneTransactionID);
- const optimisticTransactionThread = buildTransactionThread(iouAction, report, undefined, optimisticTransactionThreadReportID);
- openReport(optimisticTransactionThreadReportID, undefined, [currentUserEmail], optimisticTransactionThread, iouAction?.reportActionID);
- }
-
openReport(reportIDFromRoute, reportActionIDFromRoute);
}, [
- parentReportAction?.childMoneyRequestCount,
reportMetadata.isOptimisticReport,
+ report?.type,
+ report?.errorFields?.notFound,
isOffline,
- route.params,
+ route.params?.moneyRequestReportActionID,
+ route.params?.transactionID,
currentUserEmail,
reportIDFromRoute,
reportActionIDFromRoute,
- report,
- reportID,
- transactionThreadReport,
- transactionThreadReportID,
]);
useEffect(() => {
@@ -581,7 +559,7 @@ function ReportScreen({route, navigation}: ReportScreenProps) {
// There should be only one openReport execution per page start or navigating
fetchReport();
// eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps
- }, [route, isLinkedMessagePageReady, reportActionIDFromRoute, transactionThreadReportID]);
+ }, [route, isLinkedMessagePageReady, reportActionIDFromRoute]);
const prevReportActions = usePrevious(reportActions);
useEffect(() => {
diff --git a/src/pages/home/report/ContextMenu/BaseReportActionContextMenu.tsx b/src/pages/home/report/ContextMenu/BaseReportActionContextMenu.tsx
index cb69e74ec9057..7febb8a9f72e8 100755
--- a/src/pages/home/report/ContextMenu/BaseReportActionContextMenu.tsx
+++ b/src/pages/home/report/ContextMenu/BaseReportActionContextMenu.tsx
@@ -21,13 +21,12 @@ import useResponsiveLayout from '@hooks/useResponsiveLayout';
import useRestoreInputFocus from '@hooks/useRestoreInputFocus';
import useStyleUtils from '@hooks/useStyleUtils';
import {getExpensifyCardFromReportAction} from '@libs/CardMessageUtils';
-import {getLinkedTransactionID, getOneTransactionThreadReportID, getOriginalMessage, getReportActions, isMoneyRequestAction} from '@libs/ReportActionsUtils';
+import {getLinkedTransactionID, getOneTransactionThreadReportID, getReportAction} from '@libs/ReportActionsUtils';
import {
chatIncludesChronosWithID,
getSourceIDFromReportAction,
isArchivedNonExpenseReport,
isArchivedNonExpenseReportWithID,
- isIOUReport,
isInvoiceReport as ReportUtilsIsInvoiceReport,
isMoneyRequest as ReportUtilsIsMoneyRequest,
isMoneyRequestReport as ReportUtilsIsMoneyRequestReport,
@@ -166,7 +165,7 @@ function BaseReportActionContextMenu({
const [download] = useOnyx(`${ONYXKEYS.COLLECTION.DOWNLOAD}${sourceID}`, {canBeMissing: true});
const [childReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${reportAction?.childReportID}`, {canBeMissing: true});
- const childReportActions = childReport ? getReportActions(childReport) : undefined;
+ const parentReportAction = getReportAction(childReport?.parentReportID, childReport?.parentReportActionID);
const {reportActions: paginatedReportActions} = usePaginatedReportActions(childReport?.reportID);
const transactionThreadReportID = useMemo(
@@ -181,29 +180,24 @@ function BaseReportActionContextMenu({
const requestParentReportAction = useMemo(() => {
if (isMoneyRequestReport || isInvoiceReport) {
- if (!paginatedReportActions) {
+ if (!paginatedReportActions || !transactionThreadReport?.parentReportActionID) {
return undefined;
}
- if (transactionThreadReportID === CONST.FAKE_REPORT_ID) {
- return Object.values(childReportActions ?? {}).find((action) => action.actionName === CONST.REPORT.ACTIONS.TYPE.IOU);
- }
- return paginatedReportActions.find((action) => action.reportActionID === transactionThreadReport?.parentReportActionID);
+ return paginatedReportActions.find((action) => action.reportActionID === transactionThreadReport.parentReportActionID);
}
- return reportAction;
- }, [childReportActions, transactionThreadReportID, reportAction, isMoneyRequestReport, isInvoiceReport, paginatedReportActions, transactionThreadReport?.parentReportActionID]);
+ return parentReportAction;
+ }, [parentReportAction, isMoneyRequestReport, isInvoiceReport, paginatedReportActions, transactionThreadReport?.parentReportActionID]);
- const moneyRequestAction = transactionThreadReportID ? requestParentReportAction : reportAction;
+ const moneyRequestAction = transactionThreadReportID ? requestParentReportAction : parentReportAction;
const [childReportNameValuePairs] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${childReport?.reportID}`, {canBeMissing: true});
const [parentReportNameValuePairs] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${childReport?.parentReportID}`, {canBeMissing: true});
- const [parentReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${childReport?.parentReportID ?? (isMoneyRequestAction(reportAction) && getOriginalMessage(reportAction)?.IOUReportID)}`, {
- canBeMissing: true,
- });
+ const [parentReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${childReport?.parentReportID}`, {canBeMissing: true});
const isMoneyRequest = useMemo(() => ReportUtilsIsMoneyRequest(childReport), [childReport]);
const isTrackExpenseReport = ReportUtilsIsTrackExpenseReport(childReport);
const isSingleTransactionView = isMoneyRequest || isTrackExpenseReport;
- const isMoneyRequestOrReport = isMoneyRequestReport || isSingleTransactionView || isIOUReport(parentReport);
+ const isMoneyRequestOrReport = isMoneyRequestReport || isSingleTransactionView;
const areHoldRequirementsMet =
!isInvoiceReport &&
diff --git a/src/pages/home/report/ContextMenu/ContextMenuActions.tsx b/src/pages/home/report/ContextMenu/ContextMenuActions.tsx
index 96bbecddc053a..0d1aa64237527 100644
--- a/src/pages/home/report/ContextMenu/ContextMenuActions.tsx
+++ b/src/pages/home/report/ContextMenu/ContextMenuActions.tsx
@@ -108,6 +108,7 @@ import {
deleteReportActionDraft,
markCommentAsUnread,
navigateToAndOpenChildReport,
+ openReport,
readNewestAction,
saveReportActionDraft,
toggleEmojiReaction,
@@ -327,8 +328,9 @@ const ContextMenuActions: ContextMenuAction[] = [
onPress: (closePopover, {reportID, reportAction, draftMessage}) => {
if (isMoneyRequestAction(reportAction)) {
hideContextMenu(false);
- const originalReportID = getOriginalReportID(reportID, reportAction);
- navigateToAndOpenChildReport(reportAction?.childReportID, reportAction, originalReportID);
+ const childReportID = reportAction?.childReportID;
+ openReport(childReportID);
+ Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(childReportID));
return;
}
const editAction = () => {
diff --git a/tests/actions/IOUTest.ts b/tests/actions/IOUTest.ts
index 109611e70a119..c9e2e97beac54 100644
--- a/tests/actions/IOUTest.ts
+++ b/tests/actions/IOUTest.ts
@@ -630,6 +630,8 @@ describe('actions/IOU', () => {
let createdAction: OnyxEntry;
let iouAction: OnyxEntry>;
let transactionID: string | undefined;
+ let transactionThread: OnyxEntry;
+ let transactionThreadCreatedAction: OnyxEntry;
mockFetch?.pause?.();
requestMoney({
report: {reportID: ''},
@@ -657,14 +659,16 @@ describe('actions/IOU', () => {
callback: (allReports) => {
Onyx.disconnect(connection);
- // A chat report and an iou report should be created
+ // A chat report, a transaction thread, and an iou report should be created
const chatReports = Object.values(allReports ?? {}).filter((report) => report?.type === CONST.REPORT.TYPE.CHAT);
const iouReports = Object.values(allReports ?? {}).filter((report) => report?.type === CONST.REPORT.TYPE.IOU);
- expect(Object.keys(chatReports).length).toBe(1);
+ expect(Object.keys(chatReports).length).toBe(2);
expect(Object.keys(iouReports).length).toBe(1);
const chatReport = chatReports.at(0);
+ const transactionThreadReport = chatReports.at(1);
const iouReport = iouReports.at(0);
iouReportID = iouReport?.reportID;
+ transactionThread = transactionThreadReport;
expect(iouReport?.participants).toEqual({
[RORY_ACCOUNT_ID]: {notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN},
@@ -727,6 +731,29 @@ describe('actions/IOU', () => {
});
}),
)
+ .then(
+ () =>
+ new Promise((resolve) => {
+ const connection = Onyx.connect({
+ key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThread?.reportID}`,
+ waitForCollectionCallback: false,
+ callback: (reportActionsForTransactionThread) => {
+ Onyx.disconnect(connection);
+
+ // The transaction thread should have a CREATED action
+ expect(Object.values(reportActionsForTransactionThread ?? {}).length).toBe(1);
+ const createdActions = Object.values(reportActionsForTransactionThread ?? {}).filter(
+ (reportAction) => reportAction?.actionName === CONST.REPORT.ACTIONS.TYPE.CREATED,
+ );
+ expect(Object.values(createdActions).length).toBe(1);
+ transactionThreadCreatedAction = createdActions.at(0);
+
+ expect(transactionThreadCreatedAction?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD);
+ resolve();
+ },
+ });
+ }),
+ )
.then(
() =>
new Promise((resolve) => {
@@ -1189,6 +1216,8 @@ describe('actions/IOU', () => {
let createdAction: OnyxEntry;
let iouAction: OnyxEntry>;
let transactionID: string | undefined;
+ let transactionThreadReport: OnyxEntry;
+ let transactionThreadAction: OnyxEntry;
mockFetch?.pause?.();
requestMoney({
report: {reportID: ''},
@@ -1217,13 +1246,14 @@ describe('actions/IOU', () => {
callback: (allReports) => {
Onyx.disconnect(connection);
- // A chat report and an iou report should be created
+ // A chat report, transaction thread and an iou report should be created
const chatReports = Object.values(allReports ?? {}).filter((report) => report?.type === CONST.REPORT.TYPE.CHAT);
const iouReports = Object.values(allReports ?? {}).filter((report) => report?.type === CONST.REPORT.TYPE.IOU);
- expect(Object.values(chatReports).length).toBe(1);
+ expect(Object.values(chatReports).length).toBe(2);
expect(Object.values(iouReports).length).toBe(1);
const chatReport = chatReports.at(0);
chatReportID = chatReport?.reportID;
+ transactionThreadReport = chatReports.at(1);
const iouReport = iouReports.at(0);
iouReportID = iouReport?.reportID;
@@ -1336,6 +1366,24 @@ describe('actions/IOU', () => {
});
}),
)
+ .then(
+ () =>
+ new Promise((resolve) => {
+ const connection = Onyx.connect({
+ key: ONYXKEYS.COLLECTION.REPORT_ACTIONS,
+ waitForCollectionCallback: true,
+ callback: (reportActionsForTransactionThread) => {
+ Onyx.disconnect(connection);
+ expect(Object.values(reportActionsForTransactionThread ?? {}).length).toBe(3);
+ transactionThreadAction = Object.values(
+ reportActionsForTransactionThread?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThreadReport?.reportID}`] ?? {},
+ ).find((reportAction) => reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.CREATED);
+ expect(transactionThreadAction?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD);
+ resolve();
+ },
+ });
+ }),
+ )
.then(
() =>
new Promise((resolve) => {
@@ -1402,6 +1450,22 @@ describe('actions/IOU', () => {
}),
)
+ // Then the reportAction from transaction report should be removed from Onyx
+ .then(
+ () =>
+ new Promise((resolve) => {
+ const connection = Onyx.connect({
+ key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThreadReport?.reportID}`,
+ waitForCollectionCallback: false,
+ callback: (reportActionsForReport) => {
+ Onyx.disconnect(connection);
+ expect(reportActionsForReport).toMatchObject({});
+ resolve();
+ },
+ });
+ }),
+ )
+
// Along with the associated transaction
.then(
() =>
@@ -1425,6 +1489,9 @@ describe('actions/IOU', () => {
if (chatReportID) {
deleteReport(chatReportID);
}
+ if (transactionThreadReport?.reportID) {
+ deleteReport(transactionThreadReport?.reportID);
+ }
resolve();
}),
)