Skip to content

Commit 222e91b

Browse files
committed
refactor
1 parent f938541 commit 222e91b

6 files changed

Lines changed: 159 additions & 1 deletion

File tree

src/hooks/useAccountIDToLogin.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import {useMemo} from 'react';
2+
import {usePersonalDetails} from '@components/OnyxListItemProvider';
3+
4+
/**
5+
* Hook that returns a map from accountID to login email.
6+
*/
7+
function useAccountIDToLogin(): Record<number, string> {
8+
const personalDetails = usePersonalDetails();
9+
10+
return useMemo(() => {
11+
const map: Record<number, string> = {};
12+
for (const [id, details] of Object.entries(personalDetails ?? {})) {
13+
if (details?.login) {
14+
map[Number(id)] = details.login;
15+
}
16+
}
17+
return map;
18+
}, [personalDetails]);
19+
}
20+
21+
export default useAccountIDToLogin;

src/libs/actions/Policy/Policy.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,7 @@ type DeleteWorkspaceActionParams = {
384384
localeCompare: LocaleContextProps['localeCompare'];
385385
hasDeleteWorkspaceExpensifyCardsError?: boolean;
386386
currentUserAccountID: number;
387+
accountIDToLogin: Record<number, string>;
387388
};
388389

389390
/**
@@ -405,6 +406,7 @@ function deleteWorkspace(params: DeleteWorkspaceActionParams) {
405406
personalPolicyID,
406407
hasDeleteWorkspaceExpensifyCardsError,
407408
currentUserAccountID,
409+
accountIDToLogin,
408410
} = params;
409411

410412
const policy = policies?.[`${ONYXKEYS.COLLECTION.POLICY}${policyID}`];
@@ -547,7 +549,7 @@ function deleteWorkspace(params: DeleteWorkspaceActionParams) {
547549
// Announce & admin chats have FAKE owners, but expense chats w/ users do have owners.
548550
let emailClosingReport: string = CONST.POLICY.OWNER_EMAIL_FAKE;
549551
if (!!ownerAccountID && ownerAccountID !== CONST.POLICY.OWNER_ACCOUNT_ID_FAKE) {
550-
emailClosingReport = deprecatedAllPersonalDetails?.[ownerAccountID]?.login ?? '';
552+
emailClosingReport = accountIDToLogin[ownerAccountID] ?? '';
551553
}
552554
const optimisticClosedReportAction = ReportUtils.buildOptimisticClosedReportAction(emailClosingReport, policyName, currentUserAccountID, CONST.REPORT.ARCHIVE_REASON.POLICY_DELETED);
553555
optimisticData.push({

src/pages/workspace/WorkspaceOverviewPage.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
1414
import OfflineWithFeedback from '@components/OfflineWithFeedback';
1515
import {usePersonalDetails} from '@components/OnyxListItemProvider';
1616
import Section from '@components/Section';
17+
import useAccountIDToLogin from '@hooks/useAccountIDToLogin';
1718
import useCardFeeds from '@hooks/useCardFeeds';
1819
import {useCurrencyListActions} from '@hooks/useCurrencyList';
1920
import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
@@ -85,6 +86,7 @@ function WorkspaceOverviewPage({policyDraft, policy: policyProp, route}: Workspa
8586
const {shouldUseNarrowLayout} = useResponsiveLayout();
8687
const currentUserPersonalDetails = useCurrentUserPersonalDetails();
8788
const {getCurrencySymbol} = useCurrencyListActions();
89+
const accountIDToLogin = useAccountIDToLogin();
8890
const illustrationIcons = useMemoizedLazyIllustrations(['Building']);
8991
const expensifyIcons = useMemoizedLazyExpensifyIcons(['Exit', 'FallbackWorkspaceAvatar', 'ImageCropSquareMask', 'QrCode', 'Transfer', 'Trashcan', 'UserPlus']);
9092

@@ -268,6 +270,7 @@ function WorkspaceOverviewPage({policyDraft, policy: policyProp, route}: Workspa
268270
personalPolicyID,
269271
hasDeleteWorkspaceExpensifyCardsError,
270272
currentUserAccountID: accountID,
273+
accountIDToLogin,
271274
});
272275
if (isOffline) {
273276
setIsDeleteModalOpen(false);

src/pages/workspace/WorkspacesListPage.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import SearchBar from '@components/SearchBar';
2323
import type {ListItem} from '@components/SelectionList/types';
2424
import Text from '@components/Text';
2525
import useAndroidBackButtonHandler from '@hooks/useAndroidBackButtonHandler';
26+
import useAccountIDToLogin from '@hooks/useAccountIDToLogin';
2627
import useCardFeeds from '@hooks/useCardFeeds';
2728
import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
2829
import useDocumentTitle from '@hooks/useDocumentTitle';
@@ -135,6 +136,7 @@ function WorkspacesListPage() {
135136
const expensifyIcons = useMemoizedLazyExpensifyIcons(['Building', 'Exit', 'Copy', 'Star', 'Trashcan', 'Transfer', 'Plus', 'FallbackWorkspaceAvatar']);
136137
const {translate, localeCompare} = useLocalize();
137138
useDocumentTitle(translate('common.workspaces'));
139+
const accountIDToLogin = useAccountIDToLogin();
138140
const {isOffline} = useNetwork();
139141
const isFocused = useIsFocused();
140142
const {shouldUseNarrowLayout, isMediumScreenWidth} = useResponsiveLayout();
@@ -242,6 +244,7 @@ function WorkspacesListPage() {
242244
personalPolicyID,
243245
hasDeleteWorkspaceExpensifyCardsError,
244246
currentUserAccountID: currentUserPersonalDetails.accountID,
247+
accountIDToLogin,
245248
});
246249
if (isOffline) {
247250
setIsDeleteModalOpen(false);

tests/actions/IOUTest.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10132,6 +10132,7 @@ describe('actions/IOU', () => {
1013210132
lastUsedPaymentMethods: undefined,
1013310133
localeCompare,
1013410134
currentUserAccountID: CARLOS_ACCOUNT_ID,
10135+
accountIDToLogin: {},
1013510136
});
1013610137
}
1013710138
return waitForBatchedUpdates();

tests/actions/PolicyTest.ts

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2756,6 +2756,7 @@ describe('actions/Policy', () => {
27562756
lastUsedPaymentMethods: undefined,
27572757
localeCompare: TestHelper.localeCompare,
27582758
currentUserAccountID: ESH_ACCOUNT_ID,
2759+
accountIDToLogin: {},
27592760
});
27602761

27612762
await waitForBatchedUpdates();
@@ -2855,6 +2856,7 @@ describe('actions/Policy', () => {
28552856
lastUsedPaymentMethods: undefined,
28562857
localeCompare: TestHelper.localeCompare,
28572858
currentUserAccountID: ESH_ACCOUNT_ID,
2859+
accountIDToLogin: {},
28582860
});
28592861

28602862
await waitForBatchedUpdates();
@@ -2912,6 +2914,7 @@ describe('actions/Policy', () => {
29122914
lastUsedPaymentMethods: undefined,
29132915
localeCompare: TestHelper.localeCompare,
29142916
currentUserAccountID: ESH_ACCOUNT_ID,
2917+
accountIDToLogin: {},
29152918
});
29162919
await waitForBatchedUpdates();
29172920

@@ -2950,6 +2953,7 @@ describe('actions/Policy', () => {
29502953
lastUsedPaymentMethods: undefined,
29512954
localeCompare: TestHelper.localeCompare,
29522955
currentUserAccountID: ESH_ACCOUNT_ID,
2956+
accountIDToLogin: {},
29532957
});
29542958
await waitForBatchedUpdates();
29552959

@@ -2990,6 +2994,7 @@ describe('actions/Policy', () => {
29902994
lastUsedPaymentMethods: undefined,
29912995
localeCompare: TestHelper.localeCompare,
29922996
currentUserAccountID: ESH_ACCOUNT_ID,
2997+
accountIDToLogin: {},
29932998
});
29942999
await waitForBatchedUpdates();
29953000

@@ -3005,6 +3010,129 @@ describe('actions/Policy', () => {
30053010

30063011
expect(lastAccessedWorkspacePolicyIDAfterDelete).toBe(lastAccessedWorkspacePolicyID);
30073012
});
3013+
3014+
it('should use accountIDToLogin to resolve owner email in closed report action', async () => {
3015+
const ownerAccountID = 42;
3016+
const ownerLogin = 'owner@example.com';
3017+
const fakePolicy = createRandomPolicy(0);
3018+
const fakeReport = {
3019+
...createRandomReport(0, CONST.REPORT.CHAT_TYPE.POLICY_EXPENSE_CHAT),
3020+
ownerAccountID,
3021+
stateNum: CONST.REPORT.STATE_NUM.OPEN,
3022+
statusNum: CONST.REPORT.STATUS_NUM.OPEN,
3023+
policyName: fakePolicy.name,
3024+
};
3025+
3026+
await Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, fakePolicy);
3027+
await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${fakeReport.reportID}`, fakeReport);
3028+
3029+
Policy.deleteWorkspace({
3030+
policies: {[`${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`]: fakePolicy},
3031+
policyID: fakePolicy.id,
3032+
personalPolicyID: undefined,
3033+
activePolicyID: undefined,
3034+
policyName: fakePolicy.name,
3035+
lastAccessedWorkspacePolicyID: undefined,
3036+
policyCardFeeds: undefined,
3037+
reportsToArchive: [fakeReport],
3038+
transactionViolations: undefined,
3039+
reimbursementAccountError: undefined,
3040+
lastUsedPaymentMethods: undefined,
3041+
localeCompare: TestHelper.localeCompare,
3042+
currentUserAccountID: ESH_ACCOUNT_ID,
3043+
accountIDToLogin: {[ownerAccountID]: ownerLogin},
3044+
});
3045+
3046+
await waitForBatchedUpdates();
3047+
3048+
// Then the closed report action should contain the owner's login from accountIDToLogin
3049+
const reportActions = await getOnyxValue(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${fakeReport.reportID}` as const);
3050+
const closedAction = Object.values(reportActions ?? {}).find((action) => action && 'actionName' in action && action.actionName === CONST.REPORT.ACTIONS.TYPE.CLOSED);
3051+
expect(closedAction).toBeDefined();
3052+
const message = closedAction && 'message' in closedAction && Array.isArray(closedAction.message) ? closedAction.message.at(0) : undefined;
3053+
expect(message?.text).toBe(ownerLogin);
3054+
});
3055+
3056+
it('should use fake owner email when ownerAccountID is fake', async () => {
3057+
const fakePolicy = createRandomPolicy(0);
3058+
const fakeReport = {
3059+
...createRandomReport(0, CONST.REPORT.CHAT_TYPE.POLICY_EXPENSE_CHAT),
3060+
ownerAccountID: CONST.POLICY.OWNER_ACCOUNT_ID_FAKE,
3061+
stateNum: CONST.REPORT.STATE_NUM.OPEN,
3062+
statusNum: CONST.REPORT.STATUS_NUM.OPEN,
3063+
policyName: fakePolicy.name,
3064+
};
3065+
3066+
await Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, fakePolicy);
3067+
await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${fakeReport.reportID}`, fakeReport);
3068+
3069+
Policy.deleteWorkspace({
3070+
policies: {[`${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`]: fakePolicy},
3071+
policyID: fakePolicy.id,
3072+
personalPolicyID: undefined,
3073+
activePolicyID: undefined,
3074+
policyName: fakePolicy.name,
3075+
lastAccessedWorkspacePolicyID: undefined,
3076+
policyCardFeeds: undefined,
3077+
reportsToArchive: [fakeReport],
3078+
transactionViolations: undefined,
3079+
reimbursementAccountError: undefined,
3080+
lastUsedPaymentMethods: undefined,
3081+
localeCompare: TestHelper.localeCompare,
3082+
currentUserAccountID: ESH_ACCOUNT_ID,
3083+
accountIDToLogin: {},
3084+
});
3085+
3086+
await waitForBatchedUpdates();
3087+
3088+
// Then the closed report action should use the fake owner email
3089+
const reportActions = await getOnyxValue(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${fakeReport.reportID}` as const);
3090+
const closedAction = Object.values(reportActions ?? {}).find((action) => action && 'actionName' in action && action.actionName === CONST.REPORT.ACTIONS.TYPE.CLOSED);
3091+
expect(closedAction).toBeDefined();
3092+
const message = closedAction && 'message' in closedAction && Array.isArray(closedAction.message) ? closedAction.message.at(0) : undefined;
3093+
expect(message?.text).toBe(CONST.POLICY.OWNER_EMAIL_FAKE);
3094+
});
3095+
3096+
it('should fall back to empty string when accountIDToLogin has no entry for ownerAccountID', async () => {
3097+
const ownerAccountID = 99;
3098+
const fakePolicy = createRandomPolicy(0);
3099+
const fakeReport = {
3100+
...createRandomReport(0, CONST.REPORT.CHAT_TYPE.POLICY_EXPENSE_CHAT),
3101+
ownerAccountID,
3102+
stateNum: CONST.REPORT.STATE_NUM.OPEN,
3103+
statusNum: CONST.REPORT.STATUS_NUM.OPEN,
3104+
policyName: fakePolicy.name,
3105+
};
3106+
3107+
await Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`, fakePolicy);
3108+
await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${fakeReport.reportID}`, fakeReport);
3109+
3110+
Policy.deleteWorkspace({
3111+
policies: {[`${ONYXKEYS.COLLECTION.POLICY}${fakePolicy.id}`]: fakePolicy},
3112+
policyID: fakePolicy.id,
3113+
personalPolicyID: undefined,
3114+
activePolicyID: undefined,
3115+
policyName: fakePolicy.name,
3116+
lastAccessedWorkspacePolicyID: undefined,
3117+
policyCardFeeds: undefined,
3118+
reportsToArchive: [fakeReport],
3119+
transactionViolations: undefined,
3120+
reimbursementAccountError: undefined,
3121+
lastUsedPaymentMethods: undefined,
3122+
localeCompare: TestHelper.localeCompare,
3123+
currentUserAccountID: ESH_ACCOUNT_ID,
3124+
accountIDToLogin: {},
3125+
});
3126+
3127+
await waitForBatchedUpdates();
3128+
3129+
// Then the closed report action should have an empty string for the email
3130+
const reportActions = await getOnyxValue(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${fakeReport.reportID}` as const);
3131+
const closedAction = Object.values(reportActions ?? {}).find((action) => action && 'actionName' in action && action.actionName === CONST.REPORT.ACTIONS.TYPE.CLOSED);
3132+
expect(closedAction).toBeDefined();
3133+
const message = closedAction && 'message' in closedAction && Array.isArray(closedAction.message) ? closedAction.message.at(0) : undefined;
3134+
expect(message?.text).toBe('');
3135+
});
30083136
});
30093137

30103138
describe('leaveWorkspace', () => {

0 commit comments

Comments
 (0)