Skip to content

Commit

Permalink
Merge branch 'master' into 71999_scour_payload
Browse files Browse the repository at this point in the history
  • Loading branch information
lee-delarm6 authored Apr 16, 2024
2 parents e1cf6d8 + 9558c82 commit cfd0de0
Show file tree
Hide file tree
Showing 23 changed files with 4,632 additions and 1,535 deletions.
4 changes: 2 additions & 2 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -431,7 +431,7 @@ GEM
multipart-post (~> 2)
faraday-net_http (3.1.0)
net-http
faraday-retry (2.2.0)
faraday-retry (2.2.1)
faraday (~> 2.0)
faraday-typhoeus (1.1.0)
faraday (~> 2.0)
Expand Down Expand Up @@ -890,7 +890,7 @@ GEM
rswag-ui (2.13.0)
actionpack (>= 3.1, < 7.2)
railties (>= 3.1, < 7.2)
rubocop (1.63.1)
rubocop (1.63.2)
json (~> 2.3)
language_server-protocol (>= 3.17.0)
parallel (~> 1.10)
Expand Down
40 changes: 40 additions & 0 deletions db/migrate/20240411153910_create_accredited_individuals.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# frozen_string_literal: true

class CreateAccreditedIndividuals < ActiveRecord::Migration[7.1]
def change
create_table :accredited_individuals, id: :uuid do |t|
t.uuid :ogc_id, null: false
t.string :registration_number, null: false
t.string :poa_code, limit: 3, index: true
t.string :individual_type, null: false
t.string :first_name
t.string :middle_initial
t.string :last_name
t.string :full_name, index: true
t.string :email
t.string :phone
t.string :address_type
t.string :address_line1
t.string :address_line2
t.string :address_line3
t.string :city
t.string :country_code_iso3
t.string :country_name
t.string :county_name
t.string :county_code
t.string :international_postal_code
t.string :province
t.string :state_code
t.string :zip_code
t.string :zip_suffix
t.jsonb :raw_address
t.float :lat
t.float :long
t.geography :location, limit: { srid: 4326, type: 'st_point', geographic: true }
t.timestamps

t.index :location, using: :gist
t.index %i[ registration_number individual_type ], name: 'index_on_reg_num_and_type_for_accredited_individuals', unique: true
end
end
end
37 changes: 37 additions & 0 deletions db/schema.rb

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

132 changes: 132 additions & 0 deletions lib/lighthouse/benefits_intake/metadata.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
# frozen_string_literal: true

module BenefitsIntake
##
# Validate the required metadata which must accompany an upload:
#
# {
# 'veteranFirstName': String,
# 'veteranLastName': String,
# 'fileNumber': String, # 8-9 digits
# 'zipCode': String, # 5 or 9 digits
# 'source': String,
# 'docType': String,
# 'businessLine': String, # optional; enum in BUSINESS_LINE
# }
#
# https://developer.va.gov/explore/api/benefits-intake/docs
#
class Metadata
BUSINESS_LINE = {
CMP: 'Compensation requests such as those related to disability, unemployment, and pandemic claims',
PMC: 'Pension requests including survivor’s pension',
INS: 'Insurance such as life insurance, disability insurance, and other health insurance',
EDU: 'Education benefits, programs, and affiliations',
VRE: 'Veteran Readiness & Employment such as employment questionnaires, ' \
'employment discrimination, employment verification',
BVA: 'Board of Veteran Appeals',
FID: 'Fiduciary / financial appointee, including family member benefits',
NCA: 'National Cemetery Administration',
OTH: 'Other (this value if used, will be treated as CMP)'
}.freeze

# rubocop:disable Metrics/ParameterLists
def self.generate(first_name, last_name, file_number, zip_code, source, doc_type, business_line = nil)
validate({
'veteranFirstName' => first_name,
'veteranLastName' => last_name,
'fileNumber' => file_number,
'zipCode' => zip_code,
'source' => source,
'docType' => doc_type,
'businessLine' => business_line
})
end
# rubocop:enable Metrics/ParameterLists

def self.validate(metadata)
validate_first_name(metadata)
.then { |m| validate_last_name(m) }
.then { |m| validate_file_number(m) }
.then { |m| validate_zip_code(m) }
.then { |m| validate_source(m) }
.then { |m| validate_doc_type(m) }
.then { |m| validate_business_line(m) }
end

def self.validate_first_name(metadata)
validate_presence_and_stringiness(metadata['veteranFirstName'], 'veteran first name')

first_name = I18n.transliterate(metadata['veteranFirstName']).gsub(%r{[^a-zA-Z\-\/\s]}, '').strip.first(50)
validate_nonblank(first_name, 'veteran first name')

metadata['veteranFirstName'] = first_name
metadata
end

def self.validate_last_name(metadata)
validate_presence_and_stringiness(metadata['veteranLastName'], 'veteran last name')

last_name = I18n.transliterate(metadata['veteranLastName']).gsub(%r{[^a-zA-Z\-\/\s]}, '').strip.first(50)
validate_nonblank(last_name, 'veteran last name')

metadata['veteranLastName'] = last_name
metadata
end

def self.validate_file_number(metadata)
validate_presence_and_stringiness(metadata['fileNumber'], 'file number')
unless metadata['fileNumber'].match?(/^\d{8,9}$/)
raise ArgumentError, 'file number is invalid. It must be 8 or 9 digits'
end

metadata
end

def self.validate_zip_code(metadata)
validate_presence_and_stringiness(metadata['zipCode'], 'zip code')

zip_code = metadata['zipCode'].dup.gsub(/[^0-9]/, '')
zip_code.insert(5, '-') if zip_code.match?(/\A[0-9]{9}\z/)
zip_code = '00000' unless zip_code.match?(/\A[0-9]{5}(-[0-9]{4})?\z/)

metadata['zipCode'] = zip_code

metadata
end

def self.validate_source(metadata)
validate_presence_and_stringiness(metadata['source'], 'source')

metadata
end

def self.validate_doc_type(metadata)
validate_presence_and_stringiness(metadata['docType'], 'doc type')

metadata
end

def self.validate_business_line(metadata)
bl = metadata['businessLine']
if bl
bl = bl.dup.to_s.upcase.to_sym
bl = :OTH unless BUSINESS_LINE.key?(bl)
metadata['businessLine'] = bl.to_s
else
metadata.delete('businessLine')
end

metadata
end

def self.validate_presence_and_stringiness(value, error_label)
raise ArgumentError, "#{error_label} is missing" unless value
raise ArgumentError, "#{error_label} is not a string" if value.class != String
end

def self.validate_nonblank(value, error_label)
raise ArgumentError, "#{error_label} is blank" if value.blank?
end
end
end
Loading

0 comments on commit cfd0de0

Please sign in to comment.