From 3fe4d80fe0b3fbacd5ab420eb284304bddf9b9af Mon Sep 17 00:00:00 2001 From: dukenv0307 Date: Tue, 20 Jan 2026 11:48:30 +0700 Subject: [PATCH 01/12] refactor trackExpense --- src/components/MoneyReportHeader.tsx | 14 +++++++++++++- src/components/MoneyRequestHeader.tsx | 14 +++++++++++++- src/libs/actions/IOU/Duplicate.ts | 5 ++++- src/libs/actions/IOU/index.ts | 5 +++-- src/pages/Share/SubmitDetailsPage.tsx | 2 ++ .../iou/request/step/IOURequestStepAmount.tsx | 2 ++ .../request/step/IOURequestStepConfirmation.tsx | 3 +++ .../iou/request/step/IOURequestStepDistance.tsx | 2 ++ .../request/step/IOURequestStepDistanceManual.tsx | 2 ++ .../iou/request/step/IOURequestStepDistanceMap.tsx | 2 ++ .../step/IOURequestStepDistanceOdometer.tsx | 2 ++ .../step/IOURequestStepScan/index.native.tsx | 2 ++ .../iou/request/step/IOURequestStepScan/index.tsx | 2 ++ tests/actions/IOUTest.ts | 10 ++++++++++ tests/actions/IOUTest/DuplicateTest.ts | 2 ++ tests/ui/UnreadIndicatorsTest.tsx | 1 + tests/unit/GoogleTagManagerTest.tsx | 1 + 17 files changed, 66 insertions(+), 5 deletions(-) diff --git a/src/components/MoneyReportHeader.tsx b/src/components/MoneyReportHeader.tsx index 45362c5568d79..bf7d1c30f7fe3 100644 --- a/src/components/MoneyReportHeader.tsx +++ b/src/components/MoneyReportHeader.tsx @@ -262,6 +262,7 @@ function MoneyReportHeader({ const [allTransactions] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION, {canBeMissing: false}); const [allReports] = useOnyx(ONYXKEYS.COLLECTION.REPORT, {canBeMissing: false}); const [allPolicyCategories] = useOnyx(ONYXKEYS.COLLECTION.POLICY_CATEGORIES, {canBeMissing: false}); + const [allTransactionDrafts = {}] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_DRAFT, {canBeMissing: true}); const requestParentReportAction = useMemo(() => { if (!reportActions || !transactionThreadReport?.parentReportActionID) { @@ -652,10 +653,21 @@ function MoneyReportHeader({ targetPolicy: defaultExpensePolicy ?? undefined, targetPolicyCategories: activePolicyCategories, targetReport: activePolicyExpenseChat, + allTransactionDrafts, }); } }, - [activePolicyExpenseChat, activePolicyID, allPolicyCategories, defaultExpensePolicy, introSelected, isASAPSubmitBetaEnabled, quickAction, policyRecentlyUsedCurrencies], + [ + activePolicyExpenseChat, + activePolicyID, + allPolicyCategories, + allTransactionDrafts, + defaultExpensePolicy, + introSelected, + isASAPSubmitBetaEnabled, + quickAction, + policyRecentlyUsedCurrencies, + ], ); const getStatusIcon: (src: IconAsset) => React.ReactNode = (src) => ( diff --git a/src/components/MoneyRequestHeader.tsx b/src/components/MoneyRequestHeader.tsx index e656f28c963fe..33cfd3ed1f488 100644 --- a/src/components/MoneyRequestHeader.tsx +++ b/src/components/MoneyRequestHeader.tsx @@ -150,6 +150,7 @@ function MoneyRequestHeader({report, parentReportAction, policy, onBackButtonPre const isASAPSubmitBetaEnabled = isBetaEnabled(CONST.BETAS.ASAP_SUBMIT); const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {canBeMissing: true}); const [activePolicyID] = useOnyx(ONYXKEYS.NVP_ACTIVE_POLICY_ID, {canBeMissing: true}); + const [allTransactionDrafts = {}] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_DRAFT, {canBeMissing: true}); const {isDelegateAccessRestricted, showDelegateNoAccessModal} = useContext(DelegateNoAccessContext); const isReportInRHP = route.name === SCREENS.RIGHT_MODAL.SEARCH_REPORT; @@ -199,10 +200,21 @@ function MoneyRequestHeader({report, parentReportAction, policy, onBackButtonPre targetPolicy: defaultExpensePolicy ?? undefined, targetPolicyCategories: activePolicyCategories, targetReport: activePolicyExpenseChat, + allTransactionDrafts, }); } }, - [activePolicyExpenseChat, allPolicyCategories, defaultExpensePolicy, isASAPSubmitBetaEnabled, introSelected, activePolicyID, quickAction, policyRecentlyUsedCurrencies], + [ + activePolicyExpenseChat, + allPolicyCategories, + allTransactionDrafts, + defaultExpensePolicy, + isASAPSubmitBetaEnabled, + introSelected, + activePolicyID, + quickAction, + policyRecentlyUsedCurrencies, + ], ); const getStatusIcon: (src: IconAsset) => ReactNode = (src) => ( diff --git a/src/libs/actions/IOU/Duplicate.ts b/src/libs/actions/IOU/Duplicate.ts index da8822844c319..3f2e4738c4a80 100644 --- a/src/libs/actions/IOU/Duplicate.ts +++ b/src/libs/actions/IOU/Duplicate.ts @@ -1,5 +1,5 @@ import {format} from 'date-fns'; -import type {NullishDeep, OnyxEntry, OnyxUpdate} from 'react-native-onyx'; +import type {NullishDeep, OnyxCollection, OnyxEntry, OnyxUpdate} from 'react-native-onyx'; import Onyx from 'react-native-onyx'; import type {PartialDeep} from 'type-fest'; import * as API from '@libs/API'; @@ -462,6 +462,7 @@ type DuplicateExpenseTransactionParams = { targetPolicy?: OnyxEntry; targetPolicyCategories?: OnyxEntry; targetReport?: OnyxTypes.Report; + allTransactionDrafts: OnyxCollection; }; function duplicateExpenseTransaction({ @@ -476,6 +477,7 @@ function duplicateExpenseTransaction({ targetPolicy, targetPolicyCategories, targetReport, + allTransactionDrafts, }: DuplicateExpenseTransactionParams) { if (!transaction) { return; @@ -546,6 +548,7 @@ function duplicateExpenseTransaction({ introSelected, activePolicyID, quickAction, + allTransactionDrafts, }; return trackExpense(trackExpenseParams); } diff --git a/src/libs/actions/IOU/index.ts b/src/libs/actions/IOU/index.ts index 76be6b2098862..87ac99730171d 100644 --- a/src/libs/actions/IOU/index.ts +++ b/src/libs/actions/IOU/index.ts @@ -711,6 +711,7 @@ type CreateTrackExpenseParams = { introSelected: OnyxEntry; activePolicyID: string | undefined; quickAction: OnyxEntry; + allTransactionDrafts: OnyxCollection; }; type GetTrackExpenseInformationTransactionParams = { @@ -6482,6 +6483,7 @@ function trackExpense(params: CreateTrackExpenseParams) { introSelected, activePolicyID, quickAction, + allTransactionDrafts: allTransactionDraftsParam, } = params; const {participant, payeeAccountID, payeeEmail} = participantParams; const {policy, policyCategories, policyTagList} = policyData; @@ -6783,8 +6785,7 @@ function trackExpense(params: CreateTrackExpenseParams) { } if (shouldHandleNavigation) { - // eslint-disable-next-line @typescript-eslint/no-deprecated - InteractionManager.runAfterInteractions(() => removeDraftTransactions()); + InteractionManager.runAfterInteractions(() => removeDraftTransactions(undefined, allTransactionDraftsParam)); if (!params.isRetry) { dismissModalAndOpenReportInInboxTab(activeReportID); diff --git a/src/pages/Share/SubmitDetailsPage.tsx b/src/pages/Share/SubmitDetailsPage.tsx index 3705b202264d4..b011f94f3eca2 100644 --- a/src/pages/Share/SubmitDetailsPage.tsx +++ b/src/pages/Share/SubmitDetailsPage.tsx @@ -68,6 +68,7 @@ function SubmitDetailsPage({ const [transactionViolations] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS, {canBeMissing: true}); const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {canBeMissing: true}); const [activePolicyID] = useOnyx(ONYXKEYS.NVP_ACTIVE_POLICY_ID, {canBeMissing: true}); + const [allTransactionDrafts] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_DRAFT, {canBeMissing: true}); const [policyRecentlyUsedCurrencies] = useOnyx(ONYXKEYS.RECENTLY_USED_CURRENCIES, {canBeMissing: true}); const currentUserPersonalDetails = useCurrentUserPersonalDetails(); @@ -156,6 +157,7 @@ function SubmitDetailsPage({ activePolicyID, introSelected, quickAction, + allTransactionDrafts, }); } else { requestMoney({ diff --git a/src/pages/iou/request/step/IOURequestStepAmount.tsx b/src/pages/iou/request/step/IOURequestStepAmount.tsx index 108ba977497b0..922d47f40c429 100644 --- a/src/pages/iou/request/step/IOURequestStepAmount.tsx +++ b/src/pages/iou/request/step/IOURequestStepAmount.tsx @@ -90,6 +90,7 @@ function IOURequestStepAmount({ const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, {canBeMissing: false}); const [draftTransaction] = useOnyx(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, {canBeMissing: true}); const [splitDraftTransaction] = useOnyx(`${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${transactionID}`, {canBeMissing: true}); + const [allTransactionDrafts] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_DRAFT, {canBeMissing: true}); const [skipConfirmation] = useOnyx(`${ONYXKEYS.COLLECTION.SKIP_CONFIRMATION}${transactionID}`, {canBeMissing: true}); const [policyRecentlyUsedCurrencies] = useOnyx(ONYXKEYS.RECENTLY_USED_CURRENCIES, {canBeMissing: true}); const [quickAction] = useOnyx(ONYXKEYS.NVP_QUICK_ACTION_GLOBAL_CREATE, {canBeMissing: true}); @@ -272,6 +273,7 @@ function IOURequestStepAmount({ introSelected, activePolicyID, quickAction, + allTransactionDrafts, }); return; } diff --git a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx index 9f716c7acc1e5..e307c580929d0 100644 --- a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx +++ b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx @@ -132,6 +132,7 @@ function IOURequestStepConfirmation({ selector: transactionDraftValuesSelector, canBeMissing: true, }); + const [allTransactionDrafts] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_DRAFT, {canBeMissing: true}); const transactions = useMemo(() => { const allTransactions = optimisticTransactions && optimisticTransactions.length > 1 ? optimisticTransactions : [initialTransaction]; return allTransactions.filter((transaction): transaction is Transaction => !!transaction); @@ -800,6 +801,7 @@ function IOURequestStepConfirmation({ introSelected, activePolicyID, quickAction, + allTransactionDrafts, }); } }, @@ -824,6 +826,7 @@ function IOURequestStepConfirmation({ introSelected, activePolicyID, quickAction, + allTransactionDrafts, ], ); diff --git a/src/pages/iou/request/step/IOURequestStepDistance.tsx b/src/pages/iou/request/step/IOURequestStepDistance.tsx index 206350a30772f..3517e9a0678d9 100644 --- a/src/pages/iou/request/step/IOURequestStepDistance.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistance.tsx @@ -105,6 +105,7 @@ function IOURequestStepDistance({ const [policyRecentlyUsedCurrencies] = useOnyx(ONYXKEYS.RECENTLY_USED_CURRENCIES, {canBeMissing: true}); const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {canBeMissing: true}); const [activePolicyID] = useOnyx(ONYXKEYS.NVP_ACTIVE_POLICY_ID, {canBeMissing: true}); + const [allTransactionDrafts] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_DRAFT, {canBeMissing: true}); const waypoints = useMemo( () => optimisticWaypoints ?? @@ -365,6 +366,7 @@ function IOURequestStepDistance({ introSelected, activePolicyID, quickAction, + allTransactionDrafts, }); return; } diff --git a/src/pages/iou/request/step/IOURequestStepDistanceManual.tsx b/src/pages/iou/request/step/IOURequestStepDistanceManual.tsx index df0c8ab82a5b9..2e2d02e3abf74 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceManual.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceManual.tsx @@ -96,6 +96,7 @@ function IOURequestStepDistanceManual({ const [policyRecentlyUsedCurrencies] = useOnyx(ONYXKEYS.RECENTLY_USED_CURRENCIES, {canBeMissing: true}); const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {canBeMissing: true}); const [activePolicyID] = useOnyx(ONYXKEYS.NVP_ACTIVE_POLICY_ID, {canBeMissing: true}); + const [allTransactionDrafts] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_DRAFT, {canBeMissing: true}); const [parentReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getNonEmptyStringOnyxID(report?.parentReportID)}`, {canBeMissing: true}); const [parentReportNextStep] = useOnyx(`${ONYXKEYS.COLLECTION.NEXT_STEP}${getNonEmptyStringOnyxID(report?.parentReportID)}`, {canBeMissing: true}); @@ -242,6 +243,7 @@ function IOURequestStepDistanceManual({ introSelected, activePolicyID, quickAction, + allTransactionDrafts, }); return; } diff --git a/src/pages/iou/request/step/IOURequestStepDistanceMap.tsx b/src/pages/iou/request/step/IOURequestStepDistanceMap.tsx index efa1d6d6f3227..1c858acdcaf1b 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceMap.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceMap.tsx @@ -162,6 +162,7 @@ function IOURequestStepDistanceMap({ const isASAPSubmitBetaEnabled = isBetaEnabled(CONST.BETAS.ASAP_SUBMIT); const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {canBeMissing: true}); const [activePolicyID] = useOnyx(ONYXKEYS.NVP_ACTIVE_POLICY_ID, {canBeMissing: true}); + const [allTransactionDrafts] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_DRAFT, {canBeMissing: true}); const currentUserAccountIDParam = currentUserPersonalDetails.accountID; const currentUserEmailParam = currentUserPersonalDetails.login ?? ''; @@ -365,6 +366,7 @@ function IOURequestStepDistanceMap({ introSelected, activePolicyID, quickAction, + allTransactionDrafts, }); return; } diff --git a/src/pages/iou/request/step/IOURequestStepDistanceOdometer.tsx b/src/pages/iou/request/step/IOURequestStepDistanceOdometer.tsx index 2e7cb49d6e8c2..791f4e229ed2d 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceOdometer.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceOdometer.tsx @@ -102,6 +102,7 @@ function IOURequestStepDistanceOdometer({ const [quickAction] = useOnyx(ONYXKEYS.NVP_QUICK_ACTION_GLOBAL_CREATE, {canBeMissing: true}); const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {canBeMissing: true}); const [activePolicyID] = useOnyx(ONYXKEYS.NVP_ACTIVE_POLICY_ID, {canBeMissing: true}); + const [allTransactionDrafts] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_DRAFT, {canBeMissing: true}); const [policyRecentlyUsedCurrencies] = useOnyx(ONYXKEYS.RECENTLY_USED_CURRENCIES, {canBeMissing: true}); const [skipConfirmation] = useOnyx(`${ONYXKEYS.COLLECTION.SKIP_CONFIRMATION}${transactionID}`, {canBeMissing: true}); const [parentReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getNonEmptyStringOnyxID(report?.parentReportID)}`, {canBeMissing: true}); @@ -416,6 +417,7 @@ function IOURequestStepDistanceOdometer({ introSelected, activePolicyID, quickAction, + allTransactionDrafts, }); return; } diff --git a/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx b/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx index d467d063903ed..c3f9d2b30ee2d 100644 --- a/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx +++ b/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx @@ -138,6 +138,7 @@ function IOURequestStepScan({ const [policyRecentlyUsedCurrencies] = useOnyx(ONYXKEYS.RECENTLY_USED_CURRENCIES, {canBeMissing: true}); const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {canBeMissing: true}); const [activePolicyID] = useOnyx(ONYXKEYS.NVP_ACTIVE_POLICY_ID, {canBeMissing: true}); + const [allTransactionDrafts] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_DRAFT, {canBeMissing: true}); const defaultTaxCode = getDefaultTaxCode(policy, initialTransaction); const transactionTaxCode = (initialTransaction?.taxCode ? initialTransaction?.taxCode : defaultTaxCode) ?? ''; @@ -345,6 +346,7 @@ function IOURequestStepScan({ introSelected, activePolicyID, quickAction, + allTransactionDrafts, }); } else { requestMoney({ diff --git a/src/pages/iou/request/step/IOURequestStepScan/index.tsx b/src/pages/iou/request/step/IOURequestStepScan/index.tsx index 522a6c5cd8006..649c28d52c8d2 100644 --- a/src/pages/iou/request/step/IOURequestStepScan/index.tsx +++ b/src/pages/iou/request/step/IOURequestStepScan/index.tsx @@ -137,6 +137,7 @@ function IOURequestStepScan({ const [transactionViolations] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS, {canBeMissing: true}); const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {canBeMissing: true}); const [activePolicyID] = useOnyx(ONYXKEYS.NVP_ACTIVE_POLICY_ID, {canBeMissing: true}); + const [allTransactionDrafts] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_DRAFT, {canBeMissing: true}); const [optimisticTransactions] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_DRAFT, { selector: transactionDraftValuesSelector, @@ -401,6 +402,7 @@ function IOURequestStepScan({ introSelected, activePolicyID, quickAction, + allTransactionDrafts, }); } else { requestMoney({ diff --git a/tests/actions/IOUTest.ts b/tests/actions/IOUTest.ts index 01b1bbd6ba1fc..1173335271818 100644 --- a/tests/actions/IOUTest.ts +++ b/tests/actions/IOUTest.ts @@ -519,6 +519,7 @@ describe('actions/IOU', () => { introSelected: undefined, activePolicyID: undefined, quickAction: undefined, + allTransactionDrafts: {[`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${fakeTransaction.transactionID}`]: fakeTransaction}, }); await waitForBatchedUpdates(); await mockFetch?.resume?.(); @@ -619,6 +620,7 @@ describe('actions/IOU', () => { introSelected: undefined, activePolicyID: undefined, quickAction: undefined, + allTransactionDrafts: allTransactionsDraft ?? {}, }); await waitForBatchedUpdates(); await mockFetch?.resume?.(); @@ -702,6 +704,7 @@ describe('actions/IOU', () => { introSelected: undefined, activePolicyID: undefined, quickAction: undefined, + allTransactionDrafts: {[`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transaction.transactionID}`]: transaction}, }); await waitForBatchedUpdates(); @@ -754,6 +757,7 @@ describe('actions/IOU', () => { introSelected: undefined, activePolicyID: undefined, quickAction: undefined, + allTransactionDrafts: {[`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transaction.transactionID}`]: transaction}, }); await waitForBatchedUpdates(); @@ -832,6 +836,7 @@ describe('actions/IOU', () => { introSelected: undefined, activePolicyID: undefined, quickAction: undefined, + allTransactionDrafts: {[`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transaction.transactionID}`]: transaction}, }); await waitForBatchedUpdates(); @@ -884,6 +889,7 @@ describe('actions/IOU', () => { introSelected: undefined, activePolicyID: undefined, quickAction: undefined, + allTransactionDrafts: {[`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transaction.transactionID}`]: transaction}, }); await waitForBatchedUpdates(); @@ -2180,6 +2186,7 @@ describe('actions/IOU', () => { introSelected: undefined, activePolicyID: undefined, quickAction: undefined, + allTransactionDrafts: {}, }); mockFetch?.resume?.(); @@ -2245,6 +2252,7 @@ describe('actions/IOU', () => { introSelected: undefined, activePolicyID: undefined, quickAction: undefined, + allTransactionDrafts: {}, }); await waitForBatchedUpdates(); @@ -7417,6 +7425,7 @@ describe('actions/IOU', () => { introSelected: undefined, activePolicyID: undefined, quickAction: undefined, + allTransactionDrafts: {}, }); await waitForBatchedUpdates(); @@ -9067,6 +9076,7 @@ describe('actions/IOU', () => { introSelected: undefined, activePolicyID: undefined, quickAction: undefined, + allTransactionDrafts: {}, }); await getOnyxData({ key: ONYXKEYS.COLLECTION.TRANSACTION, diff --git a/tests/actions/IOUTest/DuplicateTest.ts b/tests/actions/IOUTest/DuplicateTest.ts index 5f60632f0d6a2..878fd091d7d73 100644 --- a/tests/actions/IOUTest/DuplicateTest.ts +++ b/tests/actions/IOUTest/DuplicateTest.ts @@ -704,6 +704,7 @@ describe('actions/Duplicate', () => { targetPolicy: mockPolicy, targetPolicyCategories: fakePolicyCategories, targetReport: policyExpenseChat, + allTransactionDrafts: {}, }); await waitForBatchedUpdates(); @@ -759,6 +760,7 @@ describe('actions/Duplicate', () => { targetPolicy: mockPolicy, targetPolicyCategories: fakePolicyCategories, targetReport: policyExpenseChat, + allTransactionDrafts: {}, }); await waitForBatchedUpdates(); diff --git a/tests/ui/UnreadIndicatorsTest.tsx b/tests/ui/UnreadIndicatorsTest.tsx index c9b27b702b0b5..ec4107d8dcd49 100644 --- a/tests/ui/UnreadIndicatorsTest.tsx +++ b/tests/ui/UnreadIndicatorsTest.tsx @@ -720,6 +720,7 @@ describe('Unread Indicators', () => { introSelected: undefined, activePolicyID: undefined, quickAction: undefined, + allTransactionDrafts: {}, }); await waitForBatchedUpdates(); diff --git a/tests/unit/GoogleTagManagerTest.tsx b/tests/unit/GoogleTagManagerTest.tsx index 2d93af6bfb83c..b2d36055204eb 100644 --- a/tests/unit/GoogleTagManagerTest.tsx +++ b/tests/unit/GoogleTagManagerTest.tsx @@ -197,6 +197,7 @@ describe('GoogleTagManagerTest', () => { introSelected: undefined, activePolicyID: undefined, quickAction: undefined, + allTransactionDrafts: {}, }); await waitForBatchedUpdatesWithAct(); From 52418f1d78c4fc5815c4efd7688e7c176c1d7eeb Mon Sep 17 00:00:00 2001 From: dukenv0307 Date: Tue, 20 Jan 2026 16:04:36 +0700 Subject: [PATCH 02/12] fix lint --- src/components/MoneyReportHeader.tsx | 3 ++- src/components/MoneyRequestHeader.tsx | 2 +- src/libs/actions/IOU/index.ts | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/components/MoneyReportHeader.tsx b/src/components/MoneyReportHeader.tsx index bf7d1c30f7fe3..1b89cd3b1d833 100644 --- a/src/components/MoneyReportHeader.tsx +++ b/src/components/MoneyReportHeader.tsx @@ -125,6 +125,7 @@ import ROUTES from '@src/ROUTES'; import SCREENS from '@src/SCREENS'; import type * as OnyxTypes from '@src/types/onyx'; import type {PaymentMethodType} from '@src/types/onyx/OriginalMessage'; +import {getEmptyObject} from '@src/types/utils/EmptyObject'; import type IconAsset from '@src/types/utils/IconAsset'; import ActivityIndicator from './ActivityIndicator'; import AnimatedSubmitButton from './AnimatedSubmitButton'; @@ -262,7 +263,7 @@ function MoneyReportHeader({ const [allTransactions] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION, {canBeMissing: false}); const [allReports] = useOnyx(ONYXKEYS.COLLECTION.REPORT, {canBeMissing: false}); const [allPolicyCategories] = useOnyx(ONYXKEYS.COLLECTION.POLICY_CATEGORIES, {canBeMissing: false}); - const [allTransactionDrafts = {}] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_DRAFT, {canBeMissing: true}); + const [allTransactionDrafts] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_DRAFT, {canBeMissing: true}); const requestParentReportAction = useMemo(() => { if (!reportActions || !transactionThreadReport?.parentReportActionID) { diff --git a/src/components/MoneyRequestHeader.tsx b/src/components/MoneyRequestHeader.tsx index 33cfd3ed1f488..ca4a724007162 100644 --- a/src/components/MoneyRequestHeader.tsx +++ b/src/components/MoneyRequestHeader.tsx @@ -150,7 +150,7 @@ function MoneyRequestHeader({report, parentReportAction, policy, onBackButtonPre const isASAPSubmitBetaEnabled = isBetaEnabled(CONST.BETAS.ASAP_SUBMIT); const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {canBeMissing: true}); const [activePolicyID] = useOnyx(ONYXKEYS.NVP_ACTIVE_POLICY_ID, {canBeMissing: true}); - const [allTransactionDrafts = {}] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_DRAFT, {canBeMissing: true}); + const [allTransactionDrafts] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_DRAFT, {canBeMissing: true}); const {isDelegateAccessRestricted, showDelegateNoAccessModal} = useContext(DelegateNoAccessContext); const isReportInRHP = route.name === SCREENS.RIGHT_MODAL.SEARCH_REPORT; diff --git a/src/libs/actions/IOU/index.ts b/src/libs/actions/IOU/index.ts index 87ac99730171d..9d86537512898 100644 --- a/src/libs/actions/IOU/index.ts +++ b/src/libs/actions/IOU/index.ts @@ -6785,6 +6785,7 @@ function trackExpense(params: CreateTrackExpenseParams) { } if (shouldHandleNavigation) { + // eslint-disable-next-line @typescript-eslint/no-deprecated InteractionManager.runAfterInteractions(() => removeDraftTransactions(undefined, allTransactionDraftsParam)); if (!params.isRetry) { From 2722d6e7e1286f8fe1d47427505489bc5daf7599 Mon Sep 17 00:00:00 2001 From: dukenv0307 Date: Sun, 25 Jan 2026 23:01:19 +0700 Subject: [PATCH 03/12] lint fix --- src/components/MoneyReportHeader.tsx | 1 - src/libs/actions/IOU/index.ts | 5 ++++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/components/MoneyReportHeader.tsx b/src/components/MoneyReportHeader.tsx index d74a3f54aac07..405907788df88 100644 --- a/src/components/MoneyReportHeader.tsx +++ b/src/components/MoneyReportHeader.tsx @@ -125,7 +125,6 @@ import ROUTES from '@src/ROUTES'; import SCREENS from '@src/SCREENS'; import type * as OnyxTypes from '@src/types/onyx'; import type {PaymentMethodType} from '@src/types/onyx/OriginalMessage'; -import {getEmptyObject} from '@src/types/utils/EmptyObject'; import type IconAsset from '@src/types/utils/IconAsset'; import ActivityIndicator from './ActivityIndicator'; import AnimatedSubmitButton from './AnimatedSubmitButton'; diff --git a/src/libs/actions/IOU/index.ts b/src/libs/actions/IOU/index.ts index dacdddf6eb4ec..8558c70c18b76 100644 --- a/src/libs/actions/IOU/index.ts +++ b/src/libs/actions/IOU/index.ts @@ -6516,8 +6516,11 @@ function trackExpense(params: CreateTrackExpenseParams) { const trackedReceipt = validWaypoints ? {source: ReceiptGeneric as ReceiptSource, state: CONST.IOU.RECEIPT_STATE.OPEN, name: 'receipt-generic.png'} : receipt; const sanitizedWaypoints = validWaypoints ? JSON.stringify(sanitizeRecentWaypoints(validWaypoints)) : undefined; + // Omit allTransactionDrafts from retryParams so getReceiptError's JSON.stringify doesn't store + // the full draft collection in Onyx, which would bloat errors and cause nested payload ballooning on retries. + const paramsWithoutDrafts = {...params, allTransactionDrafts: undefined}; const retryParams: CreateTrackExpenseParams = { - ...params, + ...paramsWithoutDrafts, report, isDraftPolicy, action, From 3ecde63b0d66246e6c14e4841c1416992e51312c Mon Sep 17 00:00:00 2001 From: dukenv0307 Date: Sun, 25 Jan 2026 23:33:07 +0700 Subject: [PATCH 04/12] fix ts --- .../iou/request/step/IOURequestStepDistanceGPS/index.native.tsx | 2 ++ tests/actions/IOUTest/DuplicateTest.ts | 1 + 2 files changed, 3 insertions(+) diff --git a/src/pages/iou/request/step/IOURequestStepDistanceGPS/index.native.tsx b/src/pages/iou/request/step/IOURequestStepDistanceGPS/index.native.tsx index 635668891478d..224b1db4a9a01 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceGPS/index.native.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceGPS/index.native.tsx @@ -53,6 +53,7 @@ function IOURequestStepDistanceGPS({ const [quickAction] = useOnyx(ONYXKEYS.NVP_QUICK_ACTION_GLOBAL_CREATE, {canBeMissing: true}); const [policyRecentlyUsedCurrencies] = useOnyx(ONYXKEYS.RECENTLY_USED_CURRENCIES, {canBeMissing: true}); const [transactionViolations] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS, {canBeMissing: true}); + const [allTransactionDrafts] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_DRAFT, {canBeMissing: true}); const isEditing = action === CONST.IOU.ACTION.EDIT; const isCreatingNewRequest = !isEditing; @@ -113,6 +114,7 @@ function IOURequestStepDistanceGPS({ privateIsArchived: reportNameValuePairs?.private_isArchived, gpsCoordinates, gpsDistance: distance, + allTransactionDrafts, }); }; diff --git a/tests/actions/IOUTest/DuplicateTest.ts b/tests/actions/IOUTest/DuplicateTest.ts index 12a563cf7d5c9..75aae0af7c63f 100644 --- a/tests/actions/IOUTest/DuplicateTest.ts +++ b/tests/actions/IOUTest/DuplicateTest.ts @@ -819,6 +819,7 @@ describe('actions/Duplicate', () => { targetPolicy: mockPolicy, targetPolicyCategories: fakePolicyCategories, targetReport: policyExpenseChat, + allTransactionDrafts: {}, }); await waitForBatchedUpdates(); From d8d290559bb9028a877824c61c7029a404341b38 Mon Sep 17 00:00:00 2001 From: dukenv0307 Date: Sat, 28 Feb 2026 10:32:14 +0700 Subject: [PATCH 05/12] lint fix --- src/components/MoneyReportHeader.tsx | 1 - src/libs/actions/IOU/Duplicate.ts | 2 +- src/pages/iou/request/step/IOURequestStepConfirmation.tsx | 1 + src/pages/iou/request/step/IOURequestStepDistanceManual.tsx | 1 + tests/actions/IOU/MoneyRequestTest.ts | 4 ++++ 5 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/components/MoneyReportHeader.tsx b/src/components/MoneyReportHeader.tsx index 85f0ae702a5de..f4a258b9d6f81 100644 --- a/src/components/MoneyReportHeader.tsx +++ b/src/components/MoneyReportHeader.tsx @@ -284,7 +284,6 @@ function MoneyReportHeader({ ); const {areStrictPolicyRulesEnabled} = useStrictPolicyRules(); const [allPolicyCategories] = useOnyx(ONYXKEYS.COLLECTION.POLICY_CATEGORIES); - const [allTransactionDrafts] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_DRAFT); const requestParentReportAction = useMemo(() => { if (!reportActions || !transactionThreadReport?.parentReportActionID) { diff --git a/src/libs/actions/IOU/Duplicate.ts b/src/libs/actions/IOU/Duplicate.ts index 267dd6037f0bb..5e752986b3b6c 100644 --- a/src/libs/actions/IOU/Duplicate.ts +++ b/src/libs/actions/IOU/Duplicate.ts @@ -1,5 +1,5 @@ import {format} from 'date-fns'; -import type {NullishDeep, OnyxCollection, OnyxEntry, OnyxUpdate} from 'react-native-onyx'; +import type {NullishDeep, OnyxEntry, OnyxUpdate} from 'react-native-onyx'; import Onyx from 'react-native-onyx'; import type {PartialDeep} from 'type-fest'; import * as API from '@libs/API'; diff --git a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx index 265c7c2ec89ba..dc4fa67c4917f 100644 --- a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx +++ b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx @@ -708,6 +708,7 @@ function IOURequestStepConfirmation({ betas, personalDetails, isGPSDistanceRequest, + draftTransactionIDs, ], ); diff --git a/src/pages/iou/request/step/IOURequestStepDistanceManual.tsx b/src/pages/iou/request/step/IOURequestStepDistanceManual.tsx index 40aa81ffbe27e..5812673686261 100644 --- a/src/pages/iou/request/step/IOURequestStepDistanceManual.tsx +++ b/src/pages/iou/request/step/IOURequestStepDistanceManual.tsx @@ -36,6 +36,7 @@ import variables from '@styles/variables'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type SCREENS from '@src/SCREENS'; +import {validTransactionDraftIDsSelector} from '@src/selectors/TransactionDraft'; import type Transaction from '@src/types/onyx/Transaction'; import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue'; import StepScreenWrapper from './StepScreenWrapper'; diff --git a/tests/actions/IOU/MoneyRequestTest.ts b/tests/actions/IOU/MoneyRequestTest.ts index 9610e506aa6f1..6740c9daa84ce 100644 --- a/tests/actions/IOU/MoneyRequestTest.ts +++ b/tests/actions/IOU/MoneyRequestTest.ts @@ -953,6 +953,9 @@ describe('MoneyRequest', () => { validWaypoints: undefined, customUnitRateID: baseParams.customUnitRateID, attendees: fakeTransaction?.comment?.attendees, + gpsCoordinates: undefined, + odometerEnd: undefined, + odometerStart: undefined, }, isASAPSubmitBetaEnabled: baseParams.isASAPSubmitBetaEnabled, currentUserAccountIDParam: baseParams.currentUserAccountID, @@ -962,6 +965,7 @@ describe('MoneyRequest', () => { introSelected: undefined, recentWaypoints: baseParams.recentWaypoints, betas: [CONST.BETAS.ALL], + draftTransactionIDs: [baseParams.transactionID], }); // The function must return after trackExpense and not call createDistanceRequest From 24e8cc191fd829572734ae91e6d9224965a33d1d Mon Sep 17 00:00:00 2001 From: dukenv0307 Date: Thu, 5 Mar 2026 17:43:09 +0700 Subject: [PATCH 06/12] remove allTransactionDrafts --- src/libs/actions/IOU/index.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/libs/actions/IOU/index.ts b/src/libs/actions/IOU/index.ts index 97af5030fe971..248f57937eb18 100644 --- a/src/libs/actions/IOU/index.ts +++ b/src/libs/actions/IOU/index.ts @@ -7428,11 +7428,8 @@ function trackExpense(params: CreateTrackExpenseParams) { const trackedReceipt = validWaypoints ? {source: ReceiptGeneric as ReceiptSource, state: CONST.IOU.RECEIPT_STATE.OPEN, name: 'receipt-generic.png'} : receipt; const sanitizedWaypoints = validWaypoints ? JSON.stringify(sanitizeRecentWaypoints(validWaypoints)) : undefined; - // Omit allTransactionDrafts from retryParams so getReceiptError's JSON.stringify doesn't store - // the full draft collection in Onyx, which would bloat errors and cause nested payload ballooning on retries. - const paramsWithoutDrafts = {...params, allTransactionDrafts: undefined}; const retryParams: CreateTrackExpenseParams = { - ...paramsWithoutDrafts, + ...params, report, isDraftPolicy, action, From 0e4bdbceccc0690a50a967c7a2624346f4b19bc5 Mon Sep 17 00:00:00 2001 From: dukenv0307 Date: Thu, 5 Mar 2026 18:20:26 +0700 Subject: [PATCH 07/12] update test --- src/libs/actions/IOU/index.ts | 22 ++++++++++++++++++++++ tests/actions/IOU/MoneyRequestTest.ts | 23 +++++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/src/libs/actions/IOU/index.ts b/src/libs/actions/IOU/index.ts index 3e631deadd690..933142941fef6 100644 --- a/src/libs/actions/IOU/index.ts +++ b/src/libs/actions/IOU/index.ts @@ -1904,6 +1904,7 @@ function buildOnyxDataForTestDriveIOU( transactionID: testDriveIOUParams.transaction.transactionID, reportActionID: testDriveIOUParams.iouOptimisticParams.action.reportActionID, }); + // eslint-disable-next-line @typescript-eslint/no-deprecated const text = Localize.translateLocal('testDrive.employeeInviteMessage', personalDetailsList?.[userAccountID]?.firstName ?? ''); const textComment = buildOptimisticAddCommentReportAction(text, undefined, userAccountID, undefined, undefined, testDriveIOUParams.testDriveCommentReportActionID); textComment.reportAction.created = DateUtils.subtractMillisecondsFromDateTime(testDriveIOUParams.iouOptimisticParams.createdAction.created, 1); @@ -2593,6 +2594,7 @@ function buildOnyxDataForMoneyRequest(moneyRequestParams: BuildOnyxDataForMoneyR key: `${ONYXKEYS.COLLECTION.NEXT_STEP}${iou.report.reportID}`, onyxMethod: Onyx.METHOD.SET, // buildOptimisticNextStep is used in parallel + // eslint-disable-next-line @typescript-eslint/no-deprecated value: buildNextStepNew({ report: iou.report, predictedNextStatus: iou.report.statusNum ?? CONST.REPORT.STATE_NUM.OPEN, @@ -3647,6 +3649,7 @@ function getMoneyRequestInformation(moneyRequestInformation: MoneyRequestInforma iouReport.statusNum ?? (policy?.reimbursementChoice === CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_NO ? CONST.REPORT.STATUS_NUM.CLOSED : CONST.REPORT.STATUS_NUM.OPEN); const hasViolations = hasViolationsReportUtils(iouReport.reportID, transactionViolations, currentUserAccountIDParam, currentUserEmailParam); // buildOptimisticNextStep is used in parallel + // eslint-disable-next-line @typescript-eslint/no-deprecated const optimisticNextStepDeprecated = buildNextStepNew({ report: iouReport, predictedNextStatus, @@ -3981,6 +3984,7 @@ function getPerDiemExpenseInformation(perDiemExpenseInformation: PerDiemExpenseI const predictedNextStatus = iouReport.statusNum ?? (policy?.reimbursementChoice === CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_NO ? CONST.REPORT.STATUS_NUM.CLOSED : CONST.REPORT.STATUS_NUM.OPEN); // buildOptimisticNextStep is used in parallel + // eslint-disable-next-line @typescript-eslint/no-deprecated const optimisticNextStepDeprecated = buildNextStepNew({ report: iouReport, predictedNextStatus, @@ -4991,6 +4995,7 @@ function getUpdateMoneyRequestParams(params: GetUpdateMoneyRequestParamsType): U onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.NEXT_STEP}${iouReport?.reportID}`, // buildOptimisticNextStep is used in parallel + // eslint-disable-next-line @typescript-eslint/no-deprecated value: buildNextStepNew({ report: moneyRequestReport, predictedNextStatus: iouReport?.statusNum ?? CONST.REPORT.STATUS_NUM.OPEN, @@ -6819,6 +6824,7 @@ function requestMoney(requestMoneyInformation: RequestMoneyInformation): {iouRep } if (shouldHandleNavigation) { + // eslint-disable-next-line @typescript-eslint/no-deprecated InteractionManager.runAfterInteractions(() => removeDraftTransactionsByIDs(draftTransactionIDs)); const trackReport = Navigation.getReportRouteByID(linkedTrackedExpenseReportAction?.childReportID); @@ -6955,6 +6961,7 @@ function submitPerDiemExpense(submitPerDiemExpenseInformation: PerDiemExpenseInf playSound(SOUNDS.DONE); API.write(WRITE_COMMANDS.CREATE_PER_DIEM_REQUEST, parameters, onyxData); + // eslint-disable-next-line @typescript-eslint/no-deprecated InteractionManager.runAfterInteractions(() => removeDraftTransaction(CONST.IOU.OPTIMISTIC_TRANSACTION_ID)); handleNavigateAfterExpenseCreate({activeReportID, transactionID: transaction.transactionID, isFromGlobalCreate, shouldHandleNavigation}); @@ -7354,6 +7361,7 @@ function submitPerDiemExpenseForSelfDM(submitPerDiemExpenseInformation: PerDiemE playSound(SOUNDS.DONE); API.write(WRITE_COMMANDS.CREATE_PER_DIEM_REQUEST, parameters, onyxData); + // eslint-disable-next-line @typescript-eslint/no-deprecated InteractionManager.runAfterInteractions(() => removeDraftTransaction(CONST.IOU.OPTIMISTIC_TRANSACTION_ID)); dismissModalAndOpenReportInInboxTab(chatReport.reportID); @@ -7823,6 +7831,7 @@ function createSplitsAndOnyxData({ reportID: CONST.REPORT.SPLIT_REPORT_ID, comment, created, + // eslint-disable-next-line @typescript-eslint/no-deprecated merchant: merchant || Localize.translateLocal('iou.expense'), receipt, category, @@ -8127,6 +8136,7 @@ function createSplitsAndOnyxData({ reportID: oneOnOneIOUReport.reportID, comment, created, + // eslint-disable-next-line @typescript-eslint/no-deprecated merchant: merchant || Localize.translateLocal('iou.expense'), category, tag, @@ -8544,6 +8554,7 @@ function createDistanceRequest(distanceRequestInformation: CreateDistanceRequest playSound(SOUNDS.DONE); API.write(WRITE_COMMANDS.CREATE_DISTANCE_REQUEST, parameters, onyxData); + // eslint-disable-next-line @typescript-eslint/no-deprecated InteractionManager.runAfterInteractions(() => removeDraftTransaction(CONST.IOU.OPTIMISTIC_TRANSACTION_ID)); const activeReportID = isMoneyRequestReport && report?.reportID ? report.reportID : parameters.chatReportID; @@ -8779,6 +8790,7 @@ function prepareToCleanUpMoneyRequest( } const hasNonReimbursableTransactions = hasNonReimbursableTransactionsReportUtils(iouReport?.reportID); + // eslint-disable-next-line @typescript-eslint/no-deprecated const messageText = Localize.translateLocal( hasNonReimbursableTransactions ? 'iou.payerSpentAmount' : 'iou.payerOwesAmount', convertToDisplayString(updatedIOUReport?.total, updatedIOUReport?.currency), @@ -9065,6 +9077,7 @@ function cleanUpMoneyRequest( // First, update the reportActions to ensure related actions are not displayed. Onyx.update(reportActionsOnyxUpdates).then(() => { Navigation.goBack(urlToNavigateBack); + // eslint-disable-next-line @typescript-eslint/no-deprecated InteractionManager.runAfterInteractions(() => { if (shouldDeleteIOUReport) { clearAllRelatedReportActionErrors(reportID, reportAction, originalReportID); @@ -10135,6 +10148,7 @@ function getPayMoneyRequestParams({ if (!isInvoiceReport) { currentNextStepDeprecated = iouReportCurrentNextStepDeprecated ?? null; // buildOptimisticNextStep is used in parallel + // eslint-disable-next-line @typescript-eslint/no-deprecated optimisticNextStepDeprecated = buildNextStepNew({report: iouReport, predictedNextStatus: CONST.REPORT.STATUS_NUM.REIMBURSED}); optimisticNextStep = buildOptimisticNextStep({report: iouReport, predictedNextStatus: CONST.REPORT.STATUS_NUM.REIMBURSED}); } @@ -10937,6 +10951,7 @@ function reopenReport( const predictedNextStatus = CONST.REPORT.STATUS_NUM.OPEN; // buildOptimisticNextStep is used in parallel + // eslint-disable-next-line @typescript-eslint/no-deprecated const optimisticNextStepDeprecated = buildNextStepNew({ report: expenseReport, predictedNextStatus: CONST.REPORT.STATUS_NUM.OPEN, @@ -11119,6 +11134,7 @@ function retractReport( const predictedNextStatus = CONST.REPORT.STATUS_NUM.OPEN; // buildOptimisticNextStep is used in parallel + // eslint-disable-next-line @typescript-eslint/no-deprecated const optimisticNextStepDeprecated = buildNextStepNew({ report: expenseReport, predictedNextStatus: CONST.REPORT.STATUS_NUM.OPEN, @@ -11289,6 +11305,7 @@ function unapproveExpenseReport( const optimisticUnapprovedReportAction = buildOptimisticUnapprovedReportAction(expenseReport.total ?? 0, expenseReport.currency ?? '', expenseReport.reportID); // buildOptimisticNextStep is used in parallel + // eslint-disable-next-line @typescript-eslint/no-deprecated const optimisticNextStepDeprecated = buildNextStepNew({ report: expenseReport, predictedNextStatus: CONST.REPORT.STATUS_NUM.SUBMITTED, @@ -11469,6 +11486,7 @@ function submitReport( const shouldAddOptimisticSubmitAction = !isDEWPolicy || isOffline(); // buildOptimisticNextStep is used in parallel + // eslint-disable-next-line @typescript-eslint/no-deprecated const optimisticNextStepDeprecated = isDEWPolicy ? null : buildNextStepNew({ @@ -11731,6 +11749,7 @@ function cancelPayment( const statusNum: ValueOf = approvalMode === CONST.POLICY.APPROVAL_MODE.OPTIONAL ? CONST.REPORT.STATUS_NUM.CLOSED : CONST.REPORT.STATUS_NUM.APPROVED; // buildOptimisticNextStep is used in parallel + // eslint-disable-next-line @typescript-eslint/no-deprecated const optimisticNextStepDeprecated = buildNextStepNew({ report: expenseReport, predictedNextStatus: statusNum, @@ -11893,6 +11912,7 @@ function cancelPayment( onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.NEXT_STEP}${expenseReport.reportID}`, // buildOptimisticNextStep is used in parallel + // eslint-disable-next-line @typescript-eslint/no-deprecated value: buildNextStepNew({ report: expenseReport, predictedNextStatus: CONST.REPORT.STATUS_NUM.REIMBURSED, @@ -13576,6 +13596,7 @@ function assignReportToMe( const takeControlReportAction = buildOptimisticChangeApproverReportAction(accountID, accountID); // buildOptimisticNextStep is used in parallel + // eslint-disable-next-line @typescript-eslint/no-deprecated const optimisticNextStepDeprecated = buildNextStepNew({ report: {...report, managerID: accountID}, predictedNextStatus: report.statusNum ?? CONST.REPORT.STATUS_NUM.SUBMITTED, @@ -13691,6 +13712,7 @@ function addReportApprover( const takeControlReportAction = buildOptimisticChangeApproverReportAction(newApproverAccountID, accountID); // buildOptimisticNextStep is used in parallel + // eslint-disable-next-line @typescript-eslint/no-deprecated const optimisticNextStepDeprecated = buildNextStepNew({ report: {...report, managerID: newApproverAccountID}, predictedNextStatus: report.statusNum ?? CONST.REPORT.STATUS_NUM.SUBMITTED, diff --git a/tests/actions/IOU/MoneyRequestTest.ts b/tests/actions/IOU/MoneyRequestTest.ts index 6740c9daa84ce..800f7a974778d 100644 --- a/tests/actions/IOU/MoneyRequestTest.ts +++ b/tests/actions/IOU/MoneyRequestTest.ts @@ -293,6 +293,19 @@ describe('MoneyRequest', () => { ); }); + it('should default draftTransactionIDs to empty array when allTransactionDrafts is undefined', () => { + createTransaction({ + ...baseParams, + allTransactionDrafts: undefined, + }); + + expect(IOU.requestMoney).toHaveBeenCalledWith( + expect.objectContaining({ + draftTransactionIDs: [], + }), + ); + }); + it('should pass billable and reimbursable flags to trackExpense', () => { createTransaction({ ...baseParams, @@ -894,6 +907,16 @@ describe('MoneyRequest', () => { expect(Navigation.goBack).toHaveBeenCalledWith(backTo); }); + it('should default draftTransactionIDs to empty array when undefined is passed', () => { + handleMoneyRequestStepDistanceNavigation({ + ...baseParams, + backTo, + draftTransactionIDs: undefined, + }); + + expect(Navigation.goBack).toHaveBeenCalledWith(backTo); + }); + it('should call resetSplitShares when splitShares exists for transaction and not from manual distance step', () => { const splitTransaction = { ...fakeTransaction, From 8abcb6d94fb0f917fd1d4de6f6e676557c83838d Mon Sep 17 00:00:00 2001 From: dukenv0307 Date: Thu, 5 Mar 2026 18:53:12 +0700 Subject: [PATCH 08/12] add tests --- src/libs/actions/IOU/index.ts | 11 +- tests/ui/IOURequestStepDistanceTest.tsx | 282 ++++++++++++++++++++++++ 2 files changed, 291 insertions(+), 2 deletions(-) create mode 100644 tests/ui/IOURequestStepDistanceTest.tsx diff --git a/src/libs/actions/IOU/index.ts b/src/libs/actions/IOU/index.ts index 933142941fef6..dd519ba4afe3b 100644 --- a/src/libs/actions/IOU/index.ts +++ b/src/libs/actions/IOU/index.ts @@ -3554,6 +3554,7 @@ function getMoneyRequestInformation(moneyRequestInformation: MoneyRequestInforma const optimisticPolicyRecentlyUsedCategories = mergePolicyRecentlyUsedCategories(category, policyRecentlyUsedCategories); const optimisticPolicyRecentlyUsedTags = buildOptimisticPolicyRecentlyUsedTags({ // TODO: Replace getPolicyTagsData (https://github.com/Expensify/App/issues/72721) and getPolicyRecentlyUsedTagsData (https://github.com/Expensify/App/issues/71491) with useOnyx hook + // eslint-disable-next-line @typescript-eslint/no-deprecated policyTags: getPolicyTagsData(iouReport.policyID), policyRecentlyUsedTags, transactionTags: tag, @@ -3927,6 +3928,7 @@ function getPerDiemExpenseInformation(perDiemExpenseInformation: PerDiemExpenseI const optimisticPolicyRecentlyUsedCategories = mergePolicyRecentlyUsedCategories(category, policyRecentlyUsedCategories); const optimisticPolicyRecentlyUsedTags = buildOptimisticPolicyRecentlyUsedTags({ // TODO: Replace getPolicyTagsData (https://github.com/Expensify/App/issues/72721) and getPolicyRecentlyUsedTagsData (https://github.com/Expensify/App/issues/71491) with useOnyx hook + // eslint-disable-next-line @typescript-eslint/no-deprecated policyTags: getPolicyTagsData(iouReport.policyID), policyRecentlyUsedTags, transactionTags: tag, @@ -4815,6 +4817,7 @@ function getUpdateMoneyRequestParams(params: GetUpdateMoneyRequestParamsType): U if (hasModifiedTag) { const optimisticPolicyRecentlyUsedTags = buildOptimisticPolicyRecentlyUsedTags({ // TODO: Replace getPolicyTagsData (https://github.com/Expensify/App/issues/72721) and getPolicyRecentlyUsedTagsData (https://github.com/Expensify/App/issues/71491) with useOnyx hook + // eslint-disable-next-line @typescript-eslint/no-deprecated policyTags: getPolicyTagsData(iouReport?.policyID), policyRecentlyUsedTags, transactionTags: transactionChanges.tag, @@ -8203,6 +8206,7 @@ function createSplitsAndOnyxData({ const optimisticPolicyRecentlyUsedTags = isPolicyExpenseChat ? buildOptimisticPolicyRecentlyUsedTags({ // TODO: Replace getPolicyTagsData (https://github.com/Expensify/App/issues/72721) and getPolicyRecentlyUsedTagsData (https://github.com/Expensify/App/issues/71491) with useOnyx hook + // eslint-disable-next-line @typescript-eslint/no-deprecated policyTags: getPolicyTagsData(participant.policyID), policyRecentlyUsedTags, transactionTags: tag, @@ -10546,6 +10550,7 @@ function getIOUReportActionToApproveOrPay( } const iouReport = updatedIouReport?.reportID === action.childReportID ? updatedIouReport : getReportOrDraftReport(action.childReportID); // This will be fixed as part of https://github.com/Expensify/Expensify/issues/507850 + // eslint-disable-next-line @typescript-eslint/no-deprecated const policy = getPolicy(iouReport?.policyID); // Only show to the actual payer, exclude admins with bank account access const shouldShowSettlementButton = @@ -11486,10 +11491,10 @@ function submitReport( const shouldAddOptimisticSubmitAction = !isDEWPolicy || isOffline(); // buildOptimisticNextStep is used in parallel - // eslint-disable-next-line @typescript-eslint/no-deprecated const optimisticNextStepDeprecated = isDEWPolicy ? null - : buildNextStepNew({ + : // eslint-disable-next-line @typescript-eslint/no-deprecated + buildNextStepNew({ report: expenseReport, predictedNextStatus: isSubmitAndClosePolicy ? CONST.REPORT.STATUS_NUM.CLOSED : CONST.REPORT.STATUS_NUM.SUBMITTED, policy, @@ -12169,6 +12174,7 @@ function detachReceipt(transactionID: string | undefined, transactionPolicy: Ony if (transactionPolicy && isPaidGroupPolicy(transactionPolicy) && newTransaction) { // TODO: Replace getPolicyTagsData (https://github.com/Expensify/App/issues/72721) and getPolicyRecentlyUsedTagsData (https://github.com/Expensify/App/issues/71491) with useOnyx hook + // eslint-disable-next-line @typescript-eslint/no-deprecated const policyTagList = getPolicyTagsData(transactionPolicy.id); const currentTransactionViolations = allTransactionViolations[`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${transactionID}`] ?? []; const violationsOnyxData = ViolationsUtils.getViolationsOnyxData( @@ -12295,6 +12301,7 @@ function replaceReceipt({transactionID, file, source, state, transactionPolicy, if (transactionPolicy && isPaidGroupPolicy(transactionPolicy) && newTransaction) { // TODO: Replace getPolicyTagsData (https://github.com/Expensify/App/issues/72721) and getPolicyRecentlyUsedTagsData (https://github.com/Expensify/App/issues/71491) with useOnyx hook + // eslint-disable-next-line @typescript-eslint/no-deprecated const policyTagList = getPolicyTagsData(transactionPolicy.id); const currentTransactionViolations = allTransactionViolations[`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${transactionID}`] ?? []; const violationsOnyxData = ViolationsUtils.getViolationsOnyxData( diff --git a/tests/ui/IOURequestStepDistanceTest.tsx b/tests/ui/IOURequestStepDistanceTest.tsx new file mode 100644 index 0000000000000..930dcebdd1c4b --- /dev/null +++ b/tests/ui/IOURequestStepDistanceTest.tsx @@ -0,0 +1,282 @@ +/* eslint-disable @typescript-eslint/no-unsafe-assignment */ +/* eslint-disable @typescript-eslint/no-unsafe-member-access */ +/* eslint-disable @typescript-eslint/no-unsafe-call */ +/* eslint-disable @typescript-eslint/no-unsafe-return */ +import {act, render, screen} from '@testing-library/react-native'; +import React from 'react'; +import Onyx from 'react-native-onyx'; +import {CurrentUserPersonalDetailsProvider} from '@components/CurrentUserPersonalDetailsProvider'; +import OnyxListItemProvider from '@components/OnyxListItemProvider'; +import IOURequestStepDistance from '@pages/iou/request/step/IOURequestStepDistance'; +import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import SCREENS from '@src/SCREENS'; +import type {Report, Transaction} from '@src/types/onyx'; +import * as IOU from '../../src/libs/actions/IOU'; +import createRandomTransaction from '../utils/collections/transaction'; +import {signInWithTestUser} from '../utils/TestHelper'; +import waitForBatchedUpdates from '../utils/waitForBatchedUpdates'; +import waitForBatchedUpdatesWithAct from '../utils/waitForBatchedUpdatesWithAct'; + +jest.mock('@rnmapbox/maps', () => ({ + default: jest.fn(), + MarkerView: jest.fn(), + setAccessToken: jest.fn(), +})); + +jest.mock('@components/LocaleContextProvider', () => { + const React2 = require('react'); + + const defaultContextValue = { + translate: (path: string) => path, + numberFormat: (number: number) => String(number), + getLocalDateFromDatetime: () => new Date(), + datetimeToRelative: () => '', + datetimeToCalendarTime: () => '', + formatPhoneNumber: (phone: string) => phone, + toLocaleDigit: (digit: string) => digit, + toLocaleOrdinal: (number: number) => String(number), + fromLocaleDigit: (localeDigit: string) => localeDigit, + localeCompare: (a: string, b: string) => a.localeCompare(b), + formatTravelDate: () => '', + preferredLocale: 'en', + }; + + const LocaleContext = React2.createContext(defaultContextValue); + + return { + LocaleContext, + LocaleContextProvider: ({children}: {children: React.ReactNode}) => React2.createElement(LocaleContext.Provider, {value: defaultContextValue}, children), + }; +}); + +jest.mock('@libs/actions/IOU', () => { + const actual = jest.requireActual('@libs/actions/IOU'); + return { + ...actual, + requestMoney: jest.fn(() => ({iouReport: undefined})), + trackExpense: jest.fn(), + createDistanceRequest: jest.fn(), + }; +}); + +jest.mock('@libs/actions/IOU/MoneyRequest', () => ({ + handleMoneyRequestStepDistanceNavigation: jest.fn(), +})); + +jest.mock('@libs/actions/MapboxToken', () => ({ + init: jest.fn(), + stop: jest.fn(), +})); + +jest.mock('@libs/actions/Transaction', () => ({ + openDraftDistanceExpense: jest.fn(), + removeWaypoint: jest.fn(() => Promise.resolve()), + updateWaypoints: jest.fn(() => Promise.resolve()), + getRoute: jest.fn(), +})); + +jest.mock('@libs/actions/TransactionEdit', () => ({ + createBackupTransaction: jest.fn(), + removeBackupTransaction: jest.fn(), + restoreOriginalTransactionFromBackup: jest.fn(), +})); + +jest.mock('@components/ProductTrainingContext', () => ({ + useProductTrainingContext: () => [false], +})); +jest.mock('@src/hooks/useResponsiveLayout'); + +jest.mock('@libs/Navigation/navigationRef', () => ({ + getCurrentRoute: jest.fn(() => ({ + name: 'Money_Request_Step_Distance', + params: {}, + })), + getState: jest.fn(() => ({})), +})); + +jest.mock('@libs/Navigation/Navigation', () => { + const mockRef = { + getCurrentRoute: jest.fn(() => ({ + name: 'Money_Request_Step_Distance', + params: {}, + })), + getState: jest.fn(() => ({})), + }; + return { + navigate: jest.fn(), + goBack: jest.fn(), + dismissModalWithReport: jest.fn(), + navigationRef: mockRef, + setNavigationActionToMicrotaskQueue: jest.fn((callback: () => void) => callback()), + getReportRouteByID: jest.fn(() => undefined), + removeScreenByKey: jest.fn(), + getActiveRouteWithoutParams: jest.fn(() => ''), + getActiveRoute: jest.fn(() => ''), + }; +}); + +jest.mock('@react-navigation/native', () => { + const mockRef = { + getCurrentRoute: jest.fn(() => ({ + name: 'Money_Request_Step_Distance', + params: {}, + })), + getState: jest.fn(() => ({})), + }; + return { + createNavigationContainerRef: jest.fn(() => mockRef), + useIsFocused: () => true, + useNavigation: () => ({navigate: jest.fn(), addListener: jest.fn()}), + useFocusEffect: jest.fn(), + usePreventRemove: jest.fn(), + useRoute: jest.fn(), + }; +}); + +// Mock DistanceRequestFooter to avoid Mapbox rendering issues +jest.mock('@components/DistanceRequest/DistanceRequestFooter', () => { + return () => null; +}); + +jest.mock('@hooks/useScreenWrapperTransitionStatus', () => ({ + __esModule: true, + default: () => ({didScreenTransitionEnd: true}), +})); + +const ACCOUNT_ID = 1; +const ACCOUNT_LOGIN = 'test@user.com'; +const REPORT_ID = 'report-1'; +const TRANSACTION_ID = 'txn-1'; +const PARTICIPANT_ACCOUNT_ID = 2; + +function createTestReport(): Report { + return { + reportID: REPORT_ID, + chatType: CONST.REPORT.CHAT_TYPE.DOMAIN_ALL, + ownerAccountID: ACCOUNT_ID, + stateNum: CONST.REPORT.STATE_NUM.OPEN, + statusNum: CONST.REPORT.STATUS_NUM.OPEN, + isPinned: false, + lastVisibleActionCreated: '', + lastReadTime: '', + participants: { + [ACCOUNT_ID]: {notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS, role: CONST.REPORT.ROLE.MEMBER}, + [PARTICIPANT_ACCOUNT_ID]: {notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS, role: CONST.REPORT.ROLE.MEMBER}, + }, + }; +} + +function createDistanceTransaction(): Transaction { + const transaction = createRandomTransaction(1); + return { + ...transaction, + transactionID: TRANSACTION_ID, + reportID: REPORT_ID, + iouRequestType: CONST.IOU.REQUEST_TYPE.DISTANCE, + comment: { + ...transaction.comment, + waypoints: { + waypoint0: {address: '123 Main St', lat: 40.7128, lng: -74.006, keyForList: 'start_waypoint'}, + waypoint1: {address: '456 Oak Ave', lat: 40.7589, lng: -73.9851, keyForList: 'stop_waypoint'}, + }, + }, + }; +} + +describe('IOURequestStepDistance - draft transactions coverage', () => { + beforeAll(() => { + Onyx.init({ + keys: ONYXKEYS, + evictableKeys: [ONYXKEYS.COLLECTION.REPORT_ACTIONS], + }); + }); + + beforeEach(async () => { + jest.clearAllMocks(); + await Onyx.clear(); + await waitForBatchedUpdates(); + }); + + it('should render and read draftTransactionIDs from Onyx', async () => { + await signInWithTestUser(ACCOUNT_ID, ACCOUNT_LOGIN); + + const transaction = createDistanceTransaction(); + const report = createTestReport(); + + await act(async () => { + await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${REPORT_ID}`, report); + await Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${TRANSACTION_ID}`, transaction); + }); + + render( + + + + + , + ); + + await waitForBatchedUpdatesWithAct(); + + // Component rendered successfully with draftTransactionIDs loaded from Onyx + // When isCreatingNewRequest is true, StepScreenWrapper doesn't use ScreenWrapper so testID isn't set + // Verify component rendered by checking for waypoint content + expect(screen.getByAccessibilityHint(/123 Main St/)).toBeTruthy(); + }); + + it('should render with multiple draft transactions in Onyx', async () => { + await signInWithTestUser(ACCOUNT_ID, ACCOUNT_LOGIN); + + const transaction = createDistanceTransaction(); + const draftTransaction2 = createRandomTransaction(2); + const report = createTestReport(); + + await act(async () => { + await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${REPORT_ID}`, report); + await Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${TRANSACTION_ID}`, transaction); + await Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${draftTransaction2.transactionID}`, draftTransaction2); + }); + + render( + + + + + , + ); + + await waitForBatchedUpdatesWithAct(); + + // Component rendered with multiple draft transaction IDs available + expect(screen.getByAccessibilityHint(/123 Main St/)).toBeTruthy(); + }); +}); From a1b94a59f769f92988edc45ff7132f16251d2468 Mon Sep 17 00:00:00 2001 From: dukenv0307 Date: Thu, 5 Mar 2026 19:02:30 +0700 Subject: [PATCH 09/12] lint fix --- tests/ui/IOURequestStepDistanceTest.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/ui/IOURequestStepDistanceTest.tsx b/tests/ui/IOURequestStepDistanceTest.tsx index 930dcebdd1c4b..bc3228e5e0500 100644 --- a/tests/ui/IOURequestStepDistanceTest.tsx +++ b/tests/ui/IOURequestStepDistanceTest.tsx @@ -12,7 +12,7 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import SCREENS from '@src/SCREENS'; import type {Report, Transaction} from '@src/types/onyx'; -import * as IOU from '../../src/libs/actions/IOU'; +import type * as IOU from '../../src/libs/actions/IOU'; import createRandomTransaction from '../utils/collections/transaction'; import {signInWithTestUser} from '../utils/TestHelper'; import waitForBatchedUpdates from '../utils/waitForBatchedUpdates'; @@ -140,6 +140,7 @@ jest.mock('@components/DistanceRequest/DistanceRequestFooter', () => { }); jest.mock('@hooks/useScreenWrapperTransitionStatus', () => ({ + // eslint-disable-next-line @typescript-eslint/naming-convention __esModule: true, default: () => ({didScreenTransitionEnd: true}), })); From f1d635d134b3aa5f3728de7dfba9ae6e85bf2800 Mon Sep 17 00:00:00 2001 From: dukenv0307 Date: Fri, 6 Mar 2026 09:12:35 +0700 Subject: [PATCH 10/12] update test --- tests/actions/IOU/MoneyRequestTest.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/actions/IOU/MoneyRequestTest.ts b/tests/actions/IOU/MoneyRequestTest.ts index 5fba89403e00a..a9c2b03de9720 100644 --- a/tests/actions/IOU/MoneyRequestTest.ts +++ b/tests/actions/IOU/MoneyRequestTest.ts @@ -884,6 +884,7 @@ describe('MoneyRequest', () => { betas: [CONST.BETAS.ALL], recentWaypoints: [] as RecentWaypoint[], amountOwed: 0, + draftTransactionIDs: undefined, }; const splitShares: SplitShares = { [firstSplitParticipantID]: { From 60f348f8b316adfbce9df0f7610c1a61e002e9b3 Mon Sep 17 00:00:00 2001 From: dukenv0307 Date: Mon, 9 Mar 2026 22:38:55 +0700 Subject: [PATCH 11/12] update lint --- src/pages/workspace/accounting/AccountingContext/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/workspace/accounting/AccountingContext/index.tsx b/src/pages/workspace/accounting/AccountingContext/index.tsx index c4e2c43bb29f9..a02fd0b38a0c8 100644 --- a/src/pages/workspace/accounting/AccountingContext/index.tsx +++ b/src/pages/workspace/accounting/AccountingContext/index.tsx @@ -8,10 +8,10 @@ import useLocalize from '@hooks/useLocalize'; import {removePolicyConnection} from '@libs/actions/connections'; import Navigation from '@libs/Navigation/Navigation'; import {isControlPolicy} from '@libs/PolicyUtils'; +import {getAccountingIntegrationData} from '@pages/workspace/accounting/utils'; import ROUTES from '@src/ROUTES'; import type Policy from '@src/types/onyx/Policy'; import type ChildrenProps from '@src/types/utils/ChildrenProps'; -import {getAccountingIntegrationData} from '../utils'; import {defaultAccountingActionsContextValue, defaultAccountingStateContextValue, popoverAnchorRefsInitialValue} from './default'; import type {AccountingActionsContextType, AccountingStateContextType, ActiveIntegration, ActiveIntegrationState} from './types'; From f48c5fb3ac1b3947bed51d7ad33e52da42c40168 Mon Sep 17 00:00:00 2001 From: dukenv0307 Date: Wed, 11 Mar 2026 23:25:42 +0700 Subject: [PATCH 12/12] update test --- tests/actions/IOU/MoneyRequestTest.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/actions/IOU/MoneyRequestTest.ts b/tests/actions/IOU/MoneyRequestTest.ts index 50ad7795b21d3..4820916ad172e 100644 --- a/tests/actions/IOU/MoneyRequestTest.ts +++ b/tests/actions/IOU/MoneyRequestTest.ts @@ -1007,15 +1007,11 @@ describe('MoneyRequest', () => { gpsCoordinates: undefined, odometerEnd: undefined, odometerStart: undefined, - odometerStart: undefined, - odometerEnd: undefined, }, isASAPSubmitBetaEnabled: baseParams.isASAPSubmitBetaEnabled, currentUserAccountIDParam: baseParams.currentUserAccountID, currentUserEmailParam: baseParams.currentUserLogin, quickAction: baseParams.quickAction, - activePolicyID: undefined, - introSelected: undefined, recentWaypoints: baseParams.recentWaypoints, betas: [CONST.BETAS.ALL], draftTransactionIDs: [baseParams.transactionID],