diff --git a/src/libs/Navigation/Navigation.js b/src/libs/Navigation/Navigation.js index 07b12486b8b2..db806f71fab0 100644 --- a/src/libs/Navigation/Navigation.js +++ b/src/libs/Navigation/Navigation.js @@ -80,7 +80,7 @@ const getActiveRouteIndex = function (route, index) { /** * Main navigation method for redirecting to a route. * @param {String} route - * @param {String} type - Type of action to perform. Currently UP is supported. + * @param {String} [type] - Type of action to perform. Currently UP is supported. */ function navigate(route = ROUTES.HOME, type) { if (!canNavigate('navigate', {route})) { diff --git a/src/libs/actions/BankAccounts.js b/src/libs/actions/BankAccounts.ts similarity index 55% rename from src/libs/actions/BankAccounts.js rename to src/libs/actions/BankAccounts.ts index 4d3c880b5983..249d7de9293a 100644 --- a/src/libs/actions/BankAccounts.js +++ b/src/libs/actions/BankAccounts.ts @@ -7,6 +7,10 @@ import * as PlaidDataProps from '../../pages/ReimbursementAccount/plaidDataPropT import Navigation from '../Navigation/Navigation'; import ROUTES from '../../ROUTES'; import * as ReimbursementAccount from './ReimbursementAccount'; +import type PlaidBankAccount from '../../types/onyx/PlaidBankAccount'; +import type {ACHContractStepProps, BankAccountStepProps, CompanyStepProps, OnfidoData, ReimbursementAccountProps, RequestorStepProps} from '../../types/onyx/ReimbursementAccountDraft'; +import type {OnyxData} from '../../types/onyx/Request'; +import type {BankAccountStep, BankAccountSubStep} from '../../types/onyx/ReimbursementAccount'; export { goToWithdrawalAccountSetupStep, @@ -23,7 +27,13 @@ export { export {openPlaidBankAccountSelector, openPlaidBankLogin} from './Plaid'; export {openOnfidoFlow, answerQuestionsForWallet, verifyIdentity, acceptWalletTerms} from './Wallet'; -function clearPlaid() { +type BankAccountCompanyInformation = BankAccountStepProps & CompanyStepProps & ReimbursementAccountProps; + +type ReimbursementAccountStep = BankAccountStep | ''; + +type ReimbursementAccountSubStep = BankAccountSubStep | ''; + +function clearPlaid(): Promise { Onyx.set(ONYXKEYS.PLAID_LINK_TOKEN, ''); return Onyx.set(ONYXKEYS.PLAID_DATA, PlaidDataProps.plaidDataDefaultProps); @@ -35,9 +45,8 @@ function openPlaidView() { /** * Open the personal bank account setup flow, with an optional exitReportID to redirect to once the flow is finished. - * @param {String} exitReportID */ -function openPersonalBankAccountSetupView(exitReportID) { +function openPersonalBankAccountSetupView(exitReportID: string) { clearPlaid().then(() => { if (exitReportID) { Onyx.merge(ONYXKEYS.PERSONAL_BANK_ACCOUNT, {exitReportID}); @@ -57,10 +66,8 @@ function clearOnfidoToken() { /** * Helper method to build the Onyx data required during setup of a Verified Business Bank Account - * @param {String | undefined} currentStep The name of the bank account setup step for which we will update the draft value when we receive the response from the API. - * @returns {Object} */ -function getVBBADataForOnyx(currentStep = undefined) { +function getVBBADataForOnyx(currentStep?: BankAccountStep): OnyxData { return { optimisticData: [ { @@ -103,14 +110,20 @@ function getVBBADataForOnyx(currentStep = undefined) { /** * Submit Bank Account step with Plaid data so php can perform some checks. - * - * @param {Number} bankAccountID - * @param {Object} selectedPlaidBankAccount */ -function connectBankAccountWithPlaid(bankAccountID, selectedPlaidBankAccount) { +function connectBankAccountWithPlaid(bankAccountID: number, selectedPlaidBankAccount: PlaidBankAccount) { const commandName = 'ConnectBankAccountWithPlaid'; - const parameters = { + type ConnectBankAccountWithPlaidParams = { + bankAccountID: number; + routingNumber: string; + accountNumber: string; + bank?: string; + plaidAccountID: string; + plaidAccessToken: string; + }; + + const parameters: ConnectBankAccountWithPlaidParams = { bankAccountID, routingNumber: selectedPlaidBankAccount.routingNumber, accountNumber: selectedPlaidBankAccount.accountNumber, @@ -125,13 +138,23 @@ function connectBankAccountWithPlaid(bankAccountID, selectedPlaidBankAccount) { /** * Adds a bank account via Plaid * - * @param {Object} account * @TODO offline pattern for this command will have to be added later once the pattern B design doc is complete */ -function addPersonalBankAccount(account) { +function addPersonalBankAccount(account: PlaidBankAccount) { const commandName = 'AddPersonalBankAccount'; - const parameters = { + type AddPersonalBankAccountParams = { + addressName: string; + routingNumber: string; + accountNumber: string; + isSavings: boolean; + setupType: string; + bank?: string; + plaidAccountID: string; + plaidAccessToken: string; + }; + + const parameters: AddPersonalBankAccountParams = { addressName: account.addressName, routingNumber: account.routingNumber, accountNumber: account.accountNumber, @@ -142,7 +165,7 @@ function addPersonalBankAccount(account) { plaidAccessToken: account.plaidAccessToken, }; - const onyxData = { + const onyxData: OnyxData = { optimisticData: [ { onyxMethod: Onyx.METHOD.MERGE, @@ -180,107 +203,94 @@ function addPersonalBankAccount(account) { API.write(commandName, parameters, onyxData); } -function deletePaymentBankAccount(bankAccountID) { - API.write( - 'DeletePaymentBankAccount', - { - bankAccountID, - }, - { - optimisticData: [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.BANK_ACCOUNT_LIST}`, - value: {[bankAccountID]: {pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE}}, - }, - ], - - // Sometimes pusher updates aren't received when we close the App while still offline, - // so we are setting the bankAccount to null here to ensure that it gets cleared out once we come back online. - successData: [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.BANK_ACCOUNT_LIST}`, - value: {[bankAccountID]: null}, - }, - ], - }, - ); +function deletePaymentBankAccount(bankAccountID: number) { + type DeletePaymentBankAccountParams = {bankAccountID: number}; + + const parameters: DeletePaymentBankAccountParams = {bankAccountID}; + + const onyxData: OnyxData = { + optimisticData: [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.BANK_ACCOUNT_LIST}`, + value: {[bankAccountID]: {pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE}}, + }, + ], + + // Sometimes pusher updates aren't received when we close the App while still offline, + // so we are setting the bankAccount to null here to ensure that it gets cleared out once we come back online. + successData: [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.BANK_ACCOUNT_LIST}`, + value: {[bankAccountID]: null}, + }, + ], + }; + + API.write('DeletePaymentBankAccount', parameters, onyxData); } /** * Update the user's personal information on the bank account in database. * * This action is called by the requestor step in the Verified Bank Account flow - * - * @param {Object} params - * - * @param {String} [params.dob] - * @param {String} [params.firstName] - * @param {String} [params.lastName] - * @param {String} [params.requestorAddressStreet] - * @param {String} [params.requestorAddressCity] - * @param {String} [params.requestorAddressState] - * @param {String} [params.requestorAddressZipCode] - * @param {String} [params.ssnLast4] - * @param {String} [params.isControllingOfficer] - * @param {Object} [params.onfidoData] - * @param {Boolean} [params.isOnfidoSetupComplete] */ -function updatePersonalInformationForBankAccount(params) { +function updatePersonalInformationForBankAccount(params: RequestorStepProps) { API.write('UpdatePersonalInformationForBankAccount', params, getVBBADataForOnyx(CONST.BANK_ACCOUNT.STEP.REQUESTOR)); } -/** - * @param {Number} bankAccountID - * @param {String} validateCode - */ -function validateBankAccount(bankAccountID, validateCode) { - API.write( - 'ValidateBankAccountWithTransactions', - { - bankAccountID, - validateCode, - }, - { - optimisticData: [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.REIMBURSEMENT_ACCOUNT, - value: { - isLoading: true, - errors: null, - }, +function validateBankAccount(bankAccountID: number, validateCode: string) { + type ValidateBankAccountWithTransactionsParams = { + bankAccountID: number; + validateCode: string; + }; + + const parameters: ValidateBankAccountWithTransactionsParams = { + bankAccountID, + validateCode, + }; + + const onyxData: OnyxData = { + optimisticData: [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.REIMBURSEMENT_ACCOUNT, + value: { + isLoading: true, + errors: null, }, - ], - successData: [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.REIMBURSEMENT_ACCOUNT, - value: { - isLoading: false, - }, + }, + ], + successData: [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.REIMBURSEMENT_ACCOUNT, + value: { + isLoading: false, }, - ], - failureData: [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.REIMBURSEMENT_ACCOUNT, - value: { - isLoading: false, - }, + }, + ], + failureData: [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.REIMBURSEMENT_ACCOUNT, + value: { + isLoading: false, }, - ], - }, - ); + }, + ], + }; + + API.write('ValidateBankAccountWithTransactions', parameters, onyxData); } function clearReimbursementAccount() { Onyx.set(ONYXKEYS.REIMBURSEMENT_ACCOUNT, null); } -function openReimbursementAccountPage(stepToOpen, subStep, localCurrentStep) { - const onyxData = { +function openReimbursementAccountPage(stepToOpen: ReimbursementAccountStep, subStep: ReimbursementAccountSubStep, localCurrentStep: ReimbursementAccountStep) { + const onyxData: OnyxData = { optimisticData: [ { onyxMethod: Onyx.METHOD.MERGE, @@ -310,122 +320,104 @@ function openReimbursementAccountPage(stepToOpen, subStep, localCurrentStep) { ], }; - const param = { + type OpenReimbursementAccountPageParams = { + stepToOpen: ReimbursementAccountStep; + subStep: ReimbursementAccountSubStep; + localCurrentStep: ReimbursementAccountStep; + }; + + const parameters: OpenReimbursementAccountPageParams = { stepToOpen, subStep, localCurrentStep, }; - return API.read('OpenReimbursementAccountPage', param, onyxData); + return API.read('OpenReimbursementAccountPage', parameters, onyxData); } /** * Updates the bank account in the database with the company step data - * - * @param {Object} bankAccount - * @param {Number} [bankAccount.bankAccountID] - * - * Fields from BankAccount step - * @param {String} [bankAccount.routingNumber] - * @param {String} [bankAccount.accountNumber] - * @param {String} [bankAccount.bankName] - * @param {String} [bankAccount.plaidAccountID] - * @param {String} [bankAccount.plaidAccessToken] - * @param {Boolean} [bankAccount.isSavings] - * - * Fields from Company step - * @param {String} [bankAccount.companyName] - * @param {String} [bankAccount.addressStreet] - * @param {String} [bankAccount.addressCity] - * @param {String} [bankAccount.addressState] - * @param {String} [bankAccount.addressZipCode] - * @param {String} [bankAccount.companyPhone] - * @param {String} [bankAccount.website] - * @param {String} [bankAccount.companyTaxID] - * @param {String} [bankAccount.incorporationType] - * @param {String} [bankAccount.incorporationState] - * @param {String} [bankAccount.incorporationDate] - * @param {Boolean} [bankAccount.hasNoConnectionToCannabis] - * @param {String} policyID */ -function updateCompanyInformationForBankAccount(bankAccount, policyID) { - API.write('UpdateCompanyInformationForBankAccount', {...bankAccount, policyID}, getVBBADataForOnyx(CONST.BANK_ACCOUNT.STEP.COMPANY)); +function updateCompanyInformationForBankAccount(bankAccount: BankAccountCompanyInformation, policyID: string) { + type UpdateCompanyInformationForBankAccountParams = BankAccountCompanyInformation & {policyID: string}; + + const parameters: UpdateCompanyInformationForBankAccountParams = {...bankAccount, policyID}; + + API.write('UpdateCompanyInformationForBankAccount', parameters, getVBBADataForOnyx(CONST.BANK_ACCOUNT.STEP.COMPANY)); } /** * Add beneficial owners for the bank account, accept the ACH terms and conditions and verify the accuracy of the information provided - * - * @param {Object} params - * - * // ACH Contract Step - * @param {Boolean} [params.ownsMoreThan25Percent] - * @param {Boolean} [params.hasOtherBeneficialOwners] - * @param {Boolean} [params.acceptTermsAndConditions] - * @param {Boolean} [params.certifyTrueInformation] - * @param {String} [params.beneficialOwners] */ -function updateBeneficialOwnersForBankAccount(params) { - API.write('UpdateBeneficialOwnersForBankAccount', {...params}, getVBBADataForOnyx()); +function updateBeneficialOwnersForBankAccount(params: ACHContractStepProps) { + API.write('UpdateBeneficialOwnersForBankAccount', params, getVBBADataForOnyx()); } /** * Create the bank account with manually entered data. * - * @param {number} [bankAccountID] - * @param {String} [accountNumber] - * @param {String} [routingNumber] - * @param {String} [plaidMask] - * */ -function connectBankAccountManually(bankAccountID, accountNumber, routingNumber, plaidMask) { - API.write( - 'ConnectBankAccountManually', - { - bankAccountID, - accountNumber, - routingNumber, - plaidMask, - }, - getVBBADataForOnyx(CONST.BANK_ACCOUNT.STEP.BANK_ACCOUNT), - ); +function connectBankAccountManually(bankAccountID: number, accountNumber?: string, routingNumber?: string, plaidMask?: string) { + type ConnectBankAccountManuallyParams = { + bankAccountID: number; + accountNumber?: string; + routingNumber?: string; + plaidMask?: string; + }; + + const parameters: ConnectBankAccountManuallyParams = { + bankAccountID, + accountNumber, + routingNumber, + plaidMask, + }; + + API.write('ConnectBankAccountManually', parameters, getVBBADataForOnyx(CONST.BANK_ACCOUNT.STEP.BANK_ACCOUNT)); } /** * Verify the user's identity via Onfido - * - * @param {Number} bankAccountID - * @param {Object} onfidoData */ -function verifyIdentityForBankAccount(bankAccountID, onfidoData) { - API.write( - 'VerifyIdentityForBankAccount', - { - bankAccountID, - onfidoData: JSON.stringify(onfidoData), - }, - getVBBADataForOnyx(), - ); +function verifyIdentityForBankAccount(bankAccountID: number, onfidoData: OnfidoData) { + type VerifyIdentityForBankAccountParams = { + bankAccountID: number; + onfidoData: string; + }; + + const parameters: VerifyIdentityForBankAccountParams = { + bankAccountID, + onfidoData: JSON.stringify(onfidoData), + }; + + API.write('VerifyIdentityForBankAccount', parameters, getVBBADataForOnyx()); } function openWorkspaceView() { - API.read('OpenWorkspaceView'); + API.read('OpenWorkspaceView', {}, {}); } -function handlePlaidError(bankAccountID, error, error_description, plaidRequestID) { - API.write('BankAccount_HandlePlaidError', { +function handlePlaidError(bankAccountID: number, error: string, errorDescription: string, plaidRequestID: string) { + type BankAccountHandlePlaidErrorParams = { + bankAccountID: number; + error: string; + errorDescription: string; + plaidRequestID: string; + }; + + const parameters: BankAccountHandlePlaidErrorParams = { bankAccountID, error, - error_description, + errorDescription, plaidRequestID, - }); + }; + + API.write('BankAccount_HandlePlaidError', parameters); } /** * Set the reimbursement account loading so that it happens right away, instead of when the API command is processed. - * - * @param {Boolean} isLoading */ -function setReimbursementAccountLoading(isLoading) { +function setReimbursementAccountLoading(isLoading: boolean) { Onyx.merge(ONYXKEYS.REIMBURSEMENT_ACCOUNT, {isLoading}); } diff --git a/src/types/onyx/BankAccount.ts b/src/types/onyx/BankAccount.ts index 5d309023e94a..61c7e44f68d7 100644 --- a/src/types/onyx/BankAccount.ts +++ b/src/types/onyx/BankAccount.ts @@ -1,3 +1,4 @@ +import {ValueOf} from 'type-fest'; import CONST from '../../CONST'; type AdditionalData = { @@ -69,6 +70,10 @@ type BankAccount = { /** All data related to the bank account */ accountData?: AccountData; + + /** Action that is waiting to happen on the bank account */ + pendingAction?: ValueOf; }; export default BankAccount; +export type {AccountData}; diff --git a/src/types/onyx/PersonalBankAccount.ts b/src/types/onyx/PersonalBankAccount.ts index 06f505a04196..ea993d7393e8 100644 --- a/src/types/onyx/PersonalBankAccount.ts +++ b/src/types/onyx/PersonalBankAccount.ts @@ -1,6 +1,8 @@ +import * as OnyxCommon from './OnyxCommon'; + type PersonalBankAccount = { /** An error message to display to the user */ - error?: string; + errors?: OnyxCommon.Errors; /** Whether we should show the view that the bank account was successfully added */ shouldShowSuccess?: boolean; @@ -10,6 +12,9 @@ type PersonalBankAccount = { /** The account ID of the selected bank account from Plaid */ plaidAccountID?: string; + + /** Any reportID we should redirect to at the end of the flow */ + exitReportID?: string; }; export default PersonalBankAccount; diff --git a/src/types/onyx/PlaidBankAccount.ts b/src/types/onyx/PlaidBankAccount.ts index d89e8ac3082d..c7cd7b5d83e4 100644 --- a/src/types/onyx/PlaidBankAccount.ts +++ b/src/types/onyx/PlaidBankAccount.ts @@ -19,6 +19,9 @@ type PlaidBankAccount = { /** Plaid access token, used to then retrieve Assets and Balances */ plaidAccessToken: string; + + /** Name of the bank */ + bankName?: string; }; export default PlaidBankAccount; diff --git a/src/types/onyx/ReimbursementAccount.ts b/src/types/onyx/ReimbursementAccount.ts index 4f2a05d7f4e1..fc46c9aa3132 100644 --- a/src/types/onyx/ReimbursementAccount.ts +++ b/src/types/onyx/ReimbursementAccount.ts @@ -2,12 +2,16 @@ import {ValueOf} from 'type-fest'; import * as OnyxCommon from './OnyxCommon'; import CONST from '../../CONST'; +type BankAccountStep = ValueOf; + +type BankAccountSubStep = ValueOf; + type ACHData = { /** Step of the setup flow that we are on. Determines which view is presented. */ - currentStep: ValueOf; + currentStep: BankAccountStep; /** Optional subStep we would like the user to start back on */ - subStep?: ValueOf; + subStep?: BankAccountSubStep; /** Bank account state */ state?: string; @@ -38,7 +42,11 @@ type ReimbursementAccount = { /** Any additional error message to show */ errors?: OnyxCommon.Errors; + /** Draft step of the setup flow from Onyx */ + draftStep?: BankAccountStep; + pendingAction?: OnyxCommon.PendingAction; }; export default ReimbursementAccount; +export type {BankAccountStep, BankAccountSubStep}; diff --git a/src/types/onyx/ReimbursementAccountDraft.ts b/src/types/onyx/ReimbursementAccountDraft.ts index d55c2b5b3567..cab1283943bc 100644 --- a/src/types/onyx/ReimbursementAccountDraft.ts +++ b/src/types/onyx/ReimbursementAccountDraft.ts @@ -1,10 +1,19 @@ -type ReimbursementAccountDraft = { +type OnfidoData = Record; + +type BankAccountStepProps = { accountNumber?: string; routingNumber?: string; acceptTerms?: boolean; plaidAccountID?: string; plaidMask?: string; +}; + +type CompanyStepProps = { companyName?: string; + addressStreet?: string; + addressCity?: string; + addressState?: string; + addressZipCode?: string; companyPhone?: string; website?: string; companyTaxID?: string; @@ -12,13 +21,32 @@ type ReimbursementAccountDraft = { incorporationDate?: string | Date; incorporationState?: string; hasNoConnectionToCannabis?: boolean; +}; + +type RequestorStepProps = { + firstName?: string; + lastName?: string; + requestorAddressStreet?: string; + requestorAddressCity?: string; + requestorAddressState?: string; + requestorAddressZipCode?: string; + dob?: string | Date; + ssnLast4?: string; isControllingOfficer?: boolean; isOnfidoSetupComplete?: boolean; + onfidoData?: OnfidoData; +}; + +type ACHContractStepProps = { ownsMoreThan25Percent?: boolean; hasOtherBeneficialOwners?: boolean; acceptTermsAndConditions?: boolean; certifyTrueInformation?: boolean; beneficialOwners?: string[]; +}; + +type ReimbursementAccountProps = { + bankAccountID?: number; isSavings?: boolean; bankName?: string; plaidAccessToken?: string; @@ -27,4 +55,7 @@ type ReimbursementAccountDraft = { amount3?: string; }; +type ReimbursementAccountDraft = BankAccountStepProps & CompanyStepProps & RequestorStepProps & ACHContractStepProps & ReimbursementAccountProps; + export default ReimbursementAccountDraft; +export type {ACHContractStepProps, RequestorStepProps, OnfidoData, BankAccountStepProps, CompanyStepProps, ReimbursementAccountProps}; diff --git a/src/types/onyx/Request.ts b/src/types/onyx/Request.ts index 94f14af0ddb3..a3032401b346 100644 --- a/src/types/onyx/Request.ts +++ b/src/types/onyx/Request.ts @@ -1,12 +1,19 @@ import {OnyxUpdate} from 'react-native-onyx'; -type Request = { +type OnyxData = { + successData?: OnyxUpdate[]; + failureData?: OnyxUpdate[]; + optimisticData?: OnyxUpdate[]; +}; + +type RequestData = { command: string; data?: Record; type?: string; shouldUseSecure?: boolean; - successData?: OnyxUpdate[]; - failureData?: OnyxUpdate[]; }; +type Request = RequestData & OnyxData; + export default Request; +export type {OnyxData};