diff --git a/app/forms/gpo_verify_form.rb b/app/forms/gpo_verify_form.rb index ad1d34425b1..4a34963a2ce 100644 --- a/app/forms/gpo_verify_form.rb +++ b/app/forms/gpo_verify_form.rb @@ -21,9 +21,9 @@ def submit if result pending_profile&.remove_gpo_deactivation_reason - if pending_in_person_enrollment? - UspsInPersonProofing::EnrollmentHelper.schedule_in_person_enrollment(user, pii) - pending_profile&.deactivate(:in_person_verification_pending) + if pending_profile&.pending_in_person_enrollment? + # note: pending_profile is not active here + pending_profile&.deactivate_for_in_person_verification_and_schedule_enrollment(pii) elsif fraud_check_failed && threatmetrix_enabled? pending_profile&.deactivate_for_fraud_review elsif fraud_check_failed @@ -40,7 +40,7 @@ def submit extra: { enqueued_at: gpo_confirmation_code&.code_sent_at, pii_like_keypaths: [[:errors, :otp], [:error_details, :otp]], - pending_in_person_enrollment: pending_in_person_enrollment?, + pending_in_person_enrollment: pending_profile&.pending_in_person_enrollment?, fraud_check_failed: fraud_check_failed, }, ) @@ -81,10 +81,6 @@ def reset_sensitive_fields self.otp = nil end - def pending_in_person_enrollment? - pending_profile&.proofing_components&.[]('document_check') == Idp::Constants::Vendors::USPS - end - def threatmetrix_enabled? FeatureManagement.proofing_device_profiling_decisioning_enabled? end diff --git a/app/models/profile.rb b/app/models/profile.rb index 5cc0c49c2a1..46a3e655bc1 100644 --- a/app/models/profile.rb +++ b/app/models/profile.rb @@ -142,6 +142,18 @@ def has_fraud_deactivation_reason? fraud_review_pending? || fraud_rejection? end + def in_person_verification_pending? + # note: deactivation reason will be replaced by timestamp column + deactivation_reason == 'in_person_verification_pending' + end + + def deactivate_for_in_person_verification_and_schedule_enrollment(pii) + transaction do + UspsInPersonProofing::EnrollmentHelper.schedule_in_person_enrollment(user, pii) + deactivate(:in_person_verification_pending) + end + end + def deactivate_for_gpo_verification update!(active: false, gpo_verification_pending_at: Time.zone.now) end @@ -219,6 +231,10 @@ def self.build_compound_pii(pii) values.join(':') end + def pending_in_person_enrollment? + proofing_components&.[]('document_check') == Idp::Constants::Vendors::USPS + end + def includes_phone_check? return false if proofing_components.blank? proofing_components['address_check'] == 'lexis_nexis_address' diff --git a/app/services/idv/profile_maker.rb b/app/services/idv/profile_maker.rb index c846e8d4b30..1eaf996f054 100644 --- a/app/services/idv/profile_maker.rb +++ b/app/services/idv/profile_maker.rb @@ -2,11 +2,18 @@ module Idv class ProfileMaker attr_reader :pii_attributes - def initialize(applicant:, user:, user_password:, initiating_service_provider: nil) + def initialize( + applicant:, + user:, + user_password:, + initiating_service_provider: nil, + in_person_verification_pending: false + ) self.pii_attributes = Pii::Attributes.new_from_hash(applicant) self.user = user self.user_password = user_password self.initiating_service_provider = initiating_service_provider + self.in_person_verification_pending = in_person_verification_pending end def save_profile( @@ -16,6 +23,9 @@ def save_profile( ) profile = Profile.new(user: user, active: false, deactivation_reason: deactivation_reason) profile.initiating_service_provider = initiating_service_provider + if in_person_verification_pending + profile.deactivation_reason = :in_person_verification_pending + end profile.encrypt_pii(pii_attributes, user_password) profile.proofing_components = current_proofing_components profile.fraud_pending_reason = fraud_pending_reason @@ -33,7 +43,13 @@ def current_proofing_components user.proofing_component&.as_json || {} end - attr_accessor :user, :user_password, :phone_confirmed, :initiating_service_provider + attr_accessor( + :user, + :user_password, + :phone_confirmed, + :initiating_service_provider, + :in_person_verification_pending, + ) attr_writer :pii_attributes end end diff --git a/app/services/idv/session.rb b/app/services/idv/session.rb index 8cbef61007c..54848545b4c 100644 --- a/app/services/idv/session.rb +++ b/app/services/idv/session.rb @@ -50,7 +50,6 @@ def respond_to_missing?(method_sym, include_private) def create_profile_from_applicant_with_password(user_password) profile_maker = build_profile_maker(user_password) profile = profile_maker.save_profile( - deactivation_reason: deactivation_reason, fraud_pending_reason: threatmetrix_fraud_pending_reason, gpo_verification_needed: gpo_verification_needed?, ) @@ -76,10 +75,6 @@ def create_profile_from_applicant_with_password(user_password) end end - def deactivation_reason - :in_person_verification_pending if in_person_enrollment? - end - def gpo_verification_needed? !phone_confirmed? || address_verification_mechanism == 'gpo' end @@ -139,7 +134,7 @@ def add_failed_phone_step_number(phone) end def in_person_enrollment? - ProofingComponent.find_by(user: current_user)&.document_check == Idp::Constants::Vendors::USPS + current_user.proofing_component&.document_check == Idp::Constants::Vendors::USPS end def verify_info_step_complete? @@ -234,6 +229,7 @@ def build_profile_maker(user_password) user: current_user, user_password: user_password, initiating_service_provider: service_provider, + in_person_verification_pending: in_person_enrollment?, ) end diff --git a/spec/models/profile_spec.rb b/spec/models/profile_spec.rb index d6839f54dbb..95ce3cbb70e 100644 --- a/spec/models/profile_spec.rb +++ b/spec/models/profile_spec.rb @@ -46,6 +46,26 @@ end end + describe '#pending_in_person_enrollment?' do + it 'returns true if the document_check component is usps' do + profile = create(:profile, proofing_components: { document_check: 'usps' }) + + expect(profile.pending_in_person_enrollment?).to eq(true) + end + + it 'returns false if the document_check component is something else' do + profile = create(:profile, proofing_components: { document_check: 'something_else' }) + + expect(profile.pending_in_person_enrollment?).to eq(false) + end + + it 'returns false if proofing_components is blank' do + profile = create(:profile, proofing_components: '') + + expect(profile.pending_in_person_enrollment?).to eq(false) + end + end + describe '#includes_phone_check?' do it 'returns true if the address_check component is lexis_nexis_address' do profile = create(:profile, proofing_components: { address_check: 'lexis_nexis_address' }) @@ -66,6 +86,26 @@ end end + describe '#in_person_verification_pending?' do + it 'returns true if the deactivation_reason is in_person_verification_pending' do + profile = create( + :profile, + :in_person_verification_pending, + user: user, + ) + + allow(profile).to receive(:update!).and_raise(RuntimeError) + + expect(profile.activated_at).to be_nil + expect(profile.active).to eq(false) + expect(profile.deactivation_reason).to eq('in_person_verification_pending') + expect(profile.fraud_review_pending?).to eq(false) + expect(profile.gpo_verification_pending_at).to be_nil + expect(profile.initiating_service_provider).to be_nil + expect(profile.verified_at).to be_nil + end + end + describe '#encrypt_pii' do subject(:encrypt_pii) { profile.encrypt_pii(pii, user.password) } @@ -860,6 +900,32 @@ end end + # TODO: does deactivating make sense for a non-active profile? Should we prevent it? + # TODO: related: should we test against an active profile here? + describe '#deactivate_for_in_person_verification_and_schedule_enrollment' do + it 'sets deactivation reason to in_person_verification_pending' do + profile = create(:profile, user: user) + + expect(profile.activated_at).to be_nil + expect(profile.active).to eq(false) + expect(profile.deactivation_reason).to be_nil # to change + expect(profile.fraud_review_pending?).to eq(false) + expect(profile.gpo_verification_pending_at).to be_nil + expect(profile.initiating_service_provider).to be_nil + expect(profile.verified_at).to be_nil + + profile.deactivate_for_in_person_verification_and_schedule_enrollment(pii) + + expect(profile.activated_at).to be_nil + expect(profile.active).to eq(false) + expect(profile.deactivation_reason).to eq('in_person_verification_pending') # changed + expect(profile.fraud_review_pending?).to eq(false) + expect(profile.gpo_verification_pending_at).to be_nil + expect(profile.initiating_service_provider).to be_nil + expect(profile.verified_at).to be_nil + end + end + # TODO: does deactivating make sense for a non-active profile? Should we prevent it? # TODO: related: should we test against an active profile here? describe '#deactivate_for_gpo_verification' do diff --git a/spec/services/idv/profile_maker_spec.rb b/spec/services/idv/profile_maker_spec.rb index 7027012f2c2..c85bd46619c 100644 --- a/spec/services/idv/profile_maker_spec.rb +++ b/spec/services/idv/profile_maker_spec.rb @@ -6,6 +6,7 @@ let(:user) { create(:user, :fully_registered) } let(:user_password) { user.password } let(:initiating_service_provider) { nil } + let(:in_person_verification_pending) { false } subject do described_class.new( @@ -13,6 +14,7 @@ user: user, user_password: user_password, initiating_service_provider: initiating_service_provider, + in_person_verification_pending: in_person_verification_pending, ) end