Skip to content

Commit db97d7d

Browse files
authored
Merge pull request #91737 from dukenv0307/fix/66415-part-8
refactor getBankAccountRoute to use policy from useOnyx
2 parents c06422f + 09179a8 commit db97d7d

9 files changed

Lines changed: 83 additions & 17 deletions

File tree

src/components/KYCWall/BaseKYCWall.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import Log from '@libs/Log';
1919
import setNavigationActionToMicrotaskQueue from '@libs/Navigation/helpers/setNavigationActionToMicrotaskQueue';
2020
import Navigation from '@libs/Navigation/Navigation';
2121
import {hasExpensifyPaymentMethod} from '@libs/PaymentUtils';
22-
import {getBankAccountRoute, isExpenseReport as isExpenseReportReportUtils, isIOUReport} from '@libs/ReportUtils';
22+
import {getBankAccountRoute, getInvoiceReceiverPolicyID, isExpenseReport as isExpenseReportReportUtils, isIOUReport} from '@libs/ReportUtils';
2323
import {getEligibleExistingBusinessBankAccounts, getOpenConnectedToPolicyBusinessBankAccounts} from '@libs/WorkflowUtils';
2424
import {createWorkspaceFromIOUPayment} from '@userActions/Policy/Policy';
2525
import {setKYCWallSource} from '@userActions/Wallet';
@@ -219,7 +219,9 @@ function KYCWall({
219219
return;
220220
}
221221

222-
const bankAccountRoute = addBankAccountRoute ?? getBankAccountRoute(chatReport);
222+
const invoiceReceiverPolicyID = getInvoiceReceiverPolicyID(chatReport);
223+
const invoiceReceiverPolicy = invoiceReceiverPolicyID ? policies?.[`${ONYXKEYS.COLLECTION.POLICY}${invoiceReceiverPolicyID}`] : undefined;
224+
const bankAccountRoute = addBankAccountRoute ?? getBankAccountRoute(chatReport, invoiceReceiverPolicy?.areInvoicesEnabled);
223225
Navigation.navigate(bankAccountRoute);
224226
}
225227
},

src/components/ReportWelcomeText.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import Navigation from '@libs/Navigation/Navigation';
1313
import {getPersonalDetailsForAccountIDs} from '@libs/OptionsListUtils';
1414
import {getReportName} from '@libs/ReportNameUtils';
1515
import {
16+
getInvoiceReceiverPolicyID,
1617
getParticipantsAccountIDsForDisplay,
1718
getPolicyName,
1819
isChatRoom as isChatRoomReportUtils,
@@ -50,7 +51,7 @@ function ReportWelcomeText({report, policy}: ReportWelcomeTextProps) {
5051
const isPolicyExpenseChat = isPolicyExpenseChatReportUtils(report);
5152
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
5253
const [reportMetadata] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_METADATA}${report?.reportID || undefined}`);
53-
const invoiceReceiverPolicyID = report?.invoiceReceiver?.type === CONST.REPORT.INVOICE_RECEIVER_TYPE.BUSINESS ? report?.invoiceReceiver?.policyID : undefined;
54+
const invoiceReceiverPolicyID = getInvoiceReceiverPolicyID(report);
5455
const [invoiceReceiverPolicy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${invoiceReceiverPolicyID}`);
5556
const isReportArchived = useReportIsArchived(report?.reportID);
5657
const [conciergeReportID] = useOnyx(ONYXKEYS.CONCIERGE_REPORT_ID);

src/hooks/useBulkPayOptions.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import {areInvoicesEnabledSelector} from '@selectors/Policy';
12
import truncate from 'lodash/truncate';
23
import type {TupleToUnion} from 'type-fest';
34
import type {PopoverMenuItem} from '@components/PopoverMenu';
@@ -10,6 +11,7 @@ import {sortPoliciesByName} from '@libs/PolicyUtils';
1011
import {hasRequestFromCurrentAccount} from '@libs/ReportActionsUtils';
1112
import {
1213
getBankAccountRoute,
14+
getInvoiceReceiverPolicyID,
1315
isExpenseReport as isExpenseReportUtil,
1416
isIndividualInvoiceRoom as isIndividualInvoiceRoomUtil,
1517
isInvoiceReport as isInvoiceReportUtil,
@@ -67,6 +69,8 @@ function useBulkPayOptions({
6769
const [bankAccountList] = useOnyx(ONYXKEYS.BANK_ACCOUNT_LIST);
6870
const [iouReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${selectedReportID}`);
6971
const [chatReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${iouReport?.chatReportID}`);
72+
const invoiceReceiverPolicyID = getInvoiceReceiverPolicyID(chatReport);
73+
const [areInvoicesEnabled] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${invoiceReceiverPolicyID}`, {selector: areInvoicesEnabledSelector});
7074
const {isBetaEnabled} = usePermissions();
7175
const isPayInvoiceViaExpensifyBetaEnabled = isBetaEnabled(CONST.BETAS.PAY_INVOICE_VIA_EXPENSIFY);
7276
const activeAdminPolicies = useActiveAdminPolicies();
@@ -193,7 +197,7 @@ function useBulkPayOptions({
193197
text: translate('bankAccount.addBankAccount'),
194198
icon: icons.Bank,
195199
onSelected: () => {
196-
const bankAccountRoute = getBankAccountRoute(chatReport);
200+
const bankAccountRoute = getBankAccountRoute(chatReport, areInvoicesEnabled);
197201
Navigation.navigate(bankAccountRoute);
198202
},
199203
};

src/hooks/usePaymentOptions.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import {areInvoicesEnabledSelector} from '@selectors/Policy';
12
import {useCallback, useEffect, useMemo, useRef} from 'react';
23
import type {OnyxEntry} from 'react-native-onyx';
34
import type {TupleToUnion} from 'type-fest';
@@ -9,6 +10,7 @@ import {getPolicyEmployeeAccountIDs} from '@libs/PolicyUtils';
910
import {
1011
doesReportBelongToWorkspace,
1112
getBankAccountRoute,
13+
getInvoiceReceiverPolicyID,
1214
isExpenseReport as isExpenseReportUtil,
1315
isIndividualInvoiceRoom as isIndividualInvoiceRoomUtil,
1416
isInvoiceReport as isInvoiceReportUtil,
@@ -70,6 +72,8 @@ function usePaymentOptions({
7072
// The app would crash due to subscribing to the entire report collection if chatReportID is an empty string. So we should have a fallback ID here.
7173
// eslint-disable-next-line rulesdir/no-default-id-values
7274
const [chatReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${chatReportID || CONST.DEFAULT_NUMBER_ID}`);
75+
const invoiceReceiverPolicyID = getInvoiceReceiverPolicyID(chatReport);
76+
const [areInvoicesEnabled] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${invoiceReceiverPolicyID}`, {selector: areInvoicesEnabledSelector});
7377
const [conciergeReportID = ''] = useOnyx(ONYXKEYS.CONCIERGE_REPORT_ID);
7478
const [userWallet] = useOnyx(ONYXKEYS.USER_WALLET);
7579
const hasActivatedWallet = ([CONST.WALLET.TIER_NAME.GOLD, CONST.WALLET.TIER_NAME.PLATINUM] as string[]).includes(userWallet?.tierName ?? '');
@@ -196,7 +200,7 @@ function usePaymentOptions({
196200
text: translate('bankAccount.addBankAccount'),
197201
icon: icons.Bank,
198202
onSelected: () => {
199-
const bankAccountRoute = getBankAccountRoute(chatReport);
203+
const bankAccountRoute = getBankAccountRoute(chatReport, areInvoicesEnabled);
200204
Navigation.navigate(bankAccountRoute);
201205
},
202206
};
@@ -263,6 +267,7 @@ function usePaymentOptions({
263267
shouldShowPayWithExpensifyOption,
264268
shouldShowPayElsewhereOption,
265269
chatReport,
270+
areInvoicesEnabled,
266271
onPress,
267272
onlyShowPayElsewhere,
268273
icons,

src/libs/ReportUtils.ts

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1722,6 +1722,13 @@ function isBusinessInvoiceRoom(reportOrID: OnyxEntry<Report> | string): boolean
17221722
return !isEmptyObject(report) && isInvoiceRoom(report) && report?.invoiceReceiver?.type === CONST.REPORT.INVOICE_RECEIVER_TYPE.BUSINESS;
17231723
}
17241724

1725+
/**
1726+
* Returns the policyID of the invoice receiver when the receiver is a business, otherwise undefined.
1727+
*/
1728+
function getInvoiceReceiverPolicyID(report: OnyxEntry<Report>): string | undefined {
1729+
return report?.invoiceReceiver?.type === CONST.REPORT.INVOICE_RECEIVER_TYPE.BUSINESS ? report.invoiceReceiver.policyID : undefined;
1730+
}
1731+
17251732
function isCurrentUserInvoiceReceiver(report: OnyxEntry<Report>): boolean {
17261733
if (report?.invoiceReceiver?.type === CONST.REPORT.INVOICE_RECEIVER_TYPE.INDIVIDUAL) {
17271734
return deprecatedCurrentUserAccountID === report.invoiceReceiver.accountID;
@@ -1798,14 +1805,13 @@ function isPublicAnnounceRoom(report: OnyxEntry<Report>): boolean {
17981805
* If the report is a policy expense, the route should be for adding bank account for that policy
17991806
* else since the report is a personal IOU, the route should be for personal bank account.
18001807
*/
1801-
function getBankAccountRoute(report: OnyxEntry<Report>): Route {
1808+
function getBankAccountRoute(report: OnyxEntry<Report>, areInvoicesEnabled: boolean | undefined): Route {
18021809
if (isPolicyExpenseChat(report)) {
18031810
return ROUTES.BANK_ACCOUNT_WITH_STEP_TO_OPEN.getRoute({policyID: report?.policyID, backTo: Navigation.getActiveRoute()});
18041811
}
18051812

18061813
if (isInvoiceRoom(report) && report?.invoiceReceiver?.type === CONST.REPORT.INVOICE_RECEIVER_TYPE.BUSINESS) {
1807-
const invoiceReceiverPolicy = allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${report?.invoiceReceiver?.policyID}`];
1808-
if (invoiceReceiverPolicy?.areInvoicesEnabled) {
1814+
if (areInvoicesEnabled) {
18091815
return ROUTES.WORKSPACE_INVOICES.getRoute(report?.invoiceReceiver?.policyID);
18101816
}
18111817
}
@@ -5925,7 +5931,7 @@ function getReportName(reportNameInformation: GetReportNameParams): string {
59255931
}
59265932

59275933
if (isInvoiceRoom(report)) {
5928-
const invoiceReceiverPolicyID = report?.invoiceReceiver?.type === CONST.REPORT.INVOICE_RECEIVER_TYPE.BUSINESS ? report?.invoiceReceiver?.policyID : undefined;
5934+
const invoiceReceiverPolicyID = getInvoiceReceiverPolicyID(report);
59295935
formattedName = getInvoicesChatName({
59305936
report,
59315937
// This will be fixed as part of https://github.com/Expensify/Expensify/issues/507850
@@ -6142,7 +6148,7 @@ function getParentNavigationSubtitle(
61426148

61436149
if (isInvoiceReport(report) || isInvoiceRoom(parentReport)) {
61446150
const senderWorkspaceName = getPolicyName({report: parentReport, policy});
6145-
const invoiceReceiverPolicyID = parentReport?.invoiceReceiver?.type === CONST.REPORT.INVOICE_RECEIVER_TYPE.BUSINESS ? parentReport.invoiceReceiver.policyID : undefined;
6151+
const invoiceReceiverPolicyID = getInvoiceReceiverPolicyID(parentReport);
61466152
const invoiceReceiverPolicy = invoiceReceiverPolicyID ? allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${invoiceReceiverPolicyID}`] : undefined;
61476153
const isCurrentUserReceiver = isCurrentUserInvoiceReceiver(parentReport);
61486154
const invoicePayerName = getInvoicePayerName(parentReport, invoiceReceiverPolicy);
@@ -13334,6 +13340,7 @@ export {
1333413340
getAllWorkspaceReports,
1333513341
getAvailableReportFields,
1333613342
getBankAccountRoute,
13343+
getInvoiceReceiverPolicyID,
1333713344
getChatByParticipants,
1333813345
getChatRoomSubtitle,
1333913346
getChildReportNotificationPreference,

src/libs/SearchUIUtils.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ import {
138138
findSelfDMReportID,
139139
generateReportID,
140140
getIcons,
141+
getInvoiceReceiverPolicyID,
141142
getMoneyRequestSpendBreakdown,
142143
getPersonalDetailsForAccountID,
143144
getPolicyName,
@@ -2644,8 +2645,8 @@ function getReportActionsSections(data: OnyxTypes.SearchResults['data'], visible
26442645
const originalMessage = isMoneyRequestAction(reportAction) ? getOriginalMessage<typeof CONST.REPORT.ACTIONS.TYPE.IOU>(reportAction) : undefined;
26452646
const isSendingMoney = isMoneyRequestAction(reportAction) && originalMessage?.type === CONST.IOU.REPORT_ACTION_TYPE.PAY && originalMessage?.IOUDetails;
26462647
const isReportArchived = isArchivedReport(data[`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report.reportID}`]);
2647-
const invoiceReceiverPolicy: OnyxTypes.Policy | undefined =
2648-
report?.invoiceReceiver?.type === CONST.REPORT.INVOICE_RECEIVER_TYPE.BUSINESS ? data[`${ONYXKEYS.COLLECTION.POLICY}${report.invoiceReceiver.policyID}`] : undefined;
2648+
const invoiceReceiverPolicyID = getInvoiceReceiverPolicyID(report);
2649+
const invoiceReceiverPolicy: OnyxTypes.Policy | undefined = invoiceReceiverPolicyID ? data[`${ONYXKEYS.COLLECTION.POLICY}${invoiceReceiverPolicyID}`] : undefined;
26492650
if (
26502651
!reportID ||
26512652
!isReportActionVisible(reportAction, reportID, canUserPerformWriteAction(report, isReportArchived), visibleReportActionsData) ||

src/pages/Debug/Report/DebugReportActions.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,8 @@ import Navigation from '@libs/Navigation/Navigation';
1414
import {getHeaderMessageForNonUserList, getPersonalDetailsForAccountIDs} from '@libs/OptionsListUtils';
1515
import Parser from '@libs/Parser';
1616
import {getOriginalMessage, getReportActionMessage, getReportActionMessageText, getSortedReportActionsForDisplay, isCreatedAction} from '@libs/ReportActionsUtils';
17-
import {canUserPerformWriteAction, formatReportLastMessageText, getParticipantsAccountIDsForDisplay} from '@libs/ReportUtils';
17+
import {canUserPerformWriteAction, formatReportLastMessageText, getInvoiceReceiverPolicyID, getParticipantsAccountIDsForDisplay} from '@libs/ReportUtils';
1818
import SidebarUtils from '@libs/SidebarUtils';
19-
import CONST from '@src/CONST';
2019
import ONYXKEYS from '@src/ONYXKEYS';
2120
import ROUTES from '@src/ROUTES';
2221
import type {ReportAction, ReportActions} from '@src/types/onyx';
@@ -31,7 +30,7 @@ function DebugReportActions({reportID}: DebugReportActionsProps) {
3130
const [searchValue, debouncedSearchValue, setSearchValue] = useDebouncedState('');
3231
const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`);
3332
const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${report?.policyID}`);
34-
const invoiceReceiverPolicyID = report?.invoiceReceiver?.type === CONST.REPORT.INVOICE_RECEIVER_TYPE.BUSINESS ? report.invoiceReceiver.policyID : undefined;
33+
const invoiceReceiverPolicyID = getInvoiceReceiverPolicyID(report);
3534
const [invoiceReceiverPolicy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${invoiceReceiverPolicyID}`);
3635
const isReportArchived = useReportIsArchived(reportID);
3736
const ifUserCanPerformWriteAction = canUserPerformWriteAction(report, isReportArchived);

src/selectors/Policy.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,8 @@ function lastWorkspaceNumberSelector(policies: OnyxCollection<Policy>, email: st
223223

224224
const policyNameSelector = (policy: OnyxEntry<Policy>) => policy?.name;
225225

226+
const areInvoicesEnabledSelector = (policy: OnyxEntry<Policy>) => policy?.areInvoicesEnabled;
227+
226228
function isAdminForPolicyByIDSelector(policyID?: string) {
227229
return (policies: OnyxCollection<Policy> | null): boolean => {
228230
if (!policyID) {
@@ -269,6 +271,7 @@ export {
269271
lastWorkspaceNumberSelector,
270272
hasOnlyPersonalPoliciesSelector,
271273
policyNameSelector,
274+
areInvoicesEnabledSelector,
272275
createAdminPoliciesSelector,
273276
isAdminForPolicyByIDSelector,
274277
};

tests/unit/ReportUtilsTest.ts

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ import {
7777
getAllReportActionsErrorsAndReportActionThatRequiresAttention,
7878
getApprovalChain,
7979
getAvailableReportFields,
80+
getBankAccountRoute,
8081
getBillableAndTaxTotal,
8182
getChatByParticipants,
8283
getChatListItemReportName,
@@ -11606,12 +11607,14 @@ describe('ReportUtils', () => {
1160611607
await flushPromises();
1160711608
});
1160811609

11610+
const mockGetActiveRoute = Navigation.getActiveRoute as jest.Mock;
11611+
1160911612
afterAll(() => {
1161011613
mockIsSearchTopmostFullScreenRoute.mockRestore();
11614+
mockGetActiveRoute.mockReset();
11615+
mockGetActiveRoute.mockReturnValue('mock-route');
1161111616
});
1161211617

11613-
const mockGetActiveRoute = Navigation.getActiveRoute as jest.Mock;
11614-
1161511618
beforeEach(() => {
1161611619
mockIsSearchTopmostFullScreenRoute.mockReset();
1161711620
mockIsSearchTopmostFullScreenRoute.mockReturnValue(false);
@@ -18166,4 +18169,45 @@ describe('ReportUtils', () => {
1816618169
expect(hasExportError(reportActions, report)).toBe(true);
1816718170
});
1816818171
});
18172+
18173+
describe('getBankAccountRoute', () => {
18174+
it('returns the policy bank account setup route when the report is a policy expense chat', () => {
18175+
const policyID = 'POLICY_EXP_1';
18176+
const report = {
18177+
reportID: '1',
18178+
chatType: CONST.REPORT.CHAT_TYPE.POLICY_EXPENSE_CHAT,
18179+
policyID,
18180+
} as Report;
18181+
18182+
expect(getBankAccountRoute(report, undefined)).toBe(ROUTES.BANK_ACCOUNT_WITH_STEP_TO_OPEN.getRoute({policyID, backTo: 'mock-route'}));
18183+
});
18184+
18185+
it('returns the workspace invoices route when the report is a business invoice room and areInvoicesEnabled is true', () => {
18186+
const invoiceReceiverPolicyID = 'POLICY_INVOICE_1';
18187+
const report = {
18188+
reportID: '2',
18189+
chatType: CONST.REPORT.CHAT_TYPE.INVOICE,
18190+
invoiceReceiver: {
18191+
type: CONST.REPORT.INVOICE_RECEIVER_TYPE.BUSINESS,
18192+
policyID: invoiceReceiverPolicyID,
18193+
},
18194+
} as Report;
18195+
18196+
expect(getBankAccountRoute(report, true)).toBe(ROUTES.WORKSPACE_INVOICES.getRoute(invoiceReceiverPolicyID));
18197+
});
18198+
18199+
it('returns the personal add bank account route when the report is a business invoice room and areInvoicesEnabled is false', () => {
18200+
const invoiceReceiverPolicyID = 'POLICY_INVOICE_2';
18201+
const report = {
18202+
reportID: '3',
18203+
chatType: CONST.REPORT.CHAT_TYPE.INVOICE,
18204+
invoiceReceiver: {
18205+
type: CONST.REPORT.INVOICE_RECEIVER_TYPE.BUSINESS,
18206+
policyID: invoiceReceiverPolicyID,
18207+
},
18208+
} as Report;
18209+
18210+
expect(getBankAccountRoute(report, false)).toBe(ROUTES.SETTINGS_ADD_BANK_ACCOUNT.route);
18211+
});
18212+
});
1816918213
});

0 commit comments

Comments
 (0)