From 6c83bf45eee54fdb9972725fc2e460639eeedbad Mon Sep 17 00:00:00 2001 From: vkghub Date: Wed, 18 Mar 2026 13:40:55 -0400 Subject: [PATCH 1/8] store enc values from hub response payload --- .../individual_market/ssa_vlp_determined.rb | 21 ++++- .../ssa_vlp_determined_spec.rb | 82 +++++++++++++++++++ 2 files changed, 102 insertions(+), 1 deletion(-) diff --git a/app/domain/operations/eligibilities/v3/individual_market/ssa_vlp_determined.rb b/app/domain/operations/eligibilities/v3/individual_market/ssa_vlp_determined.rb index 4c74daf5676..b1dbadaa177 100644 --- a/app/domain/operations/eligibilities/v3/individual_market/ssa_vlp_determined.rb +++ b/app/domain/operations/eligibilities/v3/individual_market/ssa_vlp_determined.rb @@ -248,7 +248,14 @@ def assign_five_year_bar_citizenship_result(evidence_entity, applicant) return unless individual_response_set applicant.five_year_bar_applies = vlp_response_code_to_boolean(individual_response_set[:FiveYearBarApplyCode]) if individual_response_set.key?(:FiveYearBarApplyCode) applicant.five_year_bar_met = vlp_response_code_to_boolean(individual_response_set[:FiveYearBarMetCode]) if individual_response_set.key?(:FiveYearBarMetCode) - applicant.qualified_non_citizen = qualified_non_citizen_result(raw_payload, applicant) + + if EnrollRegistry.feature_enabled?(:vlp_upgrade_v37_1_2) + applicant.immigration_information.qualified_non_citizen = qualified_non_citizen_result(raw_payload, applicant) + applicant.immigration_information.aptc_eligible_non_citizen = aptc_eligible_non_citizen_result(raw_payload) + applicant.immigration_information.medicaid_eligible_non_citizen = medicaid_eligible_non_citizen_result(raw_payload) + else + applicant.qualified_non_citizen = qualified_non_citizen_result(raw_payload, applicant) + end applicant.citizenship_result = get_citizen_status(applicant, individual_response) end @@ -274,6 +281,18 @@ def qualified_non_citizen_result(raw_payload, applicant) end end + def aptc_eligible_non_citizen_result(raw_payload) + return unless raw_payload.dig(:ResponseMetadata, :ResponseCode) == "HS000000" + individual_response = raw_payload.dig(:InitialVerificationResponseSet, :InitialVerificationIndividualResponses).first + individual_response.dig(:InitialVerificationIndividualResponseSet, :AptcEligibleNonCitizenCode) + end + + def medicaid_eligible_non_citizen_result(raw_payload) + return unless raw_payload.dig(:ResponseMetadata, :ResponseCode) == "HS000000" + individual_response = raw_payload.dig(:InitialVerificationResponseSet, :InitialVerificationIndividualResponses).first + individual_response.dig(:InitialVerificationIndividualResponseSet, :MedicaidEligibleNonCitizenCode) + end + def parse_qnc_code(applicant, individual_response) qnc_code = individual_response.dig(:InitialVerificationIndividualResponseSet, :QualifiedNonCitizenCode) diff --git a/spec/domain/operations/eligibilities/v3/individual_market/ssa_vlp_determined_spec.rb b/spec/domain/operations/eligibilities/v3/individual_market/ssa_vlp_determined_spec.rb index bafcf4fa1fa..f9b65007bfe 100644 --- a/spec/domain/operations/eligibilities/v3/individual_market/ssa_vlp_determined_spec.rb +++ b/spec/domain/operations/eligibilities/v3/individual_market/ssa_vlp_determined_spec.rb @@ -431,4 +431,86 @@ end end end + + describe 'when vlp_upgrade_v37_1_2 is enabled' do + let(:immigration_rr) do + { result: 'test_state', + source: "FDSH VLP", + code: 'HS000000', + code_description: 'SSA VLP Determined', + raw_payload: "{\"ResponseMetadata\":{\"ResponseCode\":\"HS000000\",\"ResponseDescriptionText\":\"Successful.\"}, + \"InitialVerificationResponseSet\":{\"InitialVerificationIndividualResponses\":[{\"ResponseMetadata\":{\"ResponseCode\":\"HS000000\", + \"ResponseDescriptionText\":\"Successful.\"},\"LawfulPresenceVerifiedCode\":\"P\",\"InitialVerificationIndividualResponseSet\":{\"CaseNumber\":\"0000000000000AA\",\"NonCitLastName\":\"NonCitLastName1\", + \"NonCitFirstName\":\"NonCitFirstName1\",\"NonCitMiddleName\":null,\"NonCitBirthDate\":\"2006-05-04T00:00:00.000Z\",\"NonCitEntryDate\":null,\"AdmittedToDate\":null,\"AdmittedToText\":null, + \"NonCitCountryBirthCd\":null,\"NonCitCountryCitCd\":null,\"NonCitCoaCode\":null,\"NonCitProvOfLaw\":null,\"NonCitEadsExpireDate\":null,\"EligStatementCd\":5,\"EligStatementTxt\":\"EligStatementTxt1\", + \"IAVTypeCode\":null,\"IAVTypeTxt\":null,\"WebServSftwrVer\":\"WebServSftwrVer1\",\"GrantDate\":null,\"GrantDateReasonCd\":null,\"SponsorDataFoundIndicator\":null,\"ArrayOfSponsorshipData\":null, + \"SponsorshipReasonCd\":null,\"AgencyAction\":\"AgencyAction1\",\"FiveYearBarApplyCode\":\"N\",\"QualifiedNonCitizenCode\":\"N\",\"APTCEligibleNonCitizenCode\":\"Y\",\"MCEligibleNonCitizenCode\":\"N\", + \"FiveYearBarMetCode\":\"N\",\"USCitizenCode\":\"N\"}}]}}"} + end + + before do + @application_hash = Operations::Fdsh::BuildAndValidateApplicationPayload.new.call(application).value!.to_h + @determinations = application.applicants.pluck(:person_hbx_id) + application.applicants.each do |applicant| + applicant.build_ivl_eligibility_with_evidences + individual_market_eligibility = applicant.individual_market_eligibility + # Creating both citizenship and immigration evidences for testing. + individual_market_eligibility.evidences.build( + _type: 'Eligibilities::V3::Evidences::CitizenshipEvidence', + title: 'Citizenship Evidence', + key: :citizenship_evidence, + current_state: :pending + ) + individual_market_eligibility.evidences.build( + _type: 'Eligibilities::V3::Evidences::ImmigrationEvidence', + title: 'Immigration Evidence', + key: :immigration_evidence, + current_state: :pending + ) + applicant.save + end + end + + context 'with valid application' do + before do + @application_hash[:applicants].each do |applicant| + applicant[:eligibilities] = [eligibility_hash] + end + @result = subject.call({call_type: 'application_determination', job_id: job.job_id, application_hbx_id: @application_hash[:hbx_id], + response: @application_hash.to_json, app_type: 'faa', + determinations: {ssa: @determinations, vlp: @determinations}}) + end + + it 'returns success with message' do + expect(@result).to be_success + expect(::Transmittable::Job.first.process_status.latest_state).to eq(:succeeded) + expect(::Transmittable::Transmission.first.process_status.latest_state).to eq(:succeeded) + expect(::Transmittable::Transaction.first.process_status.latest_state).to eq(:succeeded) + end + + it 'creates request results for each evidence' do + application.reload + applicant = application.applicants.first + individual_market_eligibility = applicant.individual_market_eligibility + + ssn_evidence = individual_market_eligibility.evidences.detect { |e| e.key.to_sym == :social_security_number_evidence } + + expect(ssn_evidence.request_results.count).to eq(1) + expect(ssn_evidence.request_results.first.result).to eq('test_state') + expect(ssn_evidence.request_results.first.source).to eq('FDSH SSA') + expect(ssn_evidence.request_results.first.code).to eq('HS000000') + end + + it 'updates consumer role lawful presence determination' do + application.reload + applicant = application.applicants.first + expect(applicant.five_year_bar_applies).to eq false + expect(applicant.five_year_bar_met).to eq false + expect(applicant.immigration_information.qualified_non_citizen).to eq false + expect(applicant.immigration_information.aptc_eligible_non_citizen).to eq true + expect(applicant.immigration_information.medicare_eligible_non_citizen).to eq false + expect(applicant.citizenship_result).to eq 'not_lawfully_present_in_us' + end + end + end end \ No newline at end of file From 55cb47a15c9ac6556906ede6cd07a1bfddbf7770 Mon Sep 17 00:00:00 2001 From: vkghub Date: Wed, 18 Mar 2026 14:54:09 -0400 Subject: [PATCH 2/8] remove unnecessary code --- .../v3/individual_market/ssa_vlp_determined.rb | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/app/domain/operations/eligibilities/v3/individual_market/ssa_vlp_determined.rb b/app/domain/operations/eligibilities/v3/individual_market/ssa_vlp_determined.rb index b1dbadaa177..800437a64bb 100644 --- a/app/domain/operations/eligibilities/v3/individual_market/ssa_vlp_determined.rb +++ b/app/domain/operations/eligibilities/v3/individual_market/ssa_vlp_determined.rb @@ -251,8 +251,9 @@ def assign_five_year_bar_citizenship_result(evidence_entity, applicant) if EnrollRegistry.feature_enabled?(:vlp_upgrade_v37_1_2) applicant.immigration_information.qualified_non_citizen = qualified_non_citizen_result(raw_payload, applicant) - applicant.immigration_information.aptc_eligible_non_citizen = aptc_eligible_non_citizen_result(raw_payload) - applicant.immigration_information.medicaid_eligible_non_citizen = medicaid_eligible_non_citizen_result(raw_payload) + aptc_eligible_non_citizen, medicaid_eligible_non_citizen = fetch_enc_values(raw_payload, initial_responses) + applicant.immigration_information.aptc_eligible_non_citizen = aptc_eligible_non_citizen + applicant.immigration_information.medicaid_eligible_non_citizen = medicaid_eligible_non_citizen else applicant.qualified_non_citizen = qualified_non_citizen_result(raw_payload, applicant) end @@ -281,16 +282,12 @@ def qualified_non_citizen_result(raw_payload, applicant) end end - def aptc_eligible_non_citizen_result(raw_payload) + def fetch_enc_values(raw_payload, initial_responses) return unless raw_payload.dig(:ResponseMetadata, :ResponseCode) == "HS000000" - individual_response = raw_payload.dig(:InitialVerificationResponseSet, :InitialVerificationIndividualResponses).first - individual_response.dig(:InitialVerificationIndividualResponseSet, :AptcEligibleNonCitizenCode) - end - def medicaid_eligible_non_citizen_result(raw_payload) - return unless raw_payload.dig(:ResponseMetadata, :ResponseCode) == "HS000000" - individual_response = raw_payload.dig(:InitialVerificationResponseSet, :InitialVerificationIndividualResponses).first - individual_response.dig(:InitialVerificationIndividualResponseSet, :MedicaidEligibleNonCitizenCode) + individual_response = initial_responses[0] + individual_response_set = individual_response[:InitialVerificationIndividualResponseSet] + [individual_response_set[:AptcEligibleNonCitizenCode], individual_response_set[:MedicaidEligibleNonCitizenCode]] end def parse_qnc_code(applicant, individual_response) From beebf3b2ac4d5837b579f96843dbd9736ef031d8 Mon Sep 17 00:00:00 2001 From: vkghub Date: Wed, 18 Mar 2026 15:06:37 -0400 Subject: [PATCH 3/8] fix typo --- .../eligibilities/v3/individual_market/ssa_vlp_determined.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/domain/operations/eligibilities/v3/individual_market/ssa_vlp_determined.rb b/app/domain/operations/eligibilities/v3/individual_market/ssa_vlp_determined.rb index 800437a64bb..c4af578eeab 100644 --- a/app/domain/operations/eligibilities/v3/individual_market/ssa_vlp_determined.rb +++ b/app/domain/operations/eligibilities/v3/individual_market/ssa_vlp_determined.rb @@ -283,7 +283,7 @@ def qualified_non_citizen_result(raw_payload, applicant) end def fetch_enc_values(raw_payload, initial_responses) - return unless raw_payload.dig(:ResponseMetadata, :ResponseCode) == "HS000000" + return [] unless raw_payload.dig(:ResponseMetadata, :ResponseCode) == "HS000000" individual_response = initial_responses[0] individual_response_set = individual_response[:InitialVerificationIndividualResponseSet] From 4ada32766aaed17bb8206efab3a07f8b42e7a498 Mon Sep 17 00:00:00 2001 From: vkghub Date: Wed, 18 Mar 2026 16:43:09 -0400 Subject: [PATCH 4/8] add more code --- .../individual_market/ssa_vlp_determined.rb | 67 +++++++++++-------- 1 file changed, 38 insertions(+), 29 deletions(-) diff --git a/app/domain/operations/eligibilities/v3/individual_market/ssa_vlp_determined.rb b/app/domain/operations/eligibilities/v3/individual_market/ssa_vlp_determined.rb index c4af578eeab..1cb9561e257 100644 --- a/app/domain/operations/eligibilities/v3/individual_market/ssa_vlp_determined.rb +++ b/app/domain/operations/eligibilities/v3/individual_market/ssa_vlp_determined.rb @@ -205,7 +205,7 @@ def update_evidences_for_applicant(res_applicant_entity) eligibility_entity.evidences.each do |evidence_entity| evidence = eligibility.evidences.detect { |e| e.key.to_sym == evidence_entity.key.to_sym } next unless evidence - update_evidence(evidence, evidence_entity) if evidence_entity.request_results.present? || evidence_entity.verification_histories.present? + update_evidence_state(evidence, evidence_entity) if evidence_entity.request_results.present? || evidence_entity.verification_histories.present? record_request_result(evidence, evidence_entity, applicant) if evidence_entity.request_results.present? record_verification_result(evidence, evidence_entity) if evidence_entity.verification_histories.present? end @@ -215,17 +215,19 @@ def update_evidences_for_applicant(res_applicant_entity) def record_request_result(evidence, evidence_entity, applicant) result_result_entity = evidence_entity.request_results.first evidence.request_results.new(result_result_entity.to_h) - assign_citizen_status(evidence_entity, applicant) if result_result_entity.source.to_s == "FDSH SSA" - assign_five_year_bar_citizenship_result(evidence_entity, applicant) if result_result_entity.source.to_s == "FDSH VLP" + json_raw_payload = evidence_entity.request_results.first.raw_payload + raw_payload = JSON.parse(json_raw_payload, symbolize_names: true) + + assign_citizen_status(raw_payload, applicant) if result_result_entity.source.to_s == "FDSH SSA" + assign_five_year_bar_citizenship_result(raw_payload, applicant) if result_result_entity.source.to_s == "FDSH VLP" + assign_immigration_evidence_response_codes(raw_payload, evidence) if EnrollRegistry.feature_enabled?(:vlp_upgrade_v37_1_2) && evidence.key == "immigration_evidence" rescue StandardError => e record_ingestion_result(evidence, e) end - def assign_citizen_status(evidence_entity, applicant) - json_raw_payload = evidence_entity.request_results.first.raw_payload - response = JSON.parse(json_raw_payload, symbolize_names: true) - response_code = response.dig(:ResponseMetadata, :ResponseCode) - ssa_response = response.dig(:SSACompositeIndividualResponses, 0, :SSAResponse) + def assign_citizen_status(raw_payload, applicant) + response_code = raw_payload.dig(:ResponseMetadata, :ResponseCode) + ssa_response = raw_payload.dig(:SSACompositeIndividualResponses, 0, :SSAResponse) return applicant.citizenship_result = ::ConsumerRole::NOT_LAWFULLY_PRESENT_STATUS unless response_code == "HS000000" && ssa_response.present? ssn_indicator = ssa_response[:SSNVerificationIndicator] @@ -236,9 +238,7 @@ def assign_citizen_status(evidence_entity, applicant) end # update applicant only for vlp payloads - def assign_five_year_bar_citizenship_result(evidence_entity, applicant) - json_raw_payload = evidence_entity.request_results.first.raw_payload - raw_payload = JSON.parse(json_raw_payload, symbolize_names: true) + def assign_five_year_bar_citizenship_result(raw_payload, applicant) initial_responses = raw_payload.dig(:InitialVerificationResponseSet, :InitialVerificationIndividualResponses) return unless initial_responses @@ -248,18 +248,35 @@ def assign_five_year_bar_citizenship_result(evidence_entity, applicant) return unless individual_response_set applicant.five_year_bar_applies = vlp_response_code_to_boolean(individual_response_set[:FiveYearBarApplyCode]) if individual_response_set.key?(:FiveYearBarApplyCode) applicant.five_year_bar_met = vlp_response_code_to_boolean(individual_response_set[:FiveYearBarMetCode]) if individual_response_set.key?(:FiveYearBarMetCode) - - if EnrollRegistry.feature_enabled?(:vlp_upgrade_v37_1_2) - applicant.immigration_information.qualified_non_citizen = qualified_non_citizen_result(raw_payload, applicant) - aptc_eligible_non_citizen, medicaid_eligible_non_citizen = fetch_enc_values(raw_payload, initial_responses) - applicant.immigration_information.aptc_eligible_non_citizen = aptc_eligible_non_citizen - applicant.immigration_information.medicaid_eligible_non_citizen = medicaid_eligible_non_citizen - else - applicant.qualified_non_citizen = qualified_non_citizen_result(raw_payload, applicant) - end + applicant.qualified_non_citizen = qualified_non_citizen_result(raw_payload, applicant) applicant.citizenship_result = get_citizen_status(applicant, individual_response) end + def assign_immigration_evidence_response_codes(raw_payload, evidence) + initial_responses = raw_payload.dig(:InitialVerificationResponseSet, :InitialVerificationIndividualResponses) + return unless initial_responses + + individual_response = initial_responses[0] + return unless individual_response + individual_response_set = individual_response[:InitialVerificationIndividualResponseSet] + return unless individual_response_set + + evidence.response_code = raw_payload.dig(:ResponseMetadata, :ResponseCode) + evidence.response_description_text = raw_payload.dig(:ResponseMetadata, :ResponseDescriptionText) + evidence.us_citizen_code = individual_response.dig(:InitialVerificationIndividualResponseSet, :USCitizenCode) + evidence.lawful_presence_verified_code = individual_response[:LawfulPresenceVerifiedCode] + evidence.aptc_eligible_non_citizen = individual_response_set[:AptcEligibleNonCitizenCode] + evidence.medicaid_eligible_non_citizen = individual_response_set[:MedicaidEligibleNonCitizenCode] + evidence.qualified_non_citizen = individual_response_set[:QualifiedNonCitizenCode] + evidence.five_year_bar_apply_code = individual_response_set[:FiveYearBarApplyCode] + evidence.five_year_bar_met_code = individual_response_set[:FiveYearBarMetCode] + evidence.non_cit_coa_code = individual_response_set[:NonCitizenCOACode] + evidence.elig_statement_cd = individual_response_set[:EligStatementCd] + evidence.elig_statement_txt = individual_response_set[:EligStatementTxt] + # evidence.response_transaction_id = individual_response_set[:ResponseTransactionId] + # evidence.response_timestamp = individual_response_set[:ResponseTimestamp] + end + def get_citizen_status(applicant, individual_response) return ::ConsumerRole::NOT_LAWFULLY_PRESENT_STATUS unless ['Y', 'X'].include?(individual_response[:LawfulPresenceVerifiedCode]) status = individual_response.dig(:InitialVerificationIndividualResponseSet, :EligStatementTxt) @@ -282,14 +299,6 @@ def qualified_non_citizen_result(raw_payload, applicant) end end - def fetch_enc_values(raw_payload, initial_responses) - return [] unless raw_payload.dig(:ResponseMetadata, :ResponseCode) == "HS000000" - - individual_response = initial_responses[0] - individual_response_set = individual_response[:InitialVerificationIndividualResponseSet] - [individual_response_set[:AptcEligibleNonCitizenCode], individual_response_set[:MedicaidEligibleNonCitizenCode]] - end - def parse_qnc_code(applicant, individual_response) qnc_code = individual_response.dig(:InitialVerificationIndividualResponseSet, :QualifiedNonCitizenCode) @@ -361,7 +370,7 @@ def record_ingestion_result(evidence, error) # @param evidence [Eligibilities::V3::Evidence] The evidence to update # @param evidence_entity [AcaEntities::MagiMedicaid::Evidence] The evidence entity from the response # @return [void] - def update_evidence(evidence, evidence_entity) + def update_evidence_state(evidence, evidence_entity) case evidence_entity.current_state when :attested evidence.mark_as_verified From d9f3dbb032f629da72884f26ca87f6bcb790cee0 Mon Sep 17 00:00:00 2001 From: vkghub Date: Wed, 18 Mar 2026 17:11:12 -0400 Subject: [PATCH 5/8] refactor logic --- .../individual_market/ssa_vlp_determined.rb | 31 ++++++++++------- .../ssa_vlp_determined_spec.rb | 34 +++++++++---------- 2 files changed, 34 insertions(+), 31 deletions(-) diff --git a/app/domain/operations/eligibilities/v3/individual_market/ssa_vlp_determined.rb b/app/domain/operations/eligibilities/v3/individual_market/ssa_vlp_determined.rb index 1cb9561e257..753f80a2057 100644 --- a/app/domain/operations/eligibilities/v3/individual_market/ssa_vlp_determined.rb +++ b/app/domain/operations/eligibilities/v3/individual_market/ssa_vlp_determined.rb @@ -220,7 +220,7 @@ def record_request_result(evidence, evidence_entity, applicant) assign_citizen_status(raw_payload, applicant) if result_result_entity.source.to_s == "FDSH SSA" assign_five_year_bar_citizenship_result(raw_payload, applicant) if result_result_entity.source.to_s == "FDSH VLP" - assign_immigration_evidence_response_codes(raw_payload, evidence) if EnrollRegistry.feature_enabled?(:vlp_upgrade_v37_1_2) && evidence.key == "immigration_evidence" + assign_immigration_evidence_response_codes(raw_payload, evidence) if EnrollRegistry.feature_enabled?(:vlp_upgrade_v37_1_2) && evidence.key == :immigration_evidence rescue StandardError => e record_ingestion_result(evidence, e) end @@ -258,23 +258,28 @@ def assign_immigration_evidence_response_codes(raw_payload, evidence) individual_response = initial_responses[0] return unless individual_response + individual_response_set = individual_response[:InitialVerificationIndividualResponseSet] return unless individual_response_set - evidence.response_code = raw_payload.dig(:ResponseMetadata, :ResponseCode) - evidence.response_description_text = raw_payload.dig(:ResponseMetadata, :ResponseDescriptionText) - evidence.us_citizen_code = individual_response.dig(:InitialVerificationIndividualResponseSet, :USCitizenCode) - evidence.lawful_presence_verified_code = individual_response[:LawfulPresenceVerifiedCode] - evidence.aptc_eligible_non_citizen = individual_response_set[:AptcEligibleNonCitizenCode] - evidence.medicaid_eligible_non_citizen = individual_response_set[:MedicaidEligibleNonCitizenCode] - evidence.qualified_non_citizen = individual_response_set[:QualifiedNonCitizenCode] - evidence.five_year_bar_apply_code = individual_response_set[:FiveYearBarApplyCode] - evidence.five_year_bar_met_code = individual_response_set[:FiveYearBarMetCode] - evidence.non_cit_coa_code = individual_response_set[:NonCitizenCOACode] - evidence.elig_statement_cd = individual_response_set[:EligStatementCd] - evidence.elig_statement_txt = individual_response_set[:EligStatementTxt] + evidence.assign_attributes(build_immigration_response_hash(raw_payload, individual_response)) + end + + def build_immigration_response_hash(raw_payload, individual_response) # evidence.response_transaction_id = individual_response_set[:ResponseTransactionId] # evidence.response_timestamp = individual_response_set[:ResponseTimestamp] + {response_code: raw_payload.dig(:ResponseMetadata, :ResponseCode), + response_description_text: raw_payload.dig(:ResponseMetadata, :ResponseDescriptionText), + us_citizen_code: individual_response.dig(:InitialVerificationIndividualResponseSet, :USCitizenCode), + lawful_presence_verified_code: individual_response[:LawfulPresenceVerifiedCode], + aptc_eligible_non_citizen_code: individual_response_set[:AptcEligibleNonCitizenCode], + medicaid_eligible_non_citizen_code: individual_response_set[:MedicaidEligibleNonCitizenCode], + qualified_non_citizen_code: individual_response_set[:QualifiedNonCitizenCode], + five_year_bar_apply_code: individual_response_set[:FiveYearBarApplyCode], + five_year_bar_met_code: individual_response_set[:FiveYearBarMetCode], + non_cit_coa_code: individual_response_set[:NonCitizenCOACode], + elig_statement_cd: individual_response_set[:EligStatementCd], + elig_statement_txt: individual_response_set[:EligStatementTxt]} end def get_citizen_status(applicant, individual_response) diff --git a/spec/domain/operations/eligibilities/v3/individual_market/ssa_vlp_determined_spec.rb b/spec/domain/operations/eligibilities/v3/individual_market/ssa_vlp_determined_spec.rb index f9b65007bfe..af11788ca33 100644 --- a/spec/domain/operations/eligibilities/v3/individual_market/ssa_vlp_determined_spec.rb +++ b/spec/domain/operations/eligibilities/v3/individual_market/ssa_vlp_determined_spec.rb @@ -488,28 +488,26 @@ expect(::Transmittable::Transaction.first.process_status.latest_state).to eq(:succeeded) end - it 'creates request results for each evidence' do + it 'record response code in immigration evidence' do application.reload applicant = application.applicants.first individual_market_eligibility = applicant.individual_market_eligibility - ssn_evidence = individual_market_eligibility.evidences.detect { |e| e.key.to_sym == :social_security_number_evidence } - - expect(ssn_evidence.request_results.count).to eq(1) - expect(ssn_evidence.request_results.first.result).to eq('test_state') - expect(ssn_evidence.request_results.first.source).to eq('FDSH SSA') - expect(ssn_evidence.request_results.first.code).to eq('HS000000') - end - - it 'updates consumer role lawful presence determination' do - application.reload - applicant = application.applicants.first - expect(applicant.five_year_bar_applies).to eq false - expect(applicant.five_year_bar_met).to eq false - expect(applicant.immigration_information.qualified_non_citizen).to eq false - expect(applicant.immigration_information.aptc_eligible_non_citizen).to eq true - expect(applicant.immigration_information.medicare_eligible_non_citizen).to eq false - expect(applicant.citizenship_result).to eq 'not_lawfully_present_in_us' + immigration_evidence = individual_market_eligibility.evidences.detect { |e| e.key.to_sym == :immigration_evidence } + + expect(immigration_evidence.response_code).to eq 'HS000000' + expect(immigration_evidence.response_description_text).to eq 'Successful' + expect(immigration_evidence.lawful_presence_verified_code).to eq 'P' + expect(immigration_evidence.aptc_eligible_non_citizen_code).to eq 'Y' + expect(immigration_evidence.medicaid_eligible_non_citizen_code).to eq 'N' + expect(immigration_evidence.qualified_non_citizen_code).to eq 'N' + expect(immigration_evidence.five_year_bar_apply_code).to eq 'N' + expect(immigration_evidence.five_year_bar_met_code).to eq 'N' + expect(immigration_evidence.non_cit_coa_code).to eq 'N' + expect(immigration_evidence.elig_statement_cd).to eq '5' + expect(immigration_evidence.elig_statement_txt).to eq 'EligStatementTxt1' + # expect(immigration_evidence.response_transaction_id).to be_present + # expect(immigration_evidence.response_timestamp).to be_present end end end From 9c6d438a5f1d31846ab6d2b8c34ba0946871bdb7 Mon Sep 17 00:00:00 2001 From: vkghub Date: Thu, 19 Mar 2026 09:30:33 -0400 Subject: [PATCH 6/8] fix spec --- .../v3/individual_market/ssa_vlp_determined_spec.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/domain/operations/eligibilities/v3/individual_market/ssa_vlp_determined_spec.rb b/spec/domain/operations/eligibilities/v3/individual_market/ssa_vlp_determined_spec.rb index af11788ca33..6a4d0c11bb7 100644 --- a/spec/domain/operations/eligibilities/v3/individual_market/ssa_vlp_determined_spec.rb +++ b/spec/domain/operations/eligibilities/v3/individual_market/ssa_vlp_determined_spec.rb @@ -449,6 +449,7 @@ end before do + allow(EnrollRegistry).to receive(:feature_enabled?).with(:vlp_upgrade_v37_1_2).and_return(true) @application_hash = Operations::Fdsh::BuildAndValidateApplicationPayload.new.call(application).value!.to_h @determinations = application.applicants.pluck(:person_hbx_id) application.applicants.each do |applicant| From e68459d80674dfc100dc4743b171281a45a83f24 Mon Sep 17 00:00:00 2001 From: vkghub Date: Thu, 19 Mar 2026 11:20:36 -0400 Subject: [PATCH 7/8] fix typos, refactor some code --- .../v3/individual_market/ssa_vlp_determined.rb | 15 +++++++++------ .../ssa_vlp_determined_spec.rb | 17 ++++++----------- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/app/domain/operations/eligibilities/v3/individual_market/ssa_vlp_determined.rb b/app/domain/operations/eligibilities/v3/individual_market/ssa_vlp_determined.rb index 753f80a2057..8249762c791 100644 --- a/app/domain/operations/eligibilities/v3/individual_market/ssa_vlp_determined.rb +++ b/app/domain/operations/eligibilities/v3/individual_market/ssa_vlp_determined.rb @@ -205,6 +205,7 @@ def update_evidences_for_applicant(res_applicant_entity) eligibility_entity.evidences.each do |evidence_entity| evidence = eligibility.evidences.detect { |e| e.key.to_sym == evidence_entity.key.to_sym } next unless evidence + update_evidence_state(evidence, evidence_entity) if evidence_entity.request_results.present? || evidence_entity.verification_histories.present? record_request_result(evidence, evidence_entity, applicant) if evidence_entity.request_results.present? record_verification_result(evidence, evidence_entity) if evidence_entity.verification_histories.present? @@ -220,7 +221,7 @@ def record_request_result(evidence, evidence_entity, applicant) assign_citizen_status(raw_payload, applicant) if result_result_entity.source.to_s == "FDSH SSA" assign_five_year_bar_citizenship_result(raw_payload, applicant) if result_result_entity.source.to_s == "FDSH VLP" - assign_immigration_evidence_response_codes(raw_payload, evidence) if EnrollRegistry.feature_enabled?(:vlp_upgrade_v37_1_2) && evidence.key == :immigration_evidence + assign_immigration_evidence_response_codes(raw_payload, evidence) if EnrollRegistry.feature_enabled?(:vlp_upgrade_v37_1_2) && evidence.key == "immigration_evidence" rescue StandardError => e record_ingestion_result(evidence, e) end @@ -262,22 +263,24 @@ def assign_immigration_evidence_response_codes(raw_payload, evidence) individual_response_set = individual_response[:InitialVerificationIndividualResponseSet] return unless individual_response_set - evidence.assign_attributes(build_immigration_response_hash(raw_payload, individual_response)) + evidence.assign_attributes(build_immigration_response_hash(raw_payload, individual_response, individual_response_set)) end - def build_immigration_response_hash(raw_payload, individual_response) + def build_immigration_response_hash(raw_payload, individual_response, individual_response_set) + # TODO: Use the below lines in hash once we have the logic to capture transaction id and timestamp from the response # evidence.response_transaction_id = individual_response_set[:ResponseTransactionId] # evidence.response_timestamp = individual_response_set[:ResponseTimestamp] + {response_code: raw_payload.dig(:ResponseMetadata, :ResponseCode), response_description_text: raw_payload.dig(:ResponseMetadata, :ResponseDescriptionText), us_citizen_code: individual_response.dig(:InitialVerificationIndividualResponseSet, :USCitizenCode), lawful_presence_verified_code: individual_response[:LawfulPresenceVerifiedCode], - aptc_eligible_non_citizen_code: individual_response_set[:AptcEligibleNonCitizenCode], - medicaid_eligible_non_citizen_code: individual_response_set[:MedicaidEligibleNonCitizenCode], + aptc_eligible_non_citizen_code: individual_response_set[:APTCEligibleNonCitizenCode], + medicaid_eligible_non_citizen_code: individual_response_set[:MCEligibleNonCitizenCode], qualified_non_citizen_code: individual_response_set[:QualifiedNonCitizenCode], five_year_bar_apply_code: individual_response_set[:FiveYearBarApplyCode], five_year_bar_met_code: individual_response_set[:FiveYearBarMetCode], - non_cit_coa_code: individual_response_set[:NonCitizenCOACode], + non_cit_coa_code: individual_response_set[:NonCitCoaCode], elig_statement_cd: individual_response_set[:EligStatementCd], elig_statement_txt: individual_response_set[:EligStatementTxt]} end diff --git a/spec/domain/operations/eligibilities/v3/individual_market/ssa_vlp_determined_spec.rb b/spec/domain/operations/eligibilities/v3/individual_market/ssa_vlp_determined_spec.rb index 6a4d0c11bb7..8fa02eb46a2 100644 --- a/spec/domain/operations/eligibilities/v3/individual_market/ssa_vlp_determined_spec.rb +++ b/spec/domain/operations/eligibilities/v3/individual_market/ssa_vlp_determined_spec.rb @@ -438,9 +438,9 @@ source: "FDSH VLP", code: 'HS000000', code_description: 'SSA VLP Determined', - raw_payload: "{\"ResponseMetadata\":{\"ResponseCode\":\"HS000000\",\"ResponseDescriptionText\":\"Successful.\"}, + raw_payload: "{\"ResponseMetadata\":{\"ResponseCode\":\"HS000000\",\"ResponseDescriptionText\":\"Successful\"}, \"InitialVerificationResponseSet\":{\"InitialVerificationIndividualResponses\":[{\"ResponseMetadata\":{\"ResponseCode\":\"HS000000\", - \"ResponseDescriptionText\":\"Successful.\"},\"LawfulPresenceVerifiedCode\":\"P\",\"InitialVerificationIndividualResponseSet\":{\"CaseNumber\":\"0000000000000AA\",\"NonCitLastName\":\"NonCitLastName1\", + \"ResponseDescriptionText\":\"Successful\"},\"LawfulPresenceVerifiedCode\":\"P\",\"InitialVerificationIndividualResponseSet\":{\"CaseNumber\":\"0000000000000AA\",\"NonCitLastName\":\"NonCitLastName1\", \"NonCitFirstName\":\"NonCitFirstName1\",\"NonCitMiddleName\":null,\"NonCitBirthDate\":\"2006-05-04T00:00:00.000Z\",\"NonCitEntryDate\":null,\"AdmittedToDate\":null,\"AdmittedToText\":null, \"NonCitCountryBirthCd\":null,\"NonCitCountryCitCd\":null,\"NonCitCoaCode\":null,\"NonCitProvOfLaw\":null,\"NonCitEadsExpireDate\":null,\"EligStatementCd\":5,\"EligStatementTxt\":\"EligStatementTxt1\", \"IAVTypeCode\":null,\"IAVTypeTxt\":null,\"WebServSftwrVer\":\"WebServSftwrVer1\",\"GrantDate\":null,\"GrantDateReasonCd\":null,\"SponsorDataFoundIndicator\":null,\"ArrayOfSponsorshipData\":null, @@ -455,13 +455,6 @@ application.applicants.each do |applicant| applicant.build_ivl_eligibility_with_evidences individual_market_eligibility = applicant.individual_market_eligibility - # Creating both citizenship and immigration evidences for testing. - individual_market_eligibility.evidences.build( - _type: 'Eligibilities::V3::Evidences::CitizenshipEvidence', - title: 'Citizenship Evidence', - key: :citizenship_evidence, - current_state: :pending - ) individual_market_eligibility.evidences.build( _type: 'Eligibilities::V3::Evidences::ImmigrationEvidence', title: 'Immigration Evidence', @@ -494,7 +487,7 @@ applicant = application.applicants.first individual_market_eligibility = applicant.individual_market_eligibility - immigration_evidence = individual_market_eligibility.evidences.detect { |e| e.key.to_sym == :immigration_evidence } + immigration_evidence = individual_market_eligibility.evidences.detect { |e| e.key.to_s == "immigration_evidence" } expect(immigration_evidence.response_code).to eq 'HS000000' expect(immigration_evidence.response_description_text).to eq 'Successful' @@ -504,9 +497,11 @@ expect(immigration_evidence.qualified_non_citizen_code).to eq 'N' expect(immigration_evidence.five_year_bar_apply_code).to eq 'N' expect(immigration_evidence.five_year_bar_met_code).to eq 'N' - expect(immigration_evidence.non_cit_coa_code).to eq 'N' + expect(immigration_evidence.non_cit_coa_code).to be_nil expect(immigration_evidence.elig_statement_cd).to eq '5' expect(immigration_evidence.elig_statement_txt).to eq 'EligStatementTxt1' + + # TODO: Uncomment the below lines once we have the logic to capture transaction id and timestamp from the response # expect(immigration_evidence.response_transaction_id).to be_present # expect(immigration_evidence.response_timestamp).to be_present end From 86385f72c35ad77735c06cefb90e5f35172e1cad Mon Sep 17 00:00:00 2001 From: vkghub Date: Fri, 27 Mar 2026 12:13:04 -0400 Subject: [PATCH 8/8] add response time --- .../v3/individual_market/ssa_vlp_determined.rb | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app/domain/operations/eligibilities/v3/individual_market/ssa_vlp_determined.rb b/app/domain/operations/eligibilities/v3/individual_market/ssa_vlp_determined.rb index 8249762c791..6e703bd248a 100644 --- a/app/domain/operations/eligibilities/v3/individual_market/ssa_vlp_determined.rb +++ b/app/domain/operations/eligibilities/v3/individual_market/ssa_vlp_determined.rb @@ -267,9 +267,9 @@ def assign_immigration_evidence_response_codes(raw_payload, evidence) end def build_immigration_response_hash(raw_payload, individual_response, individual_response_set) - # TODO: Use the below lines in hash once we have the logic to capture transaction id and timestamp from the response + # TODO: Use the below lines in hash once we have the logic to capture transaction id from the response # evidence.response_transaction_id = individual_response_set[:ResponseTransactionId] - # evidence.response_timestamp = individual_response_set[:ResponseTimestamp] + # evidence.response_timestamp : is set to current time as this is the response time for the evidence {response_code: raw_payload.dig(:ResponseMetadata, :ResponseCode), response_description_text: raw_payload.dig(:ResponseMetadata, :ResponseDescriptionText), @@ -282,7 +282,8 @@ def build_immigration_response_hash(raw_payload, individual_response, individual five_year_bar_met_code: individual_response_set[:FiveYearBarMetCode], non_cit_coa_code: individual_response_set[:NonCitCoaCode], elig_statement_cd: individual_response_set[:EligStatementCd], - elig_statement_txt: individual_response_set[:EligStatementTxt]} + elig_statement_txt: individual_response_set[:EligStatementTxt], + response_timestamp: DateTime.now} end def get_citizen_status(applicant, individual_response)