Skip to content

Commit 19dbed9

Browse files
authored
Merge pull request Expensify#64794 from callstack-internal/plaid-import-accounts
[Internal QA]: Change logic to fetch plaid import account
2 parents cb386ea + cacaac9 commit 19dbed9

7 files changed

Lines changed: 105 additions & 36 deletions

File tree

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import {useCallback} from 'react';
2+
import {useOnyx} from 'react-native-onyx';
3+
import {getDomainNameForPolicy} from '@libs/PolicyUtils';
4+
import {importPlaidAccounts} from '@userActions/Plaid';
5+
import ONYXKEYS from '@src/ONYXKEYS';
6+
7+
export default function useImportPlaidAccounts(policyID?: string) {
8+
const [assignCard] = useOnyx(ONYXKEYS.ASSIGN_CARD, {canBeMissing: true});
9+
const [addNewCard] = useOnyx(ONYXKEYS.ADD_NEW_COMPANY_CARD, {canBeMissing: true});
10+
11+
const plaidToken = addNewCard?.data?.publicToken ?? assignCard?.data?.plaidAccessToken;
12+
const plaidFeed = addNewCard?.data?.plaidConnectedFeed ?? assignCard?.data?.institutionId;
13+
const plaidFeedName = addNewCard?.data?.plaidConnectedFeedName ?? assignCard?.data?.plaidConnectedFeedName;
14+
const plaidAccounts = addNewCard?.data?.plaidAccounts ?? assignCard?.data?.plaidAccounts;
15+
const country = addNewCard?.data?.selectedCountry;
16+
17+
return useCallback(() => {
18+
if (!policyID || !plaidToken || !plaidFeed || !plaidFeedName || !country || !plaidAccounts?.length) {
19+
return;
20+
}
21+
importPlaidAccounts(plaidToken, plaidFeed, plaidFeedName, country, getDomainNameForPolicy(policyID), JSON.stringify(plaidAccounts));
22+
}, [country, plaidAccounts, plaidFeed, plaidFeedName, plaidToken, policyID]);
23+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
type ImportPlaidAccountsParams = {
2+
publicToken: string;
3+
feed: string;
4+
feedName: string;
5+
country: string;
6+
domainName: string;
7+
plaidAccounts: string;
8+
};
9+
10+
export default ImportPlaidAccountsParams;

src/libs/API/parameters/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ export type {default as VerifyIdentityForBankAccountParams} from './VerifyIdenti
102102
export type {default as AnswerQuestionsForWalletParams} from './AnswerQuestionsForWalletParams';
103103
export type {default as AddCommentOrAttachmentParams} from './AddCommentOrAttachmentParams';
104104
export type {default as ReadNewestActionParams} from './ReadNewestActionParams';
105+
export type {default as ImportPlaidAccountsParams} from './ImportPlaidAccountsParams';
105106
export type {default as MarkAllMessagesAsReadParams} from './MarkAllMessagesAsReadParams';
106107
export type {default as MarkAsUnreadParams} from './MarkAsUnreadParams';
107108
export type {default as TogglePinnedChatParams} from './TogglePinnedChatParams';

src/libs/API/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,7 @@ const WRITE_COMMANDS = {
486486
COMPLETE_CONCIERGE_CALL: 'CompleteConciergeCall',
487487
FINISH_CORPAY_BANK_ACCOUNT_ONBOARDING: 'FinishCorpayBankAccountOnboarding',
488488
REOPEN_REPORT: 'ReopenReport',
489+
IMPORT_PLAID_ACCOUNTS: 'ImportPlaidAccounts',
489490
} as const;
490491

491492
type WriteCommand = ValueOf<typeof WRITE_COMMANDS>;
@@ -988,6 +989,7 @@ type WriteCommandParameters = {
988989
[WRITE_COMMANDS.CHANGE_REPORT_POLICY_AND_INVITE_SUBMITTER]: Parameters.ChangeReportPolicyAndInviteSubmitterParams;
989990

990991
[WRITE_COMMANDS.PAY_AND_DOWNGRADE]: null;
992+
[WRITE_COMMANDS.IMPORT_PLAID_ACCOUNTS]: Parameters.ImportPlaidAccountsParams;
991993

992994
// Change transaction report
993995
[WRITE_COMMANDS.CHANGE_TRANSACTIONS_REPORT]: Parameters.ChangeTransactionsReportParams;

src/libs/actions/Plaid.ts

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import Onyx from 'react-native-onyx';
22
import * as API from '@libs/API';
3-
import type {OpenPlaidBankAccountSelectorParams, OpenPlaidBankLoginParams} from '@libs/API/parameters';
3+
import type {ImportPlaidAccountsParams, OpenPlaidBankAccountSelectorParams, OpenPlaidBankLoginParams} from '@libs/API/parameters';
44
import type OpenPlaidCompanyCardLoginParams from '@libs/API/parameters/OpenPlaidCompanyCardLoginParams';
5-
import {READ_COMMANDS} from '@libs/API/types';
5+
import {READ_COMMANDS, WRITE_COMMANDS} from '@libs/API/types';
66
import getPlaidLinkTokenParameters from '@libs/getPlaidLinkTokenParameters';
77
import CONST from '@src/CONST';
88
import ONYXKEYS from '@src/ONYXKEYS';
@@ -114,4 +114,17 @@ function openPlaidBankAccountSelector(publicToken: string, bankName: string, all
114114
});
115115
}
116116

117-
export {openPlaidBankAccountSelector, openPlaidBankLogin, openPlaidCompanyCardLogin};
117+
function importPlaidAccounts(publicToken: string, feed: string, feedName: string, country: string, domainName: string, plaidAccounts: string) {
118+
const parameters: ImportPlaidAccountsParams = {
119+
publicToken,
120+
feed,
121+
feedName,
122+
country,
123+
domainName,
124+
plaidAccounts,
125+
};
126+
127+
API.write(WRITE_COMMANDS.IMPORT_PLAID_ACCOUNTS, parameters);
128+
}
129+
130+
export {openPlaidBankAccountSelector, openPlaidBankLogin, openPlaidCompanyCardLogin, importPlaidAccounts};

src/pages/workspace/companyCards/BankConnection/index.native.tsx

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator';
88
import HeaderWithBackButton from '@components/HeaderWithBackButton';
99
import ScreenWrapper from '@components/ScreenWrapper';
1010
import useCardFeeds from '@hooks/useCardFeeds';
11+
import useImportPlaidAccounts from '@hooks/useImportPlaidAccounts';
1112
import useLocalize from '@hooks/useLocalize';
1213
import usePermissions from '@hooks/usePermissions';
1314
import usePrevious from '@hooks/usePrevious';
@@ -21,7 +22,7 @@ import Navigation from '@libs/Navigation/Navigation';
2122
import type {PlatformStackRouteProp} from '@navigation/PlatformStackNavigation/types';
2223
import type {SettingsNavigatorParamList} from '@navigation/types';
2324
import {setAddNewCompanyCardStepAndData} from '@userActions/CompanyCards';
24-
import {getCompanyCardBankConnection, getCompanyCardPlaidConnection} from '@userActions/getCompanyCardBankConnection';
25+
import {getCompanyCardBankConnection} from '@userActions/getCompanyCardBankConnection';
2526
import CONST from '@src/CONST';
2627
import ONYXKEYS from '@src/ONYXKEYS';
2728
import ROUTES from '@src/ROUTES';
@@ -54,15 +55,9 @@ function BankConnection({policyID: policyIDFromProps, feed, route}: BankConnecti
5455
const bankName = feed ? getBankName(feed) : (bankNameFromRoute ?? addNewCard?.data?.plaidConnectedFeed ?? selectedBank);
5556
const {isBetaEnabled} = usePermissions();
5657
const plaidToken = addNewCard?.data?.publicToken ?? assignCard?.data?.plaidAccessToken;
57-
const plaidFeed = addNewCard?.data?.plaidConnectedFeed ?? assignCard?.data?.institutionId;
58-
const plaidFeedName = addNewCard?.data?.plaidConnectedFeedName ?? assignCard?.data?.plaidConnectedFeedName;
59-
const plaidAccounts = addNewCard?.data?.plaidAccounts ?? assignCard?.data?.plaidAccounts;
60-
const country = addNewCard?.data?.selectedCountry;
58+
const isPlaid = isBetaEnabled(CONST.BETAS.PLAID_COMPANY_CARDS) && !!plaidToken;
6159

62-
const url =
63-
isBetaEnabled(CONST.BETAS.PLAID_COMPANY_CARDS) && plaidToken
64-
? getCompanyCardPlaidConnection(policyID, plaidToken, plaidFeed, plaidFeedName, country, plaidAccounts)
65-
: getCompanyCardBankConnection(policyID, bankName);
60+
const url = getCompanyCardBankConnection(policyID, bankName);
6661
const [cardFeeds] = useCardFeeds(policyID);
6762
const [isConnectionCompleted, setConnectionCompleted] = useState(false);
6863
const prevFeedsData = usePrevious(cardFeeds?.settings?.oAuthAccountDetails);
@@ -73,6 +68,7 @@ function BankConnection({policyID: policyIDFromProps, feed, route}: BankConnecti
7368
);
7469
const headerTitleAddCards = !backTo ? translate('workspace.companyCards.addCards') : undefined;
7570
const headerTitle = feed ? translate('workspace.companyCards.assignCard') : headerTitleAddCards;
71+
const onImportPlaidAccounts = useImportPlaidAccounts(policyID);
7672

7773
const renderLoading = () => <FullScreenLoadingIndicator />;
7874

@@ -100,7 +96,7 @@ function BankConnection({policyID: policyIDFromProps, feed, route}: BankConnecti
10096
};
10197

10298
useEffect(() => {
103-
if (!url) {
99+
if (!url && !isPlaid) {
104100
return;
105101
}
106102

@@ -120,7 +116,10 @@ function BankConnection({policyID: policyIDFromProps, feed, route}: BankConnecti
120116
}
121117
Navigation.navigate(ROUTES.WORKSPACE_COMPANY_CARDS.getRoute(policyID), {forceReplace: true});
122118
}
123-
}, [isNewFeedConnected, newFeed, policyID, url, feed, isFeedExpired, assignCard?.data?.dateOption]);
119+
if (isPlaid) {
120+
onImportPlaidAccounts();
121+
}
122+
}, [isNewFeedConnected, newFeed, policyID, url, feed, isFeedExpired, assignCard?.data?.dateOption, isPlaid, onImportPlaidAccounts]);
124123

125124
const checkIfConnectionCompleted = (navState: WebViewNavigation) => {
126125
if (!navState.url.includes(ROUTES.BANK_CONNECTION_COMPLETE)) {
@@ -142,7 +141,7 @@ function BankConnection({policyID: policyIDFromProps, feed, route}: BankConnecti
142141
onBackButtonPress={handleBackButtonPress}
143142
/>
144143
<FullPageOfflineBlockingView addBottomSafeAreaPadding>
145-
{!!url && !isConnectionCompleted && (
144+
{!!url && !isConnectionCompleted && !isPlaid && (
146145
<WebView
147146
ref={webViewRef}
148147
source={{
@@ -158,7 +157,7 @@ function BankConnection({policyID: policyIDFromProps, feed, route}: BankConnecti
158157
renderLoading={renderLoading}
159158
/>
160159
)}
161-
{isConnectionCompleted && (
160+
{(isConnectionCompleted || isPlaid) && (
162161
<ActivityIndicator
163162
size={CONST.ACTIVITY_INDICATOR_SIZE.LARGE}
164163
style={styles.flex1}

src/pages/workspace/companyCards/BankConnection/index.tsx

Lines changed: 41 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import React, {useCallback, useEffect, useMemo, useState} from 'react';
2+
import {ActivityIndicator} from 'react-native';
23
import {useOnyx} from 'react-native-onyx';
34
import BlockingView from '@components/BlockingViews/BlockingView';
45
import FullPageOfflineBlockingView from '@components/BlockingViews/FullPageOfflineBlockingView';
@@ -8,10 +9,12 @@ import ScreenWrapper from '@components/ScreenWrapper';
89
import Text from '@components/Text';
910
import TextLink from '@components/TextLink';
1011
import useCardFeeds from '@hooks/useCardFeeds';
12+
import useImportPlaidAccounts from '@hooks/useImportPlaidAccounts';
1113
import useLocalize from '@hooks/useLocalize';
1214
import useNetwork from '@hooks/useNetwork';
1315
import usePermissions from '@hooks/usePermissions';
1416
import usePrevious from '@hooks/usePrevious';
17+
import useTheme from '@hooks/useTheme';
1518
import useThemeStyles from '@hooks/useThemeStyles';
1619
import {setAssignCardStepAndData} from '@libs/actions/CompanyCards';
1720
import {checkIfNewFeedConnected, getBankName, isSelectedFeedExpired} from '@libs/CardUtils';
@@ -20,7 +23,7 @@ import type {PlatformStackRouteProp} from '@navigation/PlatformStackNavigation/t
2023
import type {SettingsNavigatorParamList} from '@navigation/types';
2124
import {updateSelectedFeed} from '@userActions/Card';
2225
import {setAddNewCompanyCardStepAndData} from '@userActions/CompanyCards';
23-
import {getCompanyCardBankConnection, getCompanyCardPlaidConnection} from '@userActions/getCompanyCardBankConnection';
26+
import {getCompanyCardBankConnection} from '@userActions/getCompanyCardBankConnection';
2427
import CONST from '@src/CONST';
2528
import ONYXKEYS from '@src/ONYXKEYS';
2629
import ROUTES from '@src/ROUTES';
@@ -46,6 +49,7 @@ function BankConnection({policyID: policyIDFromProps, feed, route}: BankConnecti
4649
const {translate} = useLocalize();
4750
const [addNewCard] = useOnyx(ONYXKEYS.ADD_NEW_COMPANY_CARD, {canBeMissing: true});
4851
const [assignCard] = useOnyx(ONYXKEYS.ASSIGN_CARD, {canBeMissing: true});
52+
const theme = useTheme();
4953
const {bankName: bankNameFromRoute, backTo, policyID: policyIDFromRoute} = route?.params ?? {};
5054
const policyID = policyIDFromProps ?? policyIDFromRoute;
5155
const [cardFeeds] = useCardFeeds(policyID);
@@ -59,17 +63,14 @@ function BankConnection({policyID: policyIDFromProps, feed, route}: BankConnecti
5963
);
6064
const {isOffline} = useNetwork();
6165
const plaidToken = addNewCard?.data?.publicToken ?? assignCard?.data?.plaidAccessToken;
62-
const plaidFeed = addNewCard?.data?.plaidConnectedFeed ?? assignCard?.data?.institutionId;
63-
const plaidAccounts = addNewCard?.data?.plaidAccounts ?? assignCard?.data?.plaidAccounts;
64-
const plaidFeedName = addNewCard?.data?.plaidConnectedFeedName ?? assignCard?.data?.plaidConnectedFeedName;
65-
const country = addNewCard?.data?.selectedCountry;
6666
const {isBetaEnabled} = usePermissions();
6767
const isPlaid = isBetaEnabled(CONST.BETAS.PLAID_COMPANY_CARDS) && !!plaidToken;
6868

69-
const url = isPlaid ? getCompanyCardPlaidConnection(policyID, plaidToken, plaidFeed, plaidFeedName, country, plaidAccounts) : getCompanyCardBankConnection(policyID, bankName);
69+
const url = getCompanyCardBankConnection(policyID, bankName);
7070
const isFeedExpired = feed ? isSelectedFeedExpired(cardFeeds?.settings?.oAuthAccountDetails?.[feed]) : false;
7171
const headerTitleAddCards = !backTo ? translate('workspace.companyCards.addCards') : undefined;
7272
const headerTitle = feed ? translate('workspace.companyCards.assignCard') : headerTitleAddCards;
73+
const onImportPlaidAccounts = useImportPlaidAccounts(policyID);
7374

7475
const onOpenBankConnectionFlow = useCallback(() => {
7576
if (!url) {
@@ -114,7 +115,7 @@ function BankConnection({policyID: policyIDFromProps, feed, route}: BankConnecti
114115
);
115116

116117
useEffect(() => {
117-
if (!url || isOffline) {
118+
if ((!url && !isPlaid) || isOffline) {
118119
return;
119120
}
120121

@@ -128,8 +129,14 @@ function BankConnection({policyID: policyIDFromProps, feed, route}: BankConnecti
128129
});
129130
return;
130131
}
131-
customWindow = openBankConnection(url);
132-
return;
132+
if (isPlaid) {
133+
onImportPlaidAccounts();
134+
return;
135+
}
136+
if (url) {
137+
customWindow = openBankConnection(url);
138+
return;
139+
}
133140
}
134141

135142
// Handle add new card flow
@@ -144,9 +151,15 @@ function BankConnection({policyID: policyIDFromProps, feed, route}: BankConnecti
144151
return;
145152
}
146153
if (!shouldBlockWindowOpen) {
147-
customWindow = openBankConnection(url);
154+
if (isPlaid) {
155+
onImportPlaidAccounts();
156+
return;
157+
}
158+
if (url) {
159+
customWindow = openBankConnection(url);
160+
}
148161
}
149-
}, [isNewFeedConnected, shouldBlockWindowOpen, newFeed, policyID, url, feed, isFeedExpired, isOffline, assignCard?.data?.dateOption]);
162+
}, [isNewFeedConnected, shouldBlockWindowOpen, newFeed, policyID, url, feed, isFeedExpired, isOffline, assignCard?.data?.dateOption, isPlaid, onImportPlaidAccounts]);
150163

151164
return (
152165
<ScreenWrapper
@@ -158,15 +171,23 @@ function BankConnection({policyID: policyIDFromProps, feed, route}: BankConnecti
158171
onBackButtonPress={handleBackButtonPress}
159172
/>
160173
<FullPageOfflineBlockingView addBottomSafeAreaPadding>
161-
<BlockingView
162-
icon={PendingBank}
163-
iconWidth={styles.pendingBankCardIllustration.width}
164-
iconHeight={styles.pendingBankCardIllustration.height}
165-
title={translate('workspace.moreFeatures.companyCards.pendingBankTitle')}
166-
CustomSubtitle={CustomSubtitle}
167-
onLinkPress={onOpenBankConnectionFlow}
168-
addBottomSafeAreaPadding
169-
/>
174+
{isPlaid ? (
175+
<ActivityIndicator
176+
size={CONST.ACTIVITY_INDICATOR_SIZE.LARGE}
177+
style={styles.flex1}
178+
color={theme.spinner}
179+
/>
180+
) : (
181+
<BlockingView
182+
icon={PendingBank}
183+
iconWidth={styles.pendingBankCardIllustration.width}
184+
iconHeight={styles.pendingBankCardIllustration.height}
185+
title={translate('workspace.moreFeatures.companyCards.pendingBankTitle')}
186+
CustomSubtitle={CustomSubtitle}
187+
onLinkPress={onOpenBankConnectionFlow}
188+
addBottomSafeAreaPadding
189+
/>
190+
)}
170191
</FullPageOfflineBlockingView>
171192
</ScreenWrapper>
172193
);

0 commit comments

Comments
 (0)