Skip to content

Commit a6375eb

Browse files
authored
Ksoskin/120379/claim date backup path bug take 2 (#24472)
* Adding date tests and pass through * Rubocoping * Adding in accidentially removed test * Addressing copilot stuff * let! * Adding in a flipper * rubocop * Correcting flipper * Rubocop * trying again * making better flage name * Putting back * Take 2 * Rubocop * Adding in test to check/confirm transform matches schema * Replicating so I dont need to instantiate the entire middleware for a test * Adding clarifying comment (requested) * Adding a rescue * Contant adding * Fixing linting
1 parent f116655 commit a6375eb

File tree

8 files changed

+298
-7
lines changed

8 files changed

+298
-7
lines changed

config/features.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -793,6 +793,10 @@ features:
793793
disability_526_track_saved_claim_error:
794794
actor_type: user
795795
description: enables improved logging of SavedClaim::DisabilityCompensation::Form526AllClaim save failures
796+
disability_526_add_claim_date_to_lighthouse:
797+
actor_type: user
798+
description: enables sending the claim date to Lighthouse when submitting a Form 526EZ when present
799+
enable_in_development: true
796800
disability_526_block_banking_info_retrieval:
797801
actor_type: user
798802
description: disables call to Lighthouse Direct Deposit API to fill in banking information without Veteran consent

lib/disability_compensation/providers/generate_pdf/lighthouse_generate_pdf_provider.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ def generate_526_pdf(form_content, transaction_id)
1616
end
1717

1818
def transform_service
19-
@transform_service ||= EVSS::DisabilityCompensationForm::Form526ToLighthouseTransform.new
19+
@transform_service ||= EVSS::DisabilityCompensationForm::Form526ToLighthouseTransform.new(pdf_request: true)
2020
end
2121

2222
def service

lib/disability_compensation/requests/form526_request_body.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,4 +299,9 @@ class Form526
299299
attribute :direct_deposit, DirectDeposit
300300
attribute :claim_notes, String
301301
end
302+
303+
# Currently only used for the getPDF LH Claims API endpoint for backup 526 submissions
304+
class Form526Pdf < Form526
305+
attribute :claim_date, String, default: nil
306+
end
302307
end

lib/evss/disability_compensation_form/form526_to_lighthouse_transform.rb

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
module EVSS
66
module DisabilityCompensationForm
77
class Form526ToLighthouseTransform # rubocop:disable Metrics/ClassLength
8+
VALID_LH_DATE_REGEX = /^(\d{4})-(\d{2})-(\d{2})$/
9+
810
TOXIC_EXPOSURE_CAUSE_MAP = {
911
NEW: 'My condition was caused by an injury or exposure during my military service.',
1012
WORSENED: 'My condition existed before I served in the military, but it got worse because of my military ' \
@@ -77,21 +79,24 @@ class Form526ToLighthouseTransform # rubocop:disable Metrics/ClassLength
7779
hazard: 'hazard'
7880
}.freeze
7981

82+
def initialize(pdf_request: false)
83+
@pdf_request = pdf_request
84+
end
85+
8086
# takes known EVSS Form526Submission format and converts it to a Lighthouse request body
8187
# @param evss_data will look like JSON.parse(form526_submission.form_data)
8288
# @return Requests::Form526
8389
def transform(evss_data)
8490
form526 = evss_data['form526']
85-
lh_request_body = Requests::Form526.new
91+
lh_request_body = choose_request_body(form526)
8692
lh_request_body.claimant_certification = true
8793
lh_request_body.claim_process_type = evss_claims_process_type(form526) # basic_info[:claim_process_type]
8894

8995
transform_veteran_section(form526, lh_request_body)
9096

91-
service_information = form526['serviceInformation']
92-
if service_information.present?
93-
lh_request_body.service_information = transform_service_information(service_information)
94-
end
97+
service_info = form526['serviceInformation']
98+
99+
lh_request_body.service_information = transform_service_information(service_info) if service_info.present?
95100

96101
transform_disabilities_section(form526, lh_request_body)
97102

@@ -108,11 +113,40 @@ def transform(evss_data)
108113
lh_request_body.toxic_exposure = transform_toxic_exposure(toxic_exposure) if toxic_exposure.present?
109114

110115
lh_request_body.claim_notes = form526['overflowText']
116+
111117
lh_request_body
112118
end
113119

114120
private
115121

122+
def valid_date_for_lighthouse?(date_string)
123+
date_string =~ VALID_LH_DATE_REGEX
124+
end
125+
126+
def claim_date_valid?(claim_date)
127+
claim_date.present? && valid_date_for_lighthouse?(claim_date)
128+
end
129+
130+
def choose_request_body(form526)
131+
claim_date = form526['claimDate']
132+
# if the request is for a PDF, and the claim date is present and valid, use the PDF request body
133+
if Flipper.enabled?(:disability_526_add_claim_date_to_lighthouse) &&
134+
@pdf_request &&
135+
claim_date_valid?(claim_date)
136+
lh_request_body = Requests::Form526Pdf.new
137+
lh_request_body.claim_date = form526['claimDate']
138+
lh_request_body
139+
else
140+
# if the request is not for a PDF, or the claim date is not present or invalid, use the standard request body
141+
# that does not include claim_date, otherwise, it will error Lighthouse's validation
142+
Requests::Form526.new
143+
end
144+
rescue => e
145+
# If anything goes wrong, rescue to using the non-pdf request
146+
Rails.logger.error("Error transforming Form526 to Lighthouse: #{e.message}")
147+
Requests::Form526.new
148+
end
149+
116150
# returns "STANDARD_CLAIM_PROCESS", "BDD_PROGRAM", or "FDC_PROGRAM"
117151
# based off of a few attributes in the evss data
118152
def evss_claims_process_type(form526)

lib/sidekiq/form526_backup_submission_process/processor.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ def write_to_tmp_file(content, ext = 'pdf')
327327

328328
def get_form526_pdf
329329
headers = submission.auth_headers
330-
submission_create_date = submission.created_at.iso8601
330+
submission_create_date = submission.created_at.strftime('%Y-%m-%d')
331331
form_json = submission.form[FORM_526]
332332
form_json[FORM_526]['claimDate'] ||= submission_create_date
333333
form_json[FORM_526]['applicationExpirationDate'] = 365.days.from_now.iso8601 if @ignore_expiration

spec/lib/disability_compensation/requests/form526_requests_body_spec.rb

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@
1515
expect(form).to respond_to(:claim_process_type)
1616
end
1717

18+
# this is the only difference between Form526 and Form526Pdf
19+
it 'does not have claim_date attribute' do
20+
expect(form).not_to respond_to(:claim_date)
21+
end
22+
1823
# TODO: revisit if LH adds it back to the request
1924
# it 'has claim_date attribute' do
2025
# expect(form).to respond_to(:claim_date)
@@ -57,6 +62,59 @@
5762
end
5863
end
5964

65+
describe Requests::Form526Pdf do
66+
let(:form) { Requests::Form526Pdf.new }
67+
68+
it 'has claimant_certification attribute' do
69+
expect(form).to respond_to(:claimant_certification)
70+
end
71+
72+
it 'has claim_process_type attribute' do
73+
expect(form).to respond_to(:claim_process_type)
74+
end
75+
76+
# this is the only difference between Form526 and Form526Pdf
77+
it 'has claim_date attribute' do
78+
expect(form).to respond_to(:claim_date)
79+
end
80+
81+
it 'has veteran_identification attribute' do
82+
expect(form).to respond_to(:veteran_identification)
83+
end
84+
85+
it 'has change_of_address attribute' do
86+
expect(form).to respond_to(:change_of_address)
87+
end
88+
89+
it 'has homeless attribute' do
90+
expect(form).to respond_to(:homeless)
91+
end
92+
93+
it 'has toxic_exposure attribute' do
94+
expect(form).to respond_to(:toxic_exposure)
95+
end
96+
97+
it 'has disabilities attribute' do
98+
expect(form).to respond_to(:disabilities)
99+
end
100+
101+
it 'has treatments attribute' do
102+
expect(form).to respond_to(:treatments)
103+
end
104+
105+
it 'has service_information attribute' do
106+
expect(form).to respond_to(:service_information)
107+
end
108+
109+
it 'has service_pay attribute' do
110+
expect(form).to respond_to(:service_pay)
111+
end
112+
113+
it 'has direct_deposit attribute' do
114+
expect(form).to respond_to(:direct_deposit)
115+
end
116+
end
117+
60118
describe Requests::VeteranIdentification do
61119
let(:veteran) { Requests::VeteranIdentification.new }
62120

spec/lib/evss/disability_compensation_form/form526_to_lighthouse_transform_spec.rb

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,55 @@
11
# frozen_string_literal: true
22

33
require 'rails_helper'
4+
require 'claims_api/form_schemas'
5+
require 'json_schema/json_api_missing_attribute'
46
require 'evss/disability_compensation_form/form526_to_lighthouse_transform'
57

8+
LH_SCHEMA_KEY = 'GENERATE_PDF_526'
9+
610
RSpec.describe EVSS::DisabilityCompensationForm::Form526ToLighthouseTransform do
711
let(:transformer) { subject }
12+
let(:pdf_enabled_transformer) { EVSS::DisabilityCompensationForm::Form526ToLighthouseTransform.new(pdf_request: true) }
13+
let(:pdf_disabled_transformer) { EVSS::DisabilityCompensationForm::Form526ToLighthouseTransform.new(pdf_request: false) }
14+
15+
def validate_lighthouse_schema(lh_request_body)
16+
# This validation method mimics the same validation logic used in the actual controller
17+
# https://github.com/department-of-veterans-affairs/vets-api/blob/master/modules/claims_api/app/controllers/claims_api/v2/veterans/base.rb#L18
18+
validator = ClaimsApi::FormSchemas.new(schema_version: 'v2')
19+
20+
# Convert the Vets::Model object to a hash and transform keys using the exact same
21+
# transformation as the actual controller pipeline (OliveBranch with VA key patch)
22+
request_body_hash = lh_request_body.as_json
23+
camelized_request_body = transform_with_olivebranch(request_body_hash)
24+
25+
validator.validate!(LH_SCHEMA_KEY, camelized_request_body)
26+
end
27+
28+
private
29+
30+
# Use the exact same transformation as the controller pipeline:
31+
# OliveBranch transformation with VA key patch applied using the actual middleware logic
32+
def transform_with_olivebranch(data)
33+
# Transform using OliveBranch (same as the actual controller)
34+
camelized = OliveBranch::Transformations.transform(
35+
data,
36+
OliveBranch::Transformations.method(:camelize)
37+
)
38+
39+
# Apply the VA key patch using the same regex and logic as the middleware
40+
json_string = camelized.to_json
41+
# Use the same VA_KEY_REGEX pattern and gsub logic as the middleware extension
42+
json_string.gsub!(/("[^"]+VA[^"]*"):/) do
43+
key = Regexp.last_match(1)
44+
"#{key.gsub('VA', 'Va')}:"
45+
end
46+
47+
JSON.parse(json_string)
48+
end
49+
50+
def expect_no_lighthouse_errors(lh_request_body)
51+
expect { validate_lighthouse_schema(lh_request_body) }.not_to raise_error
52+
end
853

954
describe '#transform' do
1055
let(:submission) { create(:form526_submission, :with_everything_toxic_exposure) }
@@ -13,6 +58,59 @@
1358
it 'sets claimant_certification to true in the Lighthouse request body' do
1459
lh_request_body = transformer.transform(data)
1560
expect(lh_request_body.claimant_certification).to be(true)
61+
expect_no_lighthouse_errors(lh_request_body)
62+
end
63+
64+
it 'adds claim_date to the Lighthouse request body if called as a pdf request' do
65+
data['form526']['claimDate'] = '2023-07-19' # arbitrary date
66+
lh_request_body = pdf_enabled_transformer.transform(data)
67+
expect(lh_request_body.class).to eq(Requests::Form526Pdf)
68+
expect(lh_request_body.claim_date).to eq('2023-07-19')
69+
expect_no_lighthouse_errors(lh_request_body)
70+
end
71+
72+
it 'does not add claim_date to the Lighthouse request body if called as a non-pdf request' do
73+
data['form526']['claimDate'] = '2023-07-19' # arbitrary date
74+
lh_request_body = pdf_disabled_transformer.transform(data)
75+
expect(lh_request_body.class).to eq(Requests::Form526)
76+
expect { lh_request_body.claim_date }.to raise_error(NoMethodError)
77+
expect_no_lighthouse_errors(lh_request_body)
78+
end
79+
80+
it 'does not add claim_date to the Lighthouse request body if called without a pdf flag' do
81+
data['form526']['claimDate'] = '2023-07-19' # arbitrary date
82+
lh_request_body = transformer.transform(data)
83+
expect(lh_request_body.class).to eq(Requests::Form526)
84+
expect { lh_request_body.claim_date }.to raise_error(NoMethodError)
85+
expect_no_lighthouse_errors(lh_request_body)
86+
end
87+
88+
it 'does not add claim_date attribute to the Lighthouse request body key if nil' do
89+
data['form526']['claimDate'] = nil
90+
lh_request_body = transformer.transform(data)
91+
expect { lh_request_body.claim_date }.to raise_error(NoMethodError)
92+
expect_no_lighthouse_errors(lh_request_body)
93+
end
94+
95+
it 'does not add claim_date attribute to the Lighthouse request body if not provided at all' do
96+
data['form526'].delete('claimDate')
97+
lh_request_body = transformer.transform(data)
98+
expect { lh_request_body.claim_date }.to raise_error(NoMethodError)
99+
expect_no_lighthouse_errors(lh_request_body)
100+
end
101+
102+
it 'does not add claim_date to the Lighthouse request body if blank' do
103+
data['form526']['claimDate'] = ''
104+
lh_request_body = transformer.transform(data)
105+
expect { lh_request_body.claim_date }.to raise_error(NoMethodError)
106+
expect_no_lighthouse_errors(lh_request_body)
107+
end
108+
109+
it 'does not add claim_date attribute to the Lighthouse request body if malformed date' do
110+
data['form526']['claimDate'] = 'invalid-date'
111+
lh_request_body = transformer.transform(data)
112+
expect { lh_request_body.claim_date }.to raise_error(NoMethodError)
113+
expect_no_lighthouse_errors(lh_request_body)
16114
end
17115

18116
# TODO: re-visit once we get clarification on whether claimDate needs to be restored to LH request
@@ -52,6 +150,7 @@
52150
expect(result.toxic_exposure.additional_hazard_exposures.class).to eq(Requests::AdditionalHazardExposures)
53151
expect(result.toxic_exposure.multiple_exposures.class).to eq(Array)
54152
expect(result.claim_notes).to eq('some overflow text')
153+
expect_no_lighthouse_errors(result)
55154
end
56155

57156
it 'sends uniq values in multiple exposures array' do
@@ -79,6 +178,7 @@
79178
result = transformer.transform(data)
80179
# since this is now a uniq list, it is now 12 items instead of 13
81180
expect(result.toxic_exposure.multiple_exposures.count).to eq(12)
181+
expect_no_lighthouse_errors(result)
82182
end
83183
end
84184

@@ -93,6 +193,7 @@
93193
expect(result.direct_deposit).to be_nil
94194
expect(result.treatments).to eq([])
95195
expect(result.service_pay).to be_nil
196+
expect_no_lighthouse_errors(result)
96197
end
97198
end
98199

@@ -128,6 +229,7 @@
128229
expect(result.toxic_exposure.multiple_exposures.first.hazard_exposed_to).to be_nil
129230
expect(result.toxic_exposure.multiple_exposures.last.exposure_location).to be_nil
130231
expect(result.toxic_exposure.multiple_exposures.last.hazard_exposed_to).to eq('specifyOtherExposures')
232+
expect_no_lighthouse_errors(result)
131233
end
132234

133235
it 'is not processed if missing descriptions' do
@@ -153,6 +255,7 @@
153255
# nothing should have been processed for MultipleExposures because
154256
# all of the details are missing and the descriptions are missing in the "other" objects
155257
expect(result.toxic_exposure.multiple_exposures).to eq([])
258+
expect_no_lighthouse_errors(result)
156259
end
157260
end
158261
end

0 commit comments

Comments
 (0)