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

Fix org update job #20317

Merged
merged 19 commits into from
Jan 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def queue_address_updates(data)

def rows_to_process(rows)
rows.map do |row|
org = Veteran::Service::Organization.find_by(poa: row[:id])
org = Veteran::Service::Organization.find_by!(poa: row[:id])
diff = org.diff(row)
row.merge(diff.merge({ address_exists: org.location.present? })) if diff.values.any?
rescue ActiveRecord::RecordNotFound => e
Expand Down
66 changes: 42 additions & 24 deletions modules/veteran/app/sidekiq/organizations/update.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,24 @@ class Update
include Sidekiq::Job
include SentryLogging

attr_accessor :slack_messages, :orgs_data

def initialize
@slack_messages = []
end

# Processes each organization's data provided in JSON format.
# This method parses the JSON, validates each organization's address, and updates the database records.
# @param orgs_json [String] JSON string containing an array of organization data.
def perform(orgs_json)
orgs_data = JSON.parse(orgs_json)
orgs_data.each { |org_data| process_org_data(org_data) }
@orgs_data = JSON.parse(orgs_json)
@orgs_data.each { |org_data| process_org_data(org_data) }
rescue => e
log_error("Error processing job: #{e.message}")
ensure
@slack_messages.unshift("Orgs processed: #{@orgs_data.size}") if @orgs_data&.any?
@slack_messages.unshift('Organizations::Update')
log_to_slack(@slack_messages.join("\n")) unless @slack_messages.empty?
end

private
Expand All @@ -31,20 +41,15 @@ def perform(orgs_json)
# If the address validation fails or an error occurs during the update, the error is logged and the process
# is halted for the current organization.
# @param org_data [Hash] The organization data including id and address.
def process_org_data(org_data) # rubocop:disable Metrics/MethodLength
def process_org_data(org_data)
return unless record_can_be_updated?(org_data)

address_validation_api_response = nil

if org_data['address_changed']
api_response = get_best_address_candidate(org_data['address'])

api_response = if Flipper.enabled?(:va_v3_contact_information_service)
get_best_address_candidate(org_data)
else
get_best_address_candidate(org_data['address'])
end

# don't update the record if there is not a valid address with non-zero lat and long at this point
# Don't update the record if there is not a valid address with non-zero lat and long at this point
if api_response.nil?
return
else
Expand All @@ -71,23 +76,19 @@ def record_can_be_updated?(org_data)
# @param address [Hash] A hash containing the details of the organization's address.
# @return [VAProfile::Models::ValidationAddress] A validation address object ready for address validation service.
def build_validation_address(address)
if Flipper.enabled?(:va_v3_contact_information_service)
validation_model = VAProfile::Models::V3::ValidationAddress
state_code = address['state']['state_code']
city = address['city_name']
else
validation_model = VAProfile::Models::ValidationAddress
state_code = address['state_province']['code']
city = address['city']
end
validation_model = if Flipper.enabled?(:va_v3_contact_information_service)
VAProfile::Models::V3::ValidationAddress
else
VAProfile::Models::ValidationAddress
end

validation_model.new(
address_pou: address['address_pou'],
address_line1: address['address_line1'],
address_line2: address['address_line2'],
address_line3: address['address_line3'],
city: city,
state_code: state_code,
city: address['city'],
state_code: address['state']['state_code'],
opticbob marked this conversation as resolved.
Show resolved Hide resolved
zip_code: address['zip_code5'],
zip_code_suffix: address['zip_code4'],
country_code_iso3: address['country_code_iso3']
Expand Down Expand Up @@ -138,6 +139,7 @@ def build_address_attributes(org_data, api_response)
address = api_response['candidate_addresses'].first['address']
geocode = api_response['candidate_addresses'].first['geocode']
meta = api_response['candidate_addresses'].first['address_meta_data']

build_address(address, geocode, meta).merge({ raw_address: org_data['address'].to_json })
end
end
Expand All @@ -155,7 +157,7 @@ def build_address(address, geocode, meta)
address_line3: address['address_line3'],
city: address['city'],
province: address['state_province']['name'],
state_code: address['state_province']['code'],
state_code: address['state_province']['state_code'],
zip_code: address['zip_code5'],
zip_suffix: address['zip_code4'],
country_code_iso3: address['country']['iso3_code'],
Expand All @@ -179,7 +181,7 @@ def build_v3_address(address)
state_code: address['state']['state_code'],
zip_code: address['zip_code5'],
zip_suffix: address['zip_code4'],
country_code_iso3: address['country']['iso3_code'],
country_code_iso3: address['country']['country_code_iso3'],
country_name: address['country']['country_name'],
county_name: address.dig('county', 'county_name'),
county_code: address.dig('county', 'county_code'),
Expand All @@ -192,7 +194,9 @@ def build_v3_address(address)
# Logs an error to Sentry.
# @param error [Exception] The error string to be logged.
def log_error(error)
log_message_to_sentry("Organizations::Update: #{error}", :error)
message = "Organizations::Update: #{error}"
log_message_to_sentry(message, :error)
@slack_messages << message
end

# Checks if the latitude and longitude of an address are both set to zero, which are the default values
Expand Down Expand Up @@ -261,6 +265,11 @@ def retry_validation(org_address)
# @param org_address [Hash] the address provided by OGC
# @return [Hash, Nil] the response from the address validation service
def get_best_address_candidate(org_address)
if org_address.nil?
log_error('In #get_best_address_candidate, org_address is nil')
return nil
end

candidate_address = build_validation_address(org_address)
original_response = validate_address(candidate_address)
return nil unless address_valid?(original_response)
Expand All @@ -278,6 +287,15 @@ def get_best_address_candidate(org_address)
else
original_response
end
rescue => e
log_error("In #get_best_address_candidate, address: #{org_address}, error message: #{e.message}")
end

def log_to_slack(message)
client = SlackNotify::Client.new(webhook_url: Settings.edu.slack.webhook_url,
channel: '#benefits-representation-management-notifications',
username: 'Organizations::Update Bot')
client.notify(message)
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ def process_row(row, sheet_name, column_map)
address_line2: get_value(row, column_map, 'OrganizationAddressLine2'),
address_line3: get_value(row, column_map, 'OrganizationAddressLine3'),
city: get_value(row, column_map, 'OrganizationCity'),
state_province: { code: get_value(row, column_map, 'OrganizationState') },
state: { state_code: get_value(row, column_map, 'OrganizationState') },
zip_code5:,
zip_code4:,
country_code_iso3: 'US'
Expand Down
Loading
Loading