From 520c7413b292cd33fd496e0e8168b0a258c60f33 Mon Sep 17 00:00:00 2001 From: DylanDylann Date: Thu, 2 Apr 2026 17:42:51 +0700 Subject: [PATCH 1/6] refactor --- src/components/KYCWall/BaseKYCWall.tsx | 8 ++++++- src/hooks/useSearchBulkActions.ts | 24 ++++--------------- src/libs/ReportActionsUtils.ts | 32 +++++++++++++++++++++++++ src/libs/actions/Policy/Policy.ts | 3 ++- src/libs/actions/Report/index.ts | 3 ++- src/pages/ReportChangeWorkspacePage.tsx | 8 ++++++- 6 files changed, 54 insertions(+), 24 deletions(-) diff --git a/src/components/KYCWall/BaseKYCWall.tsx b/src/components/KYCWall/BaseKYCWall.tsx index 4f1006314248..a17af513f418 100644 --- a/src/components/KYCWall/BaseKYCWall.tsx +++ b/src/components/KYCWall/BaseKYCWall.tsx @@ -19,6 +19,7 @@ import Log from '@libs/Log'; import setNavigationActionToMicrotaskQueue from '@libs/Navigation/helpers/setNavigationActionToMicrotaskQueue'; import Navigation from '@libs/Navigation/Navigation'; import {hasExpensifyPaymentMethod} from '@libs/PaymentUtils'; +import {filterReportActionsByPolicyID} from '@libs/ReportActionsUtils'; import {getBankAccountRoute, isExpenseReport as isExpenseReportReportUtils, isIOUReport} from '@libs/ReportUtils'; import {getEligibleExistingBusinessBankAccounts, getOpenConnectedToPolicyBusinessBankAccounts} from '@libs/WorkflowUtils'; import {createWorkspaceFromIOUPayment} from '@userActions/Policy/Policy'; @@ -73,6 +74,8 @@ function KYCWall({ const personalDetails = usePersonalDetails(); const employeeEmail = personalDetails?.[iouReport?.ownerAccountID ?? CONST.DEFAULT_NUMBER_ID]?.login ?? ''; const reportTransactions = useReportTransactions(iouReport?.reportID); + const [allReports] = useOnyx(ONYXKEYS.COLLECTION.REPORT); + const [allReportActions] = useOnyx(ONYXKEYS.COLLECTION.REPORT_ACTIONS); const anchorRef = useRef(null); const transferBalanceButtonRef = useRef(null); @@ -138,7 +141,8 @@ function KYCWall({ if (iouReport && isIOUReport(iouReport)) { const adminPolicy = policies?.[`${ONYXKEYS.COLLECTION.POLICY}${policy?.id}`]; if (adminPolicy) { - const inviteResult = moveIOUReportToPolicyAndInviteSubmitter(iouReport, adminPolicy, formatPhoneNumber, reportTransactions); + const policyReportActions = filterReportActionsByPolicyID(allReportActions, allReports, adminPolicy.id); + const inviteResult = moveIOUReportToPolicyAndInviteSubmitter(iouReport, adminPolicy, formatPhoneNumber, policyReportActions, reportTransactions); if (inviteResult?.policyExpenseChatReportID) { setNavigationActionToMicrotaskQueue(() => { Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(inviteResult.policyExpenseChatReportID)); @@ -213,6 +217,8 @@ function KYCWall({ introSelected, formatPhoneNumber, reportTransactions, + allReportActions, + allReports, lastPaymentMethod, isSelfTourViewed, betas, diff --git a/src/hooks/useSearchBulkActions.ts b/src/hooks/useSearchBulkActions.ts index 8c63c3f9097f..fd4f2f0d269d 100644 --- a/src/hooks/useSearchBulkActions.ts +++ b/src/hooks/useSearchBulkActions.ts @@ -36,6 +36,7 @@ import {setNameValuePair} from '@libs/actions/User'; import {getTransactionsAndReportsFromSearch} from '@libs/MergeTransactionUtils'; import Navigation from '@libs/Navigation/Navigation'; import {getConnectedIntegration, isSubmitAndClose} from '@libs/PolicyUtils'; +import {filterReportActionsByPolicyID} from '@libs/ReportActionsUtils'; import {getSecondaryExportReportActions, isMergeActionForSelectedTransactions} from '@libs/ReportSecondaryActionUtils'; import { canEditMultipleTransactions, @@ -631,7 +632,8 @@ function useSearchBulkActions({queryJSON}: UseSearchBulkActionsParams) { ); return; } - const invite = moveIOUReportToPolicyAndInviteSubmitter(itemReport, adminPolicy, formatPhoneNumber, reportTransactions); + const policyReportActions = filterReportActionsByPolicyID(allReportActions, allReports, adminPolicy.id); + const invite = moveIOUReportToPolicyAndInviteSubmitter(itemReport, adminPolicy, formatPhoneNumber, policyReportActions, reportTransactions); if (!invite?.policyExpenseChatReportID) { moveIOUReportToPolicy(itemReport, adminPolicy, false, reportTransactions); } @@ -679,25 +681,7 @@ function useSearchBulkActions({queryJSON}: UseSearchBulkActionsParams) { clearSelectedTransactions(); }); }, - [ - clearSelectedTransactions, - hash, - isOffline, - lastPaymentMethods, - selectedReports, - selectedTransactions, - policies, - formatPhoneNumber, - policyIDsWithVBBA, - isDelegateAccessRestricted, - showDelegateNoAccessModal, - personalPolicyID, - allTransactions, - allReports, - userBillingGracePeriodEnds, - amountOwed, - ownerBillingGracePeriodEnd, - ], + [hash, isOffline, isDelegateAccessRestricted, selectedReports, selectedTransactions, userBillingGracePeriodEnds, ownerBillingGracePeriodEnd, amountOwed, policies, showDelegateNoAccessModal, allReports, personalPolicyID, lastPaymentMethods, allTransactions, policyIDsWithVBBA, allReportActions, formatPhoneNumber, clearSelectedTransactions], ); const onBulkPaySelectedRef = useRef(onBulkPaySelected); diff --git a/src/libs/ReportActionsUtils.ts b/src/libs/ReportActionsUtils.ts index 2c4beee07940..015c188944ad 100644 --- a/src/libs/ReportActionsUtils.ts +++ b/src/libs/ReportActionsUtils.ts @@ -4539,6 +4539,37 @@ function hasReasoning(action: OnyxInputOrEntry): boolean { return !!originalMessage && typeof originalMessage === 'object' && 'reasoning' in originalMessage && !!originalMessage.reasoning; } +/** + * Given all report actions and all reports, return report actions keyed by reportID + * for reports whose policyID matches the given policyID. + */ +function filterReportActionsByPolicyID(allReportActions: OnyxCollection, allReports: OnyxCollection, policyID: string | undefined): Record { + if (!allReportActions || !allReports || !policyID) { + return {}; + } + + const policyReportIDs = new Set(); + for (const [key, report] of Object.entries(allReports)) { + if (report?.policyID === policyID) { + const reportID = key.replace(ONYXKEYS.COLLECTION.REPORT, ''); + policyReportIDs.add(reportID); + } + } + + const result: Record = {}; + for (const [key, actions] of Object.entries(allReportActions)) { + if (!actions) { + continue; + } + const reportID = key.replace(ONYXKEYS.COLLECTION.REPORT_ACTIONS, ''); + if (policyReportIDs.has(reportID)) { + result[reportID] = actions; + } + } + + return result; +} + export { doesReportHaveVisibleActions, extractLinksFromMessageHtml, @@ -4798,6 +4829,7 @@ export { getReportActionActorAccountID, getSettlementAccountLockedMessage, stripFollowupListFromHtml, + filterReportActionsByPolicyID, getDynamicExternalWorkflowSubmitFailedActionMessage, getDynamicExternalWorkflowApproveFailedActionMessage, }; diff --git a/src/libs/actions/Policy/Policy.ts b/src/libs/actions/Policy/Policy.ts index 06211b30d322..4f70e0b2e06b 100644 --- a/src/libs/actions/Policy/Policy.ts +++ b/src/libs/actions/Policy/Policy.ts @@ -1544,6 +1544,7 @@ function verifySetupIntentAndRequestPolicyOwnerChange(policyID: string) { function createPolicyExpenseChats( policyID: string, invitedEmailsToAccountIDs: InvitedEmailsToAccountIDs, + reportActionsList?: OnyxCollection, hasOutstandingChildRequest = false, notificationPreference: NotificationPreference = CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN, ): WorkspaceMembersChats { @@ -1583,7 +1584,7 @@ function createPolicyExpenseChats( }, }); const currentTime = DateUtils.getDBTime(); - const reportActions = deprecatedAllReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${oldChat.reportID}`] ?? {}; + const reportActions = (reportActionsList ?? deprecatedAllReportActions)?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${oldChat.reportID}`] ?? {}; for (const action of Object.values(reportActions)) { if (action.actionName !== CONST.REPORT.ACTIONS.TYPE.REPORT_PREVIEW) { continue; diff --git a/src/libs/actions/Report/index.ts b/src/libs/actions/Report/index.ts index 7166a0a90e0e..93f99c62d68f 100644 --- a/src/libs/actions/Report/index.ts +++ b/src/libs/actions/Report/index.ts @@ -6103,6 +6103,7 @@ function moveIOUReportToPolicyAndInviteSubmitter( iouReport: OnyxEntry, policy: Policy, formatPhoneNumber: LocaleContextProps['formatPhoneNumber'], + reportActions: OnyxCollection, reportTransactions: Transaction[] = [], ): {policyExpenseChatReportID?: string} | undefined { if (!policy || !iouReport) { @@ -6176,7 +6177,7 @@ function moveIOUReportToPolicyAndInviteSubmitter( const announceRoomMembers = buildRoomMembersOnyxData(CONST.REPORT.CHAT_TYPE.POLICY_ANNOUNCE, policyID, [submitterAccountID]); // Create policy expense chat for the submitter - const policyExpenseChats = createPolicyExpenseChats(policyID, invitedEmailsToAccountIDs); + const policyExpenseChats = createPolicyExpenseChats(policyID, invitedEmailsToAccountIDs, reportActions); const optimisticPolicyExpenseChatReportID = policyExpenseChats.reportCreationData[submitterEmail].reportID; const optimisticPolicyExpenseChatCreatedReportActionID = policyExpenseChats.reportCreationData[submitterEmail].reportActionID; diff --git a/src/pages/ReportChangeWorkspacePage.tsx b/src/pages/ReportChangeWorkspacePage.tsx index 96fa4c97a99a..62f187cdccda 100644 --- a/src/pages/ReportChangeWorkspacePage.tsx +++ b/src/pages/ReportChangeWorkspacePage.tsx @@ -22,6 +22,7 @@ import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavig import type {ReportChangeWorkspaceNavigatorParamList} from '@libs/Navigation/types'; import {getLoginByAccountID} from '@libs/PersonalDetailsUtils'; import {isPolicyAdmin, isPolicyMember} from '@libs/PolicyUtils'; +import {filterReportActionsByPolicyID} from '@libs/ReportActionsUtils'; import { hasViolations as hasViolationsReportUtils, isExpenseReport, @@ -74,6 +75,8 @@ function ReportChangeWorkspacePage({report, route}: ReportChangeWorkspacePagePro const hasViolations = hasViolationsReportUtils(report?.reportID, transactionViolations, session?.accountID ?? CONST.DEFAULT_NUMBER_ID, session?.email ?? ''); const [ownerBillingGracePeriodEnd] = useOnyx(ONYXKEYS.NVP_PRIVATE_OWNER_BILLING_GRACE_PERIOD_END); const [userBillingGracePeriods] = useOnyx(ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_USER_BILLING_GRACE_PERIOD_END); + const [allReports] = useOnyx(ONYXKEYS.COLLECTION.REPORT); + const [allReportActions] = useOnyx(ONYXKEYS.COLLECTION.REPORT_ACTIONS); const selectPolicy = useCallback( (policyID?: string) => { @@ -88,7 +91,8 @@ function ReportChangeWorkspacePage({report, route}: ReportChangeWorkspacePagePro const {backTo} = route.params; Navigation.goBack(backTo); if (isIOUReport(reportID)) { - const invite = moveIOUReportToPolicyAndInviteSubmitter(report, policy, formatPhoneNumber, reportTransactions); + const policyReportActions = filterReportActionsByPolicyID(allReportActions, allReports, policyID); + const invite = moveIOUReportToPolicyAndInviteSubmitter(report, policy, formatPhoneNumber, policyReportActions, reportTransactions); if (!invite?.policyExpenseChatReportID) { moveIOUReportToPolicy(report, policy, false, reportTransactions); } @@ -134,6 +138,8 @@ function ReportChangeWorkspacePage({report, route}: ReportChangeWorkspacePagePro parentReport, formatPhoneNumber, reportTransactions, + allReportActions, + allReports, isReportLastVisibleArchived, session?.accountID, session?.email, From 671c66e4561cee8dbca863dd50c9e9c6fd303980 Mon Sep 17 00:00:00 2001 From: DylanDylann Date: Thu, 2 Apr 2026 21:23:23 +0700 Subject: [PATCH 2/6] resolve comment --- src/hooks/useSearchBulkActions.ts | 21 +++++- src/libs/ReportActionsUtils.ts | 21 +++--- src/libs/actions/Policy/Policy.ts | 1 + tests/unit/ReportActionsUtilsTest.ts | 105 +++++++++++++++++++++++++++ 4 files changed, 138 insertions(+), 10 deletions(-) diff --git a/src/hooks/useSearchBulkActions.ts b/src/hooks/useSearchBulkActions.ts index fd4f2f0d269d..1b0290f683b4 100644 --- a/src/hooks/useSearchBulkActions.ts +++ b/src/hooks/useSearchBulkActions.ts @@ -681,7 +681,26 @@ function useSearchBulkActions({queryJSON}: UseSearchBulkActionsParams) { clearSelectedTransactions(); }); }, - [hash, isOffline, isDelegateAccessRestricted, selectedReports, selectedTransactions, userBillingGracePeriodEnds, ownerBillingGracePeriodEnd, amountOwed, policies, showDelegateNoAccessModal, allReports, personalPolicyID, lastPaymentMethods, allTransactions, policyIDsWithVBBA, allReportActions, formatPhoneNumber, clearSelectedTransactions], + [ + hash, + isOffline, + isDelegateAccessRestricted, + selectedReports, + selectedTransactions, + userBillingGracePeriodEnds, + ownerBillingGracePeriodEnd, + amountOwed, + policies, + showDelegateNoAccessModal, + allReports, + personalPolicyID, + lastPaymentMethods, + allTransactions, + policyIDsWithVBBA, + allReportActions, + formatPhoneNumber, + clearSelectedTransactions, + ], ); const onBulkPaySelectedRef = useRef(onBulkPaySelected); diff --git a/src/libs/ReportActionsUtils.ts b/src/libs/ReportActionsUtils.ts index 015c188944ad..dd9df776260f 100644 --- a/src/libs/ReportActionsUtils.ts +++ b/src/libs/ReportActionsUtils.ts @@ -9,7 +9,7 @@ import type {ValueOf} from 'type-fest'; import type {LocaleContextProps, LocalizedTranslate} from '@components/LocaleContextProvider'; import usePrevious from '@hooks/usePrevious'; // eslint-disable-next-line @dword-design/import-alias/prefer-alias -import {doesReportContainRequestsFromMultipleUsers, getReportOrDraftReport} from '@libs/ReportUtils'; +import {doesReportContainRequestsFromMultipleUsers, getReportOrDraftReport, isThread} from '@libs/ReportUtils'; import CONST from '@src/CONST'; import IntlStore from '@src/languages/IntlStore'; import type {TranslationPaths} from '@src/languages/types'; @@ -4543,27 +4543,30 @@ function hasReasoning(action: OnyxInputOrEntry): boolean { * Given all report actions and all reports, return report actions keyed by reportID * for reports whose policyID matches the given policyID. */ -function filterReportActionsByPolicyID(allReportActions: OnyxCollection, allReports: OnyxCollection, policyID: string | undefined): Record { - if (!allReportActions || !allReports || !policyID) { +function filterReportActionsByPolicyID( + allReportActionsParam: OnyxCollection, + allReportsPram: OnyxCollection, + policyID: string | undefined, +): Record { + if (!allReportActionsParam || !allReportsPram || !policyID) { return {}; } const policyReportIDs = new Set(); - for (const [key, report] of Object.entries(allReports)) { - if (report?.policyID === policyID) { - const reportID = key.replace(ONYXKEYS.COLLECTION.REPORT, ''); - policyReportIDs.add(reportID); + for (const [, report] of Object.entries(allReportsPram)) { + if (report?.policyID === policyID && isPolicyExpenseChat(report) && !isThread(report)) { + policyReportIDs.add(report.reportID); } } const result: Record = {}; - for (const [key, actions] of Object.entries(allReportActions)) { + for (const [key, actions] of Object.entries(allReportActionsParam)) { if (!actions) { continue; } const reportID = key.replace(ONYXKEYS.COLLECTION.REPORT_ACTIONS, ''); if (policyReportIDs.has(reportID)) { - result[reportID] = actions; + result[key] = actions; } } diff --git a/src/libs/actions/Policy/Policy.ts b/src/libs/actions/Policy/Policy.ts index 4f70e0b2e06b..4daac932f748 100644 --- a/src/libs/actions/Policy/Policy.ts +++ b/src/libs/actions/Policy/Policy.ts @@ -1544,6 +1544,7 @@ function verifySetupIntentAndRequestPolicyOwnerChange(policyID: string) { function createPolicyExpenseChats( policyID: string, invitedEmailsToAccountIDs: InvitedEmailsToAccountIDs, + // TODO: Remove optional (?) once all is updated (https://github.com/Expensify/App/issues/66578) reportActionsList?: OnyxCollection, hasOutstandingChildRequest = false, notificationPreference: NotificationPreference = CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN, diff --git a/tests/unit/ReportActionsUtilsTest.ts b/tests/unit/ReportActionsUtilsTest.ts index 1f59950c971d..ce52d655faba 100644 --- a/tests/unit/ReportActionsUtilsTest.ts +++ b/tests/unit/ReportActionsUtilsTest.ts @@ -11,6 +11,7 @@ import {chatReportR14932 as mockChatReport, iouReportR14932 as mockIOUReport} fr import CONST from '../../src/CONST'; import * as ReportActionsUtils from '../../src/libs/ReportActionsUtils'; import { + filterReportActionsByPolicyID, findLastReportActions, getAddedCardFeedMessage, getAssignedCompanyCardMessage, @@ -4676,4 +4677,108 @@ describe('ReportActionsUtils', () => { ).toBe(false); }); }); + + describe('filterReportActionsByPolicyID', () => { + const policyID = 'policy123'; + const otherPolicyID = 'otherPolicy'; + + const policyExpenseReport: Report = { + reportID: '1', + policyID, + chatType: CONST.REPORT.CHAT_TYPE.POLICY_EXPENSE_CHAT, + type: CONST.REPORT.TYPE.CHAT, + reportName: 'Expense Chat', + }; + + const otherPolicyReport: Report = { + reportID: '2', + policyID: otherPolicyID, + chatType: CONST.REPORT.CHAT_TYPE.POLICY_EXPENSE_CHAT, + type: CONST.REPORT.TYPE.CHAT, + reportName: 'Other Policy Chat', + }; + + const threadReport: Report = { + reportID: '3', + policyID, + chatType: CONST.REPORT.CHAT_TYPE.POLICY_EXPENSE_CHAT, + type: CONST.REPORT.TYPE.CHAT, + parentReportID: '1', + parentReportActionID: 'action1', + reportName: 'Thread', + }; + + const nonExpenseChatReport: Report = { + reportID: '4', + policyID, + chatType: CONST.REPORT.CHAT_TYPE.POLICY_ROOM, + type: CONST.REPORT.TYPE.CHAT, + reportName: 'Policy Room', + }; + + const actions1: ReportActions = {action1: createRandomReportAction(1)}; + const actions2: ReportActions = {action2: createRandomReportAction(2)}; + const actions3: ReportActions = {action3: createRandomReportAction(3)}; + const actions4: ReportActions = {action4: createRandomReportAction(4)}; + + const allReports = { + // eslint-disable-next-line @typescript-eslint/naming-convention + report_1: policyExpenseReport, + // eslint-disable-next-line @typescript-eslint/naming-convention + report_2: otherPolicyReport, + // eslint-disable-next-line @typescript-eslint/naming-convention + report_3: threadReport, + // eslint-disable-next-line @typescript-eslint/naming-convention + report_4: nonExpenseChatReport, + }; + + const allReportActions = { + [`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}1`]: actions1, + [`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}2`]: actions2, + [`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}3`]: actions3, + [`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}4`]: actions4, + }; + + it('returns empty object when allReportActions is undefined', () => { + expect(filterReportActionsByPolicyID(undefined, allReports, policyID)).toEqual({}); + }); + + it('returns empty object when allReports is undefined', () => { + expect(filterReportActionsByPolicyID(allReportActions, undefined, policyID)).toEqual({}); + }); + + it('returns empty object when policyID is undefined', () => { + expect(filterReportActionsByPolicyID(allReportActions, allReports, undefined)).toEqual({}); + }); + + it('returns only actions for policy expense chats matching the policyID', () => { + const result = filterReportActionsByPolicyID(allReportActions, allReports, policyID); + expect(result).toHaveProperty('1'); + expect(result['1']).toBe(actions1); + }); + + it('excludes reports with a different policyID', () => { + const result = filterReportActionsByPolicyID(allReportActions, allReports, policyID); + expect(result).not.toHaveProperty('2'); + }); + + it('excludes thread reports', () => { + const result = filterReportActionsByPolicyID(allReportActions, allReports, policyID); + expect(result).not.toHaveProperty('3'); + }); + + it('excludes non-policy-expense-chat reports', () => { + const result = filterReportActionsByPolicyID(allReportActions, allReports, policyID); + expect(result).not.toHaveProperty('4'); + }); + + it('skips null actions entries', () => { + const actionsWithNull = { + ...allReportActions, + [`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}1`]: null, + }; + const result = filterReportActionsByPolicyID(actionsWithNull, allReports, policyID); + expect(result).toEqual({}); + }); + }); }); From 9eea7fe92d632dd5f6d26ca44479fd07cbd011d9 Mon Sep 17 00:00:00 2001 From: DylanDylann Date: Thu, 2 Apr 2026 21:51:07 +0700 Subject: [PATCH 3/6] resolve comment --- src/components/KYCWall/BaseKYCWall.tsx | 11 +- .../usePolicyExpenseChatReportActions.ts | 54 +++++++++ src/hooks/useSearchBulkActions.ts | 7 +- src/libs/ReportActionsUtils.ts | 35 ------ src/libs/actions/Policy/Member.ts | 3 +- src/libs/actions/Policy/Policy.ts | 11 +- src/pages/ReportChangeWorkspacePage.tsx | 11 +- tests/unit/ReportActionsUtilsTest.ts | 105 ------------------ 8 files changed, 77 insertions(+), 160 deletions(-) create mode 100644 src/hooks/usePolicyExpenseChatReportActions.ts diff --git a/src/components/KYCWall/BaseKYCWall.tsx b/src/components/KYCWall/BaseKYCWall.tsx index a17af513f418..78ca3ab26432 100644 --- a/src/components/KYCWall/BaseKYCWall.tsx +++ b/src/components/KYCWall/BaseKYCWall.tsx @@ -8,6 +8,7 @@ import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails' import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; import useParentReportAction from '@hooks/useParentReportAction'; +import usePolicyExpenseChatReportActions from '@hooks/usePolicyExpenseChatReportActions'; import useReportTransactions from '@hooks/useReportTransactions'; import {openPersonalBankAccountSetupView} from '@libs/actions/BankAccounts'; import {completePaymentOnboarding, savePreferredPaymentMethod} from '@libs/actions/IOU'; @@ -19,7 +20,6 @@ import Log from '@libs/Log'; import setNavigationActionToMicrotaskQueue from '@libs/Navigation/helpers/setNavigationActionToMicrotaskQueue'; import Navigation from '@libs/Navigation/Navigation'; import {hasExpensifyPaymentMethod} from '@libs/PaymentUtils'; -import {filterReportActionsByPolicyID} from '@libs/ReportActionsUtils'; import {getBankAccountRoute, isExpenseReport as isExpenseReportReportUtils, isIOUReport} from '@libs/ReportUtils'; import {getEligibleExistingBusinessBankAccounts, getOpenConnectedToPolicyBusinessBankAccounts} from '@libs/WorkflowUtils'; import {createWorkspaceFromIOUPayment} from '@userActions/Policy/Policy'; @@ -74,8 +74,7 @@ function KYCWall({ const personalDetails = usePersonalDetails(); const employeeEmail = personalDetails?.[iouReport?.ownerAccountID ?? CONST.DEFAULT_NUMBER_ID]?.login ?? ''; const reportTransactions = useReportTransactions(iouReport?.reportID); - const [allReports] = useOnyx(ONYXKEYS.COLLECTION.REPORT); - const [allReportActions] = useOnyx(ONYXKEYS.COLLECTION.REPORT_ACTIONS); + const {filteredReportActions} = usePolicyExpenseChatReportActions(); const anchorRef = useRef(null); const transferBalanceButtonRef = useRef(null); @@ -141,8 +140,7 @@ function KYCWall({ if (iouReport && isIOUReport(iouReport)) { const adminPolicy = policies?.[`${ONYXKEYS.COLLECTION.POLICY}${policy?.id}`]; if (adminPolicy) { - const policyReportActions = filterReportActionsByPolicyID(allReportActions, allReports, adminPolicy.id); - const inviteResult = moveIOUReportToPolicyAndInviteSubmitter(iouReport, adminPolicy, formatPhoneNumber, policyReportActions, reportTransactions); + const inviteResult = moveIOUReportToPolicyAndInviteSubmitter(iouReport, adminPolicy, formatPhoneNumber, filteredReportActions, reportTransactions); if (inviteResult?.policyExpenseChatReportID) { setNavigationActionToMicrotaskQueue(() => { Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(inviteResult.policyExpenseChatReportID)); @@ -217,8 +215,7 @@ function KYCWall({ introSelected, formatPhoneNumber, reportTransactions, - allReportActions, - allReports, + filteredReportActions, lastPaymentMethod, isSelfTourViewed, betas, diff --git a/src/hooks/usePolicyExpenseChatReportActions.ts b/src/hooks/usePolicyExpenseChatReportActions.ts new file mode 100644 index 000000000000..9dfe41e95b53 --- /dev/null +++ b/src/hooks/usePolicyExpenseChatReportActions.ts @@ -0,0 +1,54 @@ +import {useCallback, useMemo} from 'react'; +import type {OnyxCollection} from 'react-native-onyx'; +import {isPolicyExpenseChat, isThread} from '@libs/ReportUtils'; +import ONYXKEYS from '@src/ONYXKEYS'; +import type {Report, ReportActions} from '@src/types/onyx'; +import mapOnyxCollectionItems from '@src/utils/mapOnyxCollectionItems'; +import useOnyx from './useOnyx'; + +const policyExpenseChatReportsSelector = (reports: OnyxCollection) => { + return mapOnyxCollectionItems(reports, (report) => { + if (!report || !isPolicyExpenseChat(report) || isThread(report)) { + return undefined; + } + return report; + }); +}; + +/** + * Returns all reports that satisfy isPolicyExpenseChat && !isThread (via selector), + * along with reportActions filtered to only those matching reports. + */ +function usePolicyExpenseChatReportActions() { + const [policyExpenseChatReports] = useOnyx(ONYXKEYS.COLLECTION.REPORT, {selector: policyExpenseChatReportsSelector}); + + const policyExpenseChatReportIDs = useMemo(() => { + const ids = new Set(); + for (const report of Object.values(policyExpenseChatReports ?? {})) { + if (report?.reportID) { + ids.add(report.reportID); + } + } + return ids; + }, [policyExpenseChatReports]); + + const reportActionsSelector = useCallback( + (reportActions: OnyxCollection) => { + const result: NonNullable> = {}; + for (const [key, actions] of Object.entries(reportActions ?? {})) { + const reportID = key.replace(ONYXKEYS.COLLECTION.REPORT_ACTIONS, ''); + if (policyExpenseChatReportIDs.has(reportID)) { + result[key] = actions; + } + } + return result; + }, + [policyExpenseChatReportIDs], + ); + + const [filteredReportActions] = useOnyx(ONYXKEYS.COLLECTION.REPORT_ACTIONS, {selector: reportActionsSelector}, [reportActionsSelector]); + + return {policyExpenseChatReports, filteredReportActions}; +} + +export default usePolicyExpenseChatReportActions; diff --git a/src/hooks/useSearchBulkActions.ts b/src/hooks/useSearchBulkActions.ts index 1b0290f683b4..240a7e6bd2e0 100644 --- a/src/hooks/useSearchBulkActions.ts +++ b/src/hooks/useSearchBulkActions.ts @@ -36,7 +36,6 @@ import {setNameValuePair} from '@libs/actions/User'; import {getTransactionsAndReportsFromSearch} from '@libs/MergeTransactionUtils'; import Navigation from '@libs/Navigation/Navigation'; import {getConnectedIntegration, isSubmitAndClose} from '@libs/PolicyUtils'; -import {filterReportActionsByPolicyID} from '@libs/ReportActionsUtils'; import {getSecondaryExportReportActions, isMergeActionForSelectedTransactions} from '@libs/ReportSecondaryActionUtils'; import { canEditMultipleTransactions, @@ -71,6 +70,7 @@ import useNetwork from './useNetwork'; import useOnyx from './useOnyx'; import usePermissions from './usePermissions'; import usePersonalPolicy from './usePersonalPolicy'; +import usePolicyExpenseChatReportActions from './usePolicyExpenseChatReportActions'; import useSelfDMReport from './useSelfDMReport'; import useTheme from './useTheme'; import useThemeStyles from './useThemeStyles'; @@ -111,6 +111,7 @@ function useSearchBulkActions({queryJSON}: UseSearchBulkActionsParams) { const allTransactions = useAllTransactions(); const [allReports] = useOnyx(ONYXKEYS.COLLECTION.REPORT); const [allReportActions] = useOnyx(ONYXKEYS.COLLECTION.REPORT_ACTIONS); + const {filteredReportActions: policyExpenseChatReportActions} = usePolicyExpenseChatReportActions(); const [allReportNameValuePairs] = useOnyx(ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS); const selfDMReport = useSelfDMReport(); const [lastPaymentMethods] = useOnyx(ONYXKEYS.NVP_LAST_PAYMENT_METHOD); @@ -632,8 +633,7 @@ function useSearchBulkActions({queryJSON}: UseSearchBulkActionsParams) { ); return; } - const policyReportActions = filterReportActionsByPolicyID(allReportActions, allReports, adminPolicy.id); - const invite = moveIOUReportToPolicyAndInviteSubmitter(itemReport, adminPolicy, formatPhoneNumber, policyReportActions, reportTransactions); + const invite = moveIOUReportToPolicyAndInviteSubmitter(itemReport, adminPolicy, formatPhoneNumber, policyExpenseChatReportActions, reportTransactions); if (!invite?.policyExpenseChatReportID) { moveIOUReportToPolicy(itemReport, adminPolicy, false, reportTransactions); } @@ -698,6 +698,7 @@ function useSearchBulkActions({queryJSON}: UseSearchBulkActionsParams) { allTransactions, policyIDsWithVBBA, allReportActions, + policyExpenseChatReportActions, formatPhoneNumber, clearSelectedTransactions, ], diff --git a/src/libs/ReportActionsUtils.ts b/src/libs/ReportActionsUtils.ts index dd9df776260f..66dc603ff99f 100644 --- a/src/libs/ReportActionsUtils.ts +++ b/src/libs/ReportActionsUtils.ts @@ -4539,40 +4539,6 @@ function hasReasoning(action: OnyxInputOrEntry): boolean { return !!originalMessage && typeof originalMessage === 'object' && 'reasoning' in originalMessage && !!originalMessage.reasoning; } -/** - * Given all report actions and all reports, return report actions keyed by reportID - * for reports whose policyID matches the given policyID. - */ -function filterReportActionsByPolicyID( - allReportActionsParam: OnyxCollection, - allReportsPram: OnyxCollection, - policyID: string | undefined, -): Record { - if (!allReportActionsParam || !allReportsPram || !policyID) { - return {}; - } - - const policyReportIDs = new Set(); - for (const [, report] of Object.entries(allReportsPram)) { - if (report?.policyID === policyID && isPolicyExpenseChat(report) && !isThread(report)) { - policyReportIDs.add(report.reportID); - } - } - - const result: Record = {}; - for (const [key, actions] of Object.entries(allReportActionsParam)) { - if (!actions) { - continue; - } - const reportID = key.replace(ONYXKEYS.COLLECTION.REPORT_ACTIONS, ''); - if (policyReportIDs.has(reportID)) { - result[key] = actions; - } - } - - return result; -} - export { doesReportHaveVisibleActions, extractLinksFromMessageHtml, @@ -4832,7 +4798,6 @@ export { getReportActionActorAccountID, getSettlementAccountLockedMessage, stripFollowupListFromHtml, - filterReportActionsByPolicyID, getDynamicExternalWorkflowSubmitFailedActionMessage, getDynamicExternalWorkflowApproveFailedActionMessage, }; diff --git a/src/libs/actions/Policy/Member.ts b/src/libs/actions/Policy/Member.ts index e77277022878..0765f0a001c6 100644 --- a/src/libs/actions/Policy/Member.ts +++ b/src/libs/actions/Policy/Member.ts @@ -869,7 +869,8 @@ function buildAddMembersToWorkspaceOnyxData( const announceRoomChat = optimisticAnnounceChat.announceChatData; // create onyx data for policy expense chats for each new member - const membersChats = createPolicyExpenseChats(policyID, invitedEmailsToAccountIDs, undefined, policyExpenseChatNotificationPreference); + // TODO: Update to include reportActionsList later (https://github.com/Expensify/App/issues/66578) + const membersChats = createPolicyExpenseChats(policyID, invitedEmailsToAccountIDs, undefined, undefined, policyExpenseChatNotificationPreference); const optimisticMembersState: OnyxCollectionInputValue = {}; const successMembersState: OnyxCollectionInputValue = {}; diff --git a/src/libs/actions/Policy/Policy.ts b/src/libs/actions/Policy/Policy.ts index 4daac932f748..0b2a8a7e2d40 100644 --- a/src/libs/actions/Policy/Policy.ts +++ b/src/libs/actions/Policy/Policy.ts @@ -2899,7 +2899,13 @@ function buildPolicyData(options: BuildPolicyDataOptions): OnyxData { @@ -91,8 +90,7 @@ function ReportChangeWorkspacePage({report, route}: ReportChangeWorkspacePagePro const {backTo} = route.params; Navigation.goBack(backTo); if (isIOUReport(reportID)) { - const policyReportActions = filterReportActionsByPolicyID(allReportActions, allReports, policyID); - const invite = moveIOUReportToPolicyAndInviteSubmitter(report, policy, formatPhoneNumber, policyReportActions, reportTransactions); + const invite = moveIOUReportToPolicyAndInviteSubmitter(report, policy, formatPhoneNumber, filteredReportActions, reportTransactions); if (!invite?.policyExpenseChatReportID) { moveIOUReportToPolicy(report, policy, false, reportTransactions); } @@ -138,8 +136,7 @@ function ReportChangeWorkspacePage({report, route}: ReportChangeWorkspacePagePro parentReport, formatPhoneNumber, reportTransactions, - allReportActions, - allReports, + filteredReportActions, isReportLastVisibleArchived, session?.accountID, session?.email, diff --git a/tests/unit/ReportActionsUtilsTest.ts b/tests/unit/ReportActionsUtilsTest.ts index ce52d655faba..1f59950c971d 100644 --- a/tests/unit/ReportActionsUtilsTest.ts +++ b/tests/unit/ReportActionsUtilsTest.ts @@ -11,7 +11,6 @@ import {chatReportR14932 as mockChatReport, iouReportR14932 as mockIOUReport} fr import CONST from '../../src/CONST'; import * as ReportActionsUtils from '../../src/libs/ReportActionsUtils'; import { - filterReportActionsByPolicyID, findLastReportActions, getAddedCardFeedMessage, getAssignedCompanyCardMessage, @@ -4677,108 +4676,4 @@ describe('ReportActionsUtils', () => { ).toBe(false); }); }); - - describe('filterReportActionsByPolicyID', () => { - const policyID = 'policy123'; - const otherPolicyID = 'otherPolicy'; - - const policyExpenseReport: Report = { - reportID: '1', - policyID, - chatType: CONST.REPORT.CHAT_TYPE.POLICY_EXPENSE_CHAT, - type: CONST.REPORT.TYPE.CHAT, - reportName: 'Expense Chat', - }; - - const otherPolicyReport: Report = { - reportID: '2', - policyID: otherPolicyID, - chatType: CONST.REPORT.CHAT_TYPE.POLICY_EXPENSE_CHAT, - type: CONST.REPORT.TYPE.CHAT, - reportName: 'Other Policy Chat', - }; - - const threadReport: Report = { - reportID: '3', - policyID, - chatType: CONST.REPORT.CHAT_TYPE.POLICY_EXPENSE_CHAT, - type: CONST.REPORT.TYPE.CHAT, - parentReportID: '1', - parentReportActionID: 'action1', - reportName: 'Thread', - }; - - const nonExpenseChatReport: Report = { - reportID: '4', - policyID, - chatType: CONST.REPORT.CHAT_TYPE.POLICY_ROOM, - type: CONST.REPORT.TYPE.CHAT, - reportName: 'Policy Room', - }; - - const actions1: ReportActions = {action1: createRandomReportAction(1)}; - const actions2: ReportActions = {action2: createRandomReportAction(2)}; - const actions3: ReportActions = {action3: createRandomReportAction(3)}; - const actions4: ReportActions = {action4: createRandomReportAction(4)}; - - const allReports = { - // eslint-disable-next-line @typescript-eslint/naming-convention - report_1: policyExpenseReport, - // eslint-disable-next-line @typescript-eslint/naming-convention - report_2: otherPolicyReport, - // eslint-disable-next-line @typescript-eslint/naming-convention - report_3: threadReport, - // eslint-disable-next-line @typescript-eslint/naming-convention - report_4: nonExpenseChatReport, - }; - - const allReportActions = { - [`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}1`]: actions1, - [`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}2`]: actions2, - [`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}3`]: actions3, - [`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}4`]: actions4, - }; - - it('returns empty object when allReportActions is undefined', () => { - expect(filterReportActionsByPolicyID(undefined, allReports, policyID)).toEqual({}); - }); - - it('returns empty object when allReports is undefined', () => { - expect(filterReportActionsByPolicyID(allReportActions, undefined, policyID)).toEqual({}); - }); - - it('returns empty object when policyID is undefined', () => { - expect(filterReportActionsByPolicyID(allReportActions, allReports, undefined)).toEqual({}); - }); - - it('returns only actions for policy expense chats matching the policyID', () => { - const result = filterReportActionsByPolicyID(allReportActions, allReports, policyID); - expect(result).toHaveProperty('1'); - expect(result['1']).toBe(actions1); - }); - - it('excludes reports with a different policyID', () => { - const result = filterReportActionsByPolicyID(allReportActions, allReports, policyID); - expect(result).not.toHaveProperty('2'); - }); - - it('excludes thread reports', () => { - const result = filterReportActionsByPolicyID(allReportActions, allReports, policyID); - expect(result).not.toHaveProperty('3'); - }); - - it('excludes non-policy-expense-chat reports', () => { - const result = filterReportActionsByPolicyID(allReportActions, allReports, policyID); - expect(result).not.toHaveProperty('4'); - }); - - it('skips null actions entries', () => { - const actionsWithNull = { - ...allReportActions, - [`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}1`]: null, - }; - const result = filterReportActionsByPolicyID(actionsWithNull, allReports, policyID); - expect(result).toEqual({}); - }); - }); }); From 87d62abb15e0fced912eb5626b97bea195ea267c Mon Sep 17 00:00:00 2001 From: DylanDylann Date: Thu, 2 Apr 2026 22:02:26 +0700 Subject: [PATCH 4/6] resolve comment --- src/libs/ReportActionsUtils.ts | 2 +- tests/actions/ReportTest.ts | 96 +++++++++++++++++++++++++++++++++- 2 files changed, 95 insertions(+), 3 deletions(-) diff --git a/src/libs/ReportActionsUtils.ts b/src/libs/ReportActionsUtils.ts index 66dc603ff99f..2c4beee07940 100644 --- a/src/libs/ReportActionsUtils.ts +++ b/src/libs/ReportActionsUtils.ts @@ -9,7 +9,7 @@ import type {ValueOf} from 'type-fest'; import type {LocaleContextProps, LocalizedTranslate} from '@components/LocaleContextProvider'; import usePrevious from '@hooks/usePrevious'; // eslint-disable-next-line @dword-design/import-alias/prefer-alias -import {doesReportContainRequestsFromMultipleUsers, getReportOrDraftReport, isThread} from '@libs/ReportUtils'; +import {doesReportContainRequestsFromMultipleUsers, getReportOrDraftReport} from '@libs/ReportUtils'; import CONST from '@src/CONST'; import IntlStore from '@src/languages/IntlStore'; import type {TranslationPaths} from '@src/languages/types'; diff --git a/tests/actions/ReportTest.ts b/tests/actions/ReportTest.ts index 7763d49700b0..ec603705ad79 100644 --- a/tests/actions/ReportTest.ts +++ b/tests/actions/ReportTest.ts @@ -3583,7 +3583,7 @@ describe('actions/Report', () => { await Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${policy.id}`, policy); // When moving iou to a workspace and invite the submitter - Report.moveIOUReportToPolicyAndInviteSubmitter(iouReport, policy, (phone: string) => phone); + Report.moveIOUReportToPolicyAndInviteSubmitter(iouReport, policy, (phone: string) => phone, {}); await waitForBatchedUpdates(); // Then MOVED report action should be added to the expense report @@ -3650,7 +3650,7 @@ describe('actions/Report', () => { // Call moveIOUReportToPolicyAndInviteSubmitter const formatPhoneNumber = (phoneNumber: string) => phoneNumber; - Report.moveIOUReportToPolicyAndInviteSubmitter(iouReport, policy, formatPhoneNumber); + Report.moveIOUReportToPolicyAndInviteSubmitter(iouReport, policy, formatPhoneNumber, {}); await waitForBatchedUpdates(); // Simulate network failure @@ -3677,6 +3677,98 @@ describe('actions/Report', () => { // Cleanup mockFetch.succeed?.(); }); + + it('should negate transaction amounts when reportTransactions are provided', async () => { + const ownerAccountID = 1; + const ownerEmail = 'owner@gmail.com'; + const transactionID = 'txn123'; + const iouReport: OnyxTypes.Report = { + ...createRandomReport(1, undefined), + type: CONST.REPORT.TYPE.IOU, + ownerAccountID, + total: 5000, + }; + const policy: OnyxTypes.Policy = {...createRandomPolicy(1), role: CONST.POLICY.ROLE.ADMIN}; + const transaction: OnyxTypes.Transaction = { + ...createRandomTransaction(1), + transactionID, + reportID: iouReport.reportID, + amount: 5000, + modifiedAmount: 6000, + }; + + await Onyx.merge(ONYXKEYS.PERSONAL_DETAILS_LIST, { + [ownerAccountID]: { + login: ownerEmail, + }, + }); + await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${iouReport.reportID}`, iouReport); + await Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${policy.id}`, policy); + await Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, transaction); + + // When moving IOU to a workspace with reportTransactions + Report.moveIOUReportToPolicyAndInviteSubmitter(iouReport, policy, (phone: string) => phone, {}, [transaction]); + await waitForBatchedUpdates(); + + // Then the transaction amounts should be negated optimistically + const updatedTransaction = await new Promise>((resolve) => { + const connection = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, + callback: (val) => { + resolve(val); + Onyx.disconnect(connection); + }, + }); + }); + expect(updatedTransaction?.amount).toBe(-5000); + expect(updatedTransaction?.modifiedAmount).toBe(-6000); + }); + + it('should convert IOU report to expense report with correct policyID when reportTransactions are provided', async () => { + const ownerAccountID = 1; + const ownerEmail = 'owner@gmail.com'; + const transactionID = 'txn456'; + const iouReport: OnyxTypes.Report = { + ...createRandomReport(1, undefined), + type: CONST.REPORT.TYPE.IOU, + ownerAccountID, + total: 3000, + }; + const policy: OnyxTypes.Policy = {...createRandomPolicy(1), role: CONST.POLICY.ROLE.ADMIN}; + const transaction: OnyxTypes.Transaction = { + ...createRandomTransaction(1), + transactionID, + reportID: iouReport.reportID, + amount: 3000, + }; + + await Onyx.merge(ONYXKEYS.PERSONAL_DETAILS_LIST, { + [ownerAccountID]: { + login: ownerEmail, + }, + }); + await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${iouReport.reportID}`, iouReport); + await Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${policy.id}`, policy); + await Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, transaction); + + // When moving IOU to a workspace with transactions + Report.moveIOUReportToPolicyAndInviteSubmitter(iouReport, policy, (phone: string) => phone, {}, [transaction]); + await waitForBatchedUpdates(); + + // Then the report should be converted to an expense report with the new policyID + const updatedReport = await new Promise>((resolve) => { + const connection = Onyx.connect({ + key: `${ONYXKEYS.COLLECTION.REPORT}${iouReport.reportID}`, + callback: (val) => { + resolve(val); + Onyx.disconnect(connection); + }, + }); + }); + expect(updatedReport?.type).toBe(CONST.REPORT.TYPE.EXPENSE); + expect(updatedReport?.policyID).toBe(policy.id); + expect(updatedReport?.total).toBe(-3000); + }); }); describe('buildOptimisticChangePolicyData', () => { From 33092453c8c035519406c764aeadd7fd1e378f5f Mon Sep 17 00:00:00 2001 From: DylanDylann Date: Fri, 3 Apr 2026 22:39:31 +0700 Subject: [PATCH 5/6] update deps list --- src/hooks/useSearchBulkActions.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/hooks/useSearchBulkActions.ts b/src/hooks/useSearchBulkActions.ts index 240a7e6bd2e0..3d668855e397 100644 --- a/src/hooks/useSearchBulkActions.ts +++ b/src/hooks/useSearchBulkActions.ts @@ -697,7 +697,6 @@ function useSearchBulkActions({queryJSON}: UseSearchBulkActionsParams) { lastPaymentMethods, allTransactions, policyIDsWithVBBA, - allReportActions, policyExpenseChatReportActions, formatPhoneNumber, clearSelectedTransactions, From 44fda6926b4ed386a62ad9cff16db54fd1c22141 Mon Sep 17 00:00:00 2001 From: DylanDylann Date: Fri, 3 Apr 2026 23:10:06 +0700 Subject: [PATCH 6/6] update hook name --- src/components/KYCWall/BaseKYCWall.tsx | 4 ++-- ...portActions.ts => useAllPolicyExpenseChatReportActions.ts} | 4 ++-- src/hooks/useSearchBulkActions.ts | 4 ++-- src/pages/ReportChangeWorkspacePage.tsx | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) rename src/hooks/{usePolicyExpenseChatReportActions.ts => useAllPolicyExpenseChatReportActions.ts} (95%) diff --git a/src/components/KYCWall/BaseKYCWall.tsx b/src/components/KYCWall/BaseKYCWall.tsx index bf1759f07385..531ef2b4a393 100644 --- a/src/components/KYCWall/BaseKYCWall.tsx +++ b/src/components/KYCWall/BaseKYCWall.tsx @@ -4,11 +4,11 @@ import {Dimensions} from 'react-native'; import type {EmitterSubscription, View} from 'react-native'; import AddPaymentMethodMenu from '@components/AddPaymentMethodMenu'; import {usePersonalDetails} from '@components/OnyxListItemProvider'; +import useAllPolicyExpenseChatReportActions from '@hooks/useAllPolicyExpenseChatReportActions'; import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; import useParentReportAction from '@hooks/useParentReportAction'; -import usePolicyExpenseChatReportActions from '@hooks/usePolicyExpenseChatReportActions'; import useReportTransactions from '@hooks/useReportTransactions'; import {openPersonalBankAccountSetupView} from '@libs/actions/BankAccounts'; import {completePaymentOnboarding, savePreferredPaymentMethod} from '@libs/actions/IOU'; @@ -75,7 +75,7 @@ function KYCWall({ const personalDetails = usePersonalDetails(); const employeeEmail = personalDetails?.[iouReport?.ownerAccountID ?? CONST.DEFAULT_NUMBER_ID]?.login ?? ''; const reportTransactions = useReportTransactions(iouReport?.reportID); - const {filteredReportActions} = usePolicyExpenseChatReportActions(); + const {filteredReportActions} = useAllPolicyExpenseChatReportActions(); const anchorRef = useRef(null); const transferBalanceButtonRef = useRef(null); diff --git a/src/hooks/usePolicyExpenseChatReportActions.ts b/src/hooks/useAllPolicyExpenseChatReportActions.ts similarity index 95% rename from src/hooks/usePolicyExpenseChatReportActions.ts rename to src/hooks/useAllPolicyExpenseChatReportActions.ts index 9dfe41e95b53..c09945a1d79c 100644 --- a/src/hooks/usePolicyExpenseChatReportActions.ts +++ b/src/hooks/useAllPolicyExpenseChatReportActions.ts @@ -19,7 +19,7 @@ const policyExpenseChatReportsSelector = (reports: OnyxCollection) => { * Returns all reports that satisfy isPolicyExpenseChat && !isThread (via selector), * along with reportActions filtered to only those matching reports. */ -function usePolicyExpenseChatReportActions() { +function useAllPolicyExpenseChatReportActions() { const [policyExpenseChatReports] = useOnyx(ONYXKEYS.COLLECTION.REPORT, {selector: policyExpenseChatReportsSelector}); const policyExpenseChatReportIDs = useMemo(() => { @@ -51,4 +51,4 @@ function usePolicyExpenseChatReportActions() { return {policyExpenseChatReports, filteredReportActions}; } -export default usePolicyExpenseChatReportActions; +export default useAllPolicyExpenseChatReportActions; diff --git a/src/hooks/useSearchBulkActions.ts b/src/hooks/useSearchBulkActions.ts index 3d668855e397..ea8f049a4b31 100644 --- a/src/hooks/useSearchBulkActions.ts +++ b/src/hooks/useSearchBulkActions.ts @@ -59,6 +59,7 @@ import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type {BillingGraceEndPeriod, Policy, Report, SearchResults, Transaction, TransactionViolations} from '@src/types/onyx'; import type DeepValueOf from '@src/types/utils/DeepValueOf'; +import useAllPolicyExpenseChatReportActions from './useAllPolicyExpenseChatReportActions'; import useAllTransactions from './useAllTransactions'; import useBulkPayOptions from './useBulkPayOptions'; import useConfirmModal from './useConfirmModal'; @@ -70,7 +71,6 @@ import useNetwork from './useNetwork'; import useOnyx from './useOnyx'; import usePermissions from './usePermissions'; import usePersonalPolicy from './usePersonalPolicy'; -import usePolicyExpenseChatReportActions from './usePolicyExpenseChatReportActions'; import useSelfDMReport from './useSelfDMReport'; import useTheme from './useTheme'; import useThemeStyles from './useThemeStyles'; @@ -111,7 +111,7 @@ function useSearchBulkActions({queryJSON}: UseSearchBulkActionsParams) { const allTransactions = useAllTransactions(); const [allReports] = useOnyx(ONYXKEYS.COLLECTION.REPORT); const [allReportActions] = useOnyx(ONYXKEYS.COLLECTION.REPORT_ACTIONS); - const {filteredReportActions: policyExpenseChatReportActions} = usePolicyExpenseChatReportActions(); + const {filteredReportActions: policyExpenseChatReportActions} = useAllPolicyExpenseChatReportActions(); const [allReportNameValuePairs] = useOnyx(ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS); const selfDMReport = useSelfDMReport(); const [lastPaymentMethods] = useOnyx(ONYXKEYS.NVP_LAST_PAYMENT_METHOD); diff --git a/src/pages/ReportChangeWorkspacePage.tsx b/src/pages/ReportChangeWorkspacePage.tsx index 43aadd0d7297..1b055fcf981c 100644 --- a/src/pages/ReportChangeWorkspacePage.tsx +++ b/src/pages/ReportChangeWorkspacePage.tsx @@ -7,12 +7,12 @@ import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; import type {WorkspaceListItemType} from '@components/SelectionList/ListItem/types'; import UserListItem from '@components/SelectionList/ListItem/UserListItem'; +import useAllPolicyExpenseChatReportActions from '@hooks/useAllPolicyExpenseChatReportActions'; import useDebouncedState from '@hooks/useDebouncedState'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; import useOnyx from '@hooks/useOnyx'; import usePermissions from '@hooks/usePermissions'; -import usePolicyExpenseChatReportActions from '@hooks/usePolicyExpenseChatReportActions'; import useReportIsArchived from '@hooks/useReportIsArchived'; import useReportTransactions from '@hooks/useReportTransactions'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -75,7 +75,7 @@ function ReportChangeWorkspacePage({report, route}: ReportChangeWorkspacePagePro const hasViolations = hasViolationsReportUtils(report?.reportID, transactionViolations, session?.accountID ?? CONST.DEFAULT_NUMBER_ID, session?.email ?? ''); const [ownerBillingGracePeriodEnd] = useOnyx(ONYXKEYS.NVP_PRIVATE_OWNER_BILLING_GRACE_PERIOD_END); const [userBillingGracePeriods] = useOnyx(ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_USER_BILLING_GRACE_PERIOD_END); - const {filteredReportActions} = usePolicyExpenseChatReportActions(); + const {filteredReportActions} = useAllPolicyExpenseChatReportActions(); const selectPolicy = useCallback( (policyID?: string) => {