Module: Form526ClaimFastTrackingConcern
- Extended by:
- ActiveSupport::Concern
- Included in:
- Form526Submission
- Defined in:
- app/models/concerns/form526_claim_fast_tracking_concern.rb
Overview
rubocop:disable Metrics/ModuleLength For use with Form526Submission
Constant Summary collapse
- RRD_STATSD_KEY_PREFIX =
'worker.rapid_ready_for_decision'
- MAX_CFI_STATSD_KEY_PREFIX =
'api.max_cfi'
- EP_MERGE_STATSD_KEY_PREFIX =
'worker.ep_merge'
- FLASHES_STATSD_KEY =
'worker.flashes'
- FLASH_PROTOTYPES =
['Amyotrophic Lateral Sclerosis'].freeze
- EP_MERGE_BASE_CODES =
%w[010 110 020].freeze
- EP_MERGE_SPECIAL_ISSUE =
'EMP'
- OPEN_STATUSES =
[ 'CLAIM RECEIVED', 'UNDER REVIEW', 'GATHERING OF EVIDENCE', 'REVIEW OF EVIDENCE', 'CLAIM_RECEIVED', 'INITIAL_REVIEW' ].freeze
- CLAIM_REVIEW_BASE_CODES =
%w[030 040].freeze
- CLAIM_REVIEW_TYPES =
%w[higherLevelReview supplementalClaim].freeze
- DOCUMENT_NAME_PREFIX =
'VAMC'
- DOCUMENT_NAME_SUFFIX =
'Rapid_Decision_Evidence'
- PDF_FILENAME_REGEX =
/#{DOCUMENT_NAME_PREFIX}.*#{DOCUMENT_NAME_SUFFIX}/
- RRD_CODE =
'RRD'
Instance Method Summary collapse
- #add_ep_merge_special_issue! ⇒ Object
-
#all_rated_disabilities ⇒ Object
private
fetch, memoize, and return all of the veteran’s rated disabilities from EVSS.
-
#cfi_checkbox_was_selected? ⇒ Boolean
return whether the associated InProgressForm ever logged that the CFI checkbox was selected.
- #claim_age_in_days(pending_ep) ⇒ Object
- #classify_vagov_contentions(params) ⇒ Object
- #conditionally_merge_ep ⇒ Object private
- #conditionally_notify_mas ⇒ Object private
- #diagnostic_codes ⇒ Object
- #disabilities ⇒ Object
-
#disabilities_not_service_connected? ⇒ Boolean
return whether all disabilities on this form are rated as not service-connected.
- #ep_merge_feature_enabled? ⇒ Boolean
- #flashes ⇒ Object
- #format_contention_for_vro(disability) ⇒ Object
- #in_progress_form ⇒ Object private
- #increase_disabilities ⇒ Object
- #log_and_halt_if_no_disabilities ⇒ Object
- #log_claim_level_metrics(response_body) ⇒ Object
- #log_flashes ⇒ Object private
- #log_max_cfi_metrics_on_submit ⇒ Object
- #max_rated_diagnostic_codes_from_ipf ⇒ Object private
- #max_rated_disabilities_from_ipf ⇒ Object private
- #notify_mas_all_claims_tracking ⇒ Object private
-
#open_claim_review? ⇒ Boolean
private
Check both Benefits Claim service and Caseflow Appeals status APIs for open 030 or 040 Offramps EP 400 Merge process if any are found, or if anything fails.
-
#open_claims ⇒ Object
private
Fetch and memoize all of the veteran’s open EPs.
-
#pending_eps? ⇒ Boolean
Fetch all claims from EVSS.
- #prepare_for_ep_merge! ⇒ Object
- #prepare_for_evss! ⇒ Object
- #read_metadata(key) ⇒ Object
-
#rrd_claim_processed? ⇒ Boolean
private
If this claim submission was processed and fast-tracked by RRD.
-
#rrd_pdf_added_for_uploading? ⇒ Boolean
If an RRD pdf has been included as a file to upload.
- #rrd_pdf_created? ⇒ Boolean
- #rrd_pdf_uploaded_to_s3? ⇒ Boolean
- #rrd_special_issue_set? ⇒ Boolean
- #rrd_status ⇒ Object
- #save_metadata(metadata_hash) ⇒ Object
- #send_post_evss_notifications! ⇒ Object
- #send_rrd_alert_email(subject, message, error = nil, to = Settings.rrd.alerts.recipients) ⇒ Object
-
#update_contention_classification_all! ⇒ Object
Submits contention information to the VRO contention classification service adds classification to the form for each contention provided a classification.
- #update_form_with_classification_codes(classified_contentions) ⇒ Object
Instance Method Details
#add_ep_merge_special_issue! ⇒ Object
271 272 273 274 275 276 277 |
# File 'app/models/concerns/form526_claim_fast_tracking_concern.rb', line 271 def add_ep_merge_special_issue! disabilities.each do |disability| disability['specialIssues'] ||= [] disability['specialIssues'].append(EP_MERGE_SPECIAL_ISSUE).uniq! end update!(form_json: JSON.dump(form)) end |
#all_rated_disabilities ⇒ Object (private)
fetch, memoize, and return all of the veteran’s rated disabilities from EVSS
353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 |
# File 'app/models/concerns/form526_claim_fast_tracking_concern.rb', line 353 def all_rated_disabilities settings = Settings.lighthouse.veteran_verification.form526 icn = account&.icn invoker = 'Form526ClaimFastTrackingConcern#all_rated_disabilities' api_provider = ApiProviderFactory.call( type: ApiProviderFactory::FACTORIES[:rated_disabilities], provider: nil, options: { auth_headers:, icn: }, # Flipper id is needed to check if the feature toggle works for this user current_user: OpenStruct.new({ flipper_id: user_account_id }), feature_toggle: ApiProviderFactory::FEATURE_TOGGLE_RATED_DISABILITIES_BACKGROUND ) @all_rated_disabilities ||= begin response = api_provider.get_rated_disabilities( settings.access_token.client_id, settings.access_token.rsa_key, { invoker: } ) response.rated_disabilities end end |
#cfi_checkbox_was_selected? ⇒ Boolean
return whether the associated InProgressForm ever logged that the CFI checkbox was selected
265 266 267 268 269 |
# File 'app/models/concerns/form526_claim_fast_tracking_concern.rb', line 265 def cfi_checkbox_was_selected? return false if in_progress_form.nil? ClaimFastTracking::MaxCfiMetrics.new(in_progress_form, {}).['cfiLogged'] end |
#claim_age_in_days(pending_ep) ⇒ Object
31 32 33 34 35 36 37 38 |
# File 'app/models/concerns/form526_claim_fast_tracking_concern.rb', line 31 def claim_age_in_days(pending_ep) date = if pending_ep.respond_to?(:claim_date) Date.strptime(pending_ep.claim_date, '%Y-%m-%d') else Date.strptime(pending_ep['date'], '%m/%d/%Y') end (Time.zone.today - date).round end |
#classify_vagov_contentions(params) ⇒ Object
168 169 170 171 172 173 174 175 176 177 178 179 |
# File 'app/models/concerns/form526_claim_fast_tracking_concern.rb', line 168 def classify_vagov_contentions(params) user = OpenStruct.new({ flipper_id: user_uuid }) vro_client = VirtualRegionalOffice::Client.new response = if Flipper.enabled?(:disability_526_expanded_contention_classification, user) vro_client.(params) else vro_client.classify_vagov_contentions(params) end response.body end |
#conditionally_merge_ep ⇒ Object (private)
404 405 406 407 408 409 410 411 412 |
# File 'app/models/concerns/form526_claim_fast_tracking_concern.rb', line 404 def conditionally_merge_ep pending_claim_id = (:ep_merge_pending_claim_id) return if pending_claim_id.blank? vro_client = VirtualRegionalOffice::Client.new vro_client.merge_end_products(pending_claim_id:, ep400_id: submitted_claim_id) rescue => e Rails.logger.error("EP merge request failed #{e.}.", backtrace: e.backtrace) end |
#conditionally_notify_mas ⇒ Object (private)
385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 |
# File 'app/models/concerns/form526_claim_fast_tracking_concern.rb', line 385 def conditionally_notify_mas return unless (:forward_to_mas_all_claims) notify_mas_all_claims_tracking client = MailAutomation::Client.new({ file_number: birls_id, claim_id: submitted_claim_id, form526: form }) response = client.initiate_apcas_processing mas_packet_id = response&.body ? response.body['packetId'] : nil (mas_packetId: mas_packet_id) StatsD.increment("#{RRD_STATSD_KEY_PREFIX}.notify_mas.success") rescue => e send_rrd_alert_email("Failure: MA claim - #{submitted_claim_id}", e.to_s, nil, Settings.rrd.mas_tracking.recipients) StatsD.increment("#{RRD_STATSD_KEY_PREFIX}.notify_mas.failure") end |
#diagnostic_codes ⇒ Object
115 116 117 |
# File 'app/models/concerns/form526_claim_fast_tracking_concern.rb', line 115 def diagnostic_codes disabilities.pluck('diagnosticCode') end |
#disabilities ⇒ Object
107 108 109 |
# File 'app/models/concerns/form526_claim_fast_tracking_concern.rb', line 107 def disabilities form.dig('form526', 'form526', 'disabilities') end |
#disabilities_not_service_connected? ⇒ Boolean
return whether all disabilities on this form are rated as not service-connected
256 257 258 259 260 261 262 |
# File 'app/models/concerns/form526_claim_fast_tracking_concern.rb', line 256 def disabilities_not_service_connected? disabilities.pluck('ratedDisabilityId').all? do |rated_id| rated_id.present? && (all_rated_disabilities .find { |rated| rated_id == rated.rated_disability_id } &.decision_code == 'NOTSVCCON') end end |
#ep_merge_feature_enabled? ⇒ Boolean
279 280 281 282 283 284 285 286 |
# File 'app/models/concerns/form526_claim_fast_tracking_concern.rb', line 279 def ep_merge_feature_enabled? actor = OpenStruct.new({ flipper_id: user_uuid }) if Flipper.enabled?(:disability_compensation_production_tester, actor) Rails.logger.info("EP merge skipped for submission #{id}, user_uuid #{user_uuid}") return false end Flipper.enabled?(:disability_526_ep_merge_api, actor) end |
#flashes ⇒ Object
103 104 105 |
# File 'app/models/concerns/form526_claim_fast_tracking_concern.rb', line 103 def flashes form['flashes'] || [] end |
#format_contention_for_vro(disability) ⇒ Object
181 182 183 184 185 186 187 188 |
# File 'app/models/concerns/form526_claim_fast_tracking_concern.rb', line 181 def format_contention_for_vro(disability) contention = { contention_text: disability['name'], contention_type: disability['disabilityActionType'] } contention['diagnostic_code'] = disability['diagnosticCode'] if disability['diagnosticCode'] contention end |
#in_progress_form ⇒ Object (private)
290 291 292 |
# File 'app/models/concerns/form526_claim_fast_tracking_concern.rb', line 290 def in_progress_form @in_progress_form ||= InProgressForm.find_by(form_id: '21-526EZ', user_uuid:) end |
#increase_disabilities ⇒ Object
111 112 113 |
# File 'app/models/concerns/form526_claim_fast_tracking_concern.rb', line 111 def increase_disabilities disabilities.select { |disability| disability['disabilityActionType']&.upcase == 'INCREASE' } end |
#log_and_halt_if_no_disabilities ⇒ Object
195 196 197 198 |
# File 'app/models/concerns/form526_claim_fast_tracking_concern.rb', line 195 def log_and_halt_if_no_disabilities Rails.logger.info("No disabilities found for classification on claim #{id}") false end |
#log_claim_level_metrics(response_body) ⇒ Object
190 191 192 193 |
# File 'app/models/concerns/form526_claim_fast_tracking_concern.rb', line 190 def log_claim_level_metrics(response_body) response_body['is_multi_contention_claim'] = disabilities.count > 1 Rails.logger.info('classifier response for 526Submission', payload: response_body) end |
#log_flashes ⇒ Object (private)
414 415 416 417 418 419 420 421 422 |
# File 'app/models/concerns/form526_claim_fast_tracking_concern.rb', line 414 def log_flashes flash_prototypes = FLASH_PROTOTYPES & flashes Rails.logger.info('Flash Prototype Added', { submitted_claim_id:, flashes: }) if flash_prototypes.any? flashes.each do |flash| StatsD.increment(FLASHES_STATSD_KEY, tags: ["flash:#{flash}", "prototype:#{flash_prototypes.include?(flash)}"]) end rescue => e Rails.logger.error("Failed to log Flash Prototypes #{e.}.", backtrace: e.backtrace) end |
#log_max_cfi_metrics_on_submit ⇒ Object
227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 |
# File 'app/models/concerns/form526_claim_fast_tracking_concern.rb', line 227 def log_max_cfi_metrics_on_submit max_rated_diagnostic_codes_from_ipf.each do |diagnostic_code| disability_claimed = diagnostic_codes.include?(diagnostic_code) StatsD.increment("#{MAX_CFI_STATSD_KEY_PREFIX}.submit", tags: ["diagnostic_code:#{diagnostic_code}", "claimed:#{disability_claimed}"]) end claimed_max_rated_dcs = max_rated_diagnostic_codes_from_ipf & diagnostic_codes Rails.logger.info('Max CFI form526 submission', id:, num_max_rated: max_rated_diagnostic_codes_from_ipf.count, num_max_rated_cfi: claimed_max_rated_dcs.count, total_cfi: increase_disabilities.count, cfi_checkbox_was_selected: cfi_checkbox_was_selected?) StatsD.increment("#{MAX_CFI_STATSD_KEY_PREFIX}.on_submit", tags: ["claimed:#{claimed_max_rated_dcs.any?}", "has_max_rated:#{max_rated_diagnostic_codes_from_ipf.any?}"]) rescue => e # Log the exception but but do not fail, otherwise form will not be submitted log_exception_to_sentry(e) end |
#max_rated_diagnostic_codes_from_ipf ⇒ Object (private)
306 307 308 |
# File 'app/models/concerns/form526_claim_fast_tracking_concern.rb', line 306 def max_rated_diagnostic_codes_from_ipf max_rated_disabilities_from_ipf.pluck('diagnostic_code') end |
#max_rated_disabilities_from_ipf ⇒ Object (private)
294 295 296 297 298 299 300 301 302 303 304 |
# File 'app/models/concerns/form526_claim_fast_tracking_concern.rb', line 294 def max_rated_disabilities_from_ipf return [] if in_progress_form.nil? fd = in_progress_form.form_data fd = JSON.parse(fd) if fd.is_a?(String) rated_disabilities = fd['rated_disabilities'] || [] rated_disabilities.select do |dis| dis['maximum_rating_percentage'].present? && dis['maximum_rating_percentage'] == dis['rating_percentage'] end end |
#notify_mas_all_claims_tracking ⇒ Object (private)
381 382 383 |
# File 'app/models/concerns/form526_claim_fast_tracking_concern.rb', line 381 def notify_mas_all_claims_tracking RrdMasNotificationMailer.build(self, Settings.rrd.mas_all_claims_tracking.recipients).deliver_now end |
#open_claim_review? ⇒ Boolean (private)
Check both Benefits Claim service and Caseflow Appeals status APIs for open 030 or 040 Offramps EP 400 Merge process if any are found, or if anything fails
330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 |
# File 'app/models/concerns/form526_claim_fast_tracking_concern.rb', line 330 def open_claim_review? open_claim_review = open_claims.any? do |claim| CLAIM_REVIEW_BASE_CODES.include?(claim['base_end_product_code']) && OPEN_STATUSES.include?(claim['status']) end if open_claim_review StatsD.increment("#{EP_MERGE_STATSD_KEY_PREFIX}.open_claim_review") return true end ssn = User.find(user_uuid)&.ssn ssn ||= auth_headers['va_eauth_pnid'] if auth_headers['va_eauth_pnidtype'] == 'SSN' decision_reviews = Caseflow::Service.new.get_appeals(OpenStruct.new({ ssn: })).body['data'] StatsD.increment("#{EP_MERGE_STATSD_KEY_PREFIX}.caseflow_api_called") decision_reviews.any? do |review| CLAIM_REVIEW_TYPES.include?(review['type']) && review['attributes']['active'] end rescue => e Rails.logger.error('EP Merge failed open claim review check', backtrace: e.backtrace) Rails.logger.error(e.backtrace.join('\n')) true end |
#open_claims ⇒ Object (private)
Fetch and memoize all of the veteran’s open EPs. Establishing a new EP will make the memoized value outdated if using the same Form526Submission instance.
312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 |
# File 'app/models/concerns/form526_claim_fast_tracking_concern.rb', line 312 def open_claims @open_claims ||= begin icn = account.icn api_provider = ApiProviderFactory.call( type: ApiProviderFactory::FACTORIES[:claims], provider: nil, options: { auth_headers:, icn: }, # Flipper id is needed to check if the feature toggle works for this user current_user: OpenStruct.new({ flipper_id: user_account_id }), feature_toggle: ApiProviderFactory::FEATURE_TOGGLE_CLAIMS_SERVICE ) all_claims = api_provider.all_claims all_claims['open_claims'] end end |
#pending_eps? ⇒ Boolean
Fetch all claims from EVSS
71 72 73 74 75 |
# File 'app/models/concerns/form526_claim_fast_tracking_concern.rb', line 71 def pending_eps? pending = open_claims.any? { |claim| claim['base_end_product_code'] == '020' } (offramp_reason: 'pending_ep') if pending pending end |
#prepare_for_ep_merge! ⇒ Object
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
# File 'app/models/concerns/form526_claim_fast_tracking_concern.rb', line 134 def prepare_for_ep_merge! pending_eps = open_claims.select do |claim| EP_MERGE_BASE_CODES.include?(claim['base_end_product_code']) && OPEN_STATUSES.include?(claim['status']) end Rails.logger.info('EP Merge total open EPs', id:, count: pending_eps.count) return unless pending_eps.count == 1 feature_enabled = ep_merge_feature_enabled? open_claim_review = open_claim_review? Rails.logger.info( 'EP Merge open EP eligibility', { id:, feature_enabled:, open_claim_review:, pending_ep_age: claim_age_in_days(pending_eps.first), pending_ep_status: pending_eps.first['status'] } ) if feature_enabled && !open_claim_review (ep_merge_pending_claim_id: pending_eps.first['id']) add_ep_merge_special_issue! end rescue => e Rails.logger.error("EP400 Merge eligibility failed #{e.}.", backtrace: e.backtrace) end |
#prepare_for_evss! ⇒ Object
119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
# File 'app/models/concerns/form526_claim_fast_tracking_concern.rb', line 119 def prepare_for_evss! begin is_claim_fully_classified = update_contention_classification_all! rescue => e Rails.logger.error("Contention Classification failed #{e.}.") Rails.logger.error(e.backtrace.join('\n')) end prepare_for_ep_merge! if is_claim_fully_classified return if pending_eps? || disabilities_not_service_connected? (forward_to_mas_all_claims: true) end |
#read_metadata(key) ⇒ Object
44 45 46 |
# File 'app/models/concerns/form526_claim_fast_tracking_concern.rb', line 44 def (key) form.dig('rrd_metadata', key.to_s) end |
#rrd_claim_processed? ⇒ Boolean (private)
Returns if this claim submission was processed and fast-tracked by RRD.
377 378 379 |
# File 'app/models/concerns/form526_claim_fast_tracking_concern.rb', line 377 def rrd_claim_processed? rrd_pdf_added_for_uploading? && rrd_special_issue_set? end |
#rrd_pdf_added_for_uploading? ⇒ Boolean
Returns if an RRD pdf has been included as a file to upload.
91 92 93 94 95 |
# File 'app/models/concerns/form526_claim_fast_tracking_concern.rb', line 91 def rrd_pdf_added_for_uploading? form['form526_uploads']&.any? do |upload| upload['name']&.match? PDF_FILENAME_REGEX end end |
#rrd_pdf_created? ⇒ Boolean
77 78 79 |
# File 'app/models/concerns/form526_claim_fast_tracking_concern.rb', line 77 def rrd_pdf_created? (:pdf_created) || false end |
#rrd_pdf_uploaded_to_s3? ⇒ Boolean
81 82 83 |
# File 'app/models/concerns/form526_claim_fast_tracking_concern.rb', line 81 def rrd_pdf_uploaded_to_s3? (:pdf_guid).present? end |
#rrd_special_issue_set? ⇒ Boolean
97 98 99 100 101 |
# File 'app/models/concerns/form526_claim_fast_tracking_concern.rb', line 97 def rrd_special_issue_set? disabilities.any? do |disability| disability['specialIssues']&.include?(RRD_CODE) end end |
#rrd_status ⇒ Object
58 59 60 61 62 63 64 65 66 67 |
# File 'app/models/concerns/form526_claim_fast_tracking_concern.rb', line 58 def rrd_status return 'processed' if rrd_claim_processed? offramp_reason = (:offramp_reason) return offramp_reason if offramp_reason.present? return 'error' if (:error).present? 'unknown' end |
#save_metadata(metadata_hash) ⇒ Object
49 50 51 52 53 54 55 56 |
# File 'app/models/concerns/form526_claim_fast_tracking_concern.rb', line 49 def () form['rrd_metadata'] ||= {} form['rrd_metadata'].deep_merge!() update!(form_json: JSON.dump(form)) invalidate_form_hash self end |
#send_post_evss_notifications! ⇒ Object
248 249 250 251 252 253 |
# File 'app/models/concerns/form526_claim_fast_tracking_concern.rb', line 248 def send_post_evss_notifications! conditionally_notify_mas conditionally_merge_ep log_flashes Rails.logger.info('Submitted 526Submission to eVSS', id:, saved_claim_id:, submitted_claim_id:) end |
#send_rrd_alert_email(subject, message, error = nil, to = Settings.rrd.alerts.recipients) ⇒ Object
40 41 42 |
# File 'app/models/concerns/form526_claim_fast_tracking_concern.rb', line 40 def send_rrd_alert_email(subject, , error = nil, to = Settings.rrd.alerts.recipients) RrdAlertMailer.build(self, subject, , error, to).deliver_now end |
#update_contention_classification_all! ⇒ Object
Submits contention information to the VRO contention classification service adds classification to the form for each contention provided a classification
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 |
# File 'app/models/concerns/form526_claim_fast_tracking_concern.rb', line 202 def update_contention_classification_all! return log_and_halt_if_no_disabilities if disabilities.blank? contentions_array = disabilities.map { |disability| format_contention_for_vro(disability) } params = { claim_id: saved_claim_id, form526_submission_id: id, contentions: contentions_array } classifier_response = classify_vagov_contentions(params) log_claim_level_metrics(classifier_response) classifier_response['contentions'].each do |contention| classification = nil if contention.key?('classification_code') && contention.key?('classification_name') classification = { classification_code: contention['classification_code'], classification_name: contention['classification_name'] } end # NOTE: claim_type is actually type of contention, but formatting # preserved in order to match existing datadog dashboard Rails.logger.info('Classified 526Submission', id:, saved_claim_id:, classification:, claim_type: contention['contention_type']) end update_form_with_classification_codes(classifier_response['contentions']) classifier_response['is_fully_classified'] end |
#update_form_with_classification_codes(classified_contentions) ⇒ Object
156 157 158 159 160 161 162 163 164 165 166 |
# File 'app/models/concerns/form526_claim_fast_tracking_concern.rb', line 156 def update_form_with_classification_codes(classified_contentions) classified_contentions.each_with_index do |classified_contention, index| if classified_contention['classification_code'].present? classification_code = classified_contention['classification_code'] disabilities[index]['classificationCode'] = classification_code end end update!(form_json: form.to_json) invalidate_form_hash end |