Skip to content

Commit efc6371

Browse files
authored
Merge pull request Expensify#86608 from parasharrajat/onyx/session-3
Refactor `deleteTrackExpense`
2 parents 1ebe416 + 9dc093e commit efc6371

5 files changed

Lines changed: 159 additions & 4 deletions

File tree

src/components/MoneyRequestHeaderSecondaryActions.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,7 @@ function MoneyRequestHeaderSecondaryActions({reportID, onBackButtonPress}: Money
433433
isChatIOUReportArchived,
434434
allTransactionViolationsParam: allTransactionViolations,
435435
currentUserAccountID: accountID,
436+
currentUserEmail: currentUserLogin ?? '',
436437
});
437438
} else {
438439
// eslint-disable-next-line @typescript-eslint/no-deprecated

src/libs/actions/IOU/TrackExpense.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@ type DeleteTrackExpenseParams = {
206206
isChatIOUReportArchived: boolean | undefined;
207207
allTransactionViolationsParam: OnyxCollection<OnyxTypes.TransactionViolations>;
208208
currentUserAccountID: number;
209+
currentUserEmail: string;
209210
};
210211

211212
type BuildOnyxDataForTrackExpenseParams = {
@@ -2660,6 +2661,7 @@ function deleteTrackExpense({
26602661
isChatIOUReportArchived,
26612662
allTransactionViolationsParam,
26622663
currentUserAccountID,
2664+
currentUserEmail,
26632665
}: DeleteTrackExpenseParams) {
26642666
if (!chatReportID || !transactionID) {
26652667
return;
@@ -2672,8 +2674,8 @@ function deleteTrackExpense({
26722674
reportAction,
26732675
iouReport,
26742676
chatIOUReport,
2675-
isSingleTransactionView,
26762677
isChatIOUReportArchived,
2678+
isSingleTransactionView,
26772679
);
26782680

26792681
// STEP 1: Get all collections we're updating
@@ -2689,7 +2691,7 @@ function deleteTrackExpense({
26892691
isSingleTransactionView,
26902692
allTransactionViolationsParam,
26912693
currentUserAccountID,
2692-
currentUserEmail: getCurrentUserEmail(),
2694+
currentUserEmail,
26932695
});
26942696
return urlToNavigateBack;
26952697
}

src/pages/ReportDetailsPage.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -934,6 +934,7 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail
934934
isChatIOUReportArchived,
935935
allTransactionViolationsParam: allTransactionViolations,
936936
currentUserAccountID: currentUserPersonalDetails.accountID,
937+
currentUserEmail: currentUserPersonalDetails.email ?? '',
937938
});
938939
} else if (iouTransactionID) {
939940
deleteTransactions([iouTransactionID], duplicateTransactions, duplicateTransactionViolations, undefined, isSingleTransactionView);

src/pages/inbox/report/ContextMenu/PopoverReportActionContextMenu.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,7 @@ function PopoverReportActionContextMenu({ref}: PopoverReportActionContextMenuPro
367367
isChatIOUReportArchived,
368368
allTransactionViolationsParam: allTransactionViolations,
369369
currentUserAccountID,
370+
currentUserEmail: email ?? '',
370371
});
371372
} else if (originalMessage?.IOUTransactionID) {
372373
deleteTransactions([originalMessage.IOUTransactionID], duplicateTransactions, duplicateTransactionViolations, undefined);

tests/actions/IOUTest/TrackExpenseTest.ts

Lines changed: 152 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@
33
import {format} from 'date-fns';
44
import Onyx from 'react-native-onyx';
55
import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
6-
import {convertBulkTrackedExpensesToIOU, getDeleteTrackExpenseInformation, getTrackExpenseInformation, trackExpense} from '@libs/actions/IOU/TrackExpense';
6+
import {convertBulkTrackedExpensesToIOU, deleteTrackExpense, getDeleteTrackExpenseInformation, getTrackExpenseInformation, trackExpense} from '@libs/actions/IOU/TrackExpense';
77
import initOnyxDerivedValues from '@libs/actions/OnyxDerived';
88
import {addComment, openReport} from '@libs/actions/Report';
99
import {subscribeToUserEvents} from '@libs/actions/User';
10+
import {WRITE_COMMANDS} from '@libs/API/types';
1011
import {getLoginsByAccountIDs} from '@libs/PersonalDetailsUtils';
1112
// eslint-disable-next-line no-restricted-syntax
1213
import type * as PolicyUtils from '@libs/PolicyUtils';
@@ -17,8 +18,10 @@ import {getValidWaypoints, isDistanceRequest as isDistanceRequestUtil} from '@li
1718
import CONST from '@src/CONST';
1819
import IntlStore from '@src/languages/IntlStore';
1920
import OnyxUpdateManager from '@src/libs/actions/OnyxUpdateManager';
21+
import * as API from '@src/libs/API';
2022
import DateUtils from '@src/libs/DateUtils';
2123
import ONYXKEYS from '@src/ONYXKEYS';
24+
import ROUTES from '@src/ROUTES';
2225
import type {IntroSelected, PersonalDetailsList, Policy, Report} from '@src/types/onyx';
2326
import type {Accountant} from '@src/types/onyx/IOU';
2427
import type ReportAction from '@src/types/onyx/ReportAction';
@@ -1550,7 +1553,9 @@ describe('actions/IOU/TrackExpense', () => {
15501553
expect(Object.values(allReports ?? {}).length).toBe(2);
15511554

15521555
// Then one of them should be a chat report with relevant properties
1553-
const transactionThreadReport = Object.values(allReports ?? {}).find((report) => report?.type === CONST.REPORT.TYPE.CHAT);
1556+
const transactionThreadReport = Object.values(allReports ?? {}).find(
1557+
(report) => report?.type === CONST.REPORT.TYPE.CHAT && report?.parentReportID === selfDMReport.reportID && report?.reportID !== selfDMReport.reportID,
1558+
);
15541559
if (transactionThreadReport) {
15551560
thread = transactionThreadReport;
15561561
}
@@ -1761,6 +1766,151 @@ describe('actions/IOU/TrackExpense', () => {
17611766
});
17621767
});
17631768

1769+
describe('deleteTrackExpense', () => {
1770+
const amount = 10000;
1771+
const TEST_USER_ACCOUNT_ID = 1;
1772+
const TEST_USER_LOGIN = 'test@test.com';
1773+
let selfDMReport: Report;
1774+
let iouReportAction: OnyxEntry<ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.IOU>>;
1775+
let transaction: OnyxEntry<Transaction>;
1776+
let thread: OptimisticChatReport;
1777+
1778+
beforeEach(async () => {
1779+
jest.clearAllMocks();
1780+
PusherHelper.setup();
1781+
1782+
await signInWithTestUser(TEST_USER_ACCOUNT_ID, TEST_USER_LOGIN);
1783+
subscribeToUserEvents(TEST_USER_ACCOUNT_ID, undefined);
1784+
await waitForBatchedUpdates();
1785+
await setPersonalDetails(TEST_USER_LOGIN, TEST_USER_ACCOUNT_ID);
1786+
1787+
selfDMReport = {
1788+
...createRandomReport(1, CONST.REPORT.CHAT_TYPE.SELF_DM),
1789+
reportID: '20',
1790+
};
1791+
1792+
await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${selfDMReport.reportID}`, selfDMReport);
1793+
const recentWaypoints = (await getOnyxValue(ONYXKEYS.NVP_RECENT_WAYPOINTS)) ?? [];
1794+
1795+
trackExpense({
1796+
report: selfDMReport,
1797+
isDraftPolicy: true,
1798+
action: CONST.IOU.ACTION.CREATE,
1799+
participantParams: {
1800+
payeeEmail: TEST_USER_LOGIN,
1801+
payeeAccountID: TEST_USER_ACCOUNT_ID,
1802+
participant: {login: RORY_EMAIL, accountID: RORY_ACCOUNT_ID},
1803+
},
1804+
transactionParams: {
1805+
amount,
1806+
currency: 'USD',
1807+
created: format(new Date(), CONST.DATE.FNS_FORMAT_STRING),
1808+
merchant: 'Delete tracked expense test',
1809+
billable: false,
1810+
},
1811+
isASAPSubmitBetaEnabled: false,
1812+
currentUserAccountIDParam: TEST_USER_ACCOUNT_ID,
1813+
currentUserEmailParam: TEST_USER_LOGIN,
1814+
introSelected: undefined,
1815+
activePolicyID: undefined,
1816+
quickAction: undefined,
1817+
recentWaypoints,
1818+
betas: [CONST.BETAS.ALL],
1819+
draftTransactionIDs: [],
1820+
isSelfTourViewed: false,
1821+
});
1822+
await waitForBatchedUpdates();
1823+
1824+
const allReports = await new Promise<OnyxCollection<Report>>((resolve) => {
1825+
const connection = Onyx.connect({
1826+
key: ONYXKEYS.COLLECTION.REPORT,
1827+
waitForCollectionCallback: true,
1828+
callback: (actions) => {
1829+
Onyx.disconnect(connection);
1830+
resolve(actions);
1831+
},
1832+
});
1833+
});
1834+
1835+
const allReportActions = await new Promise<OnyxCollection<ReportActions>>((resolve) => {
1836+
const connection = Onyx.connect({
1837+
key: ONYXKEYS.COLLECTION.REPORT_ACTIONS,
1838+
waitForCollectionCallback: true,
1839+
callback: (actions) => {
1840+
Onyx.disconnect(connection);
1841+
resolve(actions);
1842+
},
1843+
});
1844+
});
1845+
1846+
const allTransactions = await new Promise<OnyxCollection<Transaction>>((resolve) => {
1847+
const connection = Onyx.connect({
1848+
key: ONYXKEYS.COLLECTION.TRANSACTION,
1849+
waitForCollectionCallback: true,
1850+
callback: (actions) => {
1851+
Onyx.disconnect(connection);
1852+
resolve(actions);
1853+
},
1854+
});
1855+
});
1856+
1857+
const transactionThreadReport = Object.values(allReports ?? {}).find(
1858+
(report) => report?.type === CONST.REPORT.TYPE.CHAT && report?.parentReportID === selfDMReport.reportID && report?.reportID !== selfDMReport.reportID,
1859+
);
1860+
if (transactionThreadReport) {
1861+
thread = transactionThreadReport;
1862+
}
1863+
1864+
iouReportAction = Object.values(allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${selfDMReport.reportID}`] ?? {}).find(
1865+
(reportAction): reportAction is ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.IOU> => reportAction.reportActionID === thread?.parentReportActionID,
1866+
);
1867+
transaction = Object.values(allTransactions ?? {}).find((trackedTransaction) => trackedTransaction);
1868+
1869+
expect(thread).toBeTruthy();
1870+
expect(iouReportAction).toBeTruthy();
1871+
expect(transaction).toBeTruthy();
1872+
});
1873+
1874+
afterEach(PusherHelper.teardown);
1875+
1876+
it('should call API.write with delete money request onyx data for selfDM track expenses and return the parent report route in single transaction view', () => {
1877+
const writeSpy = jest.spyOn(API, 'write').mockImplementation(jest.fn());
1878+
1879+
const result = deleteTrackExpense({
1880+
chatReportID: selfDMReport.reportID,
1881+
chatReport: selfDMReport,
1882+
transactionID: transaction?.transactionID,
1883+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
1884+
reportAction: iouReportAction!,
1885+
iouReport: undefined,
1886+
chatIOUReport: undefined,
1887+
transactions: {},
1888+
violations: {},
1889+
isSingleTransactionView: true,
1890+
isChatReportArchived: false,
1891+
isChatIOUReportArchived: false,
1892+
allTransactionViolationsParam: {},
1893+
currentUserAccountID: TEST_USER_ACCOUNT_ID,
1894+
currentUserEmail: TEST_USER_LOGIN,
1895+
});
1896+
1897+
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
1898+
expect(result).toBe(ROUTES.REPORT_WITH_ID.getRoute(selfDMReport.reportID));
1899+
expect(writeSpy).toHaveBeenCalledWith(
1900+
WRITE_COMMANDS.DELETE_MONEY_REQUEST,
1901+
expect.objectContaining({
1902+
transactionID: transaction?.transactionID,
1903+
reportActionID: iouReportAction?.reportActionID,
1904+
}),
1905+
expect.objectContaining({
1906+
optimisticData: expect.any(Array),
1907+
successData: expect.any(Array),
1908+
failureData: expect.any(Array),
1909+
}),
1910+
);
1911+
});
1912+
});
1913+
17641914
describe('convertBulkTrackedExpensesToIOU', () => {
17651915
it('should accept personalDetails as a required parameter', async () => {
17661916
const currentUserAccountID = 1;

0 commit comments

Comments
 (0)