diff --git a/app/controllers/idv/personal_key_controller.rb b/app/controllers/idv/personal_key_controller.rb index 231bc782a46..861e0bc6308 100644 --- a/app/controllers/idv/personal_key_controller.rb +++ b/app/controllers/idv/personal_key_controller.rb @@ -22,8 +22,8 @@ def update analytics.idv_personal_key_submitted( address_verification_method: address_verification_method, deactivation_reason: idv_session.profile&.deactivation_reason, - fraud_review_pending: idv_session.profile&.fraud_review_pending, - fraud_rejection: idv_session.profile&.fraud_rejection, + fraud_review_pending: idv_session.profile&.fraud_review_pending?, + fraud_rejection: idv_session.profile&.fraud_rejection?, ) redirect_to next_step end diff --git a/app/controllers/idv/review_controller.rb b/app/controllers/idv/review_controller.rb index 5c648c2f146..8d2dcd0e272 100644 --- a/app/controllers/idv/review_controller.rb +++ b/app/controllers/idv/review_controller.rb @@ -53,16 +53,16 @@ def create analytics.idv_review_complete( success: true, - fraud_review_pending: idv_session.profile.fraud_review_pending, - fraud_rejection: idv_session.profile.fraud_rejection, + fraud_review_pending: idv_session.profile.fraud_review_pending?, + fraud_rejection: idv_session.profile.fraud_rejection?, deactivation_reason: idv_session.profile.deactivation_reason, ) Funnel::DocAuth::RegisterStep.new(current_user.id, current_sp&.issuer). call(:verified, :view, true) analytics.idv_final( success: true, - fraud_review_pending: idv_session.profile.fraud_review_pending, - fraud_rejection: idv_session.profile.fraud_rejection, + fraud_review_pending: idv_session.profile.fraud_review_pending?, + fraud_rejection: idv_session.profile.fraud_rejection?, deactivation_reason: idv_session.profile.deactivation_reason, ) diff --git a/app/models/profile.rb b/app/models/profile.rb index 66ac064e4ad..03c97de5f22 100644 --- a/app/models/profile.rb +++ b/app/models/profile.rb @@ -27,6 +27,14 @@ class Profile < ApplicationRecord attr_reader :personal_key + def fraud_review_pending? + !!(fraud_review_pending || fraud_review_pending_at) + end + + def fraud_rejection? + !!(fraud_rejection || fraud_rejection_at) + end + # rubocop:disable Rails/SkipsModelValidations def activate return if fraud_review_pending? || fraud_rejection? @@ -48,7 +56,10 @@ def activate # rubocop:enable Rails/SkipsModelValidations def activate_after_passing_review - update!(fraud_review_pending: false, fraud_rejection: false) + update!( + fraud_review_pending: false, fraud_rejection: false, fraud_review_pending_at: nil, + fraud_rejection_at: nil + ) track_fraud_review_adjudication(decision: 'pass') activate end @@ -58,11 +69,17 @@ def deactivate(reason) end def deactivate_for_fraud_review - update!(active: false, fraud_review_pending: true, fraud_rejection: false) + update!( + active: false, fraud_review_pending: true, fraud_rejection: false, + fraud_review_pending_at: Time.zone.now, fraud_rejection_at: nil + ) end def reject_for_fraud(notify_user:) - update!(active: false, fraud_review_pending: false, fraud_rejection: true) + update!( + active: false, fraud_review_pending: false, fraud_rejection: true, + fraud_review_pending_at: nil, fraud_rejection_at: Time.zone.now + ) track_fraud_review_adjudication( decision: notify_user ? 'manual_reject' : 'automatic_reject', ) diff --git a/db/primary_migrate/20230403201505_add_fraud_review_pending_at_to_profiles.rb b/db/primary_migrate/20230403201505_add_fraud_review_pending_at_to_profiles.rb new file mode 100644 index 00000000000..efd28ec2948 --- /dev/null +++ b/db/primary_migrate/20230403201505_add_fraud_review_pending_at_to_profiles.rb @@ -0,0 +1,8 @@ +class AddFraudReviewPendingAtToProfiles < ActiveRecord::Migration[7.0] + disable_ddl_transaction! + + def change + add_column :profiles, :fraud_review_pending_at, :datetime + add_index :profiles, :fraud_review_pending_at, algorithm: :concurrently + end +end diff --git a/db/primary_migrate/20230403201954_add_fraud_rejection_at_to_profiles.rb b/db/primary_migrate/20230403201954_add_fraud_rejection_at_to_profiles.rb new file mode 100644 index 00000000000..b2c6c89b8e1 --- /dev/null +++ b/db/primary_migrate/20230403201954_add_fraud_rejection_at_to_profiles.rb @@ -0,0 +1,8 @@ +class AddFraudRejectionAtToProfiles < ActiveRecord::Migration[7.0] + disable_ddl_transaction! + + def change + add_column :profiles, :fraud_rejection_at, :datetime + add_index :profiles, :fraud_rejection_at, algorithm: :concurrently + end +end diff --git a/db/schema.rb b/db/schema.rb index 1110da21d52..7767e896d09 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -446,7 +446,11 @@ t.string "initiating_service_provider_issuer" t.boolean "fraud_review_pending", default: false t.boolean "fraud_rejection", default: false + t.datetime "fraud_review_pending_at" + t.datetime "fraud_rejection_at" + t.index ["fraud_rejection_at"], name: "index_profiles_on_fraud_rejection_at" t.index ["fraud_review_pending"], name: "index_profiles_on_fraud_review_pending" + t.index ["fraud_review_pending_at"], name: "index_profiles_on_fraud_review_pending_at" t.index ["name_zip_birth_year_signature"], name: "index_profiles_on_name_zip_birth_year_signature" t.index ["reproof_at"], name: "index_profiles_on_reproof_at" t.index ["ssn_signature"], name: "index_profiles_on_ssn_signature" diff --git a/spec/lib/tasks/review_profile_spec.rb b/spec/lib/tasks/review_profile_spec.rb index 6aa98f44bd2..895ce545e4b 100644 --- a/spec/lib/tasks/review_profile_spec.rb +++ b/spec/lib/tasks/review_profile_spec.rb @@ -78,6 +78,7 @@ invoke_task expect(user.reload.profiles.first.active).to eq(false) expect(user.reload.profiles.first.fraud_rejection).to eq(true) + expect(user.reload.profiles.first.fraud_rejection_at).to_not be_nil end it 'sends the user an email about their account deactivation' do diff --git a/spec/models/profile_spec.rb b/spec/models/profile_spec.rb index f701a0c7b99..e7a9087c22c 100644 --- a/spec/models/profile_spec.rb +++ b/spec/models/profile_spec.rb @@ -264,14 +264,14 @@ end it 'does not activate a profile if under fraud review' do - profile.update(fraud_review_pending: true) + profile.update(fraud_review_pending_at: Time.zone.today - 1.day) profile.activate expect(profile).to_not be_active end it 'does not activate a profile if rejected for fraud' do - profile.update(fraud_rejection: true) + profile.update(fraud_rejection_at: Time.zone.now - 1.day) profile.activate expect(profile).to_not be_active @@ -294,7 +294,10 @@ describe '#activate_after_passing_review' do it 'activates a profile if it passes fraud review' do - profile = create(:profile, user: user, active: false, fraud_review_pending: true) + profile = create( + :profile, user: user, active: false, + fraud_review_pending_at: Time.zone.today - 1.day + ) profile.activate_after_passing_review expect(profile).to be_active @@ -307,7 +310,7 @@ :profile, user: user, active: false, - fraud_review_pending: true, + fraud_review_pending_at: Time.zone.today - 1.day, initiating_service_provider: sp, ) end @@ -353,7 +356,7 @@ :profile, user: user, active: false, - fraud_review_pending: true, + fraud_review_pending_at: Time.zone.today - 1.day, initiating_service_provider: sp, ) expect(profile.initiating_service_provider.irs_attempts_api_enabled?).to be_falsey @@ -371,7 +374,9 @@ expect(profile).to_not be_active expect(profile.fraud_review_pending).to eq(true) + expect(profile.fraud_review_pending_at).to_not be_nil expect(profile.fraud_rejection).to eq(false) + expect(profile.fraud_rejection_at).to be_nil end end @@ -389,7 +394,7 @@ context 'it notifies the user' do let(:profile) do - profile = create(:profile, user: user, fraud_review_pending: true) + profile = create(:profile, user: user, fraud_review_pending_at: Time.zone.today - 1.day) profile.reject_for_fraud(notify_user: true) profile end @@ -401,11 +406,15 @@ it 'sends an email' do expect { profile }.to change(ActionMailer::Base.deliveries, :count).by(1) end + + it 'sets the fraud_rejection_at timestamp' do + expect(profile.fraud_rejection_at).to_not be_nil + end end context 'it does not notify the user' do let(:profile) do - profile = create(:profile, user: user, fraud_review_pending: true) + profile = create(:profile, user: user, fraud_review_pending_at: Time.zone.today - 1.day) profile.reject_for_fraud(notify_user: false) profile end @@ -424,7 +433,7 @@ :profile, user: user, active: false, - fraud_review_pending: true, + fraud_review_pending_at: Time.zone.today - 1.day, initiating_service_provider: sp, ) end @@ -471,7 +480,7 @@ :profile, user: user, active: false, - fraud_review_pending: true, + fraud_review_pending_at: Time.zone.today - 1.day, initiating_service_provider: sp, ) allow(IdentityConfig.store).to receive(:irs_attempt_api_enabled).and_return(true)