Skip to content

Commit

Permalink
72706 Create ivc_champva Module (#16091)
Browse files Browse the repository at this point in the history
* 72706: Initial commit for IVC ChampVA Module

* 72706: Update logic tto appease Rubocop and tests

* 72706: Add middle name to metadata for S3

* 72706: Push gemfile.lock updates

* 72706: Clean up Gemfile.lock; Remove old file from copy

* 72706: A bit more cleanup for gemfile.lock

* 72706: Create FileUploader to break out of controller code; Add specs

* 72706: Clean up JSON being rendered

* 72706: Wraop submit in DD logic for monitoring

* 72706: Typo!

* 72706: Update logic to add file attachments for 10-7959f-2

* 72706: Move attachment logic to own file

* 72706: Add some more test coverage; Add logic for 10-7959c; Update PDF stamper with platform updates

* 72706: Update logic to remove unencessary pieces
  • Loading branch information
balexandr authored Mar 29, 2024
1 parent 1bfc2aa commit 99fea10
Show file tree
Hide file tree
Showing 53 changed files with 5,528 additions and 0 deletions.
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,100 @@
# frozen_string_literal: true

require 'ddtrace'

module IvcChampva
module V1
class UploadsController < ApplicationController
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',
'10-7959C' => 'vha_10_7959c'
}.freeze

def submit
Datadog::Tracing.trace('Start IVC File Submission') do
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 = FileUploader.new(form_id, metadata, file_paths).handle_uploads

render json: build_json(Array(status), error_message)
rescue
puts 'An unknown error occurred while uploading document(s).'
end
end

def submit_supporting_documents
if %w[10-10D 10-7959F-2].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

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 get_form_id
form_number = params[:form_number]
raise 'missing form_number in params' unless form_number

FORM_NUMBER_MAP[form_number]
end

def build_json(status, error_message)
if status.all? { |s| s == 200 }
{
status: 200
}
elsif status.all? { |s| s == 400 }
{
error_message:,
status: 400
}
else
{
error_message: 'Partial upload failure',
status: 206
}
end
end

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

def should_authenticate
true
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

0 comments on commit 99fea10

Please sign in to comment.