From 341ff67a0c4b8b087a175f87ac3404c21238cc14 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Mon, 19 Jan 2026 15:23:42 +0700 Subject: [PATCH 1/2] fix: Expense-Keep this one option doesn't resolve duplicates in track map expense --- src/hooks/useTransactionsByID.ts | 24 ++++++++++-------------- src/libs/TransactionPreviewUtils.ts | 20 +++++++++++--------- src/libs/actions/Transaction.ts | 12 ++++++++---- 3 files changed, 29 insertions(+), 27 deletions(-) diff --git a/src/hooks/useTransactionsByID.ts b/src/hooks/useTransactionsByID.ts index b5e6761313c5..bf943b3ddaa0 100644 --- a/src/hooks/useTransactionsByID.ts +++ b/src/hooks/useTransactionsByID.ts @@ -1,23 +1,19 @@ -import {useCallback} from 'react'; -import type {OnyxCollection} from 'react-native-onyx'; +import {useMemo} from 'react'; import ONYXKEYS from '@src/ONYXKEYS'; import type {Transaction} from '@src/types/onyx'; import useOnyx from './useOnyx'; function useTransactionsByID(transactionIDs: string[] | undefined) { - const transactionsSelector = useCallback( - (transactions: OnyxCollection) => transactionIDs?.map((id) => transactions?.[`${ONYXKEYS.COLLECTION.TRANSACTION}${id}`]) ?? [], - [transactionIDs], - ); + const [allTransactions] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION, { + canBeMissing: true, + }); - const [transactions] = useOnyx( - ONYXKEYS.COLLECTION.TRANSACTION, - { - selector: transactionsSelector, - canBeMissing: true, - }, - [transactionsSelector], - ); + const transactions = useMemo(() => { + if (!transactionIDs || transactionIDs.length === 0 || !allTransactions) { + return []; + } + return transactionIDs.map((id) => allTransactions?.[`${ONYXKEYS.COLLECTION.TRANSACTION}${id}`]).filter(Boolean) as Transaction[]; + }, [transactionIDs, allTransactions]); return [transactions]; } diff --git a/src/libs/TransactionPreviewUtils.ts b/src/libs/TransactionPreviewUtils.ts index 1802d921a4b7..d1d5fe303a63 100644 --- a/src/libs/TransactionPreviewUtils.ts +++ b/src/libs/TransactionPreviewUtils.ts @@ -5,7 +5,7 @@ import type {TranslationPaths} from '@src/languages/types'; import ROUTES from '@src/ROUTES'; import type * as OnyxTypes from '@src/types/onyx'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; -import {abandonReviewDuplicateTransactions, setReviewDuplicatesKey} from './actions/Transaction'; +import {setReviewDuplicatesKey} from './actions/Transaction'; import {isCategoryMissing} from './CategoryUtils'; import {convertToDisplayString} from './CurrencyUtils'; import DateUtils from './DateUtils'; @@ -79,16 +79,18 @@ const getReviewNavigationRoute = ( policyCategories: OnyxTypes.PolicyCategories | undefined, transactionReport: OnyxEntry, ) => { - // Clear the draft before selecting a different expense to prevent merging fields from the previous expense + // Use set method to prevent merging fields from the previous expense // (e.g., category, tag, tax) that may be not enabled/available in the new expense's policy. - abandonReviewDuplicateTransactions(); const comparisonResult = compareDuplicateTransactionFields(transaction, duplicates, transactionReport, transaction?.transactionID, policyCategories); - setReviewDuplicatesKey({ - ...comparisonResult.keep, - duplicates: duplicates.map((duplicate) => duplicate?.transactionID).filter(Boolean) as string[], - transactionID: transaction?.transactionID, - reportID: transaction?.reportID, - }); + setReviewDuplicatesKey( + { + ...comparisonResult.keep, + duplicates: duplicates.map((duplicate) => duplicate?.transactionID).filter(Boolean) as string[], + transactionID: transaction?.transactionID, + reportID: transaction?.reportID, + }, + true, + ); if (comparisonResult.change.merchant) { return ROUTES.TRANSACTION_DUPLICATE_REVIEW_MERCHANT_PAGE.getRoute(threadReportID, backTo); diff --git a/src/libs/actions/Transaction.ts b/src/libs/actions/Transaction.ts index b9df2b05e8dc..ee520c56d2ab 100644 --- a/src/libs/actions/Transaction.ts +++ b/src/libs/actions/Transaction.ts @@ -587,10 +587,14 @@ function dismissDuplicateTransactionViolation({ }); } -function setReviewDuplicatesKey(values: Partial) { - Onyx.merge(`${ONYXKEYS.REVIEW_DUPLICATES}`, { - ...values, - }); +function setReviewDuplicatesKey(values: Partial, shouldUseSetMethod = false) { + if (shouldUseSetMethod) { + Onyx.set(`${ONYXKEYS.REVIEW_DUPLICATES}`, values); + } else { + Onyx.merge(`${ONYXKEYS.REVIEW_DUPLICATES}`, { + ...values, + }); + } } function abandonReviewDuplicateTransactions() { From 21c3a52ce601ac7eb36acedaa84345f3fa642c4c Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Wed, 21 Jan 2026 15:11:43 +0700 Subject: [PATCH 2/2] change to to use selector again --- src/hooks/useTransactionsByID.ts | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/hooks/useTransactionsByID.ts b/src/hooks/useTransactionsByID.ts index bf943b3ddaa0..b5e6761313c5 100644 --- a/src/hooks/useTransactionsByID.ts +++ b/src/hooks/useTransactionsByID.ts @@ -1,19 +1,23 @@ -import {useMemo} from 'react'; +import {useCallback} from 'react'; +import type {OnyxCollection} from 'react-native-onyx'; import ONYXKEYS from '@src/ONYXKEYS'; import type {Transaction} from '@src/types/onyx'; import useOnyx from './useOnyx'; function useTransactionsByID(transactionIDs: string[] | undefined) { - const [allTransactions] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION, { - canBeMissing: true, - }); + const transactionsSelector = useCallback( + (transactions: OnyxCollection) => transactionIDs?.map((id) => transactions?.[`${ONYXKEYS.COLLECTION.TRANSACTION}${id}`]) ?? [], + [transactionIDs], + ); - const transactions = useMemo(() => { - if (!transactionIDs || transactionIDs.length === 0 || !allTransactions) { - return []; - } - return transactionIDs.map((id) => allTransactions?.[`${ONYXKEYS.COLLECTION.TRANSACTION}${id}`]).filter(Boolean) as Transaction[]; - }, [transactionIDs, allTransactions]); + const [transactions] = useOnyx( + ONYXKEYS.COLLECTION.TRANSACTION, + { + selector: transactionsSelector, + canBeMissing: true, + }, + [transactionsSelector], + ); return [transactions]; }