diff --git a/app/controllers/concerns/idv/verify_info_concern.rb b/app/controllers/concerns/idv/verify_info_concern.rb index f5e0afbdc04..c942a596823 100644 --- a/app/controllers/concerns/idv/verify_info_concern.rb +++ b/app/controllers/concerns/idv/verify_info_concern.rb @@ -208,6 +208,7 @@ def async_state_done(current_async_state) extra: { address_edited: !!idv_session.address_edited, address_line2_present: !pii[:address2].blank?, + last_name_spaced: pii[:last_name].split(' ').many?, previous_ssn_edit_distance: previous_ssn_edit_distance, pii_like_keypaths: [ [:errors, :ssn], diff --git a/app/services/analytics_events.rb b/app/services/analytics_events.rb index 6aa1ecea9b1..990337b3d69 100644 --- a/app/services/analytics_events.rb +++ b/app/services/analytics_events.rb @@ -2151,6 +2151,7 @@ def idv_doc_auth_verify_polling_wait_visited(**extra) # @param analytics_id [String] "Doc Auth" for remote unsupervised, "In Person Proofing" for IPP # @param errors [Hash] Details about vendor-specific errors encountered during the stages of the identity resolution process # @param flow_path [String] "hybrid" for hybrid handoff, "standard" otherwise + # @param last_name_spaced [Boolean] Whether the user's last name includes an empty space # @param lexisnexis_instant_verify_workflow_ab_test_bucket [String] A/B test bucket for Lexis Nexis InstantVerify workflow testing # @param opted_in_to_in_person_proofing [Boolean] Whether this user explicitly opted into in-person proofing # @param proofing_results [Hash] @@ -2217,6 +2218,7 @@ def idv_doc_auth_verify_proofing_results( analytics_id: nil, errors: nil, flow_path: nil, + last_name_spaced: nil, lexisnexis_instant_verify_workflow_ab_test_bucket: nil, opted_in_to_in_person_proofing: nil, proofing_results: nil, @@ -2237,6 +2239,7 @@ def idv_doc_auth_verify_proofing_results( errors:, flow_path:, lexisnexis_instant_verify_workflow_ab_test_bucket:, + last_name_spaced:, opted_in_to_in_person_proofing:, proofing_results:, skip_hybrid_handoff:, diff --git a/app/services/proofing/aamva/request/verification_request.rb b/app/services/proofing/aamva/request/verification_request.rb index 30dc750dc6c..7cf9c623267 100644 --- a/app/services/proofing/aamva/request/verification_request.rb +++ b/app/services/proofing/aamva/request/verification_request.rb @@ -274,10 +274,10 @@ def transaction_locator_id def user_provided_data_map { - state_id_number: state_id_number, + state_id_number:, state_id_jurisdiction: message_destination_id, first_name: applicant.first_name, - last_name: applicant.last_name, + last_name:, dob: applicant.dob, address1: applicant.address1, city: applicant.city, @@ -295,6 +295,15 @@ def state_id_number end end + def last_name + if IdentityConfig.store.idv_aamva_split_last_name_states + .include? applicant.state_id_data.state_id_jurisdiction + applicant.last_name.split(' ').first + else + applicant.last_name + end + end + def timeout (config.verification_request_timeout || 5).to_f end diff --git a/config/application.yml.default b/config/application.yml.default index e5c7dc8b244..df6928ce03f 100644 --- a/config/application.yml.default +++ b/config/application.yml.default @@ -164,6 +164,7 @@ hmac_fingerprinter_key: hmac_fingerprinter_key_queue: '[]' identity_pki_disabled: false identity_pki_local_dev: false +idv_aamva_split_last_name_states: '[]' idv_account_verified_email_campaign_id: '20241028' idv_acuant_sdk_upgrade_a_b_testing_enabled: false idv_acuant_sdk_upgrade_a_b_testing_percent: 50 diff --git a/lib/identity_config.rb b/lib/identity_config.rb index 25d7549af81..e148ccf800b 100644 --- a/lib/identity_config.rb +++ b/lib/identity_config.rb @@ -209,6 +209,7 @@ def self.store config.add(:idv_socure_shadow_mode_enabled, type: :boolean) config.add(:idv_socure_shadow_mode_enabled_for_docv_users, type: :boolean) config.add(:idv_sp_required, type: :boolean) + config.add(:idv_aamva_split_last_name_states, type: :json) config.add(:in_person_completion_survey_delivery_enabled, type: :boolean) config.add(:in_person_completion_survey_url, type: :string) config.add(:in_person_doc_auth_button_enabled, type: :boolean) diff --git a/spec/features/idv/analytics_spec.rb b/spec/features/idv/analytics_spec.rb index 65be952d77a..bb556f10bf7 100644 --- a/spec/features/idv/analytics_spec.rb +++ b/spec/features/idv/analytics_spec.rb @@ -266,7 +266,7 @@ end ), 'IdV: doc auth verify proofing results' => { - success: true, flow_path: 'standard', address_edited: false, address_line2_present: false, analytics_id: 'Doc Auth', step: 'verify', + success: true, flow_path: 'standard', address_edited: false, address_line2_present: false, last_name_spaced: false, analytics_id: 'Doc Auth', step: 'verify', proofing_results: doc_auth_verify_proofing_results, proofing_components: base_proofing_components }, @@ -391,7 +391,7 @@ end ), 'IdV: doc auth verify proofing results' => { - success: true, flow_path: 'hybrid', address_edited: false, address_line2_present: false, analytics_id: 'Doc Auth', step: 'verify', + success: true, flow_path: 'hybrid', address_edited: false, address_line2_present: false, last_name_spaced: false, analytics_id: 'Doc Auth', step: 'verify', proofing_results: doc_auth_verify_proofing_results, proofing_components: base_proofing_components }, @@ -514,7 +514,7 @@ end ), 'IdV: doc auth verify proofing results' => { - success: true, flow_path: 'standard', address_edited: false, address_line2_present: false, analytics_id: 'Doc Auth', step: 'verify', + success: true, flow_path: 'standard', address_edited: false, address_line2_present: false, last_name_spaced: false, analytics_id: 'Doc Auth', step: 'verify', proofing_results: doc_auth_verify_proofing_results, proofing_components: base_proofing_components }, @@ -632,7 +632,7 @@ end ), 'IdV: doc auth verify proofing results' => { - success: true, flow_path: 'standard', address_edited: false, address_line2_present: false, analytics_id: 'In Person Proofing', step: 'verify', + success: true, flow_path: 'standard', address_edited: false, address_line2_present: false, last_name_spaced: false, analytics_id: 'In Person Proofing', step: 'verify', proofing_results: in_person_path_proofing_results, proofing_components: { document_check: 'usps', resolution_check: 'ResolutionMock', residential_resolution_check: 'ResolutionMock', source_check: 'StateIdMock', threatmetrix: threatmetrix, threatmetrix_review_status: 'pass' } }, @@ -761,7 +761,7 @@ end ), 'IdV: doc auth verify proofing results' => { - success: true, flow_path: 'standard', address_edited: false, address_line2_present: false, analytics_id: 'Doc Auth', step: 'verify', + success: true, flow_path: 'standard', address_edited: false, address_line2_present: false, last_name_spaced: false, analytics_id: 'Doc Auth', step: 'verify', proofing_results: doc_auth_verify_proofing_results, proofing_components: base_proofing_components }, diff --git a/spec/services/proofing/aamva/request/verification_request_spec.rb b/spec/services/proofing/aamva/request/verification_request_spec.rb index 3a24ee8a7cd..33ca99db23a 100644 --- a/spec/services/proofing/aamva/request/verification_request_spec.rb +++ b/spec/services/proofing/aamva/request/verification_request_spec.rb @@ -6,13 +6,14 @@ let(:config) { AamvaFixtures.example_config } let(:state_id_jurisdiction) { 'CA' } let(:state_id_number) { '123456789' } + let(:last_name) { 'McTesterson' } let(:applicant_data) do { uuid: '1234-abcd-efgh', first_name: 'Testy', middle_name: nil, - last_name: 'McTesterson', + last_name:, name_suffix: nil, dob: '10/29/1942', address1: '123 Sunnyside way', @@ -36,7 +37,7 @@ Proofing::Aamva::Applicant.from_proofer_applicant(**applicant_data.compact_blank) end - subject do + subject(:request) do described_class.new( applicant: applicant, session_id: transaction_id, @@ -356,4 +357,29 @@ end end end + + describe 'compound last names' do + let(:last_name) { 'McFirst McSecond' } + + subject(:rendered_last_name) do + body = REXML::Document.new(request.body) + REXML::XPath.first(body, '//nc:PersonSurName')&.text + end + + before do + allow(IdentityConfig.store).to receive(:idv_aamva_split_last_name_states) + .and_return(['DC']) + end + it 'sends the full last name' do + expect(rendered_last_name).to eq('McFirst McSecond') + end + + context 'in state configured for last name split' do + let(:state_id_jurisdiction) { 'DC' } + + it 'only sends the first part of the last name' do + expect(rendered_last_name).to eq('McFirst') + end + end + end end