diff --git a/app/jobs/get_usps_proofing_results_job.rb b/app/jobs/get_usps_proofing_results_job.rb index a43c6a0bf12..049938d5d0f 100644 --- a/app/jobs/get_usps_proofing_results_job.rb +++ b/app/jobs/get_usps_proofing_results_job.rb @@ -28,6 +28,24 @@ def enrollment_analytics_attributes(enrollment, complete:) } end + def response_analytics_attributes(response) + { + fraud_suspected: response['fraudSuspected'], + primary_id_type: response['primaryIdType'], + secondary_id_type: response['secondaryIdType'], + failure_reason: response['failureReason'], + transaction_end_date_time: response['transactionEndDateTime'], + transaction_start_date_time: response['transactionStartDateTime'], + status: response['status'], + assurance_level: response['assuranceLevel'], + proofing_post_office: response['proofingPostOffice'], + proofing_city: response['proofingCity'], + proofing_state: response['proofingState'], + scan_count: response['scanCount'], + response_message: response['responseMessage'], + } + end + def perform(_now) return true unless IdentityConfig.store.in_person_proofing_enabled @@ -107,10 +125,11 @@ def handle_bad_request_error(err, enrollment) # Customer has not been to post office for IPP enrollment_outcomes[:enrollments_in_progress] += 1 when IPP_EXPIRED_ERROR_MESSAGE - handle_expired_status_update(enrollment) + handle_expired_status_update(enrollment, err.response) else analytics(user: enrollment.user).idv_in_person_usps_proofing_results_job_exception( **enrollment_analytics_attributes(enrollment, complete: false), + **response_analytics_attributes(err.response), reason: 'Request exception', exception_class: err.class.to_s, exception_message: err.message, @@ -123,6 +142,7 @@ def handle_standard_error(err, enrollment) enrollment_outcomes[:enrollments_errored] += 1 analytics(user: enrollment.user).idv_in_person_usps_proofing_results_job_exception( **enrollment_analytics_attributes(enrollment, complete: false), + **response_analytics_attributes(err.response), reason: 'Request exception', exception_class: err.class.to_s, exception_message: err.message, @@ -137,12 +157,13 @@ def handle_response_is_not_a_hash(enrollment) ) end - def handle_unsupported_status(enrollment, status) + def handle_unsupported_status(enrollment, response) enrollment_outcomes[:enrollments_errored] += 1 analytics(user: enrollment.user).idv_in_person_usps_proofing_results_job_exception( **enrollment_analytics_attributes(enrollment, complete: false), + **response_analytics_attributes(response), reason: 'Unsupported status', - status: status, + status: response['status'], ) end @@ -150,6 +171,7 @@ def handle_unsupported_id_type(enrollment, response) enrollment_outcomes[:enrollments_failed] += 1 analytics(user: enrollment.user).idv_in_person_usps_proofing_results_job_enrollment_updated( **enrollment_analytics_attributes(enrollment, complete: true), + **response_analytics_attributes(response), fraud_suspected: response['fraudSuspected'], passed: false, primary_id_type: response['primaryIdType'], @@ -158,11 +180,11 @@ def handle_unsupported_id_type(enrollment, response) enrollment.update(status: :failed) end - def handle_expired_status_update(enrollment) + def handle_expired_status_update(enrollment, response) enrollment_outcomes[:enrollments_expired] += 1 analytics(user: enrollment.user).idv_in_person_usps_proofing_results_job_enrollment_updated( **enrollment_analytics_attributes(enrollment, complete: true), - fraud_suspected: nil, + **response_analytics_attributes(response[:body]), passed: false, reason: 'Enrollment has expired', ) @@ -173,15 +195,9 @@ def handle_failed_status(enrollment, response) enrollment_outcomes[:enrollments_failed] += 1 analytics(user: enrollment.user).idv_in_person_usps_proofing_results_job_enrollment_updated( **enrollment_analytics_attributes(enrollment, complete: true), - failure_reason: response['failureReason'], - fraud_suspected: response['fraudSuspected'], + **response_analytics_attributes(response), passed: false, - primary_id_type: response['primaryIdType'], - proofing_state: response['proofingState'], reason: 'Failed status', - secondary_id_type: response['secondaryIdType'], - transaction_end_date_time: response['transactionEndDateTime'], - transaction_start_date_time: response['transactionStartDateTime'], ) enrollment.update(status: :failed) @@ -192,6 +208,7 @@ def handle_successful_status_update(enrollment, response) enrollment_outcomes[:enrollments_passed] += 1 analytics(user: enrollment.user).idv_in_person_usps_proofing_results_job_enrollment_updated( **enrollment_analytics_attributes(enrollment, complete: true), + **response_analytics_attributes(**response), fraud_suspected: response['fraudSuspected'], passed: true, reason: 'Successful status update', @@ -218,7 +235,7 @@ def process_enrollment_response(enrollment, response) when IPP_STATUS_FAILED handle_failed_status(enrollment, response) else - handle_unsupported_status(enrollment, response['status']) + handle_unsupported_status(enrollment, response) end end diff --git a/app/services/analytics_events.rb b/app/services/analytics_events.rb index 64804f71381..b5b79a96b71 100644 --- a/app/services/analytics_events.rb +++ b/app/services/analytics_events.rb @@ -2521,11 +2521,45 @@ def idv_in_person_usps_proofing_results_job_completed( # @param [String] enrollment_id # @param [String] exception_class # @param [String] exception_message + # @param [String] enrollment_code + # @param [Float] minutes_since_last_status_check + # @param [Float] minutes_since_last_status_update + # @param [Float] minutes_to_completion + # @param [Boolean] fraud_suspected + # @param [String] primary_id_type + # @param [String] secondary_id_type + # @param [String] failure_reason + # @param [String] transaction_end_date_time + # @param [String] transaction_start_date_time + # @param [String] status + # @param [String] assurance_level + # @param [String] proofing_post_office + # @param [String] proofing_city + # @param [String] proofing_state + # @param [String] scan_count + # @param [String] response_message def idv_in_person_usps_proofing_results_job_exception( reason:, enrollment_id:, exception_class: nil, exception_message: nil, + enrollment_code: nil, + minutes_since_last_status_check: nil, + minutes_since_last_status_update: nil, + minutes_to_completion: nil, + fraud_suspected: nil, + primary_id_type: nil, + secondary_id_type: nil, + failure_reason: nil, + transaction_end_date_time: nil, + transaction_start_date_time: nil, + status: nil, + assurance_level: nil, + proofing_post_office: nil, + proofing_city: nil, + proofing_state: nil, + scan_count: nil, + response_message: nil, **extra ) track_event( @@ -2534,6 +2568,23 @@ def idv_in_person_usps_proofing_results_job_exception( enrollment_id: enrollment_id, exception_class: exception_class, exception_message: exception_message, + enrollment_code: enrollment_code, + minutes_since_last_status_check: minutes_since_last_status_check, + minutes_since_last_status_update: minutes_since_last_status_update, + minutes_to_completion: minutes_to_completion, + fraud_suspected: fraud_suspected, + primary_id_type: primary_id_type, + secondary_id_type: secondary_id_type, + failure_reason: failure_reason, + transaction_end_date_time: transaction_end_date_time, + transaction_start_date_time: transaction_start_date_time, + status: status, + assurance_level: assurance_level, + proofing_post_office: proofing_post_office, + proofing_city: proofing_city, + proofing_state: proofing_state, + scan_count: scan_count, + response_message: response_message, **extra, ) end diff --git a/app/services/usps_in_person_proofing/mock/responses/request_expired_proofing_results_response.json b/app/services/usps_in_person_proofing/mock/responses/request_expired_proofing_results_response.json index c2622f1df7e..7f01924ad96 100644 --- a/app/services/usps_in_person_proofing/mock/responses/request_expired_proofing_results_response.json +++ b/app/services/usps_in_person_proofing/mock/responses/request_expired_proofing_results_response.json @@ -1,15 +1,3 @@ { - "status": "In-person expired", - "proofingPostOffice": "WILKES BARRE", - "proofingCity": "WILKES BARRE", - "proofingState": "PA", - "enrollmentCode": "2090002197604352", - "primaryIdType": "Uniformed Services identification card", - "transactionStartDateTime": "12/17/2020 033855", - "transactionEndDateTime": "12/17/2020 034055", - "secondaryIdType": "Deed of Trust", - "responseMessage": "More than 30 days have passed since opt-in to IPP", - "fraudSuspected": false, - "proofingConfirmationNumber": "350040248346707", - "ippAssuranceLevel": "1.5" -} \ No newline at end of file + "responseMessage": "More than 30 days have passed since opt-in to IPP" +} diff --git a/spec/jobs/get_usps_proofing_results_job_spec.rb b/spec/jobs/get_usps_proofing_results_job_spec.rb index 4fba546d105..802df0d0819 100644 --- a/spec/jobs/get_usps_proofing_results_job_spec.rb +++ b/spec/jobs/get_usps_proofing_results_job_spec.rb @@ -1,6 +1,6 @@ require 'rails_helper' -RSpec.shared_examples 'enrollment with a status update' do |passed:, status:| +RSpec.shared_examples 'enrollment with a status update' do |passed:, status:, response_json:| it 'logs a message with common attributes' do freeze_time do pending_enrollment.update( @@ -12,14 +12,28 @@ job.perform(Time.zone.now) end + response = JSON.parse(response_json) expect(job_analytics).to have_logged_event( 'GetUspsProofingResultsJob: Enrollment status updated', + assurance_level: response['assuranceLevel'], enrollment_code: pending_enrollment.enrollment_code, enrollment_id: pending_enrollment.id, + failure_reason: response['failureReason'], + fraud_suspected: response['fraudSuspected'], minutes_since_last_status_check: 15.0, minutes_since_last_status_update: 2.days.in_minutes, minutes_to_completion: 3.days.in_minutes, passed: passed, + primary_id_type: response['primaryIdType'], + proofing_city: response['proofingCity'], + proofing_post_office: response['proofingPostOffice'], + proofing_state: response['proofingState'], + response_message: response['responseMessage'], + scan_count: response['scanCount'], + secondary_id_type: response['secondaryIdType'], + status: response['status'], + transaction_end_date_time: response['transactionEndDateTime'], + transaction_start_date_time: response['transactionStartDateTime'], ) end @@ -300,14 +314,19 @@ stub_request_passed_proofing_results end - it_behaves_like('enrollment with a status update', passed: true, status: 'passed') + it_behaves_like( + 'enrollment with a status update', + passed: true, + status: 'passed', + response_json: UspsInPersonProofing::Mock::Fixtures. + request_passed_proofing_results_response, + ) it 'logs details about the success' do job.perform(Time.zone.now) expect(job_analytics).to have_logged_event( 'GetUspsProofingResultsJob: Enrollment status updated', - fraud_suspected: false, reason: 'Successful status update', ) end @@ -318,21 +337,19 @@ stub_request_failed_proofing_results end - it_behaves_like('enrollment with a status update', passed: false, status: 'failed') + it_behaves_like( + 'enrollment with a status update', + passed: false, + status: 'failed', + response_json: UspsInPersonProofing::Mock::Fixtures. + request_failed_proofing_results_response, + ) it 'logs failure details' do job.perform(Time.zone.now) expect(job_analytics).to have_logged_event( 'GetUspsProofingResultsJob: Enrollment status updated', - failure_reason: 'Clerk indicates that ID name or address does not match source data.', - fraud_suspected: false, - primary_id_type: 'Uniformed Services identification card', - proofing_state: 'PA', - reason: 'Failed status', - secondary_id_type: 'Deed of Trust', - transaction_end_date_time: '12/17/2020 034055', - transaction_start_date_time: '12/17/2020 033855', ) end end @@ -342,15 +359,19 @@ stub_request_passed_proofing_unsupported_id_results end - it_behaves_like('enrollment with a status update', passed: false, status: 'failed') + it_behaves_like( + 'enrollment with a status update', + passed: false, + status: 'failed', + response_json: UspsInPersonProofing::Mock::Fixtures. + request_passed_proofing_unsupported_id_results_response, + ) it 'logs a message about the unsupported ID' do job.perform Time.zone.now expect(job_analytics).to have_logged_event( 'GetUspsProofingResultsJob: Enrollment status updated', - fraud_suspected: false, - primary_id_type: 'Not supported', reason: 'Unsupported ID type', ) end @@ -361,7 +382,13 @@ stub_request_expired_proofing_results end - it_behaves_like('enrollment with a status update', passed: false, status: 'expired') + it_behaves_like( + 'enrollment with a status update', + passed: false, + status: 'expired', + response_json: UspsInPersonProofing::Mock::Fixtures. + request_expired_proofing_results_response, + ) it 'logs that the enrollment expired' do job.perform(Time.zone.now) @@ -378,7 +405,10 @@ stub_request_proofing_results_with_responses({}) end - it_behaves_like('enrollment encountering an exception', reason: 'Bad response structure') + it_behaves_like( + 'enrollment encountering an exception', + reason: 'Bad response structure', + ) end context 'when USPS returns an unexpected status' do @@ -386,7 +416,10 @@ stub_request_passed_proofing_unsupported_status_results end - it_behaves_like('enrollment encountering an exception', reason: 'Unsupported status') + it_behaves_like( + 'enrollment encountering an exception', + reason: 'Unsupported status', + ) it 'logs the status received' do job.perform(Time.zone.now) diff --git a/spec/support/usps_ipp_helper.rb b/spec/support/usps_ipp_helper.rb index 2a46b8a17d5..6dd73f8bdf1 100644 --- a/spec/support/usps_ipp_helper.rb +++ b/spec/support/usps_ipp_helper.rb @@ -62,16 +62,17 @@ def request_failed_proofing_results_args def stub_request_passed_proofing_unsupported_id_results stub_request(:post, %r{/ivs-ippaas-api/IPPRest/resources/rest/getProofingResults}).to_return( - status: 200, body: UspsInPersonProofing::Mock::Fixtures. - request_passed_proofing_unsupported_id_results_response + status: 200, + body: UspsInPersonProofing::Mock:: + Fixtures.request_passed_proofing_unsupported_id_results_response, ) end def stub_request_passed_proofing_unsupported_status_results stub_request(:post, %r{/ivs-ippaas-api/IPPRest/resources/rest/getProofingResults}).to_return( status: 200, - body: UspsInPersonProofing::Mock::Fixtures. - request_passed_proofing_unsupported_status_results_response, + body: UspsInPersonProofing::Mock:: + Fixtures.request_passed_proofing_unsupported_status_results_response, ) end