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

72706 Create ivc_champva Module #16100

Closed
wants to merge 5 commits into from
Closed
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
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ path 'modules' do
gem 'facilities_api'
gem 'health_quest'
gem 'income_limits'
gem 'ivc_champva'
gem 'meb_api'
gem 'mobile'
gem 'mocked_authentication'
Expand Down
2 changes: 2 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ PATH
facilities_api (0.1.0)
health_quest (0.1.0)
income_limits (0.1.0)
ivc_champva (0.1.0)
meb_api (0.1.0)
mobile (0.1.0)
dry-validation
Expand Down Expand Up @@ -1157,6 +1158,7 @@ DEPENDENCIES
ice_nine
income_limits!
iso_country_codes
ivc_champva!
json
json-schema
json_schemer
Expand Down
1 change: 1 addition & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,7 @@
mount DebtsApi::Engine, at: '/debts_api'
mount DhpConnectedDevices::Engine, at: '/dhp_connected_devices'
mount FacilitiesApi::Engine, at: '/facilities_api'
mount IvcChampva::Engine, at: '/ivc_champva'
mount RepresentationManagement::Engine, at: '/representation_management'
mount SimpleFormsApi::Engine, at: '/simple_forms_api'
mount HealthQuest::Engine, at: '/health_quest'
Expand Down
16 changes: 16 additions & 0 deletions modules/ivc_champva/Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# frozen_string_literal: true

source 'https://rubygems.org'

# Declare your gem's dependencies in ivcchampva.gemspec.
# Bundler will treat runtime dependencies like base dependencies, and
# development dependencies will be added by default to the :development group.
gemspec

# Declare any dependencies that are still in development here instead of in
# your gemspec. These might include edge Rails or gems from your path or
# Git. Remember to move these dependencies to your gemspec before releasing
# your gem to rubygems.org.

# To use a debugger
# gem 'byebug', group: [:development, :test]
19 changes: 19 additions & 0 deletions modules/ivc_champva/README.rdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
= IvcChampva
This module allows you to generate form_mappings based on a PDF file.
With this in place, you can submit a form payload from the vets-website
and have this module map that payload to the associated PDF and submit it
to PEGA via S3.

To generate files:
rails ivc_champva:generate\['path to PDF file'\]

Submission endpoint:
/ivc_champva/v1/forms

== Installation
Ensure the following line is in the root project's Gemfile:

gem 'ivcchampva', path: 'modules/ivcchampva'

== License
This module is open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
31 changes: 31 additions & 0 deletions modules/ivc_champva/Rakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# frozen_string_literal: true

begin
require 'bundler/setup'
rescue LoadError
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
end

require 'rdoc/task'

RDoc::Task.new(:rdoc) do |rdoc|
rdoc.rdoc_dir = 'rdoc'
rdoc.title = 'IvcChampva'
rdoc.options << '--line-numbers'
rdoc.rdoc_files.include('README.md')
rdoc.rdoc_files.include('lib/**/*.rb')
end

load 'rails/tasks/statistics.rake'

require 'bundler/gem_tasks'

require 'rake/testtask'

Rake::TestTask.new(:test) do |t|
t.libs << 'test'
t.pattern = 'test/**/*_test.rb'
t.verbose = false
end

task default: :test
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# frozen_string_literal: true

module IvcChampva
module V1
class ApplicationController < ::ApplicationController
service_tag 'veteran-ivc-champva-forms'
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
# frozen_string_literal: true

require 'ddtrace'

module IvcChampva
module V1
class UploadsController < ApplicationController
skip_before_action :authenticate
before_action :authenticate, if: :should_authenticate
skip_after_action :set_csrf_header

FORM_NUMBER_MAP = {
'10-10D' => 'vha_10_10d',
'10-7959F-1' => 'vha_10_7959f_1',
'10-7959F-2' => 'vha_10_7959f_2'
}.freeze

UNAUTHENTICATED_FORMS = %w[].freeze

def submit
Datadog::Tracing.active_trace&.set_tag('form_id', params[:form_number])
form_id = get_form_id
parsed_form_data = JSON.parse(params.to_json)
file_paths, metadata = get_file_paths_and_metadata(parsed_form_data)
status, error_message = handle_uploads(form_id, metadata, file_paths)

render json: {
error_message:,
status:
}
rescue
puts 'A default error occurred while uploading a document.'
end

def submit_supporting_documents
if %w[10-10D].include?(params[:form_id])
attachment = PersistentAttachments::MilitaryRecords.new(form_id: params[:form_id])
attachment.file = params['file']
raise Common::Exceptions::ValidationErrors, attachment unless attachment.valid?

attachment.save
render json: attachment
end
end

def authenticate
super
rescue Common::Exceptions::Unauthorized
Rails.logger.info(
'IVC Champva - unauthenticated user submitting form',
{ form_number: params[:form_number] }
)
end

private

def get_file_paths_and_metadata(parsed_form_data)
form_id = get_form_id
form = "IvcChampva::#{form_id.titleize.gsub(' ', '')}".constantize.new(parsed_form_data)
filler = IvcChampva::PdfFiller.new(form_number: form_id, form:)

file_path = if @current_user
filler.generate(@current_user.loa[:current])
else
filler.generate
end

metadata = IvcChampva::MetadataValidator.validate(form.metadata)
file_paths = form.handle_attachments(file_path)

[file_paths, metadata]
end

def handle_uploads(form_id, metadata, pdf_file_paths)
meta_file_name = "#{form_id}_metadata.json"
meta_file_path = "tmp/#{meta_file_name}"

pdf_results =
pdf_file_paths.map do |pdf_file_path|
pdf_file_name = pdf_file_path.gsub('tmp/', '').gsub('-tmp', '')
upload_to_ivc_s3(pdf_file_name, pdf_file_path, metadata)
end

all_pdf_success = pdf_results.all? { |(status, _)| status == 200 }

if all_pdf_success
File.write(meta_file_path, metadata)
meta_upload_status, meta_upload_error_message = upload_to_ivc_s3(meta_file_name, meta_file_path)

if meta_upload_status == 200
FileUtils.rm_f(meta_file_path)
[meta_upload_status, nil]
else
[meta_upload_status, meta_upload_error_message]
end
else
[pdf_results]
end
end

def upload_to_ivc_s3(file_name, file_path, metadata = {})
case ivc_s3_client.put_object(file_name, file_path, metadata)
in { success: true }
[200]
in { success: false, error_message: error_message }
[400, error_message]
else
[500, 'Unexpected response from S3 upload']
end
end

def get_form_id
form_number = params[:form_number]
raise 'missing form_number in params' unless form_number

FORM_NUMBER_MAP[form_number]
end

def should_authenticate
true unless UNAUTHENTICATED_FORMS.include? params[:form_number]
end

def ivc_s3_client
@ivc_s3_client ||= IvcChampva::S3.new(
region: Settings.ivc_forms.s3.region,
access_key_id: Settings.ivc_forms.s3.aws_access_key_id,
secret_access_key: Settings.ivc_forms.s3.aws_secret_access_key,
bucket_name: Settings.ivc_forms.s3.bucket
)
end
end
end
end
74 changes: 74 additions & 0 deletions modules/ivc_champva/app/form_mappings/vha_10_10d.json.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
{
"form1[0].#subform[0].VeteransLastName[0]": "<%= form.data.dig('veteran', 'full_name', 'last') %>",
"form1[0].#subform[0].VeteransFirstName[0]": "<%= form.data.dig('veteran', 'full_name', 'first') %>",
"form1[0].#subform[0].VeteransMI[0]": "<%= form.data.dig('veteran', 'full_name', 'middle') %>",
"form1[0].#subform[0].VeteransSSN[0]": "<%= form.data.dig('veteran', 'ssn_or_tin') %>",
"form1[0].#subform[0].VAFileNumber[0]": "<%= form.data.dig('veteran', 'va_claim_number') %>",
"form1[0].#subform[0].VeteransStreetAddress[0]": "<%= form.data.dig('veteran', 'address', 'street') %>",
"form1[0].#subform[0].VeteransState[0]": "<%= form.data.dig('veteran', 'address', 'state') %>",
"form1[0].#subform[0].VeteransCity[0]": "<%= form.data.dig('veteran', 'address', 'city') %>",
"form1[0].#subform[0].VeteransZipCode[0]": "<%= form.data.dig('veteran', 'address', 'postal_code') %>",
"form1[0].#subform[0].VeteransPhoneNumber[0]": "<%= form.data.dig('veteran', 'phone_number') %>",
"form1[0].#subform[0].VeteransDateOfBirth[0]": "<%= form.data.dig('veteran', 'date_of_birth') %>",
"form1[0].#subform[0].VeteransDateOfMarriage[0]": "<%= form.data.dig('veteran', 'date_of_marriage') %>",
"form1[0].#subform[0].IsTheVeteranDeceased[0]": "<%= form.data.dig('veteran', 'is_deceased') ? 1 : 0 %>",
"form1[0].#subform[0].VeteransDateOfDeath[0]": "<%= form.data.dig('veteran', 'date_of_death') %>",
"form1[0].#subform[0].DieOnActiveMilitaryService[0]": "<%= form.data.dig('veteran', 'is_active_service_death') ? 1 : 0 %>",
"form1[0].#subform[0].LastName1[0]": "<%= form.data['applicants'][0]&.dig('full_name', 'last') %>",
"form1[0].#subform[0].FirstName1[0]": "<%= form.data['applicants'][0]&.dig('full_name', 'first') %>",
"form1[0].#subform[0].MI1[0]": "<%= form.data['applicants'][0]&.dig('full_name', 'middle') %>",
"form1[0].#subform[0].SSN1[0]": "<%= form.data['applicants'][0]&.dig('ssn_or_tin') %>",
"form1[0].#subform[0].StreetAddress1[0]": "<%= form.data['applicants'][0]&.dig('address', 'street') %>",
"form1[0].#subform[0].City1[0]": "<%= form.data['applicants'][0]&.dig('address', 'city') %>",
"form1[0].#subform[0].ZipCode1[0]": "<%= form.data['applicants'][0]&.dig('address', 'postal_code') %>",
"form1[0].#subform[0].DateOfBirth1[0]": "<%= form.data['applicants'][0]&.dig('date_of_birth') %>",
"form1[0].#subform[0].EmailAddress1[0]": "<%= form.data['applicants'][0]&.dig('email') %>",
"form1[0].#subform[0].PhoneNumber1[0]": "<%= form.data['applicants'][0]&.dig('phone_number') %>",
"form1[0].#subform[0].Gender1[0]": "<%= form.data['applicants'][0]&.dig('gender') ? 1 : 0 %>",
"form1[0].#subform[0].EnrolledMedicare[0]": "<%= form.data['applicants'][0]&.dig('is_enrolled_in_medicare') ? 1 : 0 %>",
"form1[0].#subform[0].HasOtherInsurance[0]": "<%= form.data['applicants'][0]&.dig('has_other_health_insurance') ? 1 : 0 %>",
"form1[0].#subform[0].RelationshipToVeteran1[0]": "<%= form.data['applicants'][0]&.dig('vet_relationship') %>",
"form1[0].#subform[0].State1[0]": "<%= form.data['applicants'][0]&.dig('address', 'state') %>",
"form1[0].#subform[0].LastName2[0]": "<%= form.data['applicants'][1]&.dig('full_name', 'last') %>",
"form1[0].#subform[0].FirstName2[0]": "<%= form.data['applicants'][1]&.dig('full_name', 'first') %>",
"form1[0].#subform[0].MI2[0]": "<%= form.data['applicants'][1]&.dig('full_name', 'middle') %>",
"form1[0].#subform[0].SSN2[0]": "<%= form.data['applicants'][1]&.dig('ssn_or_tin') %>",
"form1[0].#subform[0].StreetAddress2[0]": "<%= form.data['applicants'][1]&.dig('address', 'street') %>",
"form1[0].#subform[0].City2[0]": "<%= form.data['applicants'][1]&.dig('address', 'city') %>",
"form1[0].#subform[0].ZipCode2[0]": "<%= form.data['applicants'][1]&.dig('address', 'postal_code') %>",
"form1[0].#subform[0].DateOfBirth2[0]": "<%= form.data['applicants'][1]&.dig('date_of_birth') %>",
"form1[0].#subform[0].EmailAddress2[0]": "<%= form.data['applicants'][1]&.dig('email') %>",
"form1[0].#subform[0].PhoneNumber2[0]": "<%= form.data['applicants'][1]&.dig('phone_number') %>",
"form1[0].#subform[0].Gender2[0]": "<%= form.data['applicants'][1]&.dig('gender') ? 1 : 0 %>",
"form1[0].#subform[0].EnrolledMedicare[1]": "<%= form.data['applicants'][1]&.dig('is_enrolled_in_medicare') ? 1 : 0 %>",
"form1[0].#subform[0].HasOtherInsurance[1]": "<%= form.data['applicants'][1]&.dig('has_other_health_insurance') ? 1 : 0 %>",
"form1[0].#subform[0].RelationshipToVeteran2[0]": "<%= form.data['applicants'][1]&.dig('vet_relationship') %>",
"form1[0].#subform[0].State2[0]": "<%= form.data['applicants'][1]&.dig('address', 'state') %>",
"form1[0].#subform[0].LastName3[0]": "<%= form.data['applicants'][2]&.dig('full_name', 'last') %>",
"form1[0].#subform[0].FirstName3[0]": "<%= form.data['applicants'][2]&.dig('full_name', 'first') %>",
"form1[0].#subform[0].MI3[0]": "<%= form.data['applicants'][2]&.dig('full_name', 'middle') %>",
"form1[0].#subform[0].SSN3[0]": "<%= form.data['applicants'][2]&.dig('ssn_or_tin') %>",
"form1[0].#subform[0].StreetAddress3[0]": "<%= form.data['applicants'][2]&.dig('address', 'street') %>",
"form1[0].#subform[0].City3[0]": "<%= form.data['applicants'][2]&.dig('address', 'city') %>",
"form1[0].#subform[0].ZipCode3[0]": "<%= form.data['applicants'][2]&.dig('address', 'postal_code') %>",
"form1[0].#subform[0].DateOfBirth3[0]": "<%= form.data['applicants'][2]&.dig('date_of_birth') %>",
"form1[0].#subform[0].EmailAddress3[0]": "<%= form.data['applicants'][2]&.dig('email') %>",
"form1[0].#subform[0].PhoneNumber3[0]": "<%= form.data['applicants'][2]&.dig('phone_number') %>",
"form1[0].#subform[0].Gender3[0]": "<%= form.data['applicants'][2]&.dig('gender') ? 1 : 0 %>",
"form1[0].#subform[0].EnrolledMedicare[2]": "<%= form.data['applicants'][2]&.dig('is_enrolled_in_medicare') ? 1 : 0 %>",
"form1[0].#subform[0].HasOtherInsurance[2]": "<%= form.data['applicants'][2]&.dig('has_other_health_insurance') ? 1 : 0 %>",
"form1[0].#subform[0].RelationshipToVeteran3[0]": "<%= form.data['applicants'][2]&.dig('vet_relationship') %>",
"form1[0].#subform[0].State3[0]": "<%= form.data['applicants'][2]&.dig('address', 'state') %>",
"form1[0].#subform[0].DateSigned[0]": "<%= form.data.dig('certification', 'date') %>",
"form1[0].#subform[0].SignatureField11[0]": "<%= form.data['statement_of_truth_signature'] %>",
"form1[0].#subform[0].LastName4[0]": "<%= form.data.dig('certification', 'lastName') %>",
"form1[0].#subform[0].FirstName4[0]": "<%= form.data.dig('certification', 'firstName') %>",
"form1[0].#subform[0].MI4[0]": "<%= form.data.dig('certification', 'middleInitial') %>",
"form1[0].#subform[0].StreetAddress4[0]": "<%= form.data.dig('certification', 'streetAddress') %>",
"form1[0].#subform[0].City4[0]": "<%= form.data.dig('certification', 'city') %>",
"form1[0].#subform[0].ZipCode4[0]": "<%= form.data.dig('certification', 'postal_code') %>",
"form1[0].#subform[0].State4[0]": "<%= form.data.dig('certification', 'state') %>",
"form1[0].#subform[0].RelationshipToApplicants[0]": "<%= form.data.dig('certification', 'relationship') %>",
"form1[0].#subform[0].PhoneNumber4[0]": "<%= form.data.dig('certification', 'phone_number') %>",
"form1[0]": "<%= form.data.dig('form1') %>"
}
Loading
Loading