Skip to content

Commit 3c4f325

Browse files
committed
fix: not validated account edgecase
1 parent 0f19c22 commit 3c4f325

7 files changed

Lines changed: 52 additions & 34 deletions

File tree

src/CONST/index.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -487,11 +487,6 @@ const CONST = {
487487
},
488488
STEP_NAMES: ['1', '2', '3', '4', '5', '6'],
489489
STEPS_HEADER_HEIGHT: 40,
490-
SUBSTEP: {
491-
MANUAL: 'manual',
492-
PLAID: 'plaid',
493-
EMPTY: '',
494-
},
495490
VERIFICATIONS: {
496491
ERROR_MESSAGE: 'verifications.errorMessage',
497492
THROTTLED: 'verifications.throttled',
@@ -510,6 +505,7 @@ const CONST = {
510505
SETUP_TYPE: {
511506
MANUAL: 'manual',
512507
PLAID: 'plaid',
508+
EMPTY: '',
513509
},
514510
REGEX: {
515511
US_ACCOUNT_NUMBER: /^[0-9]{4,17}$/,

src/ONYXKEYS.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,9 @@ const ONYXKEYS = {
304304
/** Stores Workspace ID that will be tied to reimbursement account during setup */
305305
REIMBURSEMENT_ACCOUNT_WORKSPACE_ID: 'reimbursementAccountWorkspaceID',
306306

307+
/** Stores information about type of connection user wants to perform before showing him validation code modal */
308+
REIMBURSEMENT_ACCOUNT_OPTION_PRESSED: 'reimbursementAccountOptionPressed',
309+
307310
/** Set when we are loading payment methods */
308311
IS_LOADING_PAYMENT_METHODS: 'isLoadingPaymentMethods',
309312

@@ -1104,6 +1107,7 @@ type OnyxValuesMapping = {
11041107
[ONYXKEYS.PURCHASE_LIST]: OnyxTypes.PurchaseList;
11051108
[ONYXKEYS.PERSONAL_BANK_ACCOUNT]: OnyxTypes.PersonalBankAccount;
11061109
[ONYXKEYS.REIMBURSEMENT_ACCOUNT]: OnyxTypes.ReimbursementAccount;
1110+
[ONYXKEYS.REIMBURSEMENT_ACCOUNT_OPTION_PRESSED]: ValueOf<typeof CONST.BANK_ACCOUNT.SETUP_TYPE>;
11071111
[ONYXKEYS.PREFERRED_EMOJI_SKIN_TONE]: string | number;
11081112
[ONYXKEYS.FREQUENTLY_USED_EMOJIS]: OnyxTypes.FrequentlyUsedEmoji[];
11091113
[ONYXKEYS.REIMBURSEMENT_ACCOUNT_WORKSPACE_ID]: string;

src/libs/actions/ReimbursementAccount/index.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import Onyx from 'react-native-onyx';
2+
import type {ValueOf} from 'type-fest';
3+
import type CONST from '@src/CONST';
24
import ONYXKEYS from '@src/ONYXKEYS';
35
import type {ReimbursementAccountForm} from '@src/types/form';
46
import type {BankAccountSubStep} from '@src/types/onyx/ReimbursementAccount';
@@ -49,6 +51,13 @@ function cancelResetBankAccount() {
4951
Onyx.merge(ONYXKEYS.REIMBURSEMENT_ACCOUNT, {shouldShowResetModal: false});
5052
}
5153

54+
/**
55+
* Sets pressed option during connecting reimbursement account
56+
*/
57+
function setReimbursementAccountOptionPressed(optionPressed: ValueOf<typeof CONST.BANK_ACCOUNT.SETUP_TYPE>) {
58+
Onyx.set(ONYXKEYS.REIMBURSEMENT_ACCOUNT_OPTION_PRESSED, optionPressed);
59+
}
60+
5261
export {
5362
resetUSDBankAccount,
5463
resetNonUSDBankAccount,
@@ -59,4 +68,5 @@ export {
5968
cancelResetBankAccount,
6069
clearReimbursementAccountDraft,
6170
setBankAccountState,
71+
setReimbursementAccountOptionPressed,
6272
};

src/pages/ReimbursementAccount/ReimbursementAccountPage.tsx

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -93,26 +93,23 @@ function ReimbursementAccountPage({route, policy, isLoadingPolicy}: Reimbursemen
9393
: `${environmentURL}/${ROUTES.WORKSPACE_INITIAL.getRoute(policyIDParam, Navigation.getActiveRoute())}`;
9494

9595
const contactMethodRoute = `${environmentURL}/${ROUTES.SETTINGS_CONTACT_METHODS.getRoute(backTo)}`;
96-
97-
/**
98-
The SetupWithdrawalAccount flow allows us to continue the flow from various points depending on where the
99-
user left off. This view will refer to the achData as the single source of truth to determine which route to
100-
display. We can also specify a specific route to navigate to via route params when the component first
101-
mounts which will set the achData.currentStep after the account data is fetched and overwrite the logical
102-
next step.
103-
*/
10496
const achData = reimbursementAccount?.achData;
10597
const isPreviousPolicy = policyIDParam === achData?.policyID;
10698
const hasConfirmedUSDCurrency = (reimbursementAccountDraft?.[INPUT_IDS.ADDITIONAL_DATA.COUNTRY] ?? '') !== '' || (achData?.accountNumber ?? '') !== '';
10799

100+
/**
101+
currentStep determines the step that is displayed in the USD flow. In the majority of the cases it is based on the
102+
achData?.current step with one exception - the beginning of the flow. There is a step where user confirms the currency
103+
and the country, and it exists purely from FE perspective. We return early in getInitialCurrentStep and ignore
104+
achData?.currentStep value to display very first step.
105+
*/
108106
const getInitialCurrentStep = () => {
109107
if (!hasConfirmedUSDCurrency) {
110108
return CONST.BANK_ACCOUNT.STEP.COUNTRY;
111109
}
112110

113111
return achData?.currentStep ?? CONST.BANK_ACCOUNT.STEP.COUNTRY;
114112
};
115-
116113
const currentStep = getInitialCurrentStep();
117114
const [nonUSDBankAccountStep, setNonUSDBankAccountStep] = useState<string | null>(null);
118115
const [USDBankAccountStep, setUSDBankAccountStep] = useState<string | null>(null);
@@ -258,7 +255,7 @@ function ReimbursementAccountPage({route, policy, isLoadingPolicy}: Reimbursemen
258255
);
259256

260257
const continueUSDVBBASetup = useCallback(() => {
261-
const subStep = achData?.subStep !== undefined ? achData.subStep : CONST.BANK_ACCOUNT.SUBSTEP.MANUAL;
258+
const subStep = achData?.subStep !== undefined ? achData.subStep : CONST.BANK_ACCOUNT.SETUP_TYPE.MANUAL;
262259

263260
setBankAccountSubStep(subStep).then(() => {
264261
setShouldShowContinueSetupButton(false);

src/pages/ReimbursementAccount/USD/BankInfo/BankInfo.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ function BankInfo({onBackButtonPress, policyID, setUSDBankAccountStep}: BankInfo
4646

4747
let setupType = reimbursementAccount?.achData?.setupType ?? reimbursementAccount?.achData?.subStep ?? '';
4848

49-
const shouldReinitializePlaidLink = plaidLinkToken && receivedRedirectURI && setupType !== CONST.BANK_ACCOUNT.SUBSTEP.MANUAL;
49+
const shouldReinitializePlaidLink = plaidLinkToken && receivedRedirectURI && setupType !== CONST.BANK_ACCOUNT.SETUP_TYPE.MANUAL;
5050
if (shouldReinitializePlaidLink) {
5151
setupType = CONST.BANK_ACCOUNT.SETUP_TYPE.PLAID;
5252
}

src/pages/ReimbursementAccount/VerifiedBankAccountFlowEntryPoint.tsx

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import React, {useEffect, useMemo, useRef} from 'react';
1+
import React, {useCallback, useEffect, useMemo} from 'react';
22
import {View} from 'react-native';
33
import type {OnyxEntry} from 'react-native-onyx';
4+
import type {ValueOf} from 'type-fest';
45
import HeaderWithBackButton from '@components/HeaderWithBackButton';
56
import Icon from '@components/Icon';
67
import {Bank, Connect, Lightbulb, Lock, RotateLeft} from '@components/Icon/Expensicons';
@@ -25,7 +26,7 @@ import {REIMBURSEMENT_ACCOUNT_ROUTE_NAMES} from '@libs/ReimbursementAccountUtils
2526
import WorkspaceResetBankAccountModal from '@pages/workspace/WorkspaceResetBankAccountModal';
2627
import {goToWithdrawalAccountSetupStep, openPlaidView, updateReimbursementAccountDraft} from '@userActions/BankAccounts';
2728
import {openExternalLink, openExternalLinkWithToken} from '@userActions/Link';
28-
import {requestResetBankAccount, resetReimbursementAccount, setBankAccountSubStep} from '@userActions/ReimbursementAccount';
29+
import {requestResetBankAccount, resetReimbursementAccount, setBankAccountSubStep, setReimbursementAccountOptionPressed} from '@userActions/ReimbursementAccount';
2930
import {clearContactMethodErrors, requestValidateCodeAction, validateSecondaryLogin} from '@userActions/User';
3031
import CONST from '@src/CONST';
3132
import ONYXKEYS from '@src/ONYXKEYS';
@@ -96,7 +97,7 @@ function VerifiedBankAccountFlowEntryPoint({
9697
const errors = reimbursementAccount?.errors ?? {};
9798
const pendingAction = reimbursementAccount?.pendingAction ?? null;
9899
const [loginList] = useOnyx(ONYXKEYS.LOGIN_LIST, {canBeMissing: true});
99-
const optionPressed = useRef('');
100+
const [reimbursementAccountOptionPressed] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT_OPTION_PRESSED, {canBeMissing: true});
100101
const isAccountValidated = account?.validated ?? false;
101102

102103
const contactMethod = account?.primaryLogin ?? '';
@@ -119,6 +120,18 @@ function VerifiedBankAccountFlowEntryPoint({
119120
updateReimbursementAccountDraft(bankAccountData);
120121
};
121122

123+
/**
124+
* Prepares and redirects user to next step in the USD flow
125+
*/
126+
const prepareNextStep = useCallback(
127+
(setupType: ValueOf<typeof CONST.BANK_ACCOUNT.SETUP_TYPE>) => {
128+
setBankAccountSubStep(setupType);
129+
setUSDBankAccountStep(CONST.BANK_ACCOUNT.STEP.COUNTRY);
130+
goToWithdrawalAccountSetupStep(CONST.BANK_ACCOUNT.STEP.COUNTRY);
131+
},
132+
[setUSDBankAccountStep],
133+
);
134+
122135
/**
123136
* optionPressed ref indicates what user selected before modal to validate account was displayed
124137
* In this hook we check if account was validated and then proceed with the option user selected
@@ -129,23 +142,25 @@ function VerifiedBankAccountFlowEntryPoint({
129142
return;
130143
}
131144

132-
if (optionPressed.current === CONST.BANK_ACCOUNT.SETUP_TYPE.MANUAL) {
145+
if (reimbursementAccountOptionPressed === CONST.BANK_ACCOUNT.SETUP_TYPE.MANUAL) {
133146
if (isNonUSDWorkspace) {
134147
setNonUSDBankAccountStep(CONST.NON_USD_BANK_ACCOUNT.STEP.COUNTRY);
148+
setReimbursementAccountOptionPressed(CONST.BANK_ACCOUNT.SETUP_TYPE.EMPTY);
135149
return;
136150
}
137151

138-
setBankAccountSubStep(CONST.BANK_ACCOUNT.SETUP_TYPE.MANUAL);
139-
goToWithdrawalAccountSetupStep(CONST.BANK_ACCOUNT.STEP.COUNTRY);
140-
} else if (optionPressed.current === CONST.BANK_ACCOUNT.SETUP_TYPE.PLAID) {
152+
prepareNextStep(CONST.BANK_ACCOUNT.SETUP_TYPE.MANUAL);
153+
setReimbursementAccountOptionPressed(CONST.BANK_ACCOUNT.SETUP_TYPE.EMPTY);
154+
} else if (reimbursementAccountOptionPressed === CONST.BANK_ACCOUNT.SETUP_TYPE.PLAID) {
141155
openPlaidView();
142-
goToWithdrawalAccountSetupStep(CONST.BANK_ACCOUNT.STEP.COUNTRY);
156+
prepareNextStep(CONST.BANK_ACCOUNT.SETUP_TYPE.PLAID);
157+
setReimbursementAccountOptionPressed(CONST.BANK_ACCOUNT.SETUP_TYPE.EMPTY);
143158
}
144-
}, [isAccountValidated, isNonUSDWorkspace, setNonUSDBankAccountStep]);
159+
}, [isAccountValidated, isNonUSDWorkspace, prepareNextStep, reimbursementAccountOptionPressed, setNonUSDBankAccountStep]);
145160

146161
const handleConnectManually = () => {
147162
if (!isAccountValidated) {
148-
optionPressed.current = CONST.BANK_ACCOUNT.SETUP_TYPE.MANUAL;
163+
setReimbursementAccountOptionPressed(CONST.BANK_ACCOUNT.SETUP_TYPE.MANUAL);
149164
toggleValidateCodeActionModal?.(true);
150165
return;
151166
}
@@ -156,9 +171,7 @@ function VerifiedBankAccountFlowEntryPoint({
156171
}
157172

158173
removeExistingBankAccountDetails();
159-
setBankAccountSubStep(CONST.BANK_ACCOUNT.SETUP_TYPE.MANUAL);
160-
setUSDBankAccountStep(CONST.BANK_ACCOUNT.STEP.COUNTRY);
161-
goToWithdrawalAccountSetupStep(CONST.BANK_ACCOUNT.STEP.COUNTRY);
174+
prepareNextStep(CONST.BANK_ACCOUNT.SETUP_TYPE.MANUAL);
162175
};
163176

164177
const handleConnectPlaid = () => {
@@ -167,15 +180,13 @@ function VerifiedBankAccountFlowEntryPoint({
167180
}
168181

169182
if (!isAccountValidated) {
170-
optionPressed.current = CONST.BANK_ACCOUNT.SETUP_TYPE.PLAID;
183+
setReimbursementAccountOptionPressed(CONST.BANK_ACCOUNT.SETUP_TYPE.PLAID);
171184
toggleValidateCodeActionModal?.(true);
172185
return;
173186
}
174187

175188
removeExistingBankAccountDetails();
176-
setBankAccountSubStep(CONST.BANK_ACCOUNT.SETUP_TYPE.PLAID);
177-
setUSDBankAccountStep(CONST.BANK_ACCOUNT.STEP.COUNTRY);
178-
goToWithdrawalAccountSetupStep(CONST.BANK_ACCOUNT.STEP.COUNTRY);
189+
prepareNextStep(CONST.BANK_ACCOUNT.SETUP_TYPE.PLAID);
179190
};
180191

181192
return (

src/types/onyx/ReimbursementAccount.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import type * as OnyxCommon from './OnyxCommon';
1111
type BankAccountStep = ValueOf<typeof CONST.BANK_ACCOUNT.STEP>;
1212

1313
/** Substeps to setup a reimbursement bank account */
14-
type BankAccountSubStep = ValueOf<typeof CONST.BANK_ACCOUNT.SUBSTEP>;
14+
type BankAccountSubStep = ValueOf<typeof CONST.BANK_ACCOUNT.SETUP_TYPE>;
1515

1616
/** Model of Corpay data */
1717
type Corpay = {

0 commit comments

Comments
 (0)