diff --git a/src/CONST.js b/src/CONST.js index e5ffb21bbe37..115514401bf0 100755 --- a/src/CONST.js +++ b/src/CONST.js @@ -539,6 +539,10 @@ const CONST = { }, }, ERROR: { + // If these get updated, we need to update the codes on the Web side too + SSN: 'ssnError', + KBA: 'kbaNeeded', + KYC: 'kycFailed', FULL_SSN_NOT_FOUND: 'Full SSN not found', MISSING_FIELD: 'Missing required additional details fields', WRONG_ANSWERS: 'Wrong answers', diff --git a/src/libs/actions/Wallet.js b/src/libs/actions/Wallet.js index eb75d3969119..616cd93be820 100644 --- a/src/libs/actions/Wallet.js +++ b/src/libs/actions/Wallet.js @@ -7,6 +7,7 @@ import * as DeprecatedAPI from '../deprecatedAPI'; import CONST from '../../CONST'; import * as PaymentMethods from './PaymentMethods'; import * as Localize from '../Localize'; +import * as API from '../API'; /** * Fetch and save locally the Onfido SDK token and applicantID @@ -153,6 +154,66 @@ function buildIdologyError(idologyErrors) { return `${errorStart} ${Localize.arrayToString(errorsTranslated)}. ${errorEnd}`; } +/** + * Validates a user's provided details against a series of checks + * + * @param {Object} personalDetails + */ +function updatePersonalDetails(personalDetails) { + if (!personalDetails) { + return; + } + const firstName = personalDetails.legalFirstName || ''; + const lastName = personalDetails.legalLastName || ''; + const dob = personalDetails.dob || ''; + const addressStreet = personalDetails.addressStreet || ''; + const addressCity = personalDetails.addressCity || ''; + const addressState = personalDetails.addressState || ''; + const addressZip = personalDetails.addressZip || ''; + const ssn = personalDetails.ssn || ''; + const phoneNumber = personalDetails.phoneNumber || ''; + API.write('UpdatePersonalDetailsForWallet', { + firstName, + lastName, + dob, + addressStreet, + addressCity, + addressState, + addressZip, + ssn, + phoneNumber, + }, { + optimisticData: [ + { + onyxMethod: CONST.ONYX.METHOD.MERGE, + key: ONYXKEYS.WALLET_ADDITIONAL_DETAILS, + value: { + isLoading: true, + errors: [], + }, + }, + ], + successData: [ + { + onyxMethod: CONST.ONYX.METHOD.MERGE, + key: ONYXKEYS.WALLET_ADDITIONAL_DETAILS, + value: { + isLoading: false, + }, + }, + ], + failureData: [ + { + onyxMethod: CONST.ONYX.METHOD.MERGE, + key: ONYXKEYS.WALLET_ADDITIONAL_DETAILS, + value: { + isLoading: false, + }, + }, + ], + }); +} + /** * This action can be called repeatedly with different steps until an Expensify Wallet has been activated. * @@ -361,4 +422,5 @@ export { setAdditionalDetailsQuestions, buildIdologyError, updateCurrentStep, + updatePersonalDetails, }; diff --git a/src/pages/EnablePayments/AdditionalDetailsStep.js b/src/pages/EnablePayments/AdditionalDetailsStep.js index d2ab86fccc9e..4e9ee56b3459 100644 --- a/src/pages/EnablePayments/AdditionalDetailsStep.js +++ b/src/pages/EnablePayments/AdditionalDetailsStep.js @@ -11,7 +11,6 @@ import withLocalize, {withLocalizePropTypes} from '../../components/withLocalize import Navigation from '../../libs/Navigation/Navigation'; import styles from '../../styles/styles'; import Text from '../../components/Text'; -import * as BankAccounts from '../../libs/actions/BankAccounts'; import CONST from '../../CONST'; import compose from '../../libs/compose'; import ONYXKEYS from '../../ONYXKEYS'; @@ -28,6 +27,7 @@ import FormHelper from '../../libs/FormHelper'; import walletAdditionalDetailsDraftPropTypes from './walletAdditionalDetailsDraftPropTypes'; import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsPropTypes, withCurrentUserPersonalDetailsDefaultProps} from '../../components/withCurrentUserPersonalDetails'; import * as PersonalDetails from '../../libs/actions/PersonalDetails'; +import OfflineIndicator from '../../components/OfflineIndicator'; const propTypes = { ...withLocalizePropTypes, @@ -36,13 +36,13 @@ const propTypes = { /** Stores additional information about the additional details step e.g. loading state and errors with fields */ walletAdditionalDetails: PropTypes.shape({ /** Are we waiting for a response? */ - loading: PropTypes.bool, + isLoading: PropTypes.bool, /** Which field needs attention? */ errorFields: PropTypes.objectOf(PropTypes.bool), /** Any additional error message to show */ - additionalErrorMessage: PropTypes.string, + errors: PropTypes.objectOf(PropTypes.string), /** Questions returned by Idology */ questions: PropTypes.arrayOf(PropTypes.shape({ @@ -54,8 +54,8 @@ const propTypes = { /** ExpectID ID number related to those questions */ idNumber: PropTypes.string, - /** If we should ask for the full SSN (when LexisNexis failed retrieving the first 5 from the last 4) */ - shouldAskForFullSSN: PropTypes.bool, + /** Error code to determine additional behavior */ + errorCode: PropTypes.string, }), /** Stores the personal details typed by the user */ @@ -65,11 +65,11 @@ const propTypes = { const defaultProps = { walletAdditionalDetails: { errorFields: {}, - loading: false, - additionalErrorMessage: '', + isLoading: false, + errors: {}, questions: [], idNumber: '', - shouldAskForFullSSN: false, + errorCode: '', }, walletAdditionalDetailsDraft: { legalFirstName: '', @@ -187,7 +187,7 @@ class AdditionalDetailsStep extends React.Component { errors.phoneNumber = true; } - if (this.props.walletAdditionalDetails.shouldAskForFullSSN) { + if (this.props.walletAdditionalDetails.errorCode === CONST.WALLET.ERROR.SSN) { if (!ValidationUtils.isValidSSNFullNine(this.props.walletAdditionalDetailsDraft.ssn)) { errors.ssnFull9 = true; } @@ -211,13 +211,11 @@ class AdditionalDetailsStep extends React.Component { if (!this.validate()) { return; } - - BankAccounts.activateWallet(CONST.WALLET.STEP.ADDITIONAL_DETAILS, { - personalDetails: { - ...this.props.walletAdditionalDetailsDraft, - phoneNumber: LoginUtils.getPhoneNumberWithoutUSCountryCodeAndSpecialChars(this.props.walletAdditionalDetailsDraft.phoneNumber), - }, - }); + const personalDetails = { + ...this.props.walletAdditionalDetailsDraft, + phoneNumber: LoginUtils.getPhoneNumberWithoutUSCountryCodeAndSpecialChars(this.props.walletAdditionalDetailsDraft.phoneNumber), + }; + Wallet.updatePersonalDetails(personalDetails); } /** @@ -267,10 +265,12 @@ class AdditionalDetailsStep extends React.Component { ); } + const errors = lodashGet(this.props, 'walletAdditionalDetails.errors', {}); const isErrorVisible = _.size(this.getErrors()) > 0 - || lodashGet(this.props, 'walletAdditionalDetails.additionalErrorMessage', '').length > 0; - const shouldAskForFullSSN = this.props.walletAdditionalDetails.shouldAskForFullSSN; + || !_.isEmpty(errors); + const shouldAskForFullSSN = this.props.walletAdditionalDetails.errorCode === CONST.WALLET.ERROR.SSN; const {firstName, lastName} = PersonalDetails.extractFirstAndLastNameFromAvailableDetails(this.props.currentUserPersonalDetails); + const errorMessage = _.isEmpty(errors) ? '' : _.last(_.values(errors)); return ( @@ -386,10 +386,11 @@ class AdditionalDetailsStep extends React.Component { onFixTheErrorsLinkPressed={() => { this.form.scrollTo({y: 0, animated: true}); }} - message={this.props.walletAdditionalDetails.additionalErrorMessage} - isLoading={this.props.walletAdditionalDetails.loading} + message={errorMessage} + isLoading={this.props.walletAdditionalDetails.isLoading} buttonText={this.props.translate('common.saveAndContinue')} /> + diff --git a/src/pages/EnablePayments/EnablePaymentsPage.js b/src/pages/EnablePayments/EnablePaymentsPage.js index 53f25dfeffd7..f0a27c232888 100644 --- a/src/pages/EnablePayments/EnablePaymentsPage.js +++ b/src/pages/EnablePayments/EnablePaymentsPage.js @@ -56,7 +56,7 @@ class EnablePaymentsPage extends React.Component { return ; } - if (this.props.userWallet.shouldShowFailedKYC) { + if (this.props.userWallet.errorCode === CONST.WALLET.ERROR.KYC) { return (