Skip to content

Commit fb562ec

Browse files
authored
Merge pull request #43070 from Expensify/cmartins-createTransactionThreadIfNeeded
Create transaction thread if needed
2 parents d861ec1 + 3c948de commit fb562ec

File tree

3 files changed

+47
-12
lines changed

3 files changed

+47
-12
lines changed

src/components/Search.tsx

+14-8
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import useThemeStyles from '@hooks/useThemeStyles';
88
import * as SearchActions from '@libs/actions/Search';
99
import * as DeviceCapabilities from '@libs/DeviceCapabilities';
1010
import Log from '@libs/Log';
11+
import * as ReportUtils from '@libs/ReportUtils';
1112
import * as SearchUtils from '@libs/SearchUtils';
1213
import type {SearchColumnType, SortOrder} from '@libs/SearchUtils';
1314
import Navigation from '@navigation/Navigation';
@@ -34,9 +35,9 @@ type SearchProps = {
3435

3536
const sortableSearchTabs: SearchQuery[] = [CONST.TAB_SEARCH.ALL];
3637

37-
function isReportListItemType(item: TransactionListItemType | ReportListItemType): item is ReportListItemType {
38-
const reportListItem = item as ReportListItemType;
39-
return reportListItem.transactions !== undefined;
38+
function isTransactionListItemType(item: TransactionListItemType | ReportListItemType): item is TransactionListItemType {
39+
const transactionListItem = item as TransactionListItemType;
40+
return transactionListItem.transactionID !== undefined;
4041
}
4142

4243
function Search({query, policyIDs, sortBy, sortOrder}: SearchProps) {
@@ -76,11 +77,19 @@ function Search({query, policyIDs, sortBy, sortOrder}: SearchProps) {
7677
return <EmptySearchView />;
7778
}
7879

79-
const openReport = (reportID?: string) => {
80+
const openReport = (item: TransactionListItemType | ReportListItemType) => {
81+
let reportID = isTransactionListItemType(item) ? item.transactionThreadReportID : item.reportID;
82+
8083
if (!reportID) {
8184
return;
8285
}
8386

87+
// If we're trying to open a legacy transaction without a transaction thread, let's create the thread and navigate the user
88+
if (isTransactionListItemType(item) && reportID === '0' && item.moneyRequestReportActionID) {
89+
reportID = ReportUtils.generateReportID();
90+
SearchActions.createTransactionThread(hash, item.transactionID, reportID, item.moneyRequestReportActionID);
91+
}
92+
8493
Navigation.navigate(ROUTES.SEARCH_REPORT.getRoute(query, reportID));
8594
};
8695

@@ -137,10 +146,7 @@ function Search({query, policyIDs, sortBy, sortOrder}: SearchProps) {
137146
updateCellsBatchingPeriod={200}
138147
ListItem={ListItem}
139148
sections={[{data: sortedData, isDisabled: false}]}
140-
onSelectRow={(item) => {
141-
const reportID = isReportListItemType(item) ? item.reportID : item.transactionThreadReportID;
142-
openReport(reportID);
143-
}}
149+
onSelectRow={(item) => openReport(item)}
144150
shouldDebounceRowSelect
145151
shouldPreventDefaultFocusOnSelectRow={!DeviceCapabilities.canUseTouchScreen()}
146152
listHeaderWrapperStyle={[styles.ph9, styles.pv3, styles.pb5]}

src/libs/actions/Search.ts

+30-4
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,16 @@ import * as API from '@libs/API';
44
import type {SearchParams} from '@libs/API/parameters';
55
import {READ_COMMANDS} from '@libs/API/types';
66
import ONYXKEYS from '@src/ONYXKEYS';
7+
import type {SearchTransaction} from '@src/types/onyx/SearchResults';
8+
import * as Report from './Report';
9+
10+
let currentUserEmail: string;
11+
Onyx.connect({
12+
key: ONYXKEYS.SESSION,
13+
callback: (val) => {
14+
currentUserEmail = val?.email ?? '';
15+
},
16+
});
717

818
function search({hash, query, policyIDs, offset, sortBy, sortOrder}: SearchParams) {
919
const optimisticData: OnyxUpdate[] = [
@@ -32,7 +42,23 @@ function search({hash, query, policyIDs, offset, sortBy, sortOrder}: SearchParam
3242

3343
API.read(READ_COMMANDS.SEARCH, {hash, query, offset, policyIDs, sortBy, sortOrder}, {optimisticData, finallyData});
3444
}
35-
export {
36-
// eslint-disable-next-line import/prefer-default-export
37-
search,
38-
};
45+
46+
/**
47+
* It's possible that we return legacy transactions that don't have a transaction thread created yet.
48+
* In that case, when users select the search result row, we need to create the transaction thread on the fly and update the search result with the new transactionThreadReport
49+
*/
50+
function createTransactionThread(hash: number, transactionID: string, reportID: string, moneyRequestReportActionID: string) {
51+
Report.openReport(reportID, '', [currentUserEmail], {}, moneyRequestReportActionID);
52+
53+
const onyxUpdate: Record<string, Record<string, Partial<SearchTransaction>>> = {
54+
data: {
55+
[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`]: {
56+
transactionThreadReportID: reportID,
57+
},
58+
},
59+
};
60+
61+
Onyx.merge(`${ONYXKEYS.COLLECTION.SNAPSHOT}${hash}`, onyxUpdate);
62+
}
63+
64+
export {search, createTransactionThread};

src/types/onyx/SearchResults.ts

+3
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,9 @@ type SearchTransaction = {
151151

152152
/** The modified MCC Group associated with the transaction */
153153
modifiedMCCGroup?: ValueOf<typeof CONST.MCC_GROUPS>;
154+
155+
/** The ID of the money request reportAction associated with the transaction */
156+
moneyRequestReportActionID?: string;
154157
};
155158

156159
type SearchAccountDetails = Partial<SearchPolicyDetails & SearchPersonalDetails>;

0 commit comments

Comments
 (0)