Skip to content

Commit 9b4d357

Browse files
authored
Merge pull request Expensify#83906 from software-mansion-labs/Guccio163/onyx-connect/policy_tags/handleMoneyRequestStepScanParticipants
Remove Onyx.connect() for the key: ONYXKEYS.COLLECTION.POLICY_TAGS from handleMoneyRequestStepScanParticipants function
2 parents 37bf849 + 560eb7c commit 9b4d357

6 files changed

Lines changed: 102 additions & 37 deletions

File tree

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import type {OnyxCollection} from 'react-native-onyx';
2+
import ONYXKEYS from '@src/ONYXKEYS';
3+
import type {PolicyTagLists} from '@src/types/onyx';
4+
import {getEmptyObject} from '@src/types/utils/EmptyObject';
5+
import useOnyx from './useOnyx';
6+
7+
type ParticipantWithPolicyID = {
8+
policyID?: string;
9+
};
10+
11+
function getPolicyTagsSelector(participants: ParticipantWithPolicyID[]): (allTags: OnyxCollection<PolicyTagLists>) => Record<string, PolicyTagLists> {
12+
return (allTags: OnyxCollection<PolicyTagLists>) => {
13+
if (!participants) {
14+
return {};
15+
}
16+
return participants.reduce<Record<string, PolicyTagLists>>((acc, participant) => {
17+
const key = `${ONYXKEYS.COLLECTION.POLICY_TAGS}${participant.policyID}`;
18+
if (allTags?.[key] && participant.policyID) {
19+
acc[participant.policyID] = allTags[key];
20+
}
21+
return acc;
22+
}, {});
23+
};
24+
}
25+
26+
/**
27+
* Hook that extracts policy tags only for participants' policies.
28+
*
29+
* @param participants - Array of participants with optional policyID
30+
* @returns Record mapping policyID to PolicyTagLists
31+
*/
32+
function useParticipantsPolicyTags(participants: ParticipantWithPolicyID[]): Record<string, PolicyTagLists> {
33+
const [participantsPolicyTags = getEmptyObject<Record<string, PolicyTagLists>>()] = useOnyx(ONYXKEYS.COLLECTION.POLICY_TAGS, {selector: getPolicyTagsSelector(participants)}, [
34+
participants,
35+
]);
36+
37+
return participantsPolicyTags;
38+
}
39+
40+
export default useParticipantsPolicyTags;

src/libs/actions/IOU/MoneyRequest.ts

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import type {IOUType} from '@src/CONST';
1919
import CONST from '@src/CONST';
2020
import IntlStore from '@src/languages/IntlStore';
2121
import type {TranslationParameters, TranslationPaths} from '@src/languages/types';
22-
import ONYXKEYS from '@src/ONYXKEYS';
2322
import type {Route} from '@src/ROUTES';
2423
import ROUTES from '@src/ROUTES';
2524
import type {
@@ -43,7 +42,6 @@ import type {GpsPoint} from './index';
4342
import {
4443
createDistanceRequest,
4544
getMoneyRequestParticipantsFromReport,
46-
getPolicyTags,
4745
requestMoney,
4846
setCustomUnitRateID,
4947
setMoneyRequestDistance,
@@ -98,7 +96,6 @@ type MoneyRequestStepScanParticipantsFlowParams = {
9896
policy: OnyxEntry<Policy>;
9997
report: OnyxEntry<Report>;
10098
reportID: string;
101-
reportAttributesDerived?: Record<string, ReportAttributes>;
10299
transactions: Transaction[];
103100
initialTransaction: InitialTransactionParams;
104101
policyForMovingExpenses?: OnyxEntry<Policy>;
@@ -117,7 +114,6 @@ type MoneyRequestStepScanParticipantsFlowParams = {
117114
policyRecentlyUsedCurrencies?: string[];
118115
introSelected?: IntroSelected;
119116
activePolicyID?: string;
120-
privateIsArchived?: string;
121117
files: ReceiptFile[];
122118
isTestTransaction?: boolean;
123119
locationPermissionGranted?: boolean;
@@ -127,6 +123,8 @@ type MoneyRequestStepScanParticipantsFlowParams = {
127123
allTransactionDrafts: OnyxCollection<Transaction>;
128124
betas: OnyxEntry<Beta[]>;
129125
recentWaypoints: OnyxEntry<RecentWaypoint[]>;
126+
participants: Participant[];
127+
participantsPolicyTags: Record<string, PolicyTagLists>;
130128
amountOwed: OnyxEntry<number>;
131129
};
132130

@@ -304,7 +302,6 @@ function handleMoneyRequestStepScanParticipants({
304302
policy,
305303
report,
306304
reportID,
307-
reportAttributesDerived,
308305
transactions,
309306
initialTransaction,
310307
policyForMovingExpenses,
@@ -324,7 +321,6 @@ function handleMoneyRequestStepScanParticipants({
324321
policyRecentlyUsedCurrencies,
325322
introSelected,
326323
activePolicyID,
327-
privateIsArchived,
328324
files,
329325
isTestTransaction = false,
330326
locationPermissionGranted = false,
@@ -333,6 +329,8 @@ function handleMoneyRequestStepScanParticipants({
333329
allTransactionDrafts,
334330
betas,
335331
recentWaypoints,
332+
participants,
333+
participantsPolicyTags,
336334
amountOwed,
337335
}: MoneyRequestStepScanParticipantsFlowParams) {
338336
if (backTo) {
@@ -367,8 +365,6 @@ function handleMoneyRequestStepScanParticipants({
367365
// to the confirmation step.
368366
// If the user is started this flow using the Create expense option (combined submit/track flow), they should be redirected to the participants page.
369367
if (!initialTransaction?.isFromGlobalCreate && !isArchivedExpenseReport && iouType !== CONST.IOU.TYPE.CREATE) {
370-
const participants = getMoneyRequestParticipantOptions(currentUserAccountID, report, policy, personalDetails, privateIsArchived, reportAttributesDerived);
371-
372368
if (shouldSkipConfirmation) {
373369
cancelSpan(CONST.TELEMETRY.SPAN_SCAN_PROCESS_AND_NAVIGATE);
374370
cancelSpan(CONST.TELEMETRY.SPAN_CONFIRMATION_MOUNT);
@@ -380,13 +376,7 @@ function handleMoneyRequestStepScanParticipants({
380376
const splitReceipt: Receipt = firstReceiptFile.file ?? {};
381377
splitReceipt.source = firstReceiptFile.source;
382378
splitReceipt.state = CONST.IOU.RECEIPT_STATE.SCAN_READY;
383-
const allPolicyTags: OnyxCollection<PolicyTagLists> = getPolicyTags();
384-
const participantsPolicyTags = participants.reduce<Record<string, PolicyTagLists>>((acc, participant) => {
385-
if (participant.policyID) {
386-
acc[participant.policyID] = allPolicyTags?.[`${ONYXKEYS.COLLECTION.POLICY_TAGS}${participant.policyID}`] ?? {};
387-
}
388-
return acc;
389-
}, {});
379+
390380
startSplitBill({
391381
participants,
392382
currentUserLogin: currentUserLogin ?? '',
@@ -784,5 +774,5 @@ function handleMoneyRequestStepDistanceNavigation({
784774
}
785775
}
786776

787-
export {createTransaction, handleMoneyRequestStepScanParticipants, handleMoneyRequestStepDistanceNavigation};
777+
export {createTransaction, handleMoneyRequestStepScanParticipants, handleMoneyRequestStepDistanceNavigation, getMoneyRequestParticipantOptions};
788778
export type {MoneyRequestStepScanParticipantsFlowParams, MoneyRequestStepDistanceNavigationParams};

src/pages/iou/request/step/IOURequestStepConfirmation.tsx

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import useOnyx from '@hooks/useOnyx';
2525
import useOptimisticDraftTransactions from '@hooks/useOptimisticDraftTransactions';
2626
import useParentReportAction from '@hooks/useParentReportAction';
2727
import useParticipantsInvoiceReport from '@hooks/useParticipantsInvoiceReport';
28+
import useParticipantsPolicyTags from '@hooks/useParticipantsPolicyTags';
2829
import usePermissions from '@hooks/usePermissions';
2930
import usePolicyForTransaction from '@hooks/usePolicyForTransaction';
3031
import usePrivateIsArchivedMap from '@hooks/usePrivateIsArchivedMap';
@@ -105,7 +106,7 @@ import CONST from '@src/CONST';
105106
import ONYXKEYS from '@src/ONYXKEYS';
106107
import ROUTES from '@src/ROUTES';
107108
import type SCREENS from '@src/SCREENS';
108-
import type {PolicyTagLists, RecentlyUsedCategories, Report} from '@src/types/onyx';
109+
import type {RecentlyUsedCategories, Report} from '@src/types/onyx';
109110
import type {Participant} from '@src/types/onyx/IOU';
110111
import type {PaymentMethodType} from '@src/types/onyx/OriginalMessage';
111112
import type {InvoiceReceiver} from '@src/types/onyx/Report';
@@ -208,7 +209,6 @@ function IOURequestStepConfirmation({
208209

209210
const [policyCategoriesDraft] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES_DRAFT}${draftPolicyID}`);
210211
const [policyRecentlyUsedCategories] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_CATEGORIES}${policyID}`);
211-
const [allPolicyTags] = useOnyx(ONYXKEYS.COLLECTION.POLICY_TAGS);
212212
const [policyTags] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`);
213213
const [policyRecentlyUsedTags] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_TAGS}${policyID}`);
214214
const [policyRecentlyUsedCurrencies] = useOnyx(ONYXKEYS.RECENTLY_USED_CURRENCIES);
@@ -319,6 +319,7 @@ function IOURequestStepConfirmation({
319319
}) ?? [],
320320
[transaction?.participants, iouType, personalDetails, reportAttributesDerived, reportDrafts, privateIsArchivedMap, policy, currentUserPersonalDetails.accountID],
321321
);
322+
const participantsPolicyTags = useParticipantsPolicyTags(participants ?? []);
322323
const isPolicyExpenseChat = useMemo(() => participants?.some((participant) => participant.isPolicyExpenseChat), [participants]);
323324
const shouldGenerateTransactionThreadReport = !isBetaEnabled(CONST.BETAS.NO_OPTIMISTIC_TRANSACTION_THREADS);
324325
const formHasBeenSubmitted = useRef(false);
@@ -1104,13 +1105,6 @@ function IOURequestStepConfirmation({
11041105
}
11051106
const itemTrimmedComment = item?.comment?.comment?.trim() ?? '';
11061107

1107-
const participantsPolicyTags = selectedParticipants.reduce<Record<string, PolicyTagLists>>((acc, participant) => {
1108-
if (participant.policyID) {
1109-
acc[participant.policyID] = allPolicyTags?.[`${ONYXKEYS.COLLECTION.POLICY_TAGS}${participant.policyID}`] ?? {};
1110-
}
1111-
return acc;
1112-
}, {});
1113-
11141108
// If we have a receipt let's start the split expense by creating only the action, the transaction, and the group DM if needed
11151109
startSplitBill({
11161110
participants: selectedParticipants,
@@ -1357,7 +1351,7 @@ function IOURequestStepConfirmation({
13571351
reportID,
13581352
requestType,
13591353
betas,
1360-
allPolicyTags,
1354+
participantsPolicyTags,
13611355
personalDetails,
13621356
],
13631357
);

src/pages/iou/request/step/IOURequestStepScan/hooks/useReceiptScan.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
import shouldStartLocationPermissionFlowSelector from '@selectors/LocationPermission';
22
import {hasSeenTourSelector} from '@selectors/Onboarding';
3-
import {useEffect, useState} from 'react';
3+
import {useEffect, useMemo, useState} from 'react';
44
import TestReceipt from '@assets/images/fake-receipt.png';
55
import useDefaultExpensePolicy from '@hooks/useDefaultExpensePolicy';
66
import useFilesValidation from '@hooks/useFilesValidation';
77
import useOnyx from '@hooks/useOnyx';
88
import useOptimisticDraftTransactions from '@hooks/useOptimisticDraftTransactions';
9+
import useParticipantsPolicyTags from '@hooks/useParticipantsPolicyTags';
910
import usePermissions from '@hooks/usePermissions';
1011
import usePersonalPolicy from '@hooks/usePersonalPolicy';
1112
import usePolicy from '@hooks/usePolicy';
1213
import usePolicyForMovingExpenses from '@hooks/usePolicyForMovingExpenses';
1314
import useReportAttributes from '@hooks/useReportAttributes';
1415
import useSelfDMReport from '@hooks/useSelfDMReport';
15-
import {handleMoneyRequestStepScanParticipants} from '@libs/actions/IOU/MoneyRequest';
16+
import {getMoneyRequestParticipantOptions, handleMoneyRequestStepScanParticipants} from '@libs/actions/IOU/MoneyRequest';
1617
import setTestReceipt from '@libs/actions/setTestReceipt';
1718
import {isArchivedReport, isPolicyExpenseChat} from '@libs/ReportUtils';
1819
import {getSpan, startSpan} from '@libs/telemetry/activeSpans';
@@ -96,19 +97,25 @@ function useReceiptScan({
9697

9798
const [recentWaypoints] = useOnyx(ONYXKEYS.NVP_RECENT_WAYPOINTS);
9899

100+
const participants = useMemo(
101+
() => getMoneyRequestParticipantOptions(currentUserPersonalDetails.accountID, report, policy, personalDetails, reportNameValuePairs?.private_isArchived, reportAttributesDerived),
102+
[currentUserPersonalDetails.accountID, report, policy, personalDetails, reportNameValuePairs?.private_isArchived, reportAttributesDerived],
103+
);
104+
105+
const participantsPolicyTags = useParticipantsPolicyTags(participants);
99106
function navigateToConfirmationStep(files: ReceiptFile[], locationPermissionGranted = false, isTestTransaction = false) {
100107
startSpan(CONST.TELEMETRY.SPAN_SCAN_PROCESS_AND_NAVIGATE, {
101108
name: CONST.TELEMETRY.SPAN_SCAN_PROCESS_AND_NAVIGATE,
102109
op: CONST.TELEMETRY.SPAN_SCAN_PROCESS_AND_NAVIGATE,
103110
parentSpan: getSpan(CONST.TELEMETRY.SPAN_SHUTTER_TO_CONFIRMATION),
104111
attributes: {[CONST.TELEMETRY.ATTRIBUTE_IS_MULTI_SCAN]: isMultiScanEnabled},
105112
});
113+
106114
handleMoneyRequestStepScanParticipants({
107115
iouType,
108116
policy,
109117
report,
110118
reportID,
111-
reportAttributesDerived,
112119
transactions,
113120
initialTransaction: {
114121
transactionID: initialTransactionID,
@@ -135,7 +142,6 @@ function useReceiptScan({
135142
policyRecentlyUsedCurrencies,
136143
introSelected,
137144
activePolicyID,
138-
privateIsArchived: reportNameValuePairs?.private_isArchived,
139145
files,
140146
isTestTransaction,
141147
locationPermissionGranted,
@@ -145,6 +151,8 @@ function useReceiptScan({
145151
betas,
146152
recentWaypoints,
147153
allTransactionDrafts,
154+
participants,
155+
participantsPolicyTags,
148156
amountOwed,
149157
});
150158
}

tests/actions/IOU/MoneyRequestTest.ts

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type {OnyxEntry} from 'react-native-onyx';
22
import Onyx from 'react-native-onyx';
33
import type {MoneyRequestStepScanParticipantsFlowParams} from '@libs/actions/IOU/MoneyRequest';
4-
import {createTransaction, handleMoneyRequestStepDistanceNavigation, handleMoneyRequestStepScanParticipants} from '@libs/actions/IOU/MoneyRequest';
4+
import {createTransaction, getMoneyRequestParticipantOptions, handleMoneyRequestStepDistanceNavigation, handleMoneyRequestStepScanParticipants} from '@libs/actions/IOU/MoneyRequest';
55
import getCurrentPosition from '@libs/getCurrentPosition';
66
import {GeolocationErrorCode} from '@libs/getCurrentPosition/getCurrentPosition.types';
77
import Navigation from '@libs/Navigation/Navigation';
@@ -10,7 +10,8 @@ import type {ReceiptFile} from '@pages/iou/request/step/IOURequestStepScan/types
1010
import CONST from '@src/CONST';
1111
import ONYXKEYS from '@src/ONYXKEYS';
1212
import ROUTES from '@src/ROUTES';
13-
import type {QuickAction, RecentWaypoint} from '@src/types/onyx';
13+
import type {PolicyTagLists, QuickAction, RecentWaypoint} from '@src/types/onyx';
14+
import type {Participant} from '@src/types/onyx/IOU';
1415
import type {SplitShares} from '@src/types/onyx/Transaction';
1516
import * as IOU from '../../../src/libs/actions/IOU';
1617
import * as Split from '../../../src/libs/actions/IOU/Split';
@@ -19,6 +20,7 @@ import createRandomPolicy from '../../utils/collections/policies';
1920
import {createRandomReport, createSelfDM} from '../../utils/collections/reports';
2021
import createRandomTransaction from '../../utils/collections/transaction';
2122
import getOnyxValue from '../../utils/getOnyxValue';
23+
import {getOnyxData} from '../../utils/TestHelper';
2224
import waitForBatchedUpdates from '../../utils/waitForBatchedUpdates';
2325

2426
jest.mock('@libs/actions/IOU', () => {
@@ -401,7 +403,6 @@ describe('MoneyRequest', () => {
401403
policy: fakePolicy,
402404
report: fakeReport,
403405
reportID: '1',
404-
reportAttributesDerived: {},
405406
transactions: [fakeTransaction],
406407
initialTransaction: {
407408
transactionID: '1',
@@ -431,6 +432,8 @@ describe('MoneyRequest', () => {
431432
betas: [],
432433
recentWaypoints: [] as RecentWaypoint[],
433434
allTransactionDrafts: {},
435+
participants: [] as Participant[],
436+
participantsPolicyTags: {} as Record<string, PolicyTagLists>,
434437
amountOwed: 0,
435438
};
436439

@@ -445,6 +448,19 @@ describe('MoneyRequest', () => {
445448
},
446449
});
447450
baseParams.recentWaypoints = (await getOnyxValue(ONYXKEYS.NVP_RECENT_WAYPOINTS)) ?? [];
451+
baseParams.participants = getMoneyRequestParticipantOptions(baseParams.currentUserAccountID, baseParams.report, baseParams.policy, baseParams.personalDetails, undefined, {});
452+
await getOnyxData({
453+
key: `${ONYXKEYS.COLLECTION.POLICY_TAGS}`,
454+
waitForCollectionCallback: true,
455+
callback: (value) => {
456+
baseParams.participantsPolicyTags = baseParams.participants.reduce<Record<string, PolicyTagLists>>((acc, participant) => {
457+
if (participant.policyID) {
458+
acc[participant.policyID] = value?.[`${ONYXKEYS.COLLECTION.POLICY_TAGS}${participant.policyID}`] ?? {};
459+
}
460+
return acc;
461+
}, {});
462+
},
463+
});
448464
});
449465

450466
afterEach(async () => {
@@ -547,13 +563,28 @@ describe('MoneyRequest', () => {
547563
});
548564

549565
it('should return if no participants found for non-SPLIT iouType when not from global create menu and skipping confirmation', async () => {
566+
const report = {
567+
...fakeReport,
568+
chatType: CONST.REPORT.CHAT_TYPE.POLICY_ROOM,
569+
};
570+
baseParams.participants = getMoneyRequestParticipantOptions(baseParams.currentUserAccountID, report, baseParams.policy, baseParams.personalDetails, undefined, {});
571+
572+
await getOnyxData({
573+
key: `${ONYXKEYS.COLLECTION.POLICY_TAGS}`,
574+
waitForCollectionCallback: true,
575+
callback: (value) => {
576+
baseParams.participantsPolicyTags = baseParams.participants.reduce<Record<string, PolicyTagLists>>((acc, participant) => {
577+
if (participant.policyID) {
578+
acc[participant.policyID] = value?.[`${ONYXKEYS.COLLECTION.POLICY_TAGS}${participant.policyID}`] ?? {};
579+
}
580+
return acc;
581+
}, {});
582+
},
583+
});
550584
handleMoneyRequestStepScanParticipants({
551585
...baseParams,
552586
iouType: CONST.IOU.TYPE.TRACK,
553-
report: {
554-
...fakeReport,
555-
chatType: CONST.REPORT.CHAT_TYPE.POLICY_ROOM,
556-
},
587+
report,
557588
shouldSkipConfirmation: true,
558589
initialTransaction: {
559590
...baseParams.initialTransaction,

tests/unit/hooks/useReceiptScan.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import type {Report, Transaction} from '@src/types/onyx';
99
import waitForBatchedUpdatesWithAct from '../../utils/waitForBatchedUpdatesWithAct';
1010

1111
const mockHandleMoneyRequestStepScanParticipants = jest.fn();
12+
const mockGetMoneyRequestParticipantOptions = jest.fn().mockReturnValue([]);
1213
const mockRemoveDraftTransactions = jest.fn();
1314
const mockRemoveTransactionReceipt = jest.fn();
1415
const mockSetMoneyRequestReceipt = jest.fn();
@@ -32,6 +33,7 @@ jest.mock('@hooks/useFilesValidation', () => ({
3233

3334
jest.mock('@libs/actions/IOU/MoneyRequest', () => ({
3435
handleMoneyRequestStepScanParticipants: (...args: unknown[]) => mockHandleMoneyRequestStepScanParticipants(...args),
36+
getMoneyRequestParticipantOptions: (...args: unknown[]) => mockGetMoneyRequestParticipantOptions(...args),
3537
}));
3638

3739
jest.mock('@userActions/TransactionEdit', () => ({

0 commit comments

Comments
 (0)