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 #16091

Merged
merged 20 commits into from
Mar 29, 2024
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
8fcd1f8
72706: Initial commit for IVC ChampVA Module
balexandr Mar 22, 2024
8f28fe5
Merge branch 'master' into 72706-create-ivcchampva-module
balexandr Mar 25, 2024
2494184
72706: Update logic tto appease Rubocop and tests
balexandr Mar 26, 2024
841c74e
Merge branch 'master' into 72706-create-ivcchampva-module
balexandr Mar 26, 2024
eccea51
72706: Add middle name to metadata for S3
balexandr Mar 26, 2024
e8d63b3
72706: Push gemfile.lock updates
balexandr Mar 26, 2024
b0ab3f7
72706: Clean up Gemfile.lock; Remove old file from copy
balexandr Mar 26, 2024
d5676f1
72706: A bit more cleanup for gemfile.lock
balexandr Mar 26, 2024
69be329
Merge branch 'master' into 72706-create-ivcchampva-module
balexandr Mar 26, 2024
86b1798
72706: Create FileUploader to break out of controller code; Add specs
balexandr Mar 27, 2024
9943046
Merge branch 'master' into 72706-create-ivcchampva-module
balexandr Mar 27, 2024
c2b2516
72706: Clean up JSON being rendered
balexandr Mar 27, 2024
fe6c48c
72706: Wraop submit in DD logic for monitoring
balexandr Mar 27, 2024
36bdc6e
72706: Typo!
balexandr Mar 27, 2024
5969200
72706: Update logic to add file attachments for 10-7959f-2
balexandr Mar 27, 2024
84654f6
72706: Move attachment logic to own file
balexandr Mar 27, 2024
b327a27
Merge branch 'master' into 72706-create-ivcchampva-module
balexandr Mar 29, 2024
85f7e53
72706: Add some more test coverage; Add logic for 10-7959c; Update PD…
balexandr Mar 29, 2024
b9f9d79
Merge branch 'master' into 72706-create-ivcchampva-module
balexandr Mar 29, 2024
4e3e0b4
72706: Update logic to remove unencessary pieces
balexandr Mar 29, 2024
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,101 @@
# frozen_string_literal: true

require 'ddtrace'

module IvcChampva
module V1
class UploadsController < ApplicationController
skip_before_action :authenticate
before_action :authenticate, if: :should_authenticate
balexandr marked this conversation as resolved.
Show resolved Hide resolved
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

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].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
balexandr marked this conversation as resolved.
Show resolved Hide resolved
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 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 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
Loading