Skip to content

Commit

Permalink
started adding transmittable for the VLP REST XML
Browse files Browse the repository at this point in the history
  • Loading branch information
kristinmerbach committed Dec 13, 2023
1 parent 9c58722 commit c9a59fe
Show file tree
Hide file tree
Showing 8 changed files with 687 additions and 0 deletions.
24 changes: 24 additions & 0 deletions app/models/transmittable/person.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# frozen_string_literal: true

module Transmittable
# The subject class of a person to be used by transmittable
class Person
include Mongoid::Document
include Mongoid::Timestamps
include Transmittable::Subject

field :correlation_id, type: String
field :hbx_id, type: String
field :encrypted_ssn, type: String
field :surname, type: String
field :given_name, type: String
field :dob, type: String
field :middle_name, type: String

# indexes
index({ correlation_id: 1 })
index({ encrypted_ssn: 1 })
index({ hbx_id: 1 })

end
end
1 change: 1 addition & 0 deletions app/models/transmittable/transaction.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class Transaction
field :description, type: String
field :ended_at, type: DateTime
field :json_payload, type: Hash
field :xml_payload, type: String

# Scopes
scope :blocked, -> { where(status: :blocked) }
Expand Down
139 changes: 139 additions & 0 deletions app/operations/fdsh/jobs/generate_transmittable_vlp_payload.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
# frozen_string_literal: true

module Fdsh
module Jobs
# create job operation that takes params of key (required), started_at(required), publish_on(required), payload (required)
class GenerateTransmittableVlpPayload
include Dry::Monads[:result, :do, :try]

def call(params)
values = yield validate_params(params)
_job = yield create_job(values)
@transmission = yield create_transmission(values)
person_subject = yield create_person_subject(values)
@transaction = yield create_transaction(values, person_subject)
@transaction = yield generate_transmittable_payload(values[:payload])
transmittable
end

private

def validate_params(params)
return Failure('Transmittable payload cannot be created without a key as a symbol') unless params[:key].is_a?(Symbol)
return Failure('Transmittable payload cannot be created without a started_at as a Datetime') unless params[:started_at].is_a?(DateTime)
return Failure('Transmittable payload cannot be created without a publish_on as a Datetime') unless params[:publish_on].is_a?(DateTime)
return Failure('Transmittable payload cannot be created without a payload') unless params[:payload]
return Failure('Transmittable payload cannot be created without a correlation_id a string') unless params[:correlation_id].is_a?(String)

Success(params)
end

def create_job(values)
result = Fdsh::Jobs::FindOrCreateJob.new.call(values)

if result.success?
@job = result.value!
@job.generate_message_id
Success(@job)
else
result
end
end

def create_transmission(values)
result = Fdsh::Jobs::CreateTransmission.new.call(values.merge({ job: @job, event: 'initial', state_key: :initial }))

return result if result.success?
add_errors({ job: @job }, "Failed to create transmission due to #{result.failure}", :create_request_transmission)
status_result = update_status({ job: @job }, :failed, result.failure)
return status_result if status_result.failure?
end

def add_errors(transmittable_objects, message, error_key)
Fdsh::Jobs::AddError.new.call({ transmittable_objects: transmittable_objects, key: error_key, message: message })
end

def update_status(transmittable_objects, state, message)
Fdsh::Jobs::UpdateProcessStatus.new.call({ transmittable_objects: transmittable_objects, state: state, message: message })
end

def create_person_subject(values)
existing_person = ::Trans::Person.where(correlation_id: values[:correlation_id]).first

if existing_person
Success(existing_person)
else
person_hash = JSON.parse(values[:payload], symbolize_names: true)
person = ::Transmittable::Person.create(hbx_id: person_hash[:hbx_id],
correlation_id: values[:correlation_id],
encrypted_ssn: person_hash[:person_demographics][:encrypted_ssn],
surname: person_hash[:person_name][:last_name],
given_name: person_hash[:person_name][:first_name],
middle_name: person_hash[:person_name][:middle_name],
dob: person_hash[:person_demographics][:dob])

return Success(person) if person.persisted?
add_errors({ job: @job, transmission: @transmission }, "Unable to save person subject due to #{person.errors&.full_messages}",
:create_person_subject)
status_result = update_status({ job: @job, transmission: @transmission }, :failed, "Unable to save person subject")
return status_result if status_result.failure?
Failure("Unable to save person subject")
end
end

def create_transaction(values, subject)
result = Fdsh::Jobs::CreateTransaction.new.call(values.merge({ transmission: @transmission,
subject: subject,
event: 'initial',
state_key: :initial }))
return result if result.success?
add_errors({ job: @job, transmission: @transmission }, "Failed to create transaction due to #{result.failure}", :create_transaction)
status_result = update_status({ job: @job, transmission: @transmission }, :failed, result.failure)
return status_result if status_result.failure?
result
end

def generate_transmittable_payload(payload)
# need to switch out the transformation to the rest xml once that operation has been created
# result = ::Fdsh::Vlp::Rx92::TransformPersonToXmlRequest.new.call(payload)
result = Fdsh::Vlp::Rx92::TransformPersonToXmlRequest.new.call(payload)
if result.success?
@transaction.xml_payload = result.value!
@transaction.save

return Success(@transaction) if @transaction.xml_payload
add_errors({ job: @job, transmission: @transmission, transaction: @transaction },
"Unable to save transaction with payload",
:generate_transmittable_payload)
status_result = update_status({ job: @job, transmission: @transmission, transaction: @transaction }, :failed,
"Unable to save transaction with payload")
return status_result if status_result.failure?
else
add_errors({ job: @job, transmission: @transmission, transaction: @transaction },
"Unable to transform payload",
:generate_transmittable_payload)
status_result = update_status({ job: @job, transmission: @transmission, transaction: @transaction }, :failed, "Unable to transform payload")
return status_result if status_result.failure?
result
end
end

def transmittable
message_id = @job.message_id

if @transaction.xml_payload && message_id
Success({ transaction: @transaction,
message_id: message_id })
else
add_errors({ job: @job, transmission: @transmission, transaction: @transaction },
"Transaction do not consists of a payload or no message id found",
:transmittable)
status_result = update_status({ job: @job, transmission: @transmission, transaction: @transaction }, :failed,
"Transaction do not consists of a payload or no message id found")
return status_result if status_result.failure?
Failure("Transaction do not consists of a payload or no message id found")
end
end
end
end
end
198 changes: 198 additions & 0 deletions app/operations/fdsh/vlp/rx92/handle_initial_verification_request.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
# frozen_string_literal: true

module Fdsh
module Vlp
module Rx92
# Invoke a Initial verification service, and, if appropriate, broadcast the response.
class HandleInitialVerificationRequest
include Dry::Monads[:result, :do, :try]
include EventSource::Command

# @return [Dry::Monads::Result]
def call(params)
validate_params = yield validate_params(params)
values = yield transmittable_payload(validate_params)
jwt = yield generate_jwt(values)
response = yield publish_vlp_request(params[:correlation_id], jwt)
# do we need to do anything with a rest envelop etc?
# initial_verification_result = yield ::Soap::RemoveSoapEnvelope.new.call(response.body)
_response_transmission = yield create_response_transmission(values, params[:correlation_id])
_response_transaction = yield create_response_transaction(values, response)
initial_verification_outcome = yield process_response(response)
event = yield build_event(params[:correlation_id], initial_verification_outcome)
result = yield publish(event)

Success(result)
end

protected

def validate_params(params)
return Failure('Cannot process VLP request without correlation id') unless params[:correlation_id].is_a?(String)
return Failure('Cannot process VLP request without payload') if params[:payload].blank?

Success(params)
end

def transmittable_payload(params)
result = ::Fdsh::Jobs::GenerateTransmittableVlpPayload.new.call({ key: :vlp_verification_request,
title: 'VLP Verification Request',
description: 'Request for VLP verification to CMS',
payload: params[:payload],
correlation_id: params[:correlation_id],
started_at: DateTime.now,
publish_on: DateTime.now })

result.success? ? Success(result.value!) : result
end

def generate_jwt(values)
@request_transaction = values[:transaction]
@request_transmission = @request_transaction.transactions_transmissions.last.transmission
@job = @request_transmission.job
result = Jwt::GetJwt.new.call({})

return result if result.success?

add_errors({ transaction: @request_transaction, transmission: @request_transmission, job: @job },
result.failure,
:generate_jwt)
status_result = update_status({ transaction: @request_transaction, transmission: @request_transmission, job: @job }, :failed,
result.failure)
return status_result if status_result.failure?
result
end

def publish_vlp_request(correlation_id, jwt)
result = Fdsh::Vlp::Rx92::RequestVlpVerification.new.call({ correlation_id: correlation_id, token: jwt,
transmittable_objects: { transaction: @request_transaction,
transmission: @request_transmission, job: @job } })
if result.success?
status_result = update_status({ transaction: @request_transaction, transmission: @request_transmission }, :acked, "acked from cms")
return status_result if status_result.failure?
Success(result.value!)
else
add_errors({ transaction: @request_transaction, transmission: @request_transmission, job: @job },
"Failed to receive response from cms due to #{result.failure}",
:publish_vlp_request)
status_result = update_status({ transaction: @request_transaction, transmission: @request_transmission, job: @job }, :failed,
"Failed to receive response from cms")
return status_result if status_result.failure?
result
end
end

def create_response_transmission(values, correlation_id)
result = Fdsh::Jobs::CreateTransmission.new.call(values.merge({ key: :vlp_verification_response,
started_at: DateTime.now,
job: @job,
event: 'received',
state_key: :received,
title: 'VLP Verification Response',
description: 'Response for VLP verification from CMS',
correlation_id: correlation_id }))

if result.success?
@response_transmission = result.value!
Success(@response_transmission)
else
add_errors({ transaction: @request_transaction, transmission: @request_transmission, job: @job },
"Failed to create response transmission due to #{result.failure}",
:create_response_transmission)
status_result = update_status({ job: @job }, :failed, "Failed to create response transmission")
return status_result if status_result.failure?
result
end
end

def create_response_transaction(values, vlp_response)
subject = values[:transaction].transactable
result = Fdsh::Jobs::CreateTransaction.new.call(values.merge({ key: :vlp_verification_response,
started_at: DateTime.now,
transmission: @response_transmission,
title: 'VLP Verification Response',
description: 'Response for VLP verification from CMS',
subject: subject,
event: 'received',
state_key: :received }))

if result.success?
@response_transaction = result.value!
# this is best guess, will need to verify when testing locally.
@response_transaction.xml_payload = vlp_response.env.response_body
@response_transaction.save
Success(@response_transaction)
else
add_errors({ transaction: @request_transaction, transmission: @request_transmission, job: @job },
"Failed to create response transaction due to #{result.failure}",
:create_response_transaction)
status_result = update_status({ transmission: @response_transmission, job: @job }, :failed, "Failed to create response transaction")
return status_result if status_result.failure?
result
end
end

# def publish_vlp_request(correlation_id, jwt)
# result = Fdsh::Vlp::Rx92::RequestVlpInitialVerification.new.call({
# correlation_id: correlation_id, token: jwt,
# transmittable_objects: { transaction: @request_transaction,
# transmission: @request_transmission, job: @job } })
# if result.success?
# status_result = update_status({ transaction: @request_transaction, transmission: @request_transmission }, :acked, "acked from cms")
# return status_result if status_result.failure?
# Success(result.value!)
# else
# add_errors({ transaction: @request_transaction, transmission: @request_transmission, job: @job },
# "Failed to receive response from cms due to #{result.failure}",
# :publish_vlp_request)
# status_result = update_status({ transaction: @request_transaction, transmission: @request_transmission, job: @job }, :failed,
# "Failed to receive response from cms")
# return status_result if status_result.failure?
# result
# end
# end

def process_response(response)
result = ProcessInitialVerificationResponse.new.call(response)

if result.success?
status_result = update_status({ transaction: @response_transaction, transmission: @response_transmission }, :succeeded,
"processed the payload from VLP")
return status_result if status_result.failure?
Success(result.value!)
else
add_errors({ transaction: @response_transaction, transmission: @response_transmission, job: @job },
"Failed to process response from cms due to #{result.failure}",
:process_response)
status_result = update_status({ transaction: @response_transaction, transmission: @response_transmission, job: @job }, :failed,
"Failed to process response from cms")
return status_result if status_result.failure?
result
end
end

def build_event(correlation_id, initial_verification_outcome)
payload = initial_verification_outcome.to_h

event('events.fdsh.initial_verification_complete', attributes: payload, headers: { correlation_id: correlation_id })
end

def publish(event)
event.publish
status_result = update_status({ job: @job }, :succeeded, "successfully sent response to EA")
return status_result if status_result.failure?

Success('Initial REST XML verificattion response published successfully')
end

def add_errors(transmittable_objects, message, error_key)
Fdsh::Jobs::AddError.new.call({ transmittable_objects: transmittable_objects, key: error_key, message: message })
end

def update_status(transmittable_objects, state, message)
Fdsh::Jobs::UpdateProcessStatus.new.call({ transmittable_objects: transmittable_objects, state: state, message: message })
end
end
end
end
end
Loading

0 comments on commit c9a59fe

Please sign in to comment.