Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
4b5e674
handle vlp transformation failure by updating the transmittable objects
charlienparker Nov 17, 2025
2e15f07
allow ssa/vlp requests to fail piecemeal
charlienparker Nov 17, 2025
dff682a
remove response transmission/transaction params from processor module
charlienparker Nov 17, 2025
02f7927
add new module to be shared across request/response processors to con…
charlienparker Nov 17, 2025
0c5f669
add spec coverage, fix non-monad return of handle_failed_transaction …
charlienparker Nov 17, 2025
7bd4826
fix determined applicant tracking
charlienparker Nov 17, 2025
ae44f1a
modify determined applicants in place
charlienparker Nov 18, 2025
695c366
add spec for process_applicant_responses
charlienparker Nov 18, 2025
75c4984
lint fixes
charlienparker Nov 18, 2025
d07500a
remove response helper
charlienparker Nov 18, 2025
48aec5e
fix arity mismatch
charlienparker Nov 18, 2025
c65261d
remove comments
charlienparker Nov 18, 2025
49513b9
introduce intermediate orchestrator to dry constant usage while allow…
charlienparker Nov 18, 2025
834db41
use attr_reader for service_name member, other lint fixes
charlienparker Nov 18, 2025
c6f536e
remove required relative
charlienparker Nov 18, 2025
243929a
add spec for new orchestrator
charlienparker Nov 18, 2025
d1ebf71
lint fix
charlienparker Nov 18, 2025
0edff47
fix validation by removing transmission
charlienparker Nov 18, 2025
bfdafb9
lint fix
charlienparker Nov 18, 2025
39d7657
more spec fixes
charlienparker Nov 18, 2025
636fa51
only fail on true requested failures
charlienparker Nov 18, 2025
9bcf326
remove transmission
charlienparker Nov 18, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 11 additions & 6 deletions app/operations/fdsh/ssa_vlp/rj3/process_applicant_requests.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ class ProcessApplicantRequests
def call(params)
@values, @job, @application, @applicant_entity = yield validate_params(params)
@subject = yield fetch_subject
_ssa_verification = yield request_ssa_verification
_dhs_verification = yield request_dhs_verification
_requests_result = yield request_verifications

Success('Successfully invoked verifications')
end
Comment thread
charlienparker marked this conversation as resolved.
Expand All @@ -42,15 +41,21 @@ def fetch_subject
Success(subject)
end

def request_ssa_verification
return Success('Does not qualify for SSA Call') unless eligible_for_invoking_ssa?
def request_verifications
ssa_result = request_ssa_verification if eligible_for_invoking_ssa?
dhs_result = request_dhs_verification if eligible_for_invoking_dhs?

service_results = [ssa_result, dhs_result].compact
return Failure('All requested verification services failed') if service_results.any? && service_results.all?(&:failure?)

Success(nil)
end

def request_ssa_verification
Fdsh::SsaVlp::Rj3::Ssa::ApplicantRequest.new.call(build_verification_params)
end

def request_dhs_verification
return Success('Does not qualify for DHS Call') unless eligible_for_invoking_dhs?

Fdsh::SsaVlp::Rj3::Vlp::ApplicantRequest.new.call(build_verification_params)
end

Expand Down
83 changes: 83 additions & 0 deletions app/operations/fdsh/ssa_vlp/rj3/process_applicant_response.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# frozen_string_literal: true

module Fdsh
module SsaVlp
module Rj3
# This class processes a single applicant's verification response for a specific service (SSA or VLP).
# It handles transaction fetching, skip logic, tracking, and delegates to the appropriate processor.
class ProcessApplicantResponse
include Dry::Monads[:result, :do, :try]
include ServiceConstants

SERVICE_CONFIGURATION = {
"SSA" => Fdsh::SsaVlp::Rj3::Ssa::ProcessVerificationResponse,
"VLP" => Fdsh::SsaVlp::Rj3::Vlp::ProcessVerificationResponse
}.freeze

def call(params)
yield validate_params(params)

request_transaction, response_transaction = fetch_transactions
return Success(@application_hash) if applicant_unrequested?(request_transaction, response_transaction)

track_applicant_determination(response_transaction)

result = yield process_verification_response(request_transaction, response_transaction)
Success(result)
end

private

def validate_params(params)
return Failure('Application hash not provided') unless params[:application_hash]
return Failure('Applicant not provided') unless params[:applicant]
return Failure('Application type not provided') unless params[:application_type]
return Failure('Service name not provided') unless params[:service_name]
return Failure('Determined applicants hash not provided') unless params[:determined_applicants]
return Failure('Invalid service name') unless SERVICE_CONFIGURATION.key?(params[:service_name])

@application_hash = params[:application_hash]
@applicant = params[:applicant]
@application_type = params[:application_type]
@service_name = params[:service_name]
@determined_applicants = params[:determined_applicants]

Success(params)
end

def fetch_transactions
request_transaction = @applicant.transactions.where(key: request_key).last
response_transaction = @applicant.transactions.where(key: response_key).last
[request_transaction, response_transaction]
end

def applicant_unrequested?(request_transaction, response_transaction)
request_transaction.nil? && response_transaction.nil?
end

def track_applicant_determination(response_transaction)
return unless @applicant.hbx_id
return unless response_transaction&.process_status&.latest_state == :succeeded

service_key = @service_name.downcase.to_sym
@determined_applicants[service_key] ||= []
@determined_applicants[service_key] << @applicant.hbx_id
end

def process_verification_response(request_transaction, response_transaction)
processor_class = SERVICE_CONFIGURATION[@service_name]

processor_class.new.call(
application_hash: @application_hash,
applicant: @applicant,
application_type: @application_type,
request_transaction: request_transaction,
response_transaction: response_transaction
)
end

attr_reader :service_name
end
end
end
end
68 changes: 17 additions & 51 deletions app/operations/fdsh/ssa_vlp/rj3/process_applicant_responses.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ def call(params)
@job, @application, @application_hash, @application_type = yield validate_params(params)
application_hash = yield update_ssa_verification_response(@application_hash, @application_type)
application_hash = yield update_dhs_verification_response(application_hash, @application_type)
payload_to_ea = yield filter_processed_evidences(application_hash)
determined_application_payload = yield filter_processed_evidences(application_hash)

Success([payload_to_ea, @determined_applicants])
Success([determined_application_payload, @determined_applicants])
end

private
Expand All @@ -24,17 +24,19 @@ def validate_params(params)
return Failure('Application hash not provided') unless params[:application_hash]
return Failure('Application type not provided') unless params[:application_type]

@determined_applicants = { ssa: [], vlp: [] }
@determined_applicants = {}
Success([params[:job], params[:application], params[:application_hash], params[:application_type]])
end

def update_ssa_verification_response(application_hash, application_type)
@application.applicants.each do |applicant|
response_transaction = find_ssa_response_transaction(applicant)
next unless response_transaction

record_determined_applicant(response_transaction, applicant, :ssa)
result = process_ssa_verification_response(response_transaction, application_hash, applicant, application_type)
result = ProcessApplicantResponse.new.call(
application_hash: application_hash,
applicant: applicant,
application_type: application_type,
service_name: "SSA",
determined_applicants: @determined_applicants
)
return result if result.failure?
application_hash = result.value!
end
Expand All @@ -47,10 +49,13 @@ def update_ssa_verification_response(application_hash, application_type)

def update_dhs_verification_response(application_hash, application_type)
@application.applicants.each do |applicant|
response_transaction = find_vlp_response_transaction(applicant)
next unless response_transaction
record_determined_applicant(response_transaction, applicant, :vlp)
result = process_vlp_verification_response(response_transaction, application_hash, applicant, application_type)
result = ProcessApplicantResponse.new.call(
application_hash: application_hash,
applicant: applicant,
application_type: application_type,
service_name: "VLP",
determined_applicants: @determined_applicants
)
return result if result.failure?
application_hash = result.value!
end
Expand All @@ -61,45 +66,6 @@ def update_dhs_verification_response(application_hash, application_type)
handle_error(:update_dhs_verification_response, "Error while updating DHS verification response: #{e.message}")
end

def record_determined_applicant(response_transaction, applicant, key)
return unless response_transaction.process_status&.latest_state == :succeeded

hbx_id = applicant.hbx_id
return unless hbx_id

@determined_applicants[key] << hbx_id
end

def find_ssa_response_transaction(applicant)
applicant.transactions.where(key: :ssa_verification_response).last
end

def find_vlp_response_transaction(applicant)
applicant.transactions.where(key: :vlp_verification_response).last
end

def process_ssa_verification_response(response_transaction, application_hash, applicant, application_type)
response_transmission = response_transaction.transmission
Fdsh::SsaVlp::Rj3::Ssa::ProcessVerificationResponse.new.call(
response_transaction: response_transaction,
response_transmission: response_transmission,
application_hash: application_hash,
applicant: applicant,
application_type: application_type
)
end

def process_vlp_verification_response(response_transaction, application_hash, applicant, application_type)
response_transmission = response_transaction.transmission
Fdsh::SsaVlp::Rj3::Vlp::ProcessVerificationResponse.new.call(
response_transaction: response_transaction,
response_transmission: response_transmission,
application_hash: application_hash,
applicant: applicant,
application_type: application_type
)
end

def save_application_response(application_hash)
@application.response_application_cv = application_hash
@application.save!
Expand Down
2 changes: 2 additions & 0 deletions app/operations/fdsh/ssa_vlp/rj3/request_processor_utils.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ module SsaVlp
module Rj3
# This module contains utility methods for SSA and VLP verification requests.
module RequestProcessorUtils
include ServiceConstants

private

def validate_params(params)
Expand Down
16 changes: 11 additions & 5 deletions app/operations/fdsh/ssa_vlp/rj3/response_processor_utils.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,31 @@ module SsaVlp
module Rj3
# This module contains utility methods for processing SSA and VLP verification responses.
module ResponseProcessorUtils

private

def validate_params(params)
return Failure('Response transaction not provided') unless params[:response_transaction]
return Failure('Response transmission not provided') unless params[:response_transmission]
return Failure('Request transaction not provided') unless params[:request_transaction]
return Failure('Application hash not provided') unless params[:application_hash]
return Failure('Application type not provided') unless params[:application_type]
return Failure('Applicant must be a Transmittable::Applicant instance') unless params[:applicant].is_a?(Transmittable::Applicant)

Success([params[:response_transaction], params[:response_transmission], params[:application_hash], params[:application_type]])
@application_hash = params[:application_hash]
@app_type = params[:application_type]
@applicant = params[:applicant]
@request_transaction = params[:request_transaction]
@response_transaction = params[:response_transaction]

Success(params)
end

def handle_failed_transaction
updated_application_hash = yield record_verification_failure(@application_hash)
Success(updated_application_hash)
record_verification_failure(@application_hash)
end

def transaction_failed?
@response_transaction.process_status&.latest_state == :failed
(@response_transaction || @request_transaction)&.process_status&.latest_state == :failed
end

def record_verification_failure(application_hash)
Expand Down
29 changes: 29 additions & 0 deletions app/operations/fdsh/ssa_vlp/rj3/service_constants.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# frozen_string_literal: true

module Fdsh
module SsaVlp
module Rj3
# This module contains service constants for SSA and VLP verification processing.
module ServiceConstants
private

def base_transaction_key
case service_name
when "SSA"
:ssa_verification
when "VLP"
:vlp_verification
end
end

def request_key
:"#{base_transaction_key}_request"
end

def response_key
:"#{base_transaction_key}_response"
end
end
end
end
end
8 changes: 0 additions & 8 deletions app/operations/fdsh/ssa_vlp/rj3/ssa/applicant_request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,6 @@ def service_name
"SSA"
end

def request_key
:ssa_verification_request
end

def response_key
:ssa_verification_response
end

def generate_request_payload
result = if @values[:application_type] == 'faa'
AcaEntities::Fdsh::Ssa::H3::Operations::FinancialAssistance::VerificationJsonRequest.new.call(@applicant_entity)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ class ProcessVerificationResponse
EVIDENCE_KEYS = %w[social_security_number_evidence citizenship_evidence immigration_evidence].freeze

def call(params)
@response_transaction, @response_transmission, @application_hash, @app_type = yield validate_params(params)
@applicant = params[:applicant]
yield validate_params(params)

return handle_failed_transaction if transaction_failed?

Expand Down
21 changes: 10 additions & 11 deletions app/operations/fdsh/ssa_vlp/rj3/vlp/applicant_request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,18 @@ def service_name
"VLP"
end

def request_key
:vlp_verification_request
end

def response_key
:vlp_verification_response
end

def generate_initial_verification_request
if @values[:application_type] == 'faa'
AcaEntities::Fdsh::Vlp::H92::Operations::FinancialAssistance::ApplicantToInitialRequest.new.call(@applicant_entity)
result = if @values[:application_type] == 'faa'
AcaEntities::Fdsh::Vlp::H92::Operations::FinancialAssistance::ApplicantToInitialRequest.new.call(@applicant_entity)
else
AcaEntities::Fdsh::Vlp::H92::Operations::IndividualMarket::ApplicantToInitialRequest.new.call(@applicant_entity)
end
if result.failure?
handle_failure(:generate_initial_verification_request,
{ transaction: @request_transaction, transmission: @request_transmission, job: @job },
"Failed to create VLP request transaction due to #{result.failure}")
else
AcaEntities::Fdsh::Vlp::H92::Operations::IndividualMarket::ApplicantToInitialRequest.new.call(@applicant_entity)
result
end
rescue StandardError => e
handle_failure(:generate_initial_verification_request,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ class ProcessVerificationResponse
VERIFIED_CODES = %w[Y X].freeze

def call(params)
@response_transaction, @response_transmission, @application_hash, @app_type = yield validate_params(params)
@applicant = params[:applicant]
yield validate_params(params)

return handle_failed_transaction if transaction_failed?

Expand Down
Loading
Loading