Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mec check 21.10.11 #35

Merged
merged 12 commits into from
Oct 5, 2021
10 changes: 8 additions & 2 deletions DEPLOY.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
# Environment Variables

The following environment variables must be set for the application to work:
1. `ACES_ATP_SERVICE_URI` - the uri of the endpoint to which medicaid_gateway will submit ATP requests, should be something like: `https://portal.maine.gov:443/ACA/AccountTransferService`

1. `ACES_ATP_SERVICE_URI` - the uri of the endpoint to which medicaid_gateway will submit ATP requests to ACES, should be something like: `https://portal.maine.gov:443/ACA/AccountTransferService`
2. `ACES_ATP_SERVICE_USERNAME` - the username to use for the above service
3. `ACES_ATP_SERVICE_PASSWORD` - the password to use for the above service
4. `ACES_ATP_CALLER_USERNAME` - the username we expect ACES to call **us** with
5. `ACES_ATP_CALLER_PASSWORD` - the password we expect ACES to call **us** with
5. `ACES_ATP_CALLER_PASSWORD` - the password we expect ACES to call **us** with
6. `ACES_MEC_CHECK_URI` - the uri of the endpoint we will submit mec checks to
7. `CURAM_ATP_SERVICE_URI` - the uri of the endpoint to which medicaid_gateway will submit ATP requests to Curam
8. `CURAM_ATP_SERVICE_USERNAME` - the username to use for the above service
9. `CURAM_ATP_SERVICE_PASSWORD` - the password to use for the above service
10. `CURAM_ATP_CHECK_URI` - the uri of the endpoint to which medicaid_gateway will check for the status of a transfer
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ group :development, :test do
gem 'rspec-rails', '~> 5.0'
gem 'shoulda-matchers', '~> 3'
gem 'yard'
gem 'pry'
end

group :development do
Expand Down
1 change: 1 addition & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,7 @@ DEPENDENCIES
mitc_service!
mongoid (~> 7.2.1)
nokogiri (>= 1.10.8)
pry
pry-byebug
puma (~> 5.0)
rack-mini-profiler (~> 2.0)
Expand Down
14 changes: 14 additions & 0 deletions app/contracts/mec_check_contract.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# frozen_string_literal: true

# Schema and validation rules
class MecCheckContract < Dry::Validation::Contract
# @!method call(opts)
# @param [Hash] opts the parameters to validate using this contract
# @return [Dry::Monads::Result]
params do
required(:application_identifier).filled(:string)
required(:family_identifier).filled(:string)
required(:applicant_responses).filled(:hash)
required(:type).filled(:string)
end
end
11 changes: 11 additions & 0 deletions app/event_source/events/magi_medicaid/mec_check/mec_checked.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# frozen_string_literal: true

module Events
module MagiMedicaid
module MecCheck
class MecChecked < EventSource::Event
publisher_path 'publishers.mec_check_publisher'
end
end
end
end
9 changes: 9 additions & 0 deletions app/event_source/publishers/mec_check_publisher.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# frozen_string_literal: true

module Publishers
# Publisher will send MEC check results payload to EA
class MecCheckPublisher
include ::EventSource::Publisher[amqp: 'magi_medicaid.mec_check']
register_event 'mec_checked'
end
end
24 changes: 24 additions & 0 deletions app/event_source/subscribers/mec_check_subscriber.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# frozen_string_literal: true

module Subscribers
# Subscriber will receive request payload from EA
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)
if result.success?
ack(delivery_info.delivery_tag)
logger.debug "application_submitted_subscriber_message; acked"
else
errors = result.failure.errors.to_h
nack(delivery_info.delivery_tag)
logger.debug "application_submitted_subscriber_message; nacked due to:#{errors}"
end
rescue StandardError => e
nack(delivery_info.delivery_tag)
logger.debug "application_submitted_subscriber_error: baacktrace: #{e.backtrace}; nacked"
end

end
end
24 changes: 24 additions & 0 deletions app/models/aces/mec_check.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# frozen_string_literal: true

module Aces
# MecCheck to see if person is in Medicaid System
class MecCheck
include Mongoid::Document
include Mongoid::Timestamps

# Unique Identifier(application_id) of the application.
# For example: EA's FinancialAssistance::Application's hbx_id
field :application_identifier, type: String

# Unique Identifier(hbx_id) of the family.
# For example: EA's FinancialAssistance::Family's hbx_id
field :family_identifier, type: String

# Server response from the service
field :applicant_responses, type: Hash

# Payload type of person or application
field :type, type: String

end
end
43 changes: 43 additions & 0 deletions app/operations/aces/create_mec_check.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# frozen_string_literal: true

require 'dry/monads'
require 'dry/monads/do'

module Aces
# Operation creates persitance application object with
# application identifier, family identifer and application results
# params only.
class CreateMecCheck
include Dry::Monads[:result, :do]

# @param [Hash] opts The options to create application object
# @option opts [Hash] :params MEC Check params
# @return [Dry::Monads::Result]
def call(params)
values = yield validate_params(params)
application = yield persist(values)

Success(application)
end

private

def validate_params(params)
result = MecCheckContract.new.call(params)
if result.success?
Success(result.to_h)
else
Failure(result)
end
end

def persist(values)
application = ::Aces::MecCheck.new(values)
if application.save
Success(application)
else
Failure('Unable to persist MEC Check.')
end
end
end
end
82 changes: 82 additions & 0 deletions app/operations/aces/initiate_mec_check.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# frozen_string_literal: true

require 'dry/monads'
require 'dry/monads/do'

module Aces
# Take a payload and find people. For each person, initiate a MecCheck
class InitiateMecCheck
send(:include, Dry::Monads[:result, :do])

# @param [String] payload received from Enroll
# @return [Dry::Result]
def call(payload)
json = JSON.parse(payload)
checks = yield get_person_check(json) if json["person"]
checks = yield get_people_checks(json) if json["people"]
results = yield save_check(checks, json)
publish_to_enroll(results)
end

protected

def get_person_check(json)
results = {}
person_hash = {}
person_hash["person"] = { person: json["person"] }
mc_response = mec_check(person_hash)
return Failure(mc_response.failure) if mc_response.failure?

results[json["person"]["hbx_id"]] = mc_response.value!
Success(results)
end

def get_people_checks(json)
results = {}
people = json["people"]
people.each do |person|
person_hash = { "person" => {} }
person_hash["person"]["person"] = person
mc_response = mec_check(person_hash)
return Failure(mc_response.failure) if mc_response.failure?

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?

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

def call_mec_check(person)
Aces::MecCheckCall.new.call(person)
end

def save_check(check_results, json)
application = json["application"] || "n/a"
family = json["family_id"]
results = Aces::CreateMecCheck.new.call(
{
application_identifier: application,
family_identifier: family,
applicant_responses: check_results,
type: json["type"]
}
)
results.success? ? results : Failure("Failed to save MEC check: #{results.failure.errors.to_h}")
end

def publish_to_enroll(payload)
transfer = Aces::InitiateMecCheckToEnroll.new.call(payload.attributes)
transfer.success? ? Success("Transferred MEC Check to Enroll") : Failure(transfer)
end
end
end
35 changes: 35 additions & 0 deletions app/operations/aces/initiate_mec_check_to_enroll.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# frozen_string_literal: true

require 'dry/monads'
require 'dry/monads/do'

module Aces
# InitiateMecCheckToEnroll will publish MEC check events to enroll
class InitiateMecCheckToEnroll
include EventSource::Command
include Dry::Monads[:result, :do]
include EventSource::Logging

# @option opts [Hash] :mec_check
# @return [Dry::Monads::Result]
def call(params)
event = yield build_event(params)
result = send_to_enroll(event)

Success(result)
end

private

def build_event(params)
result = event("events.magi_medicaid.mec_check.mec_checked", attributes: params)
logger.info "MedicaidGateway MEC Check Publisher to enroll, event_key: mec_checked, attributes: #{params.to_h}, result: #{result}"
logger.info('-' * 100)
result
end

def send_to_enroll(event)
event.publish
end
end
end
57 changes: 57 additions & 0 deletions app/operations/aces/mec_check_call.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# frozen_string_literal: true

require 'dry/monads'
require 'dry/monads/do'
require 'aca_entities/medicaid/mec_check/operations/generate_xml'

module Aces
# Check for the existance of a person in the Medicare system already, and if so did they have coverage.
class MecCheckCall
send(:include, Dry::Monads[:result, :do])

# @param [String] hbxid of application
# @return [Dry::Result]
def call(person_payload)
xml = yield generate_xml(person_payload)
_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 generate_xml(payload)
transfer_request = ::AcaEntities::Medicaid::MecCheck::Operations::GenerateXml.new.call(payload.to_json)
transfer_request.success? ? Success(transfer_request) : Failure("Transform failure")
end

def validate_xml(seralized_xml)
document = Nokogiri::XML(seralized_xml.value!)
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.value!)
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
39 changes: 39 additions & 0 deletions app/operations/aces/submit_mec_check_payload.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# frozen_string_literal: true

require 'dry/monads'
require 'dry/monads/do'

module Aces
# Submits the MecCheck Request
class SubmitMecCheckPayload
send(:include, Dry::Monads[:result, :do, :try])

# @param [String] payload
# @return [Dry::Result]
def call(payload)
endpoint_uri = yield read_endpoint_setting
submit_request(endpoint_uri, payload)
end

protected

def read_endpoint_setting
result = Try do
MedicaidGatewayRegistry[:aces_connection].setting(:aces_mec_check_uri).item
end
result.or(Failure("Failed to find setting: :aces_connection, :aces_mec_check_uri"))
end

def submit_request(service_uri, payload)
clean_payload = payload.to_s.gsub("<?xml version=\"1.0\"?>", "").gsub("<?xml version=\"1.0\"??>", "")
result = Try do
Faraday.post(
service_uri,
clean_payload,
"Content-Type" => "application/soap+xml;charset=UTF-8"
)
end
result.or(Failure(result.exception))
end
end
end
Loading