Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions src/components/MoneyReportHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import {isUserValidatedSelector} from '@selectors/Account';
import {hasSeenTourSelector} from '@selectors/Onboarding';
import {getArchiveReason} from '@selectors/Report';
import {validTransactionDraftsSelector} from '@selectors/TransactionDraft';
import React, {useCallback, useContext, useEffect, useMemo, useRef, useState} from 'react';
import {InteractionManager, View} from 'react-native';
import type {OnyxEntry} from 'react-native-onyx';
Expand Down Expand Up @@ -45,6 +46,7 @@
import {isPersonalCard} from '@libs/CardUtils';
import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
import getPlatform from '@libs/getPlatform';
import {getExistingTransactionID} from '@libs/IOUUtils';
import Log from '@libs/Log';
import {getThreadReportIDsForTransactions, getTotalAmountForIOUReportPreviewButton} from '@libs/MoneyRequestReportUtils';
import Navigation from '@libs/Navigation/Navigation';
Expand Down Expand Up @@ -269,6 +271,9 @@
] as const);
const [lastDistanceExpenseType] = useOnyx(ONYXKEYS.NVP_LAST_DISTANCE_EXPENSE_TYPE);
const [reportMetadata] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_METADATA}${moneyRequestReport?.reportID}`);
const [transactionDrafts] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_DRAFT, {selector: validTransactionDraftsSelector});
const draftTransactionIDs = Object.keys(transactionDrafts ?? {});

const {translate, localeCompare} = useLocalize();
const encryptedAuthToken = session?.encryptedAuthToken ?? '';

Expand Down Expand Up @@ -707,6 +712,9 @@
const activePolicyCategories = allPolicyCategories?.[`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${defaultExpensePolicy?.id}`] ?? {};

for (const item of transactionList) {
const existingTransactionID = getExistingTransactionID(item.linkedTrackedExpenseReportAction);
const existingTransactionDraft = existingTransactionID ? transactionDrafts?.[existingTransactionID] : undefined;

duplicateTransactionAction({
transaction: item,
optimisticChatReportID,
Expand All @@ -721,6 +729,8 @@
targetPolicy: defaultExpensePolicy ?? undefined,
targetPolicyCategories: activePolicyCategories,
targetReport: activePolicyExpenseChat,
existingTransactionDraft,
draftTransactionIDs,
betas,
personalDetails,
recentWaypoints,
Expand All @@ -731,7 +741,9 @@
activePolicyExpenseChat,
activePolicyID,
allPolicyCategories,
transactionDrafts,
defaultExpensePolicy,
draftTransactionIDs,
introSelected,
isASAPSubmitBetaEnabled,
quickAction,
Expand Down Expand Up @@ -1764,7 +1776,7 @@
}
return option;
});
}, [originalSelectedTransactionsOptions, showDeleteModal, dismissedRejectUseExplanation]);

Check warning on line 1779 in src/components/MoneyReportHeader.tsx

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

React Hook useMemo has missing dependencies: 'isDelegateAccessRestricted' and 'showDelegateNoAccessModal'. Either include them or remove the dependency array

Check warning on line 1779 in src/components/MoneyReportHeader.tsx

View workflow job for this annotation

GitHub Actions / ESLint check

React Hook useMemo has missing dependencies: 'isDelegateAccessRestricted' and 'showDelegateNoAccessModal'. Either include them or remove the dependency array

const shouldShowSelectedTransactionsButton = !!selectedTransactionsOptions.length && !transactionThreadReportID;

Expand Down
12 changes: 12 additions & 0 deletions src/components/MoneyRequestHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {useRoute} from '@react-navigation/native';
import {hasSeenTourSelector} from '@selectors/Onboarding';
import {validTransactionDraftsSelector} from '@selectors/TransactionDraft';
import type {ReactNode} from 'react';
import React, {useCallback, useMemo, useState} from 'react';
import {View} from 'react-native';
Expand Down Expand Up @@ -29,6 +30,7 @@ import initSplitExpense from '@libs/actions/SplitExpenses';
import {setNameValuePair} from '@libs/actions/User';
import {isPersonalCard} from '@libs/CardUtils';
import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
import {getExistingTransactionID} from '@libs/IOUUtils';
import Navigation from '@libs/Navigation/Navigation';
import type {PlatformStackRouteProp} from '@libs/Navigation/PlatformStackNavigation/types';
import type {ReportsSplitNavigatorParamList, RightModalNavigatorParamList} from '@libs/Navigation/types';
Expand Down Expand Up @@ -163,6 +165,9 @@ function MoneyRequestHeader({report, parentReportAction, policy, onBackButtonPre
const {removeTransaction} = useSearchActionsContext();
const {isExpenseSplit} = getOriginalTransactionWithSplitInfo(transaction, originalTransaction);
const [cardList] = useOnyx(ONYXKEYS.CARD_LIST);
const [transactionDrafts] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_DRAFT, {selector: validTransactionDraftsSelector});
const draftTransactionIDs = Object.keys(transactionDrafts ?? {});

const {deleteTransactions} = useDeleteTransactions({report: parentReport, reportActions: parentReportAction ? [parentReportAction] : [], policy});
const {isBetaEnabled} = usePermissions();
const isASAPSubmitBetaEnabled = isBetaEnabled(CONST.BETAS.ASAP_SUBMIT);
Expand Down Expand Up @@ -209,6 +214,9 @@ function MoneyRequestHeader({report, parentReportAction, policy, onBackButtonPre
const activePolicyCategories = allPolicyCategories?.[`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${defaultExpensePolicy?.id}`] ?? {};

for (const item of transactions) {
const existingTransactionID = getExistingTransactionID(item.linkedTrackedExpenseReportAction);
const existingTransactionDraft = existingTransactionID ? transactionDrafts?.[existingTransactionID] : undefined;

duplicateTransactionAction({
transaction: item,
optimisticChatReportID,
Expand All @@ -223,6 +231,8 @@ function MoneyRequestHeader({report, parentReportAction, policy, onBackButtonPre
targetPolicy: defaultExpensePolicy ?? undefined,
targetPolicyCategories: activePolicyCategories,
targetReport: activePolicyExpenseChat,
existingTransactionDraft,
draftTransactionIDs,
betas,
personalDetails,
recentWaypoints,
Expand All @@ -232,7 +242,9 @@ function MoneyRequestHeader({report, parentReportAction, policy, onBackButtonPre
[
activePolicyExpenseChat,
allPolicyCategories,
transactionDrafts,
defaultExpensePolicy,
draftTransactionIDs,
isASAPSubmitBetaEnabled,
introSelected,
activePolicyID,
Expand Down
15 changes: 14 additions & 1 deletion src/libs/IOUUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ import type {ValueOf} from 'type-fest';
import type {IOUAction, IOUType} from '@src/CONST';
import CONST from '@src/CONST';
import ROUTES from '@src/ROUTES';
import type {OnyxInputOrEntry, PersonalDetails, Policy, Report} from '@src/types/onyx';
import type {OnyxInputOrEntry, PersonalDetails, Policy, Report, ReportAction} from '@src/types/onyx';
import type {Attendee, Participant} from '@src/types/onyx/IOU';
import SafeString from '@src/utils/SafeString';
import type {IOURequestType} from './actions/IOU';
import {getCurrencyUnit} from './CurrencyUtils';
import Navigation from './Navigation/Navigation';
import {isPaidGroupPolicy} from './PolicyUtils';
import {getOriginalMessage, isMoneyRequestAction} from './ReportActionsUtils';
import {getReportTransactions} from './ReportUtils';
import {getCurrency, getTagArrayFromName} from './TransactionUtils';

Expand Down Expand Up @@ -356,6 +357,17 @@ function navigateToConfirmationPage(
}
}

/**
* Get the existing transaction ID from a linked tracked expense report action.
* This is used when moving a transaction from track expense to submit.
*/
function getExistingTransactionID(linkedTrackedExpenseReportAction: ReportAction | undefined): string | undefined {
if (!linkedTrackedExpenseReportAction || !isMoneyRequestAction(linkedTrackedExpenseReportAction)) {
return undefined;
}
return getOriginalMessage(linkedTrackedExpenseReportAction)?.IOUTransactionID;
}

function calculateDefaultReimbursable({
iouType,
policy,
Expand All @@ -380,6 +392,7 @@ export {
calculateAmount,
calculateSplitAmountFromPercentage,
calculateSplitPercentagesFromAmounts,
getExistingTransactionID,
insertTagIntoTransactionTagsString,
isIOUReportPendingCurrencyConversion,
isMovingTransactionFromTrackExpense,
Expand Down
6 changes: 6 additions & 0 deletions src/libs/actions/IOU/Duplicate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,8 @@ type DuplicateExpenseTransactionParams = {
targetPolicy?: OnyxEntry<OnyxTypes.Policy>;
targetPolicyCategories?: OnyxEntry<OnyxTypes.PolicyCategories>;
targetReport?: OnyxTypes.Report;
existingTransactionDraft: OnyxEntry<OnyxTypes.Transaction>;
draftTransactionIDs: string[];
betas: OnyxEntry<OnyxTypes.Beta[]>;
personalDetails: OnyxEntry<OnyxTypes.PersonalDetailsList>;
recentWaypoints: OnyxEntry<OnyxTypes.RecentWaypoint[]>;
Expand All @@ -521,6 +523,8 @@ function duplicateExpenseTransaction({
targetPolicy,
targetPolicyCategories,
targetReport,
existingTransactionDraft,
draftTransactionIDs,
betas,
personalDetails,
recentWaypoints,
Expand Down Expand Up @@ -581,6 +585,8 @@ function duplicateExpenseTransaction({
transactionViolations: {},
policyRecentlyUsedCurrencies,
quickAction,
existingTransactionDraft,
draftTransactionIDs,
isSelfTourViewed,
betas,
personalDetails,
Expand Down
16 changes: 15 additions & 1 deletion src/libs/actions/IOU/MoneyRequest.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
import DistanceRequestUtils from '@libs/DistanceRequestUtils';
import getCurrentPosition from '@libs/getCurrentPosition';
import {calculateDefaultReimbursable, navigateToConfirmationPage, navigateToParticipantPage} from '@libs/IOUUtils';
import {calculateDefaultReimbursable, getExistingTransactionID, navigateToConfirmationPage, navigateToParticipantPage} from '@libs/IOUUtils';
import Log from '@libs/Log';
import Navigation from '@libs/Navigation/Navigation';
import {roundToTwoDecimalPlaces} from '@libs/NumberUtils';
Expand Down Expand Up @@ -58,6 +58,7 @@ type CreateTransactionParams = {
policyParams?: {policy: OnyxEntry<Policy>};
billable?: boolean;
reimbursable?: boolean;
allTransactionDrafts: OnyxCollection<Transaction>;
isSelfTourViewed: boolean;
betas: OnyxEntry<Beta[]>;
personalDetails: OnyxEntry<PersonalDetailsList>;
Expand Down Expand Up @@ -105,6 +106,7 @@ type MoneyRequestStepScanParticipantsFlowParams = {
shouldGenerateTransactionThreadReport: boolean;
selfDMReport: OnyxEntry<Report>;
isSelfTourViewed: boolean;
allTransactionDrafts: OnyxCollection<Transaction>;
betas: OnyxEntry<Beta[]>;
recentWaypoints: OnyxEntry<RecentWaypoint[]>;
};
Expand Down Expand Up @@ -172,11 +174,14 @@ function createTransaction({
policyParams,
billable,
reimbursable = true,
allTransactionDrafts,
isSelfTourViewed,
betas,
personalDetails,
recentWaypoints,
}: CreateTransactionParams) {
const draftTransactionIDs = Object.keys(allTransactionDrafts ?? {});

for (const [index, receiptFile] of files.entries()) {
const transaction = transactions.find((item) => item.transactionID === receiptFile.transactionID);
const receipt: Receipt = receiptFile.file ?? {};
Expand Down Expand Up @@ -212,6 +217,9 @@ function createTransaction({
betas,
});
} else {
const existingTransactionID = getExistingTransactionID(transaction?.linkedTrackedExpenseReportAction);
const existingTransactionDraft = existingTransactionID ? allTransactionDrafts?.[existingTransactionID] : undefined;

requestMoney({
report,
betas,
Expand Down Expand Up @@ -241,6 +249,8 @@ function createTransaction({
transactionViolations,
quickAction,
policyRecentlyUsedCurrencies: policyRecentlyUsedCurrencies ?? [],
existingTransactionDraft,
draftTransactionIDs,
isSelfTourViewed,
personalDetails,
});
Expand Down Expand Up @@ -296,6 +306,7 @@ function handleMoneyRequestStepScanParticipants({
locationPermissionGranted = false,
selfDMReport,
isSelfTourViewed,
allTransactionDrafts,
betas,
recentWaypoints,
}: MoneyRequestStepScanParticipantsFlowParams) {
Expand Down Expand Up @@ -399,6 +410,7 @@ function handleMoneyRequestStepScanParticipants({
billable: false,
reimbursable: defaultReimbursable,
isSelfTourViewed,
allTransactionDrafts,
betas,
personalDetails,
recentWaypoints,
Expand All @@ -425,6 +437,7 @@ function handleMoneyRequestStepScanParticipants({
participant,
reimbursable: defaultReimbursable,
isSelfTourViewed,
allTransactionDrafts,
betas,
personalDetails,
recentWaypoints,
Expand All @@ -451,6 +464,7 @@ function handleMoneyRequestStepScanParticipants({
participant,
reimbursable: defaultReimbursable,
isSelfTourViewed,
allTransactionDrafts,
betas,
personalDetails,
recentWaypoints,
Expand Down
18 changes: 8 additions & 10 deletions src/libs/actions/IOU/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@
import {buildInviteToRoomOnyxData, completeOnboarding, notifyNewAction, optimisticReportLastData} from '@userActions/Report';
import {clearAllRelatedReportActionErrors} from '@userActions/ReportActions';
import {mergeTransactionIdsHighlightOnSearchRoute, sanitizeRecentWaypoints} from '@userActions/Transaction';
import {removeDraftTransaction, removeDraftTransactions} from '@userActions/TransactionEdit';
import {removeDraftTransaction, removeDraftTransactions, removeDraftTransactionsByIDs} from '@userActions/TransactionEdit';
import {getOnboardingMessages} from '@userActions/Welcome/OnboardingFlow';
import type {OnboardingCompanySize} from '@userActions/Welcome/OnboardingFlow';
import type {IOUAction, IOUActionParams, IOUType, OdometerImageType} from '@src/CONST';
Expand Down Expand Up @@ -573,6 +573,8 @@
transactionViolations: OnyxCollection<OnyxTypes.TransactionViolation[]>;
quickAction: OnyxEntry<OnyxTypes.QuickAction>;
policyRecentlyUsedCurrencies: string[];
existingTransactionDraft: OnyxEntry<OnyxTypes.Transaction>;
draftTransactionIDs: string[];
isSelfTourViewed: boolean;
betas: OnyxEntry<OnyxTypes.Beta[]>;
personalDetails: OnyxEntry<OnyxTypes.PersonalDetailsList>;
Expand Down Expand Up @@ -806,7 +808,7 @@
};

let allPersonalDetails: OnyxTypes.PersonalDetailsList = {};
Onyx.connect({

Check warning on line 811 in src/libs/actions/IOU/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.PERSONAL_DETAILS_LIST,
callback: (value) => {
allPersonalDetails = value ?? {};
Expand Down Expand Up @@ -899,7 +901,7 @@
};

let allTransactions: NonNullable<OnyxCollection<OnyxTypes.Transaction>> = {};
Onyx.connect({

Check warning on line 904 in src/libs/actions/IOU/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.TRANSACTION,
waitForCollectionCallback: true,
callback: (value) => {
Expand All @@ -913,7 +915,7 @@
});

let allTransactionDrafts: NonNullable<OnyxCollection<OnyxTypes.Transaction>> = {};
Onyx.connect({

Check warning on line 918 in src/libs/actions/IOU/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.TRANSACTION_DRAFT,
waitForCollectionCallback: true,
callback: (value) => {
Expand All @@ -922,7 +924,7 @@
});

let allTransactionViolations: NonNullable<OnyxCollection<OnyxTypes.TransactionViolations>> = {};
Onyx.connect({

Check warning on line 927 in src/libs/actions/IOU/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS,
waitForCollectionCallback: true,
callback: (value) => {
Expand All @@ -936,7 +938,7 @@
});

let allPolicyTags: OnyxCollection<OnyxTypes.PolicyTagLists> = {};
Onyx.connect({

Check warning on line 941 in src/libs/actions/IOU/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.POLICY_TAGS,
waitForCollectionCallback: true,
callback: (value) => {
Expand All @@ -949,7 +951,7 @@
});

let allReports: OnyxCollection<OnyxTypes.Report>;
Onyx.connect({

Check warning on line 954 in src/libs/actions/IOU/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.REPORT,
waitForCollectionCallback: true,
callback: (value) => {
Expand All @@ -958,7 +960,7 @@
});

let allReportNameValuePairs: OnyxCollection<OnyxTypes.ReportNameValuePairs>;
Onyx.connect({

Check warning on line 963 in src/libs/actions/IOU/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS,
waitForCollectionCallback: true,
callback: (value) => {
Expand All @@ -968,7 +970,7 @@

let userAccountID = -1;
let currentUserEmail = '';
Onyx.connect({

Check warning on line 973 in src/libs/actions/IOU/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.SESSION,
callback: (value) => {
currentUserEmail = value?.email ?? '';
Expand All @@ -977,7 +979,7 @@
});

let deprecatedCurrentUserPersonalDetails: OnyxEntry<OnyxTypes.PersonalDetails>;
Onyx.connect({

Check warning on line 982 in src/libs/actions/IOU/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.PERSONAL_DETAILS_LIST,
callback: (value) => {
deprecatedCurrentUserPersonalDetails = value?.[userAccountID] ?? undefined;
Expand Down Expand Up @@ -6583,6 +6585,8 @@
transactionViolations,
quickAction,
policyRecentlyUsedCurrencies,
existingTransactionDraft,
draftTransactionIDs,
isSelfTourViewed,
betas,
personalDetails,
Expand Down Expand Up @@ -6628,14 +6632,8 @@
const currentChatReport = isMoneyRequestReport ? getReportOrDraftReport(report?.chatReportID) : report;
const moneyRequestReportID = isMoneyRequestReport ? report?.reportID : '';
const isMovingTransactionFromTrackExpense = isMovingTransactionFromTrackExpenseIOUUtils(action);
const existingTransactionID =
isMovingTransactionFromTrackExpense && linkedTrackedExpenseReportAction && isMoneyRequestAction(linkedTrackedExpenseReportAction)
? getOriginalMessage(linkedTrackedExpenseReportAction)?.IOUTransactionID
: undefined;
const existingTransaction =
action === CONST.IOU.ACTION.SUBMIT
? allTransactionDrafts[`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${existingTransactionID}`]
: allTransactions[`${ONYXKEYS.COLLECTION.TRANSACTION}${existingTransactionID}`];
const existingTransactionID = existingTransactionDraft?.transactionID;
const existingTransaction = action === CONST.IOU.ACTION.SUBMIT ? existingTransactionDraft : allTransactions[`${ONYXKEYS.COLLECTION.TRANSACTION}${existingTransactionID}`];

const retryParams = {
...requestMoneyInformation,
Expand Down Expand Up @@ -6819,7 +6817,7 @@

if (shouldHandleNavigation) {
// eslint-disable-next-line @typescript-eslint/no-deprecated
InteractionManager.runAfterInteractions(() => removeDraftTransactions());
InteractionManager.runAfterInteractions(() => removeDraftTransactionsByIDs(draftTransactionIDs));
Comment on lines -6822 to +6820
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dukenv0307 Could you explain this change?
removeDraftTransactions() will remove all draft transactions
removeDraftTransactionsByIDs(draftTransactionIDs)); only reset some draft transactions

Copy link
Contributor Author

@dukenv0307 dukenv0307 Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@DylanDylann but the draftTransactionIDs are taken from allTransactionDraft. I don't want to pass the whole allTransactionDrafts to removeDraftTransactions

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like we need to pass all draft transactions, but we only need the IDs, not the full objects.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@DylanDylann Why do we need to pass all draft transactions?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dukenv0307 Isn't this the original implementation (that removeDraftTransactions function did)? I think in this refactor we should keep the existing behavior and only focus on removing the Onyx.connect method

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@DylanDylann Hmm, I don't change the original behavior, in removeDraftTransactions we just use the transactionID, so we don't need to pass all transactionDrafts

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dukenv0307 This is the original removeDraftTransactions. In case we don't pass any params, it loops through all draft transactions

Screenshot 2026-02-16 at 17 27 39

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@DylanDylann

if (shouldExcludeInitialTransaction && item.transactionID === CONST.IOU.OPTIMISTIC_TRANSACTION_ID) {
return acc;
}

In this case, we just use item.transactionID to compare with OPTIMISTIC_TRANSACTION_ID, then return acc, so we don't modify this transaction.

acc[${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${item.transactionID}] = null;

Otherwise, we'll clear the transaction by assigning it to null, we also just use item.transactionID.

So passing the transactionIDs is enough

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, I agree that we only need to pass the ID. But we should pass all draft transaction IDs

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks like all IDs are already being passed. I recall we had some filtering before, but it seems that's no longer the case


const trackReport = Navigation.getReportRouteByID(linkedTrackedExpenseReportAction?.childReportID);
if (trackReport?.key) {
Expand Down
16 changes: 16 additions & 0 deletions src/libs/actions/TransactionEdit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,21 @@ function removeDraftTransactions(shouldExcludeInitialTransaction = false, allTra
Onyx.multiSet(draftTransactionsSet);
}

function removeDraftTransactionsByIDs(transactionIDs: string[]) {
if (!transactionIDs.length) {
return;
}

const draftTransactionsSet = transactionIDs.reduce(
(acc, transactionID) => {
acc[`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`] = null;
return acc;
},
{} as Record<string, null>,
);
Onyx.multiSet(draftTransactionsSet);
}

function replaceDefaultDraftTransaction(transaction: OnyxEntry<Transaction>) {
if (!transaction) {
return;
Expand Down Expand Up @@ -176,6 +191,7 @@ export {
removeDraftTransaction,
removeTransactionReceipt,
removeDraftTransactions,
removeDraftTransactionsByIDs,
removeDraftSplitTransaction,
replaceDefaultDraftTransaction,
buildOptimisticTransactionAndCreateDraft,
Expand Down
10 changes: 10 additions & 0 deletions src/pages/Share/SubmitDetailsPage.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type {StackScreenProps} from '@react-navigation/stack';
import {hasSeenTourSelector} from '@selectors/Onboarding';
import {validTransactionDraftsSelector} from '@selectors/TransactionDraft';
import React, {useEffect, useState} from 'react';
import {View} from 'react-native';
import type {OnyxEntry} from 'react-native-onyx';
Expand All @@ -22,6 +23,7 @@ import {getIOURequestPolicyID, getMoneyRequestParticipantsFromReport, initMoneyR
import DateUtils from '@libs/DateUtils';
import {getFileName, readFileAsync} from '@libs/fileDownload/FileUtils';
import getCurrentPosition from '@libs/getCurrentPosition';
import {getExistingTransactionID} from '@libs/IOUUtils';
import Log from '@libs/Log';
import navigateAfterInteraction from '@libs/Navigation/navigateAfterInteraction';
import Navigation from '@libs/Navigation/Navigation';
Expand Down Expand Up @@ -71,6 +73,9 @@ function SubmitDetailsPage({
const [activePolicyID] = useOnyx(ONYXKEYS.NVP_ACTIVE_POLICY_ID);
const [isSelfTourViewed = false] = useOnyx(ONYXKEYS.NVP_ONBOARDING, {selector: hasSeenTourSelector});
const [policyRecentlyUsedCurrencies] = useOnyx(ONYXKEYS.RECENTLY_USED_CURRENCIES);
const [transactionDrafts] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_DRAFT, {selector: validTransactionDraftsSelector});
const draftTransactionIDs = Object.keys(transactionDrafts ?? {});

const [betas] = useOnyx(ONYXKEYS.BETAS);
const currentUserPersonalDetails = useCurrentUserPersonalDetails();
const personalPolicy = usePersonalPolicy();
Expand Down Expand Up @@ -169,6 +174,9 @@ function SubmitDetailsPage({
betas,
});
} else {
const existingTransactionID = getExistingTransactionID(transaction.linkedTrackedExpenseReportAction);
const existingTransactionDraft = existingTransactionID ? transactionDrafts?.[existingTransactionID] : undefined;

requestMoney({
report,
participantParams: {payeeEmail: currentUserPersonalDetails.login, payeeAccountID: currentUserPersonalDetails.accountID, participant},
Expand Down Expand Up @@ -201,6 +209,8 @@ function SubmitDetailsPage({
transactionViolations,
policyRecentlyUsedCurrencies: policyRecentlyUsedCurrencies ?? [],
quickAction,
existingTransactionDraft,
draftTransactionIDs,
isSelfTourViewed,
betas,
personalDetails,
Expand Down
Loading
Loading