From 9624ed25164692021e0f225e480c1f14cf4f5572 Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Tue, 25 Nov 2025 11:26:17 +0100 Subject: [PATCH 01/22] allow admin to create report on behald of employee --- src/libs/API/parameters/CreateAppReportParams.ts | 1 + src/libs/actions/Report.ts | 3 ++- src/pages/iou/request/step/IOURequestEditReportCommon.tsx | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/libs/API/parameters/CreateAppReportParams.ts b/src/libs/API/parameters/CreateAppReportParams.ts index 6ac0152ad7a6..66dbfb487445 100644 --- a/src/libs/API/parameters/CreateAppReportParams.ts +++ b/src/libs/API/parameters/CreateAppReportParams.ts @@ -1,4 +1,5 @@ type CreateAppReportParams = { + accountID?: number; reportName: string; policyID?: string; type: string; diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index c9cba6e269fd..568c1081a5d5 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -2985,6 +2985,7 @@ function createNewReport( const reportActionID = rand64(); const reportPreviewReportActionID = rand64(); + // s77rt fix optimistic data if accountID is provided const {optimisticReportName, parentReportID, reportPreviewAction, optimisticData, successData, failureData, optimisticReportData} = buildNewReportOptimisticData( policy, optimisticReportID, @@ -2997,7 +2998,7 @@ function createNewReport( API.write( WRITE_COMMANDS.CREATE_APP_REPORT, - {reportName: optimisticReportName, type: CONST.REPORT.TYPE.EXPENSE, policyID, reportID: optimisticReportID, reportActionID, reportPreviewReportActionID}, + {accountID: 14725, reportName: optimisticReportName, type: CONST.REPORT.TYPE.EXPENSE, policyID, reportID: optimisticReportID, reportActionID, reportPreviewReportActionID}, {optimisticData, successData, failureData}, ); if (shouldNotifyNewAction) { diff --git a/src/pages/iou/request/step/IOURequestEditReportCommon.tsx b/src/pages/iou/request/step/IOURequestEditReportCommon.tsx index b5d71d45f0d2..0735f46a60d5 100644 --- a/src/pages/iou/request/step/IOURequestEditReportCommon.tsx +++ b/src/pages/iou/request/step/IOURequestEditReportCommon.tsx @@ -214,7 +214,7 @@ function IOURequestEditReportCommon({ const headerMessage = useMemo(() => (searchValue && !reportOptions.length ? translate('common.noResultsFound') : ''), [searchValue, reportOptions, translate]); const createReportOption = useMemo(() => { - if (!createReport || (isEditing && !isOwner)) { + if (!createReport) { return undefined; } From a2a4db8fa7a56bc718d42283f9060320019492b0 Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Wed, 26 Nov 2025 13:08:21 +0100 Subject: [PATCH 02/22] lint --- src/pages/iou/request/step/IOURequestEditReportCommon.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/iou/request/step/IOURequestEditReportCommon.tsx b/src/pages/iou/request/step/IOURequestEditReportCommon.tsx index 0735f46a60d5..c462a83a6a79 100644 --- a/src/pages/iou/request/step/IOURequestEditReportCommon.tsx +++ b/src/pages/iou/request/step/IOURequestEditReportCommon.tsx @@ -226,7 +226,7 @@ function IOURequestEditReportCommon({ icon={icons.Document} /> ); - }, [icons.Document, createReport, isEditing, isOwner, translate, policyForMovingExpenses?.name]); + }, [icons.Document, createReport, translate, policyForMovingExpenses?.name]); // eslint-disable-next-line rulesdir/no-negated-variables const shouldShowNotFoundPage = useMemo(() => { From a8c2633ba8b7132397d444b1dba00a524e4ce9b9 Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Wed, 26 Nov 2025 13:19:30 +0100 Subject: [PATCH 03/22] pass accountID to CreateAppReport --- src/libs/actions/Report.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index 90d8c6de5fe8..4f8672e93539 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -2998,7 +2998,15 @@ function createNewReport( API.write( WRITE_COMMANDS.CREATE_APP_REPORT, - {accountID: 14725, reportName: optimisticReportName, type: CONST.REPORT.TYPE.EXPENSE, policyID, reportID: optimisticReportID, reportActionID, reportPreviewReportActionID}, + { + accountID: creatorPersonalDetails.accountID, + reportName: optimisticReportName, + type: CONST.REPORT.TYPE.EXPENSE, + policyID, + reportID: optimisticReportID, + reportActionID, + reportPreviewReportActionID, + }, {optimisticData, successData, failureData}, ); if (shouldNotifyNewAction) { From 9123cb96fb92106ed894a62ce8c597b5f52dc0c4 Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Wed, 26 Nov 2025 14:54:40 +0100 Subject: [PATCH 04/22] pass owner personal details on report creation --- src/libs/actions/Report.ts | 1 - .../Search/SearchTransactionsChangeReport.tsx | 11 ++++++----- .../iou/request/step/IOURequestEditReport.tsx | 12 ++++++------ .../iou/request/step/IOURequestStepReport.tsx | 14 +++++++------- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index 4f8672e93539..f2957e4ee2ef 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -2985,7 +2985,6 @@ function createNewReport( const reportActionID = rand64(); const reportPreviewReportActionID = rand64(); - // s77rt fix optimistic data if accountID is provided const {optimisticReportName, parentReportID, reportPreviewAction, optimisticData, successData, failureData, optimisticReportData} = buildNewReportOptimisticData( policy, optimisticReportID, diff --git a/src/pages/Search/SearchTransactionsChangeReport.tsx b/src/pages/Search/SearchTransactionsChangeReport.tsx index 6e48fa2879bd..448542d3dfe4 100644 --- a/src/pages/Search/SearchTransactionsChangeReport.tsx +++ b/src/pages/Search/SearchTransactionsChangeReport.tsx @@ -1,10 +1,9 @@ import React, {useMemo} from 'react'; import {InteractionManager} from 'react-native'; -import {useSession} from '@components/OnyxListItemProvider'; +import {usePersonalDetails, useSession} from '@components/OnyxListItemProvider'; import {useSearchContext} from '@components/Search/SearchContext'; import type {ListItem} from '@components/SelectionListWithSections/types'; import useConditionalCreateEmptyReportConfirmation from '@hooks/useConditionalCreateEmptyReportConfirmation'; -import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import useOnyx from '@hooks/useOnyx'; import usePermissions from '@hooks/usePermissions'; import usePolicyForMovingExpenses from '@hooks/usePolicyForMovingExpenses'; @@ -12,12 +11,13 @@ import {createNewReport} from '@libs/actions/Report'; import {changeTransactionsReport} from '@libs/actions/Transaction'; import setNavigationActionToMicrotaskQueue from '@libs/Navigation/helpers/setNavigationActionToMicrotaskQueue'; import Navigation from '@libs/Navigation/Navigation'; -import {getReportOrDraftReport, hasViolations as hasViolationsReportUtils} from '@libs/ReportUtils'; +import {getPersonalDetailsForAccountID, getReportOrDraftReport, hasViolations as hasViolationsReportUtils} from '@libs/ReportUtils'; import {shouldRestrictUserBillableActions} from '@libs/SubscriptionUtils'; import IOURequestEditReportCommon from '@pages/iou/request/step/IOURequestEditReportCommon'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; +import type {PersonalDetails} from '@src/types/onyx'; type TransactionGroupListItem = ListItem & { /** reportID of the report */ @@ -37,7 +37,7 @@ function SearchTransactionsChangeReport() { const {isBetaEnabled} = usePermissions(); const isASAPSubmitBetaEnabled = isBetaEnabled(CONST.BETAS.ASAP_SUBMIT); const session = useSession(); - const currentUserPersonalDetails = useCurrentUserPersonalDetails(); + const personalDetails = usePersonalDetails(); const policyForMovingExpenses = policyForMovingExpensesID ? allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${policyForMovingExpensesID}`] : undefined; const firstTransactionKey = selectedTransactionsKeys.at(0); @@ -70,9 +70,10 @@ function SearchTransactionsChangeReport() { const report = getReportOrDraftReport(reportIDWithOwner); return report?.ownerAccountID; }, [selectedTransactions, selectedTransactionsKeys]); + const targetOwnerPersonalDetails = useMemo(() => getPersonalDetailsForAccountID(targetOwnerAccountID) as PersonalDetails, [personalDetails, targetOwnerAccountID]); const createReportForPolicy = () => { - const optimisticReport = createNewReport(currentUserPersonalDetails, hasViolations, isASAPSubmitBetaEnabled, policyForMovingExpensesID); + const optimisticReport = createNewReport(targetOwnerPersonalDetails, hasViolations, isASAPSubmitBetaEnabled, policyForMovingExpensesID); const reportNextStep = allReportNextSteps?.[`${ONYXKEYS.COLLECTION.NEXT_STEP}${optimisticReport.reportID}`]; setNavigationActionToMicrotaskQueue(() => { changeTransactionsReport( diff --git a/src/pages/iou/request/step/IOURequestEditReport.tsx b/src/pages/iou/request/step/IOURequestEditReport.tsx index 3ef9e681e4e4..5ae404347807 100644 --- a/src/pages/iou/request/step/IOURequestEditReport.tsx +++ b/src/pages/iou/request/step/IOURequestEditReport.tsx @@ -1,10 +1,9 @@ import React, {useMemo} from 'react'; import type {OnyxEntry} from 'react-native-onyx'; -import {useSession} from '@components/OnyxListItemProvider'; +import {usePersonalDetails, useSession} from '@components/OnyxListItemProvider'; import {useSearchContext} from '@components/Search/SearchContext'; import type {ListItem} from '@components/SelectionListWithSections/types'; import useConditionalCreateEmptyReportConfirmation from '@hooks/useConditionalCreateEmptyReportConfirmation'; -import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import useOnyx from '@hooks/useOnyx'; import usePermissions from '@hooks/usePermissions'; import usePolicyForMovingExpenses from '@hooks/usePolicyForMovingExpenses'; @@ -12,7 +11,7 @@ import {turnOffMobileSelectionMode} from '@libs/actions/MobileSelectionMode'; import {changeTransactionsReport} from '@libs/actions/Transaction'; import setNavigationActionToMicrotaskQueue from '@libs/Navigation/helpers/setNavigationActionToMicrotaskQueue'; import Navigation from '@libs/Navigation/Navigation'; -import {hasViolations as hasViolationsReportUtils} from '@libs/ReportUtils'; +import {getPersonalDetailsForAccountID, hasViolations as hasViolationsReportUtils} from '@libs/ReportUtils'; import {shouldRestrictUserBillableActions} from '@libs/SubscriptionUtils'; import {isPerDiemRequest} from '@libs/TransactionUtils'; import {createNewReport} from '@userActions/Report'; @@ -20,7 +19,7 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; -import type {Report} from '@src/types/onyx'; +import type {PersonalDetails, Report} from '@src/types/onyx'; import IOURequestEditReportCommon from './IOURequestEditReportCommon'; import withWritableReportOrNotFound from './withWritableReportOrNotFound'; import type {WithWritableReportOrNotFoundProps} from './withWritableReportOrNotFound'; @@ -45,7 +44,8 @@ function IOURequestEditReport({route}: IOURequestEditReportProps) { const [allPolicies] = useOnyx(ONYXKEYS.COLLECTION.POLICY, {canBeMissing: true}); const [allPolicyCategories] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}`, {canBeMissing: true}); const [allTransactions] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION, {canBeMissing: true}); - const currentUserPersonalDetails = useCurrentUserPersonalDetails(); + const personalDetails = usePersonalDetails(); + const ownerPersonalDetails = useMemo(() => getPersonalDetailsForAccountID(selectedReport?.ownerAccountID) as PersonalDetails, [personalDetails, selectedReport]); const hasPerDiemTransactions = useMemo(() => { return selectedTransactionIDs.some((transactionID) => { @@ -102,7 +102,7 @@ function IOURequestEditReport({route}: IOURequestEditReportProps) { return; } - const optimisticReport = createNewReport(currentUserPersonalDetails, hasViolations, isASAPSubmitBetaEnabled, policyForMovingExpensesID); + const optimisticReport = createNewReport(ownerPersonalDetails, hasViolations, isASAPSubmitBetaEnabled, policyForMovingExpensesID); selectReport({value: optimisticReport.reportID}, optimisticReport); }; diff --git a/src/pages/iou/request/step/IOURequestStepReport.tsx b/src/pages/iou/request/step/IOURequestStepReport.tsx index 02cb2f9d9d95..5d8dd47a5b1c 100644 --- a/src/pages/iou/request/step/IOURequestStepReport.tsx +++ b/src/pages/iou/request/step/IOURequestStepReport.tsx @@ -1,11 +1,10 @@ -import React from 'react'; +import React, {useMemo} from 'react'; import {InteractionManager} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; -import {useSession} from '@components/OnyxListItemProvider'; +import {usePersonalDetails, useSession} from '@components/OnyxListItemProvider'; import {useSearchContext} from '@components/Search/SearchContext'; import type {ListItem} from '@components/SelectionListWithSections/types'; import useConditionalCreateEmptyReportConfirmation from '@hooks/useConditionalCreateEmptyReportConfirmation'; -import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import useOnyx from '@hooks/useOnyx'; import usePermissions from '@hooks/usePermissions'; import usePolicyForMovingExpenses from '@hooks/usePolicyForMovingExpenses'; @@ -14,14 +13,14 @@ import useShowNotFoundPageInIOUStep from '@hooks/useShowNotFoundPageInIOUStep'; import {createNewReport} from '@libs/actions/Report'; import {changeTransactionsReport, setTransactionReport} from '@libs/actions/Transaction'; import Navigation from '@libs/Navigation/Navigation'; -import {getReportOrDraftReport, hasViolations as hasViolationsReportUtils, isPolicyExpenseChat, isReportOutstanding} from '@libs/ReportUtils'; +import {getPersonalDetailsForAccountID, getReportOrDraftReport, hasViolations as hasViolationsReportUtils, isPolicyExpenseChat, isReportOutstanding} from '@libs/ReportUtils'; import {shouldRestrictUserBillableActions} from '@libs/SubscriptionUtils'; import {isPerDiemRequest} from '@libs/TransactionUtils'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; -import type {Report} from '@src/types/onyx'; +import type {PersonalDetails, Report} from '@src/types/onyx'; import IOURequestEditReportCommon from './IOURequestEditReportCommon'; import withFullTransactionOrNotFound from './withFullTransactionOrNotFound'; import type {WithFullTransactionOrNotFoundProps} from './withFullTransactionOrNotFound'; @@ -55,7 +54,8 @@ function IOURequestStepReport({route, transaction}: IOURequestStepReportProps) { const {isBetaEnabled} = usePermissions(); const isASAPSubmitBetaEnabled = isBetaEnabled(CONST.BETAS.ASAP_SUBMIT); const session = useSession(); - const currentUserPersonalDetails = useCurrentUserPersonalDetails(); + const personalDetails = usePersonalDetails(); + const ownerPersonalDetails = useMemo(() => getPersonalDetailsForAccountID(reportOrDraftReport?.ownerAccountID) as PersonalDetails, [personalDetails, reportOrDraftReport]); const {policyForMovingExpensesID, shouldSelectPolicy} = usePolicyForMovingExpenses(isPerDiemRequest(transaction)); const [transactionViolations] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS, {canBeMissing: true}); const hasViolations = hasViolationsReportUtils(undefined, transactionViolations); @@ -179,7 +179,7 @@ function IOURequestStepReport({route, transaction}: IOURequestStepReportProps) { return; } - const optimisticReport = createNewReport(currentUserPersonalDetails, hasViolations, isASAPSubmitBetaEnabled, policyForMovingExpensesID); + const optimisticReport = createNewReport(ownerPersonalDetails, hasViolations, isASAPSubmitBetaEnabled, policyForMovingExpensesID); handleRegularReportSelection({value: optimisticReport.reportID}, optimisticReport); }; From e39050678843d5a98ae13667e0308d140ed20bb5 Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Wed, 26 Nov 2025 15:16:49 +0100 Subject: [PATCH 05/22] get owner from selected report --- src/pages/iou/request/step/IOURequestStepReport.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pages/iou/request/step/IOURequestStepReport.tsx b/src/pages/iou/request/step/IOURequestStepReport.tsx index 5d8dd47a5b1c..1c1d7a56bdee 100644 --- a/src/pages/iou/request/step/IOURequestStepReport.tsx +++ b/src/pages/iou/request/step/IOURequestStepReport.tsx @@ -44,6 +44,7 @@ function IOURequestStepReport({route, transaction}: IOURequestStepReportProps) { const shouldUseTransactionReport = (!!transactionReport && isReportOutstanding(transactionReport, transactionReport?.policyID)) || isUnreported; const outstandingReportID = isPolicyExpenseChat(participantReport) ? participantReport?.iouReportID : participantReportID; const selectedReportID = shouldUseTransactionReport ? transactionReport?.reportID : outstandingReportID; + const [selectedReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${selectedReportID}`, {canBeMissing: false}); const [allPolicies] = useOnyx(ONYXKEYS.COLLECTION.POLICY, {canBeMissing: true}); const [allPolicyCategories] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}`, {canBeMissing: true}); const {removeTransaction, setSelectedTransactions} = useSearchContext(); @@ -55,7 +56,7 @@ function IOURequestStepReport({route, transaction}: IOURequestStepReportProps) { const isASAPSubmitBetaEnabled = isBetaEnabled(CONST.BETAS.ASAP_SUBMIT); const session = useSession(); const personalDetails = usePersonalDetails(); - const ownerPersonalDetails = useMemo(() => getPersonalDetailsForAccountID(reportOrDraftReport?.ownerAccountID) as PersonalDetails, [personalDetails, reportOrDraftReport]); + const ownerPersonalDetails = useMemo(() => getPersonalDetailsForAccountID(selectedReport?.ownerAccountID) as PersonalDetails, [personalDetails, selectedReport]); const {policyForMovingExpensesID, shouldSelectPolicy} = usePolicyForMovingExpenses(isPerDiemRequest(transaction)); const [transactionViolations] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS, {canBeMissing: true}); const hasViolations = hasViolationsReportUtils(undefined, transactionViolations); From 84983e5f73a5ca72a16032a77671bded23fde47d Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Fri, 28 Nov 2025 00:21:41 +0100 Subject: [PATCH 06/22] allow editing unreported managed card transaction --- src/libs/ReportUtils.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index ef6dd168b651..f98ba3d215c3 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -285,6 +285,7 @@ import { isDistanceRequest, isExpensifyCardTransaction, isFetchingWaypointsFromServer, + isManagedCardTransaction, isManualDistanceRequest as isManualDistanceRequestTransactionUtils, isOnHold as isOnHoldTransactionUtils, isPayAtEndExpense, @@ -4508,6 +4509,10 @@ function canEditMoneyRequest( return false; } + if (transaction.reportID === CONST.REPORT.UNREPORTED_REPORT_ID && isManagedCardTransaction(transaction)) { + return true; + } + const moneyRequestReportID = originalMessage?.IOUReportID; const isRequestor = currentUserAccountID === reportAction?.actorAccountID; From 23e156f8b906a365634f8ab3c38a796f2d8158d0 Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Fri, 28 Nov 2025 02:05:15 +0100 Subject: [PATCH 07/22] make changeTransactionsReport accept transactions --- src/libs/actions/Transaction.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/libs/actions/Transaction.ts b/src/libs/actions/Transaction.ts index 7469c6d515f7..2c1a25cba82a 100644 --- a/src/libs/actions/Transaction.ts +++ b/src/libs/actions/Transaction.ts @@ -693,7 +693,7 @@ function setTransactionReport(transactionID: string, transaction: Partial, ) { const reportID = newReport?.reportID ?? CONST.REPORT.UNREPORTED_REPORT_ID; - - const transactions = transactionIDs.map((id) => allTransactions?.[id]).filter((t): t is NonNullable => t !== undefined); + const transactions = + typeof transactionsOrIDs.at(0) === 'string' + ? (transactionsOrIDs as string[]).map((id) => allTransactions?.[id]).filter((t): t is NonNullable => t !== undefined) + : (transactionsOrIDs as Transaction[]); + const transactionIDs = transactions.map((t) => t.transactionID); const transactionIDToReportActionAndThreadData: Record = {}; const updatedReportTotals: Record = {}; const updatedReportNonReimbursableTotals: Record = {}; From b790fdbbdd2625d7c912ad48578ec5e4da813d85 Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Sat, 29 Nov 2025 09:20:23 +0100 Subject: [PATCH 08/22] add transaction to SelectedTransactionInfo --- src/components/Search/index.tsx | 4 ++++ src/components/Search/types.ts | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/components/Search/index.tsx b/src/components/Search/index.tsx index 325e3824dadc..c23ae196b032 100644 --- a/src/components/Search/index.tsx +++ b/src/components/Search/index.tsx @@ -99,6 +99,7 @@ function mapTransactionItemToSelectedEntry(item: TransactionListItemType, outsta return [ item.keyForList, { + transaction: item, isSelected: true, canDelete: item.canDelete, canHold: canHoldRequest, @@ -181,6 +182,7 @@ function prepareTransactionsList(item: TransactionListItemType, selectedTransact return { ...selectedTransactions, [item.keyForList]: { + transaction: item, isSelected: true, canDelete: item.canDelete, canHold: canHoldRequest, @@ -491,6 +493,7 @@ function Search({ ); newTransactionList[transactionItem.transactionID] = { + transaction: transactionItem, action: transactionItem.action, canHold: canHoldRequest, isHeld: isOnHold(transactionItem), @@ -536,6 +539,7 @@ function Search({ ); newTransactionList[transactionItem.transactionID] = { + transaction: transactionItem, action: transactionItem.action, canHold: canHoldRequest, isHeld: isOnHold(transactionItem), diff --git a/src/components/Search/types.ts b/src/components/Search/types.ts index 2e61b1240bf8..f6b87b84bf67 100644 --- a/src/components/Search/types.ts +++ b/src/components/Search/types.ts @@ -3,11 +3,15 @@ import type {PaymentMethod} from '@components/KYCWall/types'; import type {ReportActionListItemType, TaskListItemType, TransactionGroupListItemType, TransactionListItemType} from '@components/SelectionListWithSections/types'; import type {SearchKey} from '@libs/SearchUIUtils'; import type CONST from '@src/CONST'; +import type {Transaction} from '@src/types/onyx'; import type {SearchDataTypes} from '@src/types/onyx/SearchResults'; import type IconAsset from '@src/types/utils/IconAsset'; /** Model of the selected transaction */ type SelectedTransactionInfo = { + /** The transaction itself */ + transaction: Transaction; + /** Whether the transaction is selected */ isSelected: boolean; From 1dcfb456a28079d7125f20fb77cea96a24f87518 Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Sat, 29 Nov 2025 09:24:38 +0100 Subject: [PATCH 09/22] pass transactions to changeTransactionsReport --- src/pages/Search/SearchTransactionsChangeReport.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/pages/Search/SearchTransactionsChangeReport.tsx b/src/pages/Search/SearchTransactionsChangeReport.tsx index 448542d3dfe4..dbf7221afff4 100644 --- a/src/pages/Search/SearchTransactionsChangeReport.tsx +++ b/src/pages/Search/SearchTransactionsChangeReport.tsx @@ -27,6 +27,7 @@ type TransactionGroupListItem = ListItem & { function SearchTransactionsChangeReport() { const {selectedTransactions, clearSelectedTransactions} = useSearchContext(); const selectedTransactionsKeys = useMemo(() => Object.keys(selectedTransactions), [selectedTransactions]); + const transactions = useMemo(() => Object.values(selectedTransactions).map((t) => t.transaction), [selectedTransactions]); const [allReportNextSteps] = useOnyx(ONYXKEYS.COLLECTION.NEXT_STEP, {canBeMissing: true}); const [allReports] = useOnyx(ONYXKEYS.COLLECTION.REPORT, {canBeMissing: false}); const [allPolicies] = useOnyx(ONYXKEYS.COLLECTION.POLICY, {canBeMissing: true}); @@ -77,7 +78,7 @@ function SearchTransactionsChangeReport() { const reportNextStep = allReportNextSteps?.[`${ONYXKEYS.COLLECTION.NEXT_STEP}${optimisticReport.reportID}`]; setNavigationActionToMicrotaskQueue(() => { changeTransactionsReport( - selectedTransactionsKeys, + transactions, isASAPSubmitBetaEnabled, session?.accountID ?? CONST.DEFAULT_NUMBER_ID, session?.email ?? '', @@ -118,7 +119,7 @@ function SearchTransactionsChangeReport() { const reportNextStep = allReportNextSteps?.[`${ONYXKEYS.COLLECTION.NEXT_STEP}${item.value}`]; const destinationReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${item.value}`]; changeTransactionsReport( - selectedTransactionsKeys, + transactions, isASAPSubmitBetaEnabled, session?.accountID ?? CONST.DEFAULT_NUMBER_ID, session?.email ?? '', @@ -139,7 +140,7 @@ function SearchTransactionsChangeReport() { if (selectedTransactionsKeys.length === 0) { return; } - changeTransactionsReport(selectedTransactionsKeys, isASAPSubmitBetaEnabled, session?.accountID ?? CONST.DEFAULT_NUMBER_ID, session?.email ?? ''); + changeTransactionsReport(transactions, isASAPSubmitBetaEnabled, session?.accountID ?? CONST.DEFAULT_NUMBER_ID, session?.email ?? ''); clearSelectedTransactions(); Navigation.goBack(); }; From 2b2077fd35b983744f1e5367388c12d99acea1ea Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Sat, 29 Nov 2025 11:27:17 +0100 Subject: [PATCH 10/22] update CreateAppReportParams to use reportCreateEmail --- src/libs/API/parameters/CreateAppReportParams.ts | 2 +- src/libs/actions/Report.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/API/parameters/CreateAppReportParams.ts b/src/libs/API/parameters/CreateAppReportParams.ts index 66dbfb487445..30a2541ea640 100644 --- a/src/libs/API/parameters/CreateAppReportParams.ts +++ b/src/libs/API/parameters/CreateAppReportParams.ts @@ -1,10 +1,10 @@ type CreateAppReportParams = { - accountID?: number; reportName: string; policyID?: string; type: string; reportID: string; reportActionID: string; reportPreviewReportActionID: string; + reportCreatorEmail?: string; }; export default CreateAppReportParams; diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index f2957e4ee2ef..c9740ab7c393 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -2998,13 +2998,13 @@ function createNewReport( API.write( WRITE_COMMANDS.CREATE_APP_REPORT, { - accountID: creatorPersonalDetails.accountID, reportName: optimisticReportName, type: CONST.REPORT.TYPE.EXPENSE, policyID, reportID: optimisticReportID, reportActionID, reportPreviewReportActionID, + reportCreatorEmail: creatorPersonalDetails.login, }, {optimisticData, successData, failureData}, ); From 169288702a0045db62f06efd1dfc61e1bc606732 Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Sat, 29 Nov 2025 11:29:16 +0100 Subject: [PATCH 11/22] lint --- src/pages/Search/SearchTransactionsChangeReport.tsx | 2 +- src/pages/iou/request/step/IOURequestEditReport.tsx | 5 ++++- src/pages/iou/request/step/IOURequestStepReport.tsx | 5 ++++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/pages/Search/SearchTransactionsChangeReport.tsx b/src/pages/Search/SearchTransactionsChangeReport.tsx index dbf7221afff4..5bc60087288f 100644 --- a/src/pages/Search/SearchTransactionsChangeReport.tsx +++ b/src/pages/Search/SearchTransactionsChangeReport.tsx @@ -71,7 +71,7 @@ function SearchTransactionsChangeReport() { const report = getReportOrDraftReport(reportIDWithOwner); return report?.ownerAccountID; }, [selectedTransactions, selectedTransactionsKeys]); - const targetOwnerPersonalDetails = useMemo(() => getPersonalDetailsForAccountID(targetOwnerAccountID) as PersonalDetails, [personalDetails, targetOwnerAccountID]); + const targetOwnerPersonalDetails = useMemo(() => getPersonalDetailsForAccountID(targetOwnerAccountID, personalDetails) as PersonalDetails, [personalDetails, targetOwnerAccountID]); const createReportForPolicy = () => { const optimisticReport = createNewReport(targetOwnerPersonalDetails, hasViolations, isASAPSubmitBetaEnabled, policyForMovingExpensesID); diff --git a/src/pages/iou/request/step/IOURequestEditReport.tsx b/src/pages/iou/request/step/IOURequestEditReport.tsx index 5ae404347807..cf05c13c3744 100644 --- a/src/pages/iou/request/step/IOURequestEditReport.tsx +++ b/src/pages/iou/request/step/IOURequestEditReport.tsx @@ -45,7 +45,10 @@ function IOURequestEditReport({route}: IOURequestEditReportProps) { const [allPolicyCategories] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}`, {canBeMissing: true}); const [allTransactions] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION, {canBeMissing: true}); const personalDetails = usePersonalDetails(); - const ownerPersonalDetails = useMemo(() => getPersonalDetailsForAccountID(selectedReport?.ownerAccountID) as PersonalDetails, [personalDetails, selectedReport]); + const ownerPersonalDetails = useMemo( + () => getPersonalDetailsForAccountID(selectedReport?.ownerAccountID, personalDetails) as PersonalDetails, + [personalDetails, selectedReport?.ownerAccountID], + ); const hasPerDiemTransactions = useMemo(() => { return selectedTransactionIDs.some((transactionID) => { diff --git a/src/pages/iou/request/step/IOURequestStepReport.tsx b/src/pages/iou/request/step/IOURequestStepReport.tsx index 1c1d7a56bdee..3b23a5072ede 100644 --- a/src/pages/iou/request/step/IOURequestStepReport.tsx +++ b/src/pages/iou/request/step/IOURequestStepReport.tsx @@ -56,7 +56,10 @@ function IOURequestStepReport({route, transaction}: IOURequestStepReportProps) { const isASAPSubmitBetaEnabled = isBetaEnabled(CONST.BETAS.ASAP_SUBMIT); const session = useSession(); const personalDetails = usePersonalDetails(); - const ownerPersonalDetails = useMemo(() => getPersonalDetailsForAccountID(selectedReport?.ownerAccountID) as PersonalDetails, [personalDetails, selectedReport]); + const ownerPersonalDetails = useMemo( + () => getPersonalDetailsForAccountID(selectedReport?.ownerAccountID, personalDetails) as PersonalDetails, + [personalDetails, selectedReport?.ownerAccountID], + ); const {policyForMovingExpensesID, shouldSelectPolicy} = usePolicyForMovingExpenses(isPerDiemRequest(transaction)); const [transactionViolations] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS, {canBeMissing: true}); const hasViolations = hasViolationsReportUtils(undefined, transactionViolations); From 7efe9832a19857b075a2c33e189ed461d96e304f Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Tue, 13 Jan 2026 15:08:21 +0100 Subject: [PATCH 12/22] handle unreported expenses --- .../iou/request/step/IOURequestStepReport.tsx | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/pages/iou/request/step/IOURequestStepReport.tsx b/src/pages/iou/request/step/IOURequestStepReport.tsx index c4b86249a5ba..9ee495f2ab33 100644 --- a/src/pages/iou/request/step/IOURequestStepReport.tsx +++ b/src/pages/iou/request/step/IOURequestStepReport.tsx @@ -14,6 +14,7 @@ import {createNewReport} from '@libs/actions/Report'; import {changeTransactionsReport, setTransactionReport} from '@libs/actions/Transaction'; import Navigation from '@libs/Navigation/Navigation'; import {getPolicyByCustomUnitID} from '@libs/PolicyUtils'; +import {isMoneyRequestAction} from '@libs/ReportActionsUtils'; import {getPersonalDetailsForAccountID, getReportOrDraftReport, hasViolations as hasViolationsReportUtils, isPolicyExpenseChat, isReportOutstanding} from '@libs/ReportUtils'; import {shouldRestrictUserBillableActions} from '@libs/SubscriptionUtils'; import {isPerDiemRequest} from '@libs/TransactionUtils'; @@ -21,7 +22,7 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; -import type {PersonalDetails, Report} from '@src/types/onyx'; +import type {PersonalDetails, Report, ReportAction, ReportActions} from '@src/types/onyx'; import IOURequestEditReportCommon from './IOURequestEditReportCommon'; import withFullTransactionOrNotFound from './withFullTransactionOrNotFound'; import type {WithFullTransactionOrNotFoundProps} from './withFullTransactionOrNotFound'; @@ -35,6 +36,10 @@ type TransactionGroupListItem = ListItem & { type IOURequestStepReportProps = WithWritableReportOrNotFoundProps & WithFullTransactionOrNotFoundProps; +const getIOUActionsSelector = (actions: OnyxEntry): ReportAction[] => { + return Object.values(actions ?? {}).filter(isMoneyRequestAction); +}; + function IOURequestStepReport({route, transaction}: IOURequestStepReportProps) { const {backTo, action, iouType, transactionID, reportID: reportIDFromRoute, reportActionID} = route.params; const [allReports] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}`, {canBeMissing: false}); @@ -50,6 +55,7 @@ function IOURequestStepReport({route, transaction}: IOURequestStepReportProps) { const [allPolicyCategories] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}`, {canBeMissing: true}); const {removeTransaction, setSelectedTransactions} = useSearchContext(); const reportOrDraftReport = getReportOrDraftReport(reportIDFromRoute); + const [iouActions] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportOrDraftReport?.parentReportID}`, {canBeMissing: true, selector: getIOUActionsSelector}); const isEditing = action === CONST.IOU.ACTION.EDIT; const isCreateReport = action === CONST.IOU.ACTION.CREATE; const isFromGlobalCreate = !!transaction?.isFromGlobalCreate; @@ -57,10 +63,13 @@ function IOURequestStepReport({route, transaction}: IOURequestStepReportProps) { const isASAPSubmitBetaEnabled = isBetaEnabled(CONST.BETAS.ASAP_SUBMIT); const session = useSession(); const personalDetails = usePersonalDetails(); - const ownerPersonalDetails = useMemo( - () => getPersonalDetailsForAccountID(selectedReport?.ownerAccountID, personalDetails) as PersonalDetails, - [personalDetails, selectedReport?.ownerAccountID], - ); + const ownerAccountID = useMemo(() => { + if (isUnreported) { + return iouActions?.at(0)?.actorAccountID; + } + return selectedReport?.ownerAccountID; + }, [isUnreported, selectedReport?.ownerAccountID, iouActions]); + const ownerPersonalDetails = useMemo(() => getPersonalDetailsForAccountID(ownerAccountID, personalDetails) as PersonalDetails, [personalDetails, ownerAccountID]); const {policyForMovingExpensesID, shouldSelectPolicy} = usePolicyForMovingExpenses(isPerDiemRequest(transaction)); const [transactionViolations] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS, {canBeMissing: true}); const hasViolations = hasViolationsReportUtils(undefined, transactionViolations, session?.accountID ?? CONST.DEFAULT_NUMBER_ID, session?.email ?? ''); @@ -233,6 +242,7 @@ function IOURequestStepReport({route, transaction}: IOURequestStepReportProps) { shouldShowNotFoundPage={shouldShowNotFoundPage} isPerDiemRequest={transaction ? isPerDiemRequest(transaction) : false} createReport={action === CONST.IOU.ACTION.EDIT && (policyForMovingExpensesID || shouldSelectPolicy || isPerDiemTransaction) ? createReport : undefined} + targetOwnerAccountID={ownerAccountID} /> ); From 8a129360695bd74842b6ff90d2912eaf3b656181 Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Tue, 13 Jan 2026 15:15:03 +0100 Subject: [PATCH 13/22] add comment --- src/libs/ReportUtils.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index a6997971137e..4587b71cef26 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -4545,6 +4545,7 @@ function canEditMoneyRequest( return false; } + // Domain admins can report unreported managed card transactions if (transaction.reportID === CONST.REPORT.UNREPORTED_REPORT_ID && isManagedCardTransaction(transaction)) { return true; } From a5225d782625035855ae5c66589d13487d28296a Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Tue, 13 Jan 2026 15:16:54 +0100 Subject: [PATCH 14/22] rename param reportCreatorEmail to ownerEmail --- src/libs/API/parameters/CreateAppReportParams.ts | 2 +- src/libs/actions/Report.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/API/parameters/CreateAppReportParams.ts b/src/libs/API/parameters/CreateAppReportParams.ts index 3f0be1944159..de9e533b86d2 100644 --- a/src/libs/API/parameters/CreateAppReportParams.ts +++ b/src/libs/API/parameters/CreateAppReportParams.ts @@ -4,7 +4,7 @@ type CreateAppReportParams = { reportID: string; reportActionID: string; reportPreviewReportActionID: string; - reportCreatorEmail?: string; + ownerEmail?: string; shouldDismissEmptyReportsConfirmation?: boolean; }; export default CreateAppReportParams; diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index 8bb990a5a4fb..28b95bfa3ae7 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -3152,7 +3152,7 @@ function createNewReport( reportID: optimisticReportID, reportActionID, reportPreviewReportActionID, - reportCreatorEmail: creatorPersonalDetails.login, + ownerEmail: creatorPersonalDetails.login, ...(shouldDismissEmptyReportsConfirmation ? {shouldDismissEmptyReportsConfirmation} : {}), }, {optimisticData, successData, failureData}, From f49d6120af39f9a65fabad59940d761d6db7cd59 Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Tue, 13 Jan 2026 15:18:18 +0100 Subject: [PATCH 15/22] rename variable --- src/libs/actions/Report.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index 28b95bfa3ae7..5b59cdaebec2 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -2900,12 +2900,12 @@ function buildNewReportOptimisticData( policy: OnyxEntry, reportID: string, reportActionID: string, - creatorPersonalDetails: CurrentUserPersonalDetails, + ownerPersonalDetails: CurrentUserPersonalDetails, reportPreviewReportActionID: string, hasViolationsParam: boolean, isASAPSubmitBetaEnabled: boolean, ) { - const {accountID, login, email} = creatorPersonalDetails; + const {accountID, login, email} = ownerPersonalDetails; const timeOfCreation = DateUtils.getDBTime(); const parentReport = getPolicyExpenseChat(accountID, policy?.id); const optimisticReportData = buildOptimisticEmptyReport(reportID, accountID, parentReport, reportPreviewReportActionID, policy, timeOfCreation); @@ -2957,7 +2957,7 @@ function buildNewReportOptimisticData( shouldShow: true, childOwnerAccountID: accountID, automatic: false, - avatar: creatorPersonalDetails.avatar, + avatar: ownerPersonalDetails.avatar, isAttachmentOnly: false, reportActionID: reportPreviewReportActionID, message: createReportActionMessage, @@ -3119,7 +3119,7 @@ function buildNewReportOptimisticData( } function createNewReport( - creatorPersonalDetails: CurrentUserPersonalDetails, + ownerPersonalDetails: CurrentUserPersonalDetails, hasViolationsParam: boolean, isASAPSubmitBetaEnabled: boolean, policy: OnyxEntry, @@ -3134,7 +3134,7 @@ function createNewReport( policy, optimisticReportID, reportActionID, - creatorPersonalDetails, + ownerPersonalDetails, reportPreviewReportActionID, hasViolationsParam, isASAPSubmitBetaEnabled, @@ -3152,13 +3152,13 @@ function createNewReport( reportID: optimisticReportID, reportActionID, reportPreviewReportActionID, - ownerEmail: creatorPersonalDetails.login, + ownerEmail: ownerPersonalDetails.login, ...(shouldDismissEmptyReportsConfirmation ? {shouldDismissEmptyReportsConfirmation} : {}), }, {optimisticData, successData, failureData}, ); if (shouldNotifyNewAction) { - notifyNewAction(parentReportID, creatorPersonalDetails.accountID, reportPreviewAction); + notifyNewAction(parentReportID, ownerPersonalDetails.accountID, reportPreviewAction); } return optimisticReportData; From 607b09d2139dd73395bb5d408914a740db0b19e4 Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Tue, 13 Jan 2026 15:20:41 +0100 Subject: [PATCH 16/22] lint --- src/components/Search/types.ts | 3 +-- src/pages/iou/request/step/IOURequestEditReportCommon.tsx | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/components/Search/types.ts b/src/components/Search/types.ts index 1735c30ce737..e7d0bbba11bb 100644 --- a/src/components/Search/types.ts +++ b/src/components/Search/types.ts @@ -3,8 +3,7 @@ import type {PaymentMethod} from '@components/KYCWall/types'; import type {ReportActionListItemType, TaskListItemType, TransactionGroupListItemType, TransactionListItemType} from '@components/SelectionListWithSections/types'; import type {SearchKey} from '@libs/SearchUIUtils'; import type CONST from '@src/CONST'; -import type {Transaction} from '@src/types/onyx'; -import type {ReportAction} from '@src/types/onyx'; +import type {ReportAction, Transaction} from '@src/types/onyx'; import type {SearchDataTypes} from '@src/types/onyx/SearchResults'; import type IconAsset from '@src/types/utils/IconAsset'; diff --git a/src/pages/iou/request/step/IOURequestEditReportCommon.tsx b/src/pages/iou/request/step/IOURequestEditReportCommon.tsx index 1180d335624e..b6962f385c8b 100644 --- a/src/pages/iou/request/step/IOURequestEditReportCommon.tsx +++ b/src/pages/iou/request/step/IOURequestEditReportCommon.tsx @@ -280,7 +280,7 @@ function IOURequestEditReportCommon({ icon={icons.Document} /> ); - }, [icons.Document, createReport, isEditing, isOwner, translate, policyForMovingExpenses?.name, handleCreateReport]); + }, [icons.Document, createReport, translate, policyForMovingExpenses?.name, handleCreateReport]); // eslint-disable-next-line rulesdir/no-negated-variables const shouldShowNotFoundPage = useMemo(() => { From e1727f0f4458b79314765fa5cf2b9fdfae80b2a8 Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Tue, 13 Jan 2026 15:48:00 +0100 Subject: [PATCH 17/22] lint --- src/pages/iou/request/step/IOURequestEditReportCommon.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/iou/request/step/IOURequestEditReportCommon.tsx b/src/pages/iou/request/step/IOURequestEditReportCommon.tsx index b6962f385c8b..43965da25060 100644 --- a/src/pages/iou/request/step/IOURequestEditReportCommon.tsx +++ b/src/pages/iou/request/step/IOURequestEditReportCommon.tsx @@ -80,6 +80,7 @@ function IOURequestEditReportCommon({ const {translate, localeCompare} = useLocalize(); const {options} = useOptionsList(); const [outstandingReportsByPolicyID] = useOnyx(ONYXKEYS.DERIVED.OUTSTANDING_REPORTS_BY_POLICY_ID, {canBeMissing: true}); + const [personalPolicyID] = useOnyx(ONYXKEYS.PERSONAL_POLICY_ID, {canBeMissing: true}); const [allPolicies] = useOnyx(ONYXKEYS.COLLECTION.POLICY, {canBeMissing: true}); const [allTransactions] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION, {canBeMissing: true}); const currentUserPersonalDetails = useCurrentUserPersonalDetails(); @@ -131,7 +132,6 @@ function IOURequestEditReportCommon({ if (!outstandingReportsByPolicyID || isEmptyObject(outstandingReportsByPolicyID)) { return []; } - const personalPolicyID = getPersonalPolicy()?.id; if (!selectedPolicyID || selectedPolicyID === personalPolicyID || isSelfDM(selectedReport)) { return Object.values(allPoliciesID ?? {}) .filter((policyID) => personalPolicyID !== policyID) @@ -157,7 +157,7 @@ function IOURequestEditReportCommon({ reportNameValuePairs, isEditing, ); - }, [outstandingReportsByPolicyID, resolvedReportOwnerAccountID, allPoliciesID, reportNameValuePairs, selectedReport, selectedPolicyID, isEditing]); + }, [personalPolicyID, outstandingReportsByPolicyID, resolvedReportOwnerAccountID, allPoliciesID, reportNameValuePairs, selectedReport, selectedPolicyID, isEditing]); const reportOptions: TransactionGroupListItem[] = useMemo(() => { if (!outstandingReportsByPolicyID || isEmptyObject(outstandingReportsByPolicyID)) { From 0eb413b18072737fa886226b441e8522fa2da830 Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Wed, 14 Jan 2026 17:27:49 +0100 Subject: [PATCH 18/22] lint --- src/pages/iou/request/step/IOURequestEditReportCommon.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/iou/request/step/IOURequestEditReportCommon.tsx b/src/pages/iou/request/step/IOURequestEditReportCommon.tsx index 43965da25060..c7efc739e063 100644 --- a/src/pages/iou/request/step/IOURequestEditReportCommon.tsx +++ b/src/pages/iou/request/step/IOURequestEditReportCommon.tsx @@ -18,7 +18,7 @@ import usePolicy from '@hooks/usePolicy'; import usePolicyForMovingExpenses from '@hooks/usePolicyForMovingExpenses'; import useReportTransactions from '@hooks/useReportTransactions'; import Navigation from '@libs/Navigation/Navigation'; -import {getPersonalPolicy, isPolicyAdmin} from '@libs/PolicyUtils'; +import {isPolicyAdmin} from '@libs/PolicyUtils'; import { canAddTransaction, getOutstandingReportsForUser, From 30e992737547b277ea82782a2bce1bb9da183c19 Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Wed, 14 Jan 2026 17:34:06 +0100 Subject: [PATCH 19/22] remove transaction from SelectedTransactionInfo --- src/components/Search/index.tsx | 4 ---- src/components/Search/types.ts | 5 +---- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/src/components/Search/index.tsx b/src/components/Search/index.tsx index 58da7f32ac65..184e35802e5b 100644 --- a/src/components/Search/index.tsx +++ b/src/components/Search/index.tsx @@ -102,7 +102,6 @@ function mapTransactionItemToSelectedEntry( return [ item.keyForList, { - transaction: item, isSelected: true, canReject: canRejectRequest, canHold: canHoldRequest, @@ -155,7 +154,6 @@ function prepareTransactionsList( return { ...selectedTransactions, [item.keyForList]: { - transaction: item, isSelected: true, canReject: canRejectRequest, canHold: canHoldRequest, @@ -482,7 +480,6 @@ function Search({ const originalItemTransaction = searchResults?.data?.[`${ONYXKEYS.COLLECTION.TRANSACTION}${itemTransaction?.comment?.originalTransactionID}`]; newTransactionList[transactionItem.transactionID] = { - transaction: transactionItem, action: transactionItem.action, canHold: canHoldRequest, isHeld: isOnHold(transactionItem), @@ -536,7 +533,6 @@ function Search({ const originalItemTransaction = searchResults?.data?.[`${ONYXKEYS.COLLECTION.TRANSACTION}${itemTransaction?.comment?.originalTransactionID}`]; newTransactionList[transactionItem.transactionID] = { - transaction: transactionItem, action: transactionItem.action, canHold: canHoldRequest, isHeld: isOnHold(transactionItem), diff --git a/src/components/Search/types.ts b/src/components/Search/types.ts index e7d0bbba11bb..289d2a889634 100644 --- a/src/components/Search/types.ts +++ b/src/components/Search/types.ts @@ -3,15 +3,12 @@ import type {PaymentMethod} from '@components/KYCWall/types'; import type {ReportActionListItemType, TaskListItemType, TransactionGroupListItemType, TransactionListItemType} from '@components/SelectionListWithSections/types'; import type {SearchKey} from '@libs/SearchUIUtils'; import type CONST from '@src/CONST'; -import type {ReportAction, Transaction} from '@src/types/onyx'; +import type {ReportAction} from '@src/types/onyx'; import type {SearchDataTypes} from '@src/types/onyx/SearchResults'; import type IconAsset from '@src/types/utils/IconAsset'; /** Model of the selected transaction */ type SelectedTransactionInfo = { - /** The transaction itself */ - transaction: Transaction; - /** Whether the transaction is selected */ isSelected: boolean; From f4aacedcffe504e37359df9008af75c21fe52c5e Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Wed, 14 Jan 2026 18:04:00 +0100 Subject: [PATCH 20/22] more robust condition --- src/pages/iou/request/step/IOURequestStepReport.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/pages/iou/request/step/IOURequestStepReport.tsx b/src/pages/iou/request/step/IOURequestStepReport.tsx index 0fff15ca0a89..f606a5f54a65 100644 --- a/src/pages/iou/request/step/IOURequestStepReport.tsx +++ b/src/pages/iou/request/step/IOURequestStepReport.tsx @@ -14,7 +14,7 @@ import {createNewReport} from '@libs/actions/Report'; import {changeTransactionsReport, setTransactionReport} from '@libs/actions/Transaction'; import Navigation from '@libs/Navigation/Navigation'; import {getPolicyByCustomUnitID} from '@libs/PolicyUtils'; -import {isMoneyRequestAction} from '@libs/ReportActionsUtils'; +import {getOriginalMessage, isMoneyRequestAction} from '@libs/ReportActionsUtils'; import {getPersonalDetailsForAccountID, getReportOrDraftReport, hasViolations as hasViolationsReportUtils, isPolicyExpenseChat, isReportOutstanding} from '@libs/ReportUtils'; import {shouldRestrictUserBillableActions} from '@libs/SubscriptionUtils'; import {isPerDiemRequest} from '@libs/TransactionUtils'; @@ -65,10 +65,11 @@ function IOURequestStepReport({route, transaction}: IOURequestStepReportProps) { const personalDetails = usePersonalDetails(); const ownerAccountID = useMemo(() => { if (isUnreported) { - return iouActions?.at(0)?.actorAccountID; + return iouActions?.find((iouAction) => getOriginalMessage(iouAction as ReportAction)?.IOUTransactionID === transaction.transactionID) + ?.actorAccountID; } return selectedReport?.ownerAccountID; - }, [isUnreported, selectedReport?.ownerAccountID, iouActions]); + }, [isUnreported, selectedReport?.ownerAccountID, iouActions, transaction?.transactionID]); const ownerPersonalDetails = useMemo(() => getPersonalDetailsForAccountID(ownerAccountID, personalDetails) as PersonalDetails, [personalDetails, ownerAccountID]); const {policyForMovingExpensesID, shouldSelectPolicy} = usePolicyForMovingExpenses(isPerDiemRequest(transaction)); const [transactionViolations] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS, {canBeMissing: true}); From 24b9b010f576131b26f3b94aa79272a176ebf530 Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Wed, 21 Jan 2026 20:35:44 +0100 Subject: [PATCH 21/22] get transactions from SelectedTransactions object --- src/components/Search/index.tsx | 4 ++++ src/components/Search/types.ts | 5 ++++- .../Search/SearchTransactionsChangeReport.tsx | 21 ++++++++++++++----- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/components/Search/index.tsx b/src/components/Search/index.tsx index 0423f0fba432..458d59c5e833 100644 --- a/src/components/Search/index.tsx +++ b/src/components/Search/index.tsx @@ -104,6 +104,7 @@ function mapTransactionItemToSelectedEntry( return [ item.keyForList, { + transaction: item, isSelected: true, canReject: canRejectRequest, canHold: canHoldRequest, @@ -157,6 +158,7 @@ function prepareTransactionsList( return { ...selectedTransactions, [item.keyForList]: { + transaction: item, isSelected: true, canReject: canRejectRequest, canHold: canHoldRequest, @@ -539,6 +541,7 @@ function Search({ const originalItemTransaction = searchResults?.data?.[`${ONYXKEYS.COLLECTION.TRANSACTION}${itemTransaction?.comment?.originalTransactionID}`]; newTransactionList[transactionItem.transactionID] = { + transaction: transactionItem, action: transactionItem.action, canHold: canHoldRequest, isHeld: isOnHold(transactionItem), @@ -593,6 +596,7 @@ function Search({ const originalItemTransaction = searchResults?.data?.[`${ONYXKEYS.COLLECTION.TRANSACTION}${itemTransaction?.comment?.originalTransactionID}`]; newTransactionList[transactionItem.transactionID] = { + transaction: transactionItem, action: transactionItem.action, canHold: canHoldRequest, isHeld: isOnHold(transactionItem), diff --git a/src/components/Search/types.ts b/src/components/Search/types.ts index b4272937bfed..add360fa1c93 100644 --- a/src/components/Search/types.ts +++ b/src/components/Search/types.ts @@ -3,12 +3,15 @@ import type {PaymentMethod} from '@components/KYCWall/types'; import type {ReportActionListItemType, TaskListItemType, TransactionGroupListItemType, TransactionListItemType} from '@components/SelectionListWithSections/types'; import type {SearchKey} from '@libs/SearchUIUtils'; import type CONST from '@src/CONST'; -import type {ReportAction, SearchResults} from '@src/types/onyx'; +import type {ReportAction, SearchResults, Transaction} from '@src/types/onyx'; import type {SearchDataTypes} from '@src/types/onyx/SearchResults'; import type IconAsset from '@src/types/utils/IconAsset'; /** Model of the selected transaction */ type SelectedTransactionInfo = { + /** The transaction itself */ + transaction: Transaction; + /** Whether the transaction is selected */ isSelected: boolean; diff --git a/src/pages/Search/SearchTransactionsChangeReport.tsx b/src/pages/Search/SearchTransactionsChangeReport.tsx index ebfc16284713..1358f66bc574 100644 --- a/src/pages/Search/SearchTransactionsChangeReport.tsx +++ b/src/pages/Search/SearchTransactionsChangeReport.tsx @@ -1,5 +1,6 @@ import React, {useMemo} from 'react'; import {InteractionManager} from 'react-native'; +import type {OnyxCollection} from 'react-native-onyx'; import {usePersonalDetails, useSession} from '@components/OnyxListItemProvider'; import {useSearchContext} from '@components/Search/SearchContext'; import type {ListItem} from '@components/SelectionListWithSections/types'; @@ -18,7 +19,7 @@ import IOURequestEditReportCommon from '@pages/iou/request/step/IOURequestEditRe import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; -import type {PersonalDetails} from '@src/types/onyx'; +import type {PersonalDetails, Transaction} from '@src/types/onyx'; type TransactionGroupListItem = ListItem & { /** reportID of the report */ @@ -28,6 +29,17 @@ type TransactionGroupListItem = ListItem & { function SearchTransactionsChangeReport() { const {selectedTransactions, clearSelectedTransactions} = useSearchContext(); const selectedTransactionsKeys = useMemo(() => Object.keys(selectedTransactions), [selectedTransactions]); + const transactions = useMemo( + () => + Object.values(selectedTransactions).reduce( + (transactionsCollection, transactionItem) => { + transactionsCollection[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionItem.transaction.transactionID}`] = transactionItem.transaction; + return transactionsCollection; + }, + {} as NonNullable>, + ), + [selectedTransactions], + ); const [allReportNextSteps] = useOnyx(ONYXKEYS.COLLECTION.NEXT_STEP, {canBeMissing: true}); const [allReports] = useOnyx(ONYXKEYS.COLLECTION.REPORT, {canBeMissing: false}); const [allPolicies] = useOnyx(ONYXKEYS.COLLECTION.POLICY, {canBeMissing: true}); @@ -36,7 +48,6 @@ function SearchTransactionsChangeReport() { const {policyForMovingExpensesID, shouldSelectPolicy} = usePolicyForMovingExpenses(hasPerDiemTransactions); const [transactionViolations] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS, {canBeMissing: true}); const [allBetas] = useOnyx(ONYXKEYS.BETAS, {canBeMissing: false}); - const [allTransactions] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION, {canBeMissing: true}); const {isBetaEnabled} = usePermissions(); const isASAPSubmitBetaEnabled = isBetaEnabled(CONST.BETAS.ASAP_SUBMIT); const session = useSession(); @@ -95,7 +106,7 @@ function SearchTransactionsChangeReport() { policy: policyForMovingExpenses, reportNextStep, policyCategories: allPolicyCategories?.[`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${policyForMovingExpensesID}`], - allTransactions, + allTransactions: transactions, }); clearSelectedTransactions(); }); @@ -137,7 +148,7 @@ function SearchTransactionsChangeReport() { policy: allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${item.policyID}`], reportNextStep, policyCategories: allPolicyCategories?.[`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${item.policyID}`], - allTransactions, + allTransactions: transactions, }); // eslint-disable-next-line @typescript-eslint/no-deprecated InteractionManager.runAfterInteractions(() => { @@ -156,7 +167,7 @@ function SearchTransactionsChangeReport() { isASAPSubmitBetaEnabled, accountID: session?.accountID ?? CONST.DEFAULT_NUMBER_ID, email: session?.email ?? '', - allTransactions, + allTransactions: transactions, }); clearSelectedTransactions(); Navigation.goBack(); From 1d3e0809914db7a87335fb760a15a9043b001a88 Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Wed, 21 Jan 2026 20:52:02 +0100 Subject: [PATCH 22/22] lint --- src/pages/Search/SearchTransactionsChangeReport.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pages/Search/SearchTransactionsChangeReport.tsx b/src/pages/Search/SearchTransactionsChangeReport.tsx index 1358f66bc574..e1773b937baa 100644 --- a/src/pages/Search/SearchTransactionsChangeReport.tsx +++ b/src/pages/Search/SearchTransactionsChangeReport.tsx @@ -33,6 +33,7 @@ function SearchTransactionsChangeReport() { () => Object.values(selectedTransactions).reduce( (transactionsCollection, transactionItem) => { + // eslint-disable-next-line no-param-reassign transactionsCollection[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionItem.transaction.transactionID}`] = transactionItem.transaction; return transactionsCollection; },