diff --git a/src/libs/models/BankAccount.js b/src/libs/models/BankAccount.ts similarity index 51% rename from src/libs/models/BankAccount.js rename to src/libs/models/BankAccount.ts index c4366a48aa6a..6fd77b161aa9 100644 --- a/src/libs/models/BankAccount.js +++ b/src/libs/models/BankAccount.ts @@ -1,10 +1,24 @@ import Str from 'expensify-common/lib/str'; -import lodashGet from 'lodash/get'; -import lodashHas from 'lodash/has'; -import _ from 'underscore'; +import {ValueOf} from 'type-fest'; import CONST from '@src/CONST'; +import BankAccountJSON, {AdditionalData} from '@src/types/onyx/BankAccount'; + +type State = ValueOf; + +type ACHData = { + routingNumber: string; + accountNumber: string; + addressName: string; + isSavings: boolean; + bankAccountID: number; + state: State; + validateCodeExpectedDate: string; + needsToUpgrade: boolean; +}; class BankAccount { + json: BankAccountJSON; + static STATE = { PENDING: 'PENDING', OPEN: 'OPEN', @@ -14,14 +28,12 @@ class BankAccount { VERIFYING: 'VERIFYING', }; - constructor(accountJSON) { + constructor(accountJSON: BankAccountJSON) { this.json = accountJSON; } /** * Return the ID of the reimbursement account - * - * @returns {Number} */ getID() { return this.json.methodID; @@ -30,61 +42,43 @@ class BankAccount { /** * Return the account number, which has been obfuscated by the back end * example "XXXXXX3956" - * - * @returns {String} */ getMaskedAccountNumber() { - return this.json.accountData.accountNumber; + return this.json.accountData?.accountNumber; } /** * Used as the display name for the account... - * @returns {String} */ getAddressName() { - return this.json.accountData.addressName; + return this.json.accountData?.addressName; } - /** - * @returns {String} - */ getProcessor() { - return this.json.accountData.processor; + return this.json.accountData?.processor; } - /** - * @returns {String} - */ getRoutingNumber() { - return this.json.accountData.routingNumber; + return this.json.accountData?.routingNumber; } /** * Get all user emails that have access to this bank account - * @return {String[]} */ getSharees() { - return this.json.accountData.sharees; + return this.json.accountData?.sharees; } - /** - * @returns {String} - * @private - */ getState() { - return this.json.accountData.state; + return this.json.accountData?.state; } - /** - * @returns {Boolean} - */ isOpen() { return this.getState() === BankAccount.STATE.OPEN; } /** * @deprecated Use !isPending instead. - * @returns {Boolean} */ isVerified() { return !this.isPending(); @@ -92,7 +86,6 @@ class BankAccount { /** * If the user still needs to enter the 3 micro deposit amounts. - * @returns {Boolean} */ isPending() { return this.getState() === BankAccount.STATE.PENDING; @@ -100,7 +93,6 @@ class BankAccount { /** * If success team is currently verifying the bank account data provided by the user. - * @returns {Boolean} */ isVerifying() { return this.getState() === BankAccount.STATE.VERIFYING; @@ -108,158 +100,132 @@ class BankAccount { /** * If the user didn't finish entering all their info. - * @returns {Boolean} */ isInSetup() { return this.getState() === BankAccount.STATE.SETUP; } - /** - * @returns {Boolean} - */ isLocked() { return this.getState() === BankAccount.STATE.LOCKED; } /** * Is it the account to use by default to receive money? - * - * @returns {Boolean} */ isDefaultCredit() { - return this.json.accountData.defaultCredit === true; + return this.json.accountData?.defaultCredit === true; } /** * Can we use this account to pay other people? - * - * @returns {Boolean} */ isWithdrawal() { - return this.json.accountData.allowDebit === true; + return this.json.accountData?.allowDebit === true; } getType() { - return this.json.accountData.type; + return this.json.accountData?.type; } /** * Return the client ID of this bank account * * @NOTE WARNING KEEP IN SYNC WITH THE PHP - * @returns {String} */ getClientID() { // eslint-disable-next-line max-len - return `${Str.makeID(this.getMaskedAccountNumber())}${Str.makeID(this.getAddressName())}${Str.makeID(this.getRoutingNumber())}${this.getTransactionType()}`; + return `${Str.makeID(this.getMaskedAccountNumber() ?? '')}${Str.makeID(this.getAddressName() ?? '')}${Str.makeID(this.getRoutingNumber() ?? '')}${this.getTransactionType()}`; } - /** - * @returns {String} - * @private - */ - getTransactionType() { + private getTransactionType() { return this.isWithdrawal() ? 'withdrawal' : 'direct-deposit'; } /** * Return the internal json data structure used by auth - * @returns {Object} */ getJSON() { return this.json; } /** - * Return whether or not this bank account has been risk checked - * @returns {Boolean} + * Return whether this bank account has been risk checked */ isRiskChecked() { - return Boolean(this.json.accountData.riskChecked); + return Boolean(this.json.accountData?.riskChecked); } /** * Return when the 3 micro amounts for validation were supposed to reach the bank account. - * @returns {String} */ getValidateCodeExpectedDate() { - return this.json.validateCodeExpectedDate || ''; + return this.json.validateCodeExpectedDate ?? ''; } /** * In which country is the bank account? - * @returns {string} */ getCountry() { - return lodashGet(this.json, ['accountData', 'additionalData', 'country'], CONST.COUNTRY.US); + return this.json.accountData?.additionalData?.country ?? CONST.COUNTRY.US; } /** * In which currency is the bank account? - * @returns {String} */ getCurrency() { - return lodashGet(this.json, ['accountData', 'additionalData', 'currency'], 'USD'); + return this.json.accountData?.additionalData?.currency ?? 'USD'; } /** * In which bank is the bank account? - * @returns {String} */ getBankName() { - return lodashGet(this.json, ['accountData', 'additionalData', 'bankName'], ''); + return this.json.accountData?.additionalData?.bankName ?? ''; } /** * Did we get bank account details for local transfer or international wire? - * @returns {Boolean} */ hasInternationalWireDetails() { - return lodashGet(this.json, ['accountData', 'additionalData', 'fieldsType'], 'local') === 'international'; + return (this.json.accountData?.additionalData?.fieldsType ?? 'local') === 'international'; } /** * Get the additional data of a bankAccount - * @returns {Object} */ - getAdditionalData() { - return this.json.accountData.additionalData || {}; + getAdditionalData(): Partial { + return this.json.accountData?.additionalData ?? {}; } /** * Get the pending action of the bank account - * @returns {String} */ getPendingAction() { - return lodashGet(this.json, 'pendingAction', ''); + return this.json.pendingAction ?? ''; } /** - * Return a map needed to setup a withdrawal account - * @returns {Object} + * Return a map needed to set up a withdrawal account */ - toACHData() { - return _.extend( - { - routingNumber: this.getRoutingNumber(), - accountNumber: this.getMaskedAccountNumber(), - addressName: this.getAddressName(), - isSavings: this.json.isSavings, - bankAccountID: this.getID(), - state: this.getState(), - validateCodeExpectedDate: this.getValidateCodeExpectedDate(), - needsToUpgrade: this.needsToUpgrade(), - }, - this.getAdditionalData(), - ); + toACHData(): Partial { + return { + routingNumber: this.getRoutingNumber(), + accountNumber: this.getMaskedAccountNumber(), + addressName: this.getAddressName(), + isSavings: this.json.isSavings, + bankAccountID: this.getID(), + state: this.getState(), + validateCodeExpectedDate: this.getValidateCodeExpectedDate(), + needsToUpgrade: this.needsToUpgrade(), + ...this.getAdditionalData(), + } as ACHData; } /** * Check if user hasn't upgraded their bank account yet. - * @return {Boolean} */ needsToUpgrade() { - return !this.isInSetup() && !lodashHas(this.json, ['accountData', 'additionalData', 'beneficialOwners']); + return !this.isInSetup() && this.json.accountData?.additionalData?.beneficialOwners === undefined; } } diff --git a/src/types/onyx/BankAccount.ts b/src/types/onyx/BankAccount.ts index 2b2bee7df6b0..4dd46c82f800 100644 --- a/src/types/onyx/BankAccount.ts +++ b/src/types/onyx/BankAccount.ts @@ -2,6 +2,15 @@ import CONST from '@src/CONST'; import AccountData from './AccountData'; import * as OnyxCommon from './OnyxCommon'; +type AdditionalData = { + isP2PDebitCard?: boolean; + beneficialOwners?: string[]; + currency?: string; + bankName?: string; + fieldsType?: string; + country?: string; +}; + type BankAccount = { /** The bank account type */ accountType?: typeof CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT; @@ -11,6 +20,12 @@ type BankAccount = { isDefault?: boolean; + /* Determines if the bank account is a savings account */ + isSavings?: boolean; + + /** Date when the 3 micro amounts for validation were supposed to reach the bank account. */ + validateCodeExpectedDate?: string; + /** string like 'bankAccount-{}' where is the bankAccountID */ key?: string; @@ -31,4 +46,4 @@ type BankAccount = { }; export default BankAccount; -export type {AccountData}; +export type {AccountData, AdditionalData};