diff --git a/.gitignore b/.gitignore index 7208598a..5800920d 100644 --- a/.gitignore +++ b/.gitignore @@ -52,7 +52,7 @@ coverage event_source.* -.vscode +# .vscode # Make sure no PII is accidently commited # add w/ git add --force if actually docs diff --git a/app/event_source/subscribers/mec_check_subscriber.rb b/app/event_source/subscribers/mec_check_subscriber.rb index 9f1c54e2..ce3fd7c0 100644 --- a/app/event_source/subscribers/mec_check_subscriber.rb +++ b/app/event_source/subscribers/mec_check_subscriber.rb @@ -5,8 +5,13 @@ module Subscribers class MecCheckSubscriber include ::EventSource::Subscriber[amqp: 'enroll.iap.mec_check'] - subscribe(:on_enroll_iap_mec_check) do |delivery_info, _metadata, response| - result = Aces::InitiateMecCheck.new.call(response) + subscribe(:on_enroll_iap_mec_check) do |delivery_info, metadata, response| + payload_type = metadata[:headers]["payload_type"] + result = if payload_type == "person" + Aces::InitiateMecCheck.new.call(response) + else + Aces::InitiateMecChecks.new.call(response) + end if result.success? ack(delivery_info.delivery_tag) logger.debug "application_submitted_subscriber_message; acked" diff --git a/app/event_source/subscribers/transfer_subscriber.rb b/app/event_source/subscribers/transfer_subscriber.rb index 11812d4b..80b3553b 100644 --- a/app/event_source/subscribers/transfer_subscriber.rb +++ b/app/event_source/subscribers/transfer_subscriber.rb @@ -43,7 +43,7 @@ class TransferSubscriber Aces::Transfer.new.call( { application_identifier: response.to_s, - family_identifier: result, + family_identifier: result.to_s, service: "subscriber failure", failure: e } diff --git a/app/operations/aces/applicant_mec_check_call.rb b/app/operations/aces/applicant_mec_check_call.rb new file mode 100644 index 00000000..aa571921 --- /dev/null +++ b/app/operations/aces/applicant_mec_check_call.rb @@ -0,0 +1,76 @@ +# frozen_string_literal: true + +require 'dry/monads' +require 'dry/monads/do' +require 'aca_entities/medicaid/mec_check/operations/generate_xml' +require 'aca_entities/operations/encryption/decrypt' + +module Aces + # Check for the existance of an applicant in the Medicare system already, and if so did they have coverage. + class ApplicantMecCheckCall + send(:include, Dry::Monads[:result, :do]) + + # @param [String] hbxid of application + # @return [Dry::Result] + def call(person_payload) + ssn = yield decrypt_ssn(person_payload) + person_hash = yield map_to_person(person_payload, ssn) + xml = yield generate_xml(person_hash) + _validate_xml = yield validate_xml(xml) + built_check = yield build_check_request(xml) + encoded_check = yield encode_check(built_check) + submit_check(encoded_check) + end + + protected + + def decrypt_ssn(payload) + ssn = payload["identifying_information"]["encrypted_ssn"] + AcaEntities::Operations::Encryption::Decrypt.new.call({ value: ssn }) + end + + def map_to_person(payload, ssn) + payload["person"] = {} + payload["person"]["person"] = {} + payload["person"]["person"]["person_demographics"] = {} + payload["person"]["person"]["person_name"] = payload["name"] + payload["person"]["person"]["person_demographics"]["ssn"] = ssn + payload["person"]["person"]["person_demographics"]["dob"] = payload["demographic"]["dob"] + payload["person"]["person"]["person_demographics"]["gender"] = payload["demographic"]["gender"] + Success(payload) + end + + def generate_xml(payload) + transfer_request = ::AcaEntities::Medicaid::MecCheck::Operations::GenerateXml.new.call(payload.to_json) + transfer_request.success? ? transfer_request : Failure("Generate XML failure: #{transfer_request.failure}") + end + + def validate_xml(seralized_xml) + document = Nokogiri::XML(seralized_xml) + xsd_path = File.open(Pathname.pwd.join("spec/test_data/nonesi_mec.xsd")) + schema_location = File.expand_path(xsd_path) + schema = Nokogiri::XML::Schema(File.open(schema_location)) + result = schema.validate(document).each_with_object([]) do |error, collect| + collect << error.message + end + + if result.empty? + Success(true) + else + Failure("validate_xml -> #{result}") + end + end + + def build_check_request(transfer) + Aces::BuildAccountTransferRequest.new.call(transfer) + end + + def encode_check(payload) + Aces::EncodeAccountTransferRequest.new.call(payload) + end + + def submit_check(encoded_check) + Aces::SubmitMecCheckPayload.new.call(encoded_check) + end + end +end \ No newline at end of file diff --git a/app/operations/aces/initiate_mec_check.rb b/app/operations/aces/initiate_mec_check.rb index e7b6ef36..f9458a6e 100644 --- a/app/operations/aces/initiate_mec_check.rb +++ b/app/operations/aces/initiate_mec_check.rb @@ -4,7 +4,7 @@ require 'dry/monads/do' module Aces - # Take a payload and find people. For each person, initiate a MecCheck + # Take a payload and for each person, initiate a MEC Check class InitiateMecCheck send(:include, Dry::Monads[:result, :do]) @@ -12,11 +12,9 @@ class InitiateMecCheck # @return [Dry::Result] def call(payload) return Failure({ error: "MEC Check feature not enabled." }) unless MedicaidGatewayRegistry[:mec_check].enabled? - json = JSON.parse(payload) mec_check = yield create_mec_check(json) - checks = yield get_person_check(mec_check, json) if json["person"] - checks = yield get_people_checks(mec_check, json) if json["people"] + checks = yield get_person_check(mec_check, json) results = yield update_mec_check(mec_check, checks) publish_to_enroll(mec_check, results) @@ -56,27 +54,6 @@ def get_person_check(mec_check, json) Success(results) end - def get_people_checks(mec_check, json) - results = {} - people = json["people"] - people.each do |person| - person_hash = { "person" => {} } - person_hash["person"]["person"] = person - mc_response = mec_check(person_hash) - - if mc_response.failure? - error_result = { - mc_id: mec_check.id, - error: "#{mc_response.failure} on Person: #{person['hbx_id']}" - } - return Failure(error_result) - end - - results[person["hbx_id"]] = mc_response.value! - end - Success(results) - end - def mec_check(person) result = call_mec_check(person) return Failure(result.failure) if result.failure? @@ -84,7 +61,6 @@ def mec_check(person) response = JSON.parse(result.value!.to_json) xml = Nokogiri::XML(response["body"]) response_description = xml.xpath("//xmlns:ResponseDescription", "xmlns" => "http://gov.hhs.cms.hix.dsh.ee.nonesi_mec.ext") - response_description.empty? ? Failure("XML error: ResponseDescription tag missing.") : Success(response_description.text) end @@ -103,7 +79,7 @@ def update_mec_check(mec_check, checks) end def publish_to_enroll(mec_check, payload) - transfer = Aces::InitiateMecCheckToEnroll.new.call(payload.attributes) + transfer = Aces::InitiateMecCheckToEnroll.new.call(payload.attributes, "person") if transfer.success? Success("Transferred MEC Check to Enroll") else diff --git a/app/operations/aces/initiate_mec_check_to_enroll.rb b/app/operations/aces/initiate_mec_check_to_enroll.rb index 224e274d..f2ee4998 100644 --- a/app/operations/aces/initiate_mec_check_to_enroll.rb +++ b/app/operations/aces/initiate_mec_check_to_enroll.rb @@ -12,8 +12,8 @@ class InitiateMecCheckToEnroll # @option opts [Hash] :mec_check # @return [Dry::Monads::Result] - def call(params) - event = yield build_event(params) + def call(params, payload_type) + event = yield build_event(params, payload_type) result = send_to_enroll(event) Success(result) @@ -21,8 +21,8 @@ def call(params) private - def build_event(params) - result = event("events.magi_medicaid.mec_check.mec_checked", attributes: params) + def build_event(params, payload_type) + result = event("events.magi_medicaid.mec_check.mec_checked", attributes: params, headers: { payload_type: payload_type }) logger.info "MedicaidGateway MEC Check Publisher to enroll, event_key: mec_checked, attributes: #{params.to_h}, result: #{result}" logger.info('-' * 100) result diff --git a/app/operations/aces/initiate_mec_checks.rb b/app/operations/aces/initiate_mec_checks.rb new file mode 100644 index 00000000..7b509216 --- /dev/null +++ b/app/operations/aces/initiate_mec_checks.rb @@ -0,0 +1,113 @@ +# frozen_string_literal: true + +require 'dry/monads' +require 'dry/monads/do' +require 'aca_entities/medicaid/mec_check' + +module Aces + # Take an application payload and add mec check results as evidence to applicants + class InitiateMecChecks + send(:include, Dry::Monads[:result, :do]) + + # @param [String] payload received from Enroll + # @return [Dry::Result] + def call(payload) + return Failure({ error: "MEC Check feature not enabled." }) unless MedicaidGatewayRegistry[:mec_check].enabled? + json = JSON.parse(payload) + mec_check = yield create_mec_check(json) + checks = yield get_applicant_checks(mec_check, json) + _results = yield update_mec_check(mec_check, checks) + + publish_to_enroll(mec_check, checks) + end + + protected + + def create_mec_check(json) + application = json["hbx_id"] || "n/a" + family = json["family_reference"]["hbx_id"] || "n/a" + results = Aces::CreateMecCheck.new.call( + { + application_identifier: application, + family_identifier: family, + type: "application" + } + ) + + return results if results.success? + Failure({ error: "Failed to save MEC check: #{results.failure}" }) + end + + def get_applicant_checks(mec_check, json) + results = {} + people = json["applicants"] + people.each do |person| + hbx_id = person["person_hbx_id"] + evidence = person["evidences"].detect { |evi| evi["key"] == "aces_mec" } + if evidence + mc_response = mec_check(person) + if mc_response.failure? + error_result = { + mc_id: mec_check.id, + error: "#{mc_response.failure} on Person}" + } + return Failure(error_result) + end + response = mc_response.value! + results[hbx_id] = response[:code_description] + evidence["eligibility_results"] = [response] + evidence["eligibility_status"] = response[:mec_verification_code] == "Y" ? :outstanding : :attested + else + results[hbx_id] = "not MEC checked" + end + end + Success([json, results]) + rescue StandardError => e + Failure("Mec check failure => #{e}") + end + + def mec_check(person) + result = call_mec_check(person) + return Failure(result.failure) if result.failure? + response = JSON.parse(result.value!.to_json) + serialize_response(response["body"]) + end + + def serialize_response(response) + xml = Nokogiri::XML(response) + body = xml.at_xpath("//xml_ns:VerifyNonESIMECResponse", "xml_ns" => "http://gov.hhs.cms.hix.dsh.ee.nonesi_mec.ext") + Success(AcaEntities::Medicaid::MecCheck::Operations::GenerateResult.new.call(body.to_xml)) + rescue StandardError => e + p e.backtrace + Failure("Serializing response error => #{e}") + end + + def call_mec_check(person) + Aces::ApplicantMecCheckCall.new.call(person) + end + + def update_mec_check(mec_check, checks) + return Success(mec_check) if mec_check.update(applicant_responses: checks[1]) + + error_result = { + mc_id: mec_check.id, + error: "Failed to save MEC check response: #{mec_check.errors.to_h}" + } + Failure(error_result) + end + + def publish_to_enroll(mec_check, results) + payload = results[0] + transfer = Aces::InitiateMecCheckToEnroll.new.call(payload, "application") + if transfer.success? + Success("Transferred MEC Check to Enroll") + else + error_result = { + mc_id: mec_check.id, + error: "Failed to transfer MEC to enroll: #{transfer.failure}" + } + Failure(error_result) + end + end + end +end \ No newline at end of file diff --git a/app/operations/aces/mec_check_call.rb b/app/operations/aces/mec_check_call.rb index 58fca706..6c47fcba 100644 --- a/app/operations/aces/mec_check_call.rb +++ b/app/operations/aces/mec_check_call.rb @@ -3,6 +3,7 @@ require 'dry/monads' require 'dry/monads/do' require 'aca_entities/medicaid/mec_check/operations/generate_xml' +require 'aca_entities/operations/encryption/decrypt' module Aces # Check for the existance of a person in the Medicare system already, and if so did they have coverage. @@ -12,7 +13,8 @@ class MecCheckCall # @param [String] hbxid of application # @return [Dry::Result] def call(person_payload) - xml = yield generate_xml(person_payload) + ssn = yield decrypt_ssn(person_payload) + xml = yield generate_xml(person_payload, ssn) _validate_xml = yield validate_xml(xml) built_check = yield build_check_request(xml) encoded_check = yield encode_check(built_check) @@ -21,7 +23,13 @@ def call(person_payload) protected - def generate_xml(payload) + def decrypt_ssn(payload) + ssn = payload["person"][:person]["person_demographics"]["encrypted_ssn"] + AcaEntities::Operations::Encryption::Decrypt.new.call({ value: ssn }) + end + + def generate_xml(payload, ssn) + payload["person"][:person]["person_demographics"]["ssn"] = ssn transfer_request = ::AcaEntities::Medicaid::MecCheck::Operations::GenerateXml.new.call(payload.to_json) transfer_request.success? ? transfer_request : Failure("Generate XML failure: #{transfer_request.failure}") end diff --git a/app/operations/transfers/to_service.rb b/app/operations/transfers/to_service.rb index a50734ec..435b6d30 100644 --- a/app/operations/transfers/to_service.rb +++ b/app/operations/transfers/to_service.rb @@ -73,7 +73,7 @@ def initiate_transfer(payload, transfer_id) end if result.success? - update_transfer(transfer_id, result.value!) + update_transfer(transfer_id, result.value!, payload) Success("Successfully transferred in account") else error_result = { @@ -84,16 +84,16 @@ def initiate_transfer(payload, transfer_id) end end - def update_transfer(transfer_id, response) + def update_transfer(transfer_id, response, payload) transfer = Aces::Transfer.find(transfer_id) response_json = response.to_json if @service == "aces" xml = Nokogiri::XML(response.to_hash[:body]) status = xml.xpath('//tns:ResponseDescriptionText', 'tns' => 'http://hix.cms.gov/0.1/hix-core') status_text = status.any? ? status.last.text : "N/A" - transfer.update!(response_payload: response_json, callback_status: status_text) + transfer.update!(response_payload: response_json, callback_status: status_text, payload: payload) else - transfer.update!(response_payload: response_json) + transfer.update!(response_payload: response_json, payload: payload) end end diff --git a/config/initializers/aca_entities.rb b/config/initializers/aca_entities.rb new file mode 100644 index 00000000..6f2c8023 --- /dev/null +++ b/config/initializers/aca_entities.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +AcaEntities::Configuration::Encryption.configure do |config| + config.secret_key = ENV['RBNACL_SECRET_KEY'] || "C639A572E14D5075C526FDDD43E4ECF6B095EA17783D32EF3D2710AF9F359DD4" + config.iv = ENV['RBNACL_IV'] || "1234567890ABCDEFGHIJKLMN" +end \ No newline at end of file diff --git a/spec/domain/operations/aces/initiate_mec_check_spec.rb b/spec/domain/operations/aces/initiate_mec_check_spec.rb index 0c237c0a..7a06abd9 100644 --- a/spec/domain/operations/aces/initiate_mec_check_spec.rb +++ b/spec/domain/operations/aces/initiate_mec_check_spec.rb @@ -2,7 +2,7 @@ require "rails_helper" -describe Aces::InitiateMecCheck, "given a person payload", dbclean: :after_each do +describe Aces::InitiateMecCheck, dbclean: :after_each do before :all do DatabaseCleaner.clean end @@ -10,6 +10,7 @@ include Dry::Monads[:result, :do] let(:payload) {File.read("./spec/test_data/person.json")} + let(:family_id) { JSON.parse(payload)["family_id"] } let(:operation) { Aces::InitiateMecCheck.new } let(:response_body) do @@ -27,6 +28,7 @@ " end + let(:response) do { :status => 200, @@ -34,9 +36,14 @@ :response_headers => {} } end + let(:event) { Success(response) } - let(:expected_response) { { "d81d92cf869540ed804b21d7b22352c6" => "Applicant Not Found" } } + let(:expected_response) do + person_id = JSON.parse(payload)["person"]["hbx_id"] + { person_id => "Applicant Not Found" } + end + let(:feature_ns) { double } let(:setting) { double(item: "SOME URI") } @@ -61,7 +68,7 @@ end it "there should be a mec check with the family id" do mec_check = Aces::MecCheck.first - expect(mec_check.family_identifier).to eq "10450" + expect(mec_check.family_identifier).to eq family_id end it "the mec check should have the correct applicant_responses value" do @@ -70,69 +77,3 @@ end end end - -describe Aces::InitiateMecCheck, "given an application payload", dbclean: :after_each do - before :all do - DatabaseCleaner.clean - end - - include Dry::Monads[:result, :do] - - let(:payload) {File.read("./spec/test_data/application_payload.json")} - let(:operation) { Aces::InitiateMecCheck.new } - - let(:response_body) do - " - - 7313 - Applicant Not Found - - 214344538 - - N - - CHIP - - - " - end - let(:response) do - { - :status => 200, - :body => response_body, - :response_headers => {} - } - end - let(:event) { Success(response) } - - let(:expected_response) { { "1003158" => "Applicant Not Found", "1002699" => "Applicant Not Found" } } - let(:feature_ns) { double } - let(:setting) { double(item: "SOME URI") } - - before :each do - allow(MedicaidGatewayRegistry).to receive(:[]).with(:aces_connection).and_return(feature_ns) - allow(MedicaidGatewayRegistry).to receive(:[]).with(:mec_check).and_return(feature_ns) - allow(feature_ns).to receive(:setting).with(:aces_atp_service_uri).and_return(setting) - allow(feature_ns).to receive(:setting).with(:aces_atp_service_username).and_return(setting) - allow(feature_ns).to receive(:setting).with(:aces_atp_service_password).and_return(setting) - allow(feature_ns).to receive(:enabled?).and_return(true) - allow(operation).to receive(:call_mec_check).and_return(event) - operation.call(payload) - end - - it "there should be a mec check with the application id from the payload" do - mec_check = Aces::MecCheck.first - expect(mec_check.application_identifier).to eq "1000886" - end - - it "there should be a mec check with the family id" do - mec_check = Aces::MecCheck.first - expect(mec_check.family_identifier).to eq "10449" - end - - it "the mec check should have the correct applicant_responses value" do - mec_check = Aces::MecCheck.first - expect(mec_check.applicant_responses).to eq expected_response - end - -end diff --git a/spec/domain/operations/aces/initiate_mec_checks_spec.rb b/spec/domain/operations/aces/initiate_mec_checks_spec.rb new file mode 100644 index 00000000..257f7bf8 --- /dev/null +++ b/spec/domain/operations/aces/initiate_mec_checks_spec.rb @@ -0,0 +1,77 @@ +# frozen_string_literal: true + +require "rails_helper" + +describe Aces::InitiateMecChecks, dbclean: :after_each do + before :all do + DatabaseCleaner.clean + end + + include Dry::Monads[:result, :do] + + let(:payload) {File.read("./spec/test_data/application_payload.json")} + let(:family_id) { JSON.parse(payload)["family_reference"]["hbx_id"] } + let(:application_id) { JSON.parse(payload)["hbx_id"] } + let(:operation) { Aces::InitiateMecChecks.new } + + let(:response_body) do + " + + 7313 + Applicant Not Found + + 214344538 + + N + + CHIP + + + " + end + + let(:response) do + { + :status => 200, + :body => response_body, + :response_headers => {} + } + end + + let(:event) { Success(response) } + + let(:expected_response) do + JSON.parse(payload)["applicants"].map do |a| + [a["person_hbx_id"], a["evidences"].empty? ? "not MEC checked" : "Applicant Not Found"] + end.to_h + end + + let(:feature_ns) { double } + let(:setting) { double(item: "SOME URI") } + + before :each do + allow(MedicaidGatewayRegistry).to receive(:[]).with(:aces_connection).and_return(feature_ns) + allow(MedicaidGatewayRegistry).to receive(:[]).with(:mec_check).and_return(feature_ns) + allow(feature_ns).to receive(:setting).with(:aces_atp_service_uri).and_return(setting) + allow(feature_ns).to receive(:setting).with(:aces_atp_service_username).and_return(setting) + allow(feature_ns).to receive(:setting).with(:aces_atp_service_password).and_return(setting) + allow(feature_ns).to receive(:enabled?).and_return(true) + allow(operation).to receive(:call_mec_check).and_return(event) + operation.call(payload) + end + + it "there should be a mec check with the application id from the payload" do + mec_check = Aces::MecCheck.first + expect(mec_check.application_identifier).to eq application_id + end + + it "there should be a mec check with the family id" do + mec_check = Aces::MecCheck.first + expect(mec_check.family_identifier).to eq family_id + end + + it "the mec check should have the correct applicant_responses value" do + mec_check = Aces::MecCheck.first + expect(mec_check.applicant_responses).to eq expected_response + end +end diff --git a/spec/test_data/application_payload.json b/spec/test_data/application_payload.json index 561c1c93..94a19d83 100644 --- a/spec/test_data/application_payload.json +++ b/spec/test_data/application_payload.json @@ -1,206 +1,702 @@ { - "application": "1000886", - "family_id": "10449", - "people": [ - { - "hbx_id": "1003158", - "person_name": { - "first_name": "asdf", - "middle_name": null, - "last_name": "asdf", - "name_sfx": null, - "name_pfx": null, - "full_name": "asdf asdf", - "alternate_name": null - }, - "person_demographics": { - "ssn": "908923122", - "no_ssn": false, - "gender": "male", - "dob": "1975-04-05", - "date_of_death": null, - "dob_check": false, - "is_incarcerated": false, - "ethnicity": ["", "", "", "", "", "", ""], - "race": null, - "tribal_id": null, - "language_code": "en" - }, - "person_health": { - "is_tobacco_user": "unknown", - "is_physically_disabled": null - }, - "no_dc_address": false, - "no_dc_address_reason": "", - "is_homeless": false, - "is_temporarily_out_of_state": false, - "age_off_excluded": false, - "is_applying_for_assistance": null, - "is_active": true, - "is_disabled": null, - "person_relationships": [], - "consumer_role": { - "five_year_bar": false, - "requested_coverage_start_date": "2021-09-24", - "aasm_state": "unverified", - "is_applicant": true, - "birth_location": null, - "marital_status": null, - "is_active": true, - "is_applying_coverage": true, - "bookmark_url": "http://localhost:3000/financial_assistance/applications/614e279fa54d752853ae3dd1/edit", - "admin_bookmark_url": null, - "contact_method": "mail", - "language_preference": "English", - "is_state_resident": null, - "identity_validation": "valid", - "identity_update_reason": "Verified from Experian", - "application_validation": "valid", - "application_update_reason": "Verified from Experian", - "identity_rejected": false, - "application_rejected": false, - "documents": [], - "vlp_documents": [], - "ridp_documents": [], - "verification_type_history_elements": [], - "lawful_presence_determination": { - "vlp_verified_at": null, - "vlp_authority": null, - "vlp_document_id": null, - "citizen_status": "us_citizen", - "citizenship_result": null, - "qualified_non_citizenship_result": null, - "aasm_state": "verification_pending", - "ssa_responses": [], - "ssa_requests": [], - "vlp_responses": [], - "vlp_requests": [] - }, - "local_residency_responses": [], - "local_residency_requests": [] - }, - "resident_role": null, - "broker_role": null, - "individual_market_transitions": [ - { - "role_type": "consumer", - "start_on": "2021-09-24", - "end_on": null, - "reason_code": "generating_consumer_role", - "submitted_at": "2021-09-24T19:06:43.000+00:00" - } - ], - "verification_types": [ + "family_reference": { + "hbx_id": "10449" + }, + "assistance_year": 2021, + "aptc_effective_date": "2021-01-08", + "years_to_renew": null, + "renewal_consent_through_year": 5, + "is_ridp_verified": true, + "is_renewal_authorized": true, + "applicants": [ { - "type_name": "Social Security Number", - "validation_status": "unverified", - "applied_roles": ["consumer_role"], - "update_reason": null, - "rejected": null, - "external_service": null, - "due_date": null, - "due_date_type": null, - "inactive": null, - "vlp_documents": [] + "name": { + "first_name": "betty", + "middle_name": null, + "last_name": "curtis", + "name_sfx": null, + "name_pfx": null + }, + "identifying_information": { + "encrypted_ssn": "stgXNlY2ksCXbGsvz4tst4kEu/sFLMlIlA==\n", + "has_ssn": false + }, + "demographic": { + "gender": "Female", + "dob": "1990-01-01", + "ethnicity": [ + "", + "", + "", + "", + "", + "", + "" + ], + "race": null, + "is_veteran_or_active_military": false, + "is_vets_spouse_or_child": false + }, + "attestation": { + "is_incarcerated": false, + "is_self_attested_disabled": false, + "is_self_attested_blind": false, + "is_self_attested_long_term_care": false + }, + "is_primary_applicant": true, + "native_american_information": { + "indian_tribe_member": false, + "tribal_name": null, + "tribal_state": null + }, + "citizenship_immigration_status_information": { + "citizen_status": "us_citizen", + "is_resident_post_092296": false, + "is_lawful_presence_self_attested": false + }, + "is_consumer_role": true, + "is_resident_role": false, + "is_applying_coverage": true, + "is_consent_applicant": false, + "vlp_document": null, + "family_member_reference": { + "family_member_hbx_id": "1624289008997662", + "first_name": "betty", + "last_name": "curtis", + "person_hbx_id": "1624289008997662", + "is_primary_family_member": true + }, + "person_hbx_id": "1624289008997662", + "is_required_to_file_taxes": true, + "is_filing_as_head_of_household": false, + "tax_filer_kind": "tax_filer", + "is_joint_tax_filing": false, + "is_claimed_as_tax_dependent": false, + "claimed_as_tax_dependent_by": null, + "student": { + "is_student": false, + "student_kind": null, + "student_school_kind": null, + "student_status_end_on": null + }, + "is_refugee": false, + "is_trafficking_victim": false, + "foster_care": { + "is_former_foster_care": false, + "age_left_foster_care": null, + "foster_care_us_state": null, + "had_medicaid_during_foster_care": false + }, + "pregnancy_information": { + "is_pregnant": false, + "is_enrolled_on_medicaid": false, + "is_post_partum_period": false, + "expected_children_count": null, + "pregnancy_due_on": null, + "pregnancy_end_on": null + }, + "is_subject_to_five_year_bar": false, + "is_five_year_bar_met": false, + "is_forty_quarters": false, + "is_ssn_applied": false, + "non_ssn_apply_reason": null, + "moved_on_or_after_welfare_reformed_law": false, + "is_currently_enrolled_in_health_plan": false, + "has_daily_living_help": false, + "need_help_paying_bills": false, + "has_job_income": false, + "has_self_employment_income": false, + "has_unemployment_income": false, + "has_other_income": false, + "has_deductions": false, + "has_enrolled_health_coverage": true, + "has_eligible_health_coverage": false, + "job_coverage_ended_in_past_3_months": false, + "job_coverage_end_date": null, + "medicaid_and_chip": { + "not_eligible_in_last_90_days": false, + "denied_on": null, + "ended_as_change_in_eligibility": false, + "hh_income_or_size_changed": false, + "medicaid_or_chip_coverage_end_date": null, + "ineligible_due_to_immigration_in_last_5_years": false, + "immigration_status_changed_since_ineligibility": false + }, + "other_health_service": { + "has_received": false, + "is_eligible": false + }, + "addresses": [ + { + "kind": "home", + "address_1": "123", + "address_2": null, + "address_3": null, + "city": "was", + "county": null, + "state": "DC", + "zip": "98272", + "country_name": null + } + ], + "emails": [], + "phones": [], + "incomes": [], + "benefits": [ + { + "name": null, + "kind": "employer_sponsored_insurance", + "status": "is_enrolled", + "is_employer_sponsored": false, + "employer": { + "employer_name": "er1", + "employer_id": "12-2132133" + }, + "esi_covered": "self", + "is_esi_waiting_period": false, + "is_esi_mec_met": true, + "employee_cost": "0.0", + "employee_cost_frequency": "Monthly", + "start_on": "2020-11-01", + "end_on": null, + "submitted_at": "2021-06-21T00:00:00.000+00:00", + "hra_kind": null + } + ], + "deductions": [], + "is_medicare_eligible": false, + "has_insurance": true, + "has_state_health_benefit": false, + "had_prior_insurance": false, + "prior_insurance_end_date": null, + "age_of_applicant": 23, + "is_self_attested_long_term_care": false, + "hours_worked_per_week": 0, + "is_temporarily_out_of_state": false, + "is_claimed_as_dependent_by_non_applicant": false, + "benchmark_premium": { + "health_only_lcsp_premiums": [ + { + "member_identifier": "1624289008997662", + "monthly_premium": "243.94" + } + ], + "health_only_slcsp_premiums": [ + { + "member_identifier": "1624289008997662", + "monthly_premium": "236.5" + } + ] + }, + "is_homeless": false, + "mitc_income": { + "amount": 0, + "taxable_interest": 0, + "tax_exempt_interest": 0, + "taxable_refunds": 0, + "alimony": 0, + "capital_gain_or_loss": 0, + "pensions_and_annuities_taxable_amount": 0, + "farm_income_or_loss": 0, + "unemployment_compensation": 0, + "other_income": 0, + "magi_deductions": 0, + "adjusted_gross_income": 0, + "deductible_part_of_self_employment_tax": 0, + "ira_deduction": 0, + "student_loan_interest_deduction": 0, + "tution_and_fees": 0, + "other_magi_eligible_income": 0 + }, + "mitc_relationships": [], + "mitc_is_required_to_file_taxes": true, + "evidences": [ + { + "key": "aces_mec", + "title": "ACES MEC", + "description": null, + "eligibility_status": "attested", + "due_on": null, + "updated_by": null, + "eligibility_results": [] + } + ] }, { - "type_name": "Citizenship", - "validation_status": "unverified", - "applied_roles": ["consumer_role"], - "update_reason": null, - "rejected": null, - "external_service": null, - "due_date": null, - "due_date_type": null, - "inactive": null, - "vlp_documents": [] + "name": { + "first_name": "betty", + "middle_name": null, + "last_name": "jackson", + "name_sfx": null, + "name_pfx": null + }, + "identifying_information": { + "encrypted_ssn": "stgXNlY2ksCXbGsvz4tst4kEu/sFLMlIlA==\n", + "has_ssn": false + }, + "demographic": { + "gender": "Female", + "dob": "1990-01-01", + "ethnicity": [ + "", + "", + "", + "", + "", + "", + "" + ], + "race": null, + "is_veteran_or_active_military": false, + "is_vets_spouse_or_child": false + }, + "attestation": { + "is_incarcerated": false, + "is_self_attested_disabled": false, + "is_self_attested_blind": false, + "is_self_attested_long_term_care": false + }, + "is_primary_applicant": true, + "native_american_information": { + "indian_tribe_member": false, + "tribal_name": null, + "tribal_state": null + }, + "citizenship_immigration_status_information": { + "citizen_status": "us_citizen", + "is_resident_post_092296": false, + "is_lawful_presence_self_attested": false + }, + "is_consumer_role": true, + "is_resident_role": false, + "is_applying_coverage": true, + "is_consent_applicant": false, + "vlp_document": null, + "family_member_reference": { + "family_member_hbx_id": "1624289008997662", + "first_name": "betty", + "last_name": "curtis", + "person_hbx_id": "1624289008997662", + "is_primary_family_member": true + }, + "person_hbx_id": "1624289008997663", + "is_required_to_file_taxes": true, + "is_filing_as_head_of_household": false, + "tax_filer_kind": "tax_filer", + "is_joint_tax_filing": false, + "is_claimed_as_tax_dependent": false, + "claimed_as_tax_dependent_by": null, + "student": { + "is_student": false, + "student_kind": null, + "student_school_kind": null, + "student_status_end_on": null + }, + "is_refugee": false, + "is_trafficking_victim": false, + "foster_care": { + "is_former_foster_care": false, + "age_left_foster_care": null, + "foster_care_us_state": null, + "had_medicaid_during_foster_care": false + }, + "pregnancy_information": { + "is_pregnant": false, + "is_enrolled_on_medicaid": false, + "is_post_partum_period": false, + "expected_children_count": null, + "pregnancy_due_on": null, + "pregnancy_end_on": null + }, + "is_subject_to_five_year_bar": false, + "is_five_year_bar_met": false, + "is_forty_quarters": false, + "is_ssn_applied": false, + "non_ssn_apply_reason": null, + "moved_on_or_after_welfare_reformed_law": false, + "is_currently_enrolled_in_health_plan": false, + "has_daily_living_help": false, + "need_help_paying_bills": false, + "has_job_income": false, + "has_self_employment_income": false, + "has_unemployment_income": false, + "has_other_income": false, + "has_deductions": false, + "has_enrolled_health_coverage": true, + "has_eligible_health_coverage": false, + "job_coverage_ended_in_past_3_months": false, + "job_coverage_end_date": null, + "medicaid_and_chip": { + "not_eligible_in_last_90_days": false, + "denied_on": null, + "ended_as_change_in_eligibility": false, + "hh_income_or_size_changed": false, + "medicaid_or_chip_coverage_end_date": null, + "ineligible_due_to_immigration_in_last_5_years": false, + "immigration_status_changed_since_ineligibility": false + }, + "other_health_service": { + "has_received": false, + "is_eligible": false + }, + "addresses": [ + { + "kind": "home", + "address_1": "123", + "address_2": null, + "address_3": null, + "city": "was", + "county": null, + "state": "DC", + "zip": "98272", + "country_name": null + } + ], + "emails": [], + "phones": [], + "incomes": [], + "benefits": [ + { + "name": null, + "kind": "employer_sponsored_insurance", + "status": "is_enrolled", + "is_employer_sponsored": false, + "employer": { + "employer_name": "er1", + "employer_id": "12-2132133" + }, + "esi_covered": "self", + "is_esi_waiting_period": false, + "is_esi_mec_met": true, + "employee_cost": "0.0", + "employee_cost_frequency": "Monthly", + "start_on": "2020-11-01", + "end_on": null, + "submitted_at": "2021-06-21T00:00:00.000+00:00", + "hra_kind": null + } + ], + "deductions": [], + "is_medicare_eligible": false, + "has_insurance": true, + "has_state_health_benefit": false, + "had_prior_insurance": false, + "prior_insurance_end_date": null, + "age_of_applicant": 23, + "is_self_attested_long_term_care": false, + "hours_worked_per_week": 0, + "is_temporarily_out_of_state": false, + "is_claimed_as_dependent_by_non_applicant": false, + "benchmark_premium": { + "health_only_lcsp_premiums": [ + { + "member_identifier": "1624289008997662", + "monthly_premium": "243.94" + } + ], + "health_only_slcsp_premiums": [ + { + "member_identifier": "1624289008997662", + "monthly_premium": "236.5" + } + ] + }, + "is_homeless": false, + "mitc_income": { + "amount": 0, + "taxable_interest": 0, + "tax_exempt_interest": 0, + "taxable_refunds": 0, + "alimony": 0, + "capital_gain_or_loss": 0, + "pensions_and_annuities_taxable_amount": 0, + "farm_income_or_loss": 0, + "unemployment_compensation": 0, + "other_income": 0, + "magi_deductions": 0, + "adjusted_gross_income": 0, + "deductible_part_of_self_employment_tax": 0, + "ira_deduction": 0, + "student_loan_interest_deduction": 0, + "tution_and_fees": 0, + "other_magi_eligible_income": 0 + }, + "mitc_relationships": [], + "mitc_is_required_to_file_taxes": true, + "evidences": [ + { + "key": "aces_mec", + "title": "ACES MEC", + "description": null, + "eligibility_status": "attested", + "due_on": null, + "updated_by": null, + "eligibility_results": [] + } + ] }, { - "type_name": "Income", - "validation_status": "unverified", - "applied_roles": ["consumer_role"], - "update_reason": null, - "rejected": null, - "external_service": null, - "due_date": null, - "due_date_type": null, - "inactive": true, - "vlp_documents": [] - } - ], - "user": { - "approved": true, - "email": "new@newaccount.com", - "oim_id": "new@newaccount.com", - "hint": true, - "identity_confirmed_token": null, - "identity_final_decision_code": "acc", - "identity_final_decision_transaction_id": "WhateverRefNumberHere", - "identity_response_code": "acc", - "identity_response_description_text": "FARS passed.", - "identity_verified_date": "2021-09-24", - "idp_uuid": null, - "idp_verified": true, - "last_portal_visited": "/insured/consumer_role/search", - "preferred_language": "en", - "profile_type": null, - "roles": ["consumer"], - "timestamps": { - "created_at": "2021-09-24T19:06:26.702+00:00", - "modified_at": "2021-09-24T19:07:33.560+00:00" + "name": { + "first_name": "betty", + "middle_name": null, + "last_name": "wydown", + "name_sfx": null, + "name_pfx": null + }, + "identifying_information": { + "encrypted_ssn": "stgXNlY2ksCXbGsvz4tst4kEu/sFLMlIlA==\n", + "has_ssn": false + }, + "demographic": { + "gender": "Female", + "dob": "1990-01-01", + "ethnicity": [ + "", + "", + "", + "", + "", + "", + "" + ], + "race": null, + "is_veteran_or_active_military": false, + "is_vets_spouse_or_child": false + }, + "attestation": { + "is_incarcerated": false, + "is_self_attested_disabled": false, + "is_self_attested_blind": false, + "is_self_attested_long_term_care": false + }, + "is_primary_applicant": true, + "native_american_information": { + "indian_tribe_member": false, + "tribal_name": null, + "tribal_state": null + }, + "citizenship_immigration_status_information": { + "citizen_status": "us_citizen", + "is_resident_post_092296": false, + "is_lawful_presence_self_attested": false + }, + "is_consumer_role": true, + "is_resident_role": false, + "is_applying_coverage": true, + "is_consent_applicant": false, + "vlp_document": null, + "family_member_reference": { + "family_member_hbx_id": "1624289008997662", + "first_name": "betty", + "last_name": "curtis", + "person_hbx_id": "1624289008997662", + "is_primary_family_member": true + }, + "person_hbx_id": "1624289008997664", + "is_required_to_file_taxes": true, + "is_filing_as_head_of_household": false, + "tax_filer_kind": "tax_filer", + "is_joint_tax_filing": false, + "is_claimed_as_tax_dependent": false, + "claimed_as_tax_dependent_by": null, + "student": { + "is_student": false, + "student_kind": null, + "student_school_kind": null, + "student_status_end_on": null + }, + "is_refugee": false, + "is_trafficking_victim": false, + "foster_care": { + "is_former_foster_care": false, + "age_left_foster_care": null, + "foster_care_us_state": null, + "had_medicaid_during_foster_care": false + }, + "pregnancy_information": { + "is_pregnant": false, + "is_enrolled_on_medicaid": false, + "is_post_partum_period": false, + "expected_children_count": null, + "pregnancy_due_on": null, + "pregnancy_end_on": null + }, + "is_subject_to_five_year_bar": false, + "is_five_year_bar_met": false, + "is_forty_quarters": false, + "is_ssn_applied": false, + "non_ssn_apply_reason": null, + "moved_on_or_after_welfare_reformed_law": false, + "is_currently_enrolled_in_health_plan": false, + "has_daily_living_help": false, + "need_help_paying_bills": false, + "has_job_income": false, + "has_self_employment_income": false, + "has_unemployment_income": false, + "has_other_income": false, + "has_deductions": false, + "has_enrolled_health_coverage": true, + "has_eligible_health_coverage": false, + "job_coverage_ended_in_past_3_months": false, + "job_coverage_end_date": null, + "medicaid_and_chip": { + "not_eligible_in_last_90_days": false, + "denied_on": null, + "ended_as_change_in_eligibility": false, + "hh_income_or_size_changed": false, + "medicaid_or_chip_coverage_end_date": null, + "ineligible_due_to_immigration_in_last_5_years": false, + "immigration_status_changed_since_ineligibility": false + }, + "other_health_service": { + "has_received": false, + "is_eligible": false + }, + "addresses": [ + { + "kind": "home", + "address_1": "123", + "address_2": null, + "address_3": null, + "city": "was", + "county": null, + "state": "DC", + "zip": "98272", + "country_name": null + } + ], + "emails": [], + "phones": [], + "incomes": [], + "benefits": [ + { + "name": null, + "kind": "employer_sponsored_insurance", + "status": "is_enrolled", + "is_employer_sponsored": false, + "employer": { + "employer_name": "er1", + "employer_id": "12-2132133" + }, + "esi_covered": "self", + "is_esi_waiting_period": false, + "is_esi_mec_met": true, + "employee_cost": "0.0", + "employee_cost_frequency": "Monthly", + "start_on": "2020-11-01", + "end_on": null, + "submitted_at": "2021-06-21T00:00:00.000+00:00", + "hra_kind": null + } + ], + "deductions": [], + "is_medicare_eligible": false, + "has_insurance": true, + "has_state_health_benefit": false, + "had_prior_insurance": false, + "prior_insurance_end_date": null, + "age_of_applicant": 23, + "is_self_attested_long_term_care": false, + "hours_worked_per_week": 0, + "is_temporarily_out_of_state": false, + "is_claimed_as_dependent_by_non_applicant": false, + "benchmark_premium": { + "health_only_lcsp_premiums": [ + { + "member_identifier": "1624289008997662", + "monthly_premium": "243.94" + } + ], + "health_only_slcsp_premiums": [ + { + "member_identifier": "1624289008997662", + "monthly_premium": "236.5" + } + ] + }, + "is_homeless": false, + "mitc_income": { + "amount": 0, + "taxable_interest": 0, + "tax_exempt_interest": 0, + "taxable_refunds": 0, + "alimony": 0, + "capital_gain_or_loss": 0, + "pensions_and_annuities_taxable_amount": 0, + "farm_income_or_loss": 0, + "unemployment_compensation": 0, + "other_income": 0, + "magi_deductions": 0, + "adjusted_gross_income": 0, + "deductible_part_of_self_employment_tax": 0, + "ira_deduction": 0, + "student_loan_interest_deduction": 0, + "tution_and_fees": 0, + "other_magi_eligible_income": 0 + }, + "mitc_relationships": [], + "mitc_is_required_to_file_taxes": true, + "evidences": [] } - }, - "addresses": [ + ], + "tax_households": [ { - "kind": "home", - "address_1": "123 fake", - "address_2": "", - "address_3": "", - "city": "city", - "county": "York", - "state": "ME", - "zip": "04005", - "country_name": "United States of America", - "has_fixed_address": true + "max_aptc": "0.0", + "hbx_id": "10069", + "is_insurance_assistance_eligible": "Yes", + "tax_household_members": [ + { + "product_eligibility_determination": { + "is_ia_eligible": false, + "is_medicaid_chip_eligible": true, + "is_totally_ineligible": false, + "is_magi_medicaid": false, + "is_non_magi_medicaid_eligible": false, + "is_without_assistance": null, + "magi_medicaid_monthly_household_income": "0.0", + "medicaid_household_size": 1, + "magi_medicaid_monthly_income_limit": "0.0", + "magi_as_percentage_of_fpl": "0.0", + "magi_medicaid_category": "adult_group" + }, + "applicant_reference": { + "first_name": "betty", + "last_name": "curtis", + "dob": "19909-01-01", + "person_hbx_id": "1624289008997662", + "encrypted_ssn": "stgXNlY2ksCXbGsvz4tst4kEu/sFLMlIlA==\n" + } + } + ], + "annual_tax_household_income": "0.0" } - ], - "emails": [{ "kind": "home", "address": "new@newaccount.com" }], - "phones": [], - "documents": [], - "timestamp": { - "created_at": "2021-09-24T19:06:43.176+00:00", - "modified_at": "2021-09-24T19:07:33.634+00:00" - } + ], + "relationships": [], + "us_state": "DC", + "hbx_id": "1000886", + "oe_start_on": "2020-11-01", + "notice_options": { + "send_eligibility_notices": true, + "send_open_enrollment_notices": false }, - { - "hbx_id": "1002699", - "person_name": { - "first_name": "test", - "middle_name": null, - "last_name": "asdf", - "name_sfx": null, - "name_pfx": null, - "full_name": "test", - "alternate_name": null - }, - "person_demographics": { - "ssn": "908923111", - "no_ssn": false, - "gender": "male", - "dob": "1975-04-05", - "date_of_death": null, - "dob_check": false, - "is_incarcerated": false, - "ethnicity": ["", "", "", "", "", "", ""], - "race": null, - "tribal_id": null, - "language_code": "en" - }, - "person_health": { - "is_tobacco_user": "unknown", - "is_physically_disabled": null - } - } - ], - "type": "application" -} + "mitc_households": [ + { + "household_id": "1", + "people": [ + { + "person_id": 1624289008997662 + } + ] + } + ], + "mitc_tax_returns": [ + { + "filers": [ + { + "person_id": 1624289008997662 + } + ], + "dependents": [] + } + ] +} \ No newline at end of file diff --git a/spec/test_data/person.json b/spec/test_data/person.json index eda53f58..977da074 100644 --- a/spec/test_data/person.json +++ b/spec/test_data/person.json @@ -19,7 +19,15 @@ "date_of_death": null, "dob_check": false, "is_incarcerated": false, - "ethnicity": ["", "", "", "", "", "", ""], + "ethnicity": [ + "", + "", + "", + "", + "", + "", + "" + ], "race": null, "tribal_id": null, "language_code": "en" @@ -92,7 +100,9 @@ { "type_name": "Social Security Number", "validation_status": "unverified", - "applied_roles": ["consumer_role"], + "applied_roles": [ + "consumer_role" + ], "update_reason": null, "rejected": null, "external_service": null, @@ -104,7 +114,9 @@ { "type_name": "Citizenship", "validation_status": "unverified", - "applied_roles": ["consumer_role"], + "applied_roles": [ + "consumer_role" + ], "update_reason": null, "rejected": null, "external_service": null, @@ -130,7 +142,9 @@ "last_portal_visited": "/insured/consumer_role/search", "preferred_language": "en", "profile_type": null, - "roles": ["consumer"], + "roles": [ + "consumer" + ], "timestamps": { "created_at": "2021-09-20T15:14:40.269+00:00", "modified_at": "2021-09-20T15:16:05.006+00:00" @@ -150,7 +164,12 @@ "has_fixed_address": true } ], - "emails": [{ "kind": "home", "address": "newtest@fake.com" }], + "emails": [ + { + "kind": "home", + "address": "newtest@fake.com" + } + ], "phones": [], "documents": [], "timestamp": { @@ -159,4 +178,4 @@ } }, "type": "person" -} +} \ No newline at end of file